summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2019-07-02 12:02:07 -0400
committerisanae <14251494+isanae@users.noreply.github.com>2019-07-02 12:02:07 -0400
commit82d985064e5105ded4b20d357eaf7cd1b97fe9da (patch)
tree2de9879fa59758d057de1bc1b8017846da377421
parentc6e80f1a5eed4a57663e7fc55c2727258eaad552 (diff)
added a ModInfoDialogTabContext to avoid passing too many things to tab constructors
mod is passed to ctors to make sure they can never be empty only call deleteRequest() to selected mod comments
-rw-r--r--src/mainwindow.cpp4
-rw-r--r--src/modinfodialog.cpp40
-rw-r--r--src/modinfodialog.h36
-rw-r--r--src/modinfodialogcategories.cpp14
-rw-r--r--src/modinfodialogcategories.h4
-rw-r--r--src/modinfodialogconflicts.cpp12
-rw-r--r--src/modinfodialogconflicts.h4
-rw-r--r--src/modinfodialogesps.cpp8
-rw-r--r--src/modinfodialogesps.h4
-rw-r--r--src/modinfodialogfiletree.cpp14
-rw-r--r--src/modinfodialogfiletree.h4
-rw-r--r--src/modinfodialogimages.cpp9
-rw-r--r--src/modinfodialogimages.h4
-rw-r--r--src/modinfodialognexus.cpp85
-rw-r--r--src/modinfodialognexus.h4
-rw-r--r--src/modinfodialogtab.cpp33
-rw-r--r--src/modinfodialogtab.h94
-rw-r--r--src/modinfodialogtextfiles.cpp30
-rw-r--r--src/modinfodialogtextfiles.h14
19 files changed, 226 insertions, 191 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index d48fae4f..7ab555fa 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -3223,11 +3223,9 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index,
} else {
modInfo->saveMeta();
- ModInfoDialog dialog(this, &m_OrganizerCore, &m_PluginContainer);
+ ModInfoDialog dialog(this, &m_OrganizerCore, &m_PluginContainer, modInfo);
connect(&dialog, SIGNAL(originModified(int)), this, SLOT(originModified(int)));
- dialog.setMod(modInfo);
-
//Open the tab first if we want to use the standard indexes of the tabs.
if (tab != -1) {
dialog.setTab(ModInfoDialog::ETabs(tab));
diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp
index 4af479c4..4ef010e4 100644
--- a/src/modinfodialog.cpp
+++ b/src/modinfodialog.cpp
@@ -127,7 +127,8 @@ bool ModInfoDialog::TabInfo::isVisible() const
ModInfoDialog::ModInfoDialog(
- MainWindow* mw, OrganizerCore* core, PluginContainer* plugin) :
+ MainWindow* mw, OrganizerCore* core, PluginContainer* plugin,
+ ModInfo::Ptr mod) :
TutorableDialog("ModInfoDialog", mw),
ui(new Ui::ModInfoDialog), m_mainWindow(mw),
m_core(core), m_plugin(plugin), m_initialTab(ETabs(-1)),
@@ -138,6 +139,7 @@ ModInfoDialog::ModInfoDialog(
auto* sc = new QShortcut(QKeySequence::Delete, this);
connect(sc, &QShortcut::activated, [&]{ onDeleteShortcut(); });
+ setMod(mod);
m_tabs = createTabs();
for (int i=0; i<ui->tabWidget->count(); ++i) {
@@ -184,19 +186,26 @@ ModInfoDialog::ModInfoDialog(
ModInfoDialog::~ModInfoDialog() = default;
+template <class T>
+std::unique_ptr<ModInfoDialogTab> createTab(ModInfoDialog& d, int index)
+{
+ return std::make_unique<T>(ModInfoDialogTabContext(
+ *d.m_core, *d.m_plugin, &d, d.ui.get(), index, d.m_mod, d.getOrigin()));
+}
+
std::vector<ModInfoDialog::TabInfo> ModInfoDialog::createTabs()
{
std::vector<TabInfo> v;
- v.push_back(createTab<TextFilesTab>(TAB_TEXTFILES));
- v.push_back(createTab<IniFilesTab>(TAB_INIFILES));
- v.push_back(createTab<ImagesTab>(TAB_IMAGES));
- v.push_back(createTab<ESPsTab>(TAB_ESPS));
- v.push_back(createTab<ConflictsTab>(TAB_CONFLICTS));
- v.push_back(createTab<CategoriesTab>(TAB_CATEGORIES));
- v.push_back(createTab<NexusTab>(TAB_NEXUS));
- v.push_back(createTab<NotesTab>(TAB_NOTES));
- v.push_back(createTab<FileTreeTab>(TAB_FILETREE));
+ v.push_back(createTab<TextFilesTab>(*this, TAB_TEXTFILES));
+ v.push_back(createTab<IniFilesTab>(*this, TAB_INIFILES));
+ v.push_back(createTab<ImagesTab>(*this, TAB_IMAGES));
+ v.push_back(createTab<ESPsTab>(*this, TAB_ESPS));
+ v.push_back(createTab<ConflictsTab>(*this, TAB_CONFLICTS));
+ v.push_back(createTab<CategoriesTab>(*this, TAB_CATEGORIES));
+ v.push_back(createTab<NexusTab>(*this, TAB_NEXUS));
+ v.push_back(createTab<NotesTab>(*this, TAB_NOTES));
+ v.push_back(createTab<FileTreeTab>(*this, TAB_FILETREE));
return v;
}
@@ -218,6 +227,7 @@ int ModInfoDialog::exec()
void ModInfoDialog::setMod(ModInfo::Ptr mod)
{
+ Q_ASSERT(mod);
m_mod = mod;
for (auto& tabInfo : m_tabs) {
@@ -584,10 +594,8 @@ void ModInfoDialog::onOriginModified(int originID)
void ModInfoDialog::onDeleteShortcut()
{
- for (auto& tabInfo : m_tabs) {
- if (tabInfo.tab->deleteRequested()) {
- break;
- }
+ if (auto* tabInfo=currentTab()) {
+ tabInfo->tab->deleteRequested();
}
}
@@ -663,7 +671,7 @@ void ModInfoDialog::onTabMoved()
void ModInfoDialog::on_nextButton_clicked()
{
auto mod = m_mainWindow->nextModInList();
- if (mod == m_mod) {
+ if (!mod || mod == m_mod) {
return;
}
@@ -674,7 +682,7 @@ void ModInfoDialog::on_nextButton_clicked()
void ModInfoDialog::on_prevButton_clicked()
{
auto mod = m_mainWindow->previousModInList();
- if (mod == m_mod) {
+ if (!mod || mod == m_mod) {
return;
}
diff --git a/src/modinfodialog.h b/src/modinfodialog.h
index 899a3eab..9eb00a3b 100644
--- a/src/modinfodialog.h
+++ b/src/modinfodialog.h
@@ -66,7 +66,11 @@ protected:
**/
class ModInfoDialog : public MOBase::TutorableDialog
{
- Q_OBJECT
+ Q_OBJECT;
+
+ template <class T>
+ friend std::unique_ptr<ModInfoDialogTab> createTab(
+ ModInfoDialog& d, int index);
public:
enum ETabs {
@@ -81,30 +85,12 @@ public:
TAB_FILETREE
};
- /**
- * @brief constructor
- *
- * @param modInfo info structure about the mod to display
- * @param parent parend widget
- **/
- ModInfoDialog(MainWindow* mw, OrganizerCore* core, PluginContainer* plugin);
+ ModInfoDialog(
+ MainWindow* mw, OrganizerCore* core, PluginContainer* plugin,
+ ModInfo::Ptr mod);
~ModInfoDialog();
- /**
- * @brief retrieve the (user-modified) version of the mod
- *
- * @return the (user-modified) version of the mod
- **/
- QString getModVersion() const;
-
- /**
- * @brief retrieve the (user-modified) mod id
- *
- * @return the (user-modified) id of the mod
- **/
- const int getModID() const;
-
void setMod(ModInfo::Ptr mod);
void setMod(const QString& name);
void setTab(ETabs id);
@@ -166,12 +152,6 @@ private:
void onOriginModified(int originID);
void onTabChanged();
void onTabMoved();
-
- template <class T>
- std::unique_ptr<ModInfoDialogTab> createTab(int index)
- {
- return std::make_unique<T>(*m_core, *m_plugin, this, ui.get(), index);
- }
};
#endif // MODINFODIALOG_H
diff --git a/src/modinfodialogcategories.cpp b/src/modinfodialogcategories.cpp
index 8ffded59..c61e248e 100644
--- a/src/modinfodialogcategories.cpp
+++ b/src/modinfodialogcategories.cpp
@@ -3,10 +3,8 @@
#include "categories.h"
#include "modinfo.h"
-CategoriesTab::CategoriesTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id)
- : ModInfoDialogTab(oc, plugin, parent, ui, id)
+CategoriesTab::CategoriesTab(ModInfoDialogTabContext cx)
+ : ModInfoDialogTab(std::move(cx))
{
connect(
ui->categories, &QTreeWidget::itemChanged,
@@ -30,7 +28,7 @@ void CategoriesTab::update()
clear();
add(
- CategoryFactory::instance(), mod()->getCategories(),
+ CategoryFactory::instance(), mod().getCategories(),
ui->categories->invisibleRootItem(), 0);
updatePrimary();
@@ -81,7 +79,7 @@ void CategoriesTab::updatePrimary()
{
ui->primaryCategories->clear();
- int primaryCategory = mod()->getPrimaryCategory();
+ int primaryCategory = mod().getPrimaryCategory();
addChecked(ui->categories->invisibleRootItem());
@@ -111,7 +109,7 @@ void CategoriesTab::save(QTreeWidgetItem* currentNode)
for (int i = 0; i < currentNode->childCount(); ++i) {
QTreeWidgetItem *childNode = currentNode->child(i);
- mod()->setCategory(
+ mod().setCategory(
childNode->data(0, Qt::UserRole).toInt(), childNode->checkState(0));
save(childNode);
@@ -134,6 +132,6 @@ void CategoriesTab::onCategoryChanged(QTreeWidgetItem* item, int)
void CategoriesTab::onPrimaryChanged(int index)
{
if (index != -1) {
- mod()->setPrimaryCategory(ui->primaryCategories->itemData(index).toInt());
+ mod().setPrimaryCategory(ui->primaryCategories->itemData(index).toInt());
}
}
diff --git a/src/modinfodialogcategories.h b/src/modinfodialogcategories.h
index 392023e7..c8b52fec 100644
--- a/src/modinfodialogcategories.h
+++ b/src/modinfodialogcategories.h
@@ -5,9 +5,7 @@ class CategoryFactory;
class CategoriesTab : public ModInfoDialogTab
{
public:
- CategoriesTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id);
+ CategoriesTab(ModInfoDialogTabContext cx);
void clear() override;
void update() override;
diff --git a/src/modinfodialogconflicts.cpp b/src/modinfodialogconflicts.cpp
index a3383a50..511d48ad 100644
--- a/src/modinfodialogconflicts.cpp
+++ b/src/modinfodialogconflicts.cpp
@@ -382,11 +382,9 @@ void for_each_in_selection(QTreeView* tree, F&& f)
}
-ConflictsTab::ConflictsTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id) :
- ModInfoDialogTab(oc, plugin, parent, ui, id),
- m_general(this, ui, oc), m_advanced(this, ui, oc)
+ConflictsTab::ConflictsTab(ModInfoDialogTabContext cx) :
+ ModInfoDialogTab(cx), // don't move, cx is used again
+ m_general(this, cx.ui, cx.core), m_advanced(this, cx.ui, cx.core)
{
connect(
&m_general, &GeneralConflictsTab::modOpen,
@@ -872,7 +870,7 @@ bool GeneralConflictsTab::update()
int numOverwritten = 0;
if (m_tab->origin() != nullptr) {
- const auto rootPath = m_tab->mod()->absolutePath();
+ const auto rootPath = m_tab->mod().absolutePath();
for (const auto& file : m_tab->origin()->getFiles()) {
// careful: these two strings are moved into createXItem() below
@@ -1085,7 +1083,7 @@ void AdvancedConflictsTab::update()
clear();
if (m_tab->origin() != nullptr) {
- const auto rootPath = m_tab->mod()->absolutePath();
+ const auto rootPath = m_tab->mod().absolutePath();
const auto& files = m_tab->origin()->getFiles();
m_model->reserve(files.size());
diff --git a/src/modinfodialogconflicts.h b/src/modinfodialogconflicts.h
index 3fa12231..a77c2ac9 100644
--- a/src/modinfodialogconflicts.h
+++ b/src/modinfodialogconflicts.h
@@ -103,9 +103,7 @@ class ConflictsTab : public ModInfoDialogTab
Q_OBJECT;
public:
- ConflictsTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id);
+ ConflictsTab(ModInfoDialogTabContext cx);
void update() override;
void clear() override;
diff --git a/src/modinfodialogesps.cpp b/src/modinfodialogesps.cpp
index 8dceaa31..fba5d39a 100644
--- a/src/modinfodialogesps.cpp
+++ b/src/modinfodialogesps.cpp
@@ -224,11 +224,9 @@ private:
-ESPsTab::ESPsTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id) :
- ModInfoDialogTab(oc, plugin, parent, ui, id),
- m_inactiveModel(new ESPListModel), m_activeModel(new ESPListModel)
+ESPsTab::ESPsTab(ModInfoDialogTabContext cx) :
+ ModInfoDialogTab(std::move(cx)),
+ m_inactiveModel(new ESPListModel), m_activeModel(new ESPListModel)
{
ui->inactiveESPList->setModel(m_inactiveModel);
ui->activeESPList->setModel(m_activeModel);
diff --git a/src/modinfodialogesps.h b/src/modinfodialogesps.h
index 217863c6..b128f279 100644
--- a/src/modinfodialogesps.h
+++ b/src/modinfodialogesps.h
@@ -11,9 +11,7 @@ class ESPsTab : public ModInfoDialogTab
Q_OBJECT;
public:
- ESPsTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id);
+ ESPsTab(ModInfoDialogTabContext cx);
void clear() override;
bool feedFile(const QString& rootPath, const QString& fullPath) override;
diff --git a/src/modinfodialogfiletree.cpp b/src/modinfodialogfiletree.cpp
index 6690dd2f..35480e2c 100644
--- a/src/modinfodialogfiletree.cpp
+++ b/src/modinfodialogfiletree.cpp
@@ -13,10 +13,8 @@ namespace shell = MOBase::shell;
// checking whether menu items apply to them, just show all of them
const int max_scan_for_context_menu = 50;
-FileTreeTab::FileTreeTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id)
- : ModInfoDialogTab(oc, plugin, parent, ui, id), m_fs(nullptr)
+FileTreeTab::FileTreeTab(ModInfoDialogTabContext cx)
+ : ModInfoDialogTab(std::move(cx)), m_fs(nullptr)
{
m_fs = new QFileSystemModel(this);
m_fs->setReadOnly(false);
@@ -58,7 +56,7 @@ void FileTreeTab::clear()
void FileTreeTab::update()
{
- const auto rootPath = mod()->absolutePath();
+ const auto rootPath = mod().absolutePath();
m_fs->setRootPath(rootPath);
ui->filetree->setRootIndex(m_fs->index(rootPath));
@@ -139,7 +137,7 @@ void FileTreeTab::onPreview()
return;
}
- core().previewFile(parentWidget(), mod()->name(), m_fs->filePath(selection));
+ core().previewFile(parentWidget(), mod().name(), m_fs->filePath(selection));
}
void FileTreeTab::onExplore()
@@ -149,7 +147,7 @@ void FileTreeTab::onExplore()
if (selection.isValid()) {
shell::ExploreFile(m_fs->filePath(selection));
} else {
- shell::ExploreFile(mod()->absolutePath());
+ shell::ExploreFile(mod().absolutePath());
}
}
@@ -205,7 +203,7 @@ void FileTreeTab::onUnhide()
void FileTreeTab::onOpenInExplorer()
{
- shell::ExploreFile(mod()->absolutePath());
+ shell::ExploreFile(mod().absolutePath());
}
bool FileTreeTab::deleteFile(const QModelIndex& index)
diff --git a/src/modinfodialogfiletree.h b/src/modinfodialogfiletree.h
index 9f5206b9..f9fa62d4 100644
--- a/src/modinfodialogfiletree.h
+++ b/src/modinfodialogfiletree.h
@@ -6,9 +6,7 @@
class FileTreeTab : public ModInfoDialogTab
{
public:
- FileTreeTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id);
+ FileTreeTab(ModInfoDialogTabContext cx);
void clear() override;
void update() override;
diff --git a/src/modinfodialogimages.cpp b/src/modinfodialogimages.cpp
index 307fa8e8..cf33f9f5 100644
--- a/src/modinfodialogimages.cpp
+++ b/src/modinfodialogimages.cpp
@@ -35,12 +35,9 @@ QString dimensionString(const QSize& s)
}
-ImagesTab::ImagesTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id) :
- ModInfoDialogTab(oc, plugin, parent, ui, id),
- m_image(new ScalableImage),
- m_ddsAvailable(false), m_ddsEnabled(false)
+ImagesTab::ImagesTab(ModInfoDialogTabContext cx) :
+ ModInfoDialogTab(std::move(cx)), m_image(new ScalableImage),
+ m_ddsAvailable(false), m_ddsEnabled(false)
{
getSupportedFormats();
diff --git a/src/modinfodialogimages.h b/src/modinfodialogimages.h
index d22a6ab2..8d9b965b 100644
--- a/src/modinfodialogimages.h
+++ b/src/modinfodialogimages.h
@@ -314,9 +314,7 @@ class ImagesTab : public ModInfoDialogTab
friend class ImagesTabHelpers::ThumbnailsWidget;
public:
- ImagesTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id);
+ ImagesTab(ModInfoDialogTabContext cx);
void clear() override;
bool feedFile(const QString& rootPath, const QString& fullPath) override;
diff --git a/src/modinfodialognexus.cpp b/src/modinfodialognexus.cpp
index 8c8ce55a..81546f58 100644
--- a/src/modinfodialognexus.cpp
+++ b/src/modinfodialognexus.cpp
@@ -14,11 +14,8 @@ bool isValidModID(int id)
return (id > 0);
}
-NexusTab::NexusTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id) :
- ModInfoDialogTab(oc, plugin, parent, ui, id), m_requestStarted(false),
- m_loading(false)
+NexusTab::NexusTab(ModInfoDialogTabContext cx) :
+ ModInfoDialogTab(std::move(cx)), m_requestStarted(false), m_loading(false)
{
ui->modID->setValidator(new QIntValidator(ui->modID));
ui->endorse->setVisible(core().settings().endorsementIntegration());
@@ -70,9 +67,9 @@ void NexusTab::update()
clear();
- ui->modID->setText(QString("%1").arg(mod()->getNexusID()));
+ ui->modID->setText(QString("%1").arg(mod().getNexusID()));
- QString gameName = mod()->getGameName();
+ QString gameName = mod().getGameName();
ui->sourceGame->addItem(
core().managedGame()->gameName(),
core().managedGame()->gameShortName());
@@ -100,10 +97,10 @@ void NexusTab::update()
[&](const QUrl& url){ shell::OpenLink(url); });
ui->endorse->setEnabled(
- (mod()->endorsedState() == ModInfo::ENDORSED_FALSE) ||
- (mod()->endorsedState() == ModInfo::ENDORSED_NEVER));
+ (mod().endorsedState() == ModInfo::ENDORSED_FALSE) ||
+ (mod().endorsedState() == ModInfo::ENDORSED_NEVER));
- setHasData(mod()->getNexusID() >= 0);
+ setHasData(mod().getNexusID() >= 0);
}
void NexusTab::firstActivation()
@@ -128,10 +125,10 @@ bool NexusTab::usesOriginFiles() const
void NexusTab::updateVersionColor()
{
- if (mod()->getVersion() != mod()->getNewestVersion()) {
+ if (mod().getVersion() != mod().getNewestVersion()) {
ui->version->setStyleSheet("color: red");
ui->version->setToolTip(tr("Current Version: %1").arg(
- mod()->getNewestVersion().canonicalString()));
+ mod().getNewestVersion().canonicalString()));
} else {
ui->version->setStyleSheet("color: green");
ui->version->setToolTip(tr("No update available"));
@@ -140,11 +137,11 @@ void NexusTab::updateVersionColor()
void NexusTab::updateWebpage()
{
- const int modID = mod()->getNexusID();
+ const int modID = mod().getNexusID();
if (isValidModID(modID)) {
const QString nexusLink = NexusInterface::instance(&plugin())
- ->getModURL(modID, mod()->getGameName());
+ ->getModURL(modID, mod().getGameName());
ui->visitNexus->setToolTip(nexusLink);
refreshData(modID);
@@ -152,19 +149,19 @@ void NexusTab::updateWebpage()
onModChanged();
}
- ui->version->setText(mod()->getVersion().displayString());
- ui->hasCustomURL->setChecked(mod()->hasCustomURL());
- ui->customURL->setText(mod()->getCustomURL());
- ui->customURL->setEnabled(mod()->hasCustomURL());
- ui->visitCustomURL->setEnabled(mod()->hasCustomURL());
- ui->visitCustomURL->setToolTip(mod()->parseCustomURL().toString());
+ ui->version->setText(mod().getVersion().displayString());
+ ui->hasCustomURL->setChecked(mod().hasCustomURL());
+ ui->customURL->setText(mod().getCustomURL());
+ ui->customURL->setEnabled(mod().hasCustomURL());
+ ui->visitCustomURL->setEnabled(mod().hasCustomURL());
+ ui->visitCustomURL->setToolTip(mod().parseCustomURL().toString());
updateTracking();
}
void NexusTab::updateTracking()
{
- if (mod()->trackedState() == ModInfo::TRACKED_TRUE) {
+ if (mod().trackedState() == ModInfo::TRACKED_TRUE) {
ui->track->setChecked(true);
ui->track->setText(tr("Tracked"));
} else {
@@ -185,7 +182,7 @@ void NexusTab::refreshData(int modID)
bool NexusTab::tryRefreshData(int modID)
{
if (isValidModID(modID) && !m_requestStarted) {
- if (mod()->updateNXMInfo()) {
+ if (mod().updateNXMInfo()) {
ui->browser->setHtml("");
return true;
}
@@ -198,7 +195,7 @@ void NexusTab::onModChanged()
{
m_requestStarted = false;
- const QString nexusDescription = mod()->getNexusDescription();
+ const QString nexusDescription = mod().getNexusDescription();
QString descriptionAsHTML = R"(
<html>
@@ -247,12 +244,12 @@ void NexusTab::onModIDChanged()
return;
}
- const int oldID = mod()->getNexusID();
+ const int oldID = mod().getNexusID();
const int newID = ui->modID->text().toInt();
if (oldID != newID){
- mod()->setNexusID(newID);
- mod()->setLastNexusQuery(QDateTime::fromSecsSinceEpoch(0));
+ mod().setNexusID(newID);
+ mod().setLastNexusQuery(QDateTime::fromSecsSinceEpoch(0));
ui->browser->page()->setHtml("");
@@ -270,9 +267,9 @@ void NexusTab::onSourceGameChanged()
for (auto game : plugin().plugins<MOBase::IPluginGame>()) {
if (game->gameName() == ui->sourceGame->currentText()) {
- mod()->setGameName(game->gameShortName());
- mod()->setLastNexusQuery(QDateTime::fromSecsSinceEpoch(0));
- refreshData(mod()->getNexusID());
+ mod().setGameName(game->gameShortName());
+ mod().setLastNexusQuery(QDateTime::fromSecsSinceEpoch(0));
+ refreshData(mod().getNexusID());
return;
}
}
@@ -285,16 +282,16 @@ void NexusTab::onVersionChanged()
}
MOBase::VersionInfo version(ui->version->text());
- mod()->setVersion(version);
+ mod().setVersion(version);
updateVersionColor();
}
void NexusTab::onRefreshBrowser()
{
- const auto modID = mod()->getNexusID();
+ const auto modID = mod().getNexusID();
if (isValidModID(modID)) {
- mod()->setLastNexusQuery(QDateTime::fromSecsSinceEpoch(0));
+ mod().setLastNexusQuery(QDateTime::fromSecsSinceEpoch(0));
updateWebpage();
} else {
qInfo("Mod has no valid Nexus ID, info can't be updated.");
@@ -303,11 +300,11 @@ void NexusTab::onRefreshBrowser()
void NexusTab::onVisitNexus()
{
- const int modID = mod()->getNexusID();
+ const int modID = mod().getNexusID();
if (isValidModID(modID)) {
const QString nexusLink = NexusInterface::instance(&plugin())
- ->getModURL(modID, mod()->getGameName());
+ ->getModURL(modID, mod().getGameName());
shell::OpenLink(QUrl(nexusLink));
}
@@ -315,12 +312,16 @@ void NexusTab::onVisitNexus()
void NexusTab::onEndorse()
{
- core().loggedInAction(parentWidget(), [m=mod()]{ m->endorse(true); });
+ // use modPtr() instead of mod() or this because the callback may be
+ // executed after the dialog is closed
+ core().loggedInAction(parentWidget(), [m=modPtr()]{ m->endorse(true); });
}
void NexusTab::onTrack()
{
- core().loggedInAction(parentWidget(), [m=mod()] {
+ // use modPtr() instead of mod() or this because the callback may be
+ // executed after the dialog is closed
+ core().loggedInAction(parentWidget(), [m=modPtr()] {
if (m->trackedState() == ModInfo::TRACKED_TRUE) {
m->track(false);
} else {
@@ -335,9 +336,9 @@ void NexusTab::onCustomURLToggled()
return;
}
- mod()->setHasCustomURL(ui->hasCustomURL->isChecked());
- ui->customURL->setEnabled(mod()->hasCustomURL());
- ui->visitCustomURL->setEnabled(mod()->hasCustomURL());
+ mod().setHasCustomURL(ui->hasCustomURL->isChecked());
+ ui->customURL->setEnabled(mod().hasCustomURL());
+ ui->visitCustomURL->setEnabled(mod().hasCustomURL());
}
void NexusTab::onCustomURLChanged()
@@ -346,13 +347,13 @@ void NexusTab::onCustomURLChanged()
return;
}
- mod()->setCustomURL(ui->customURL->text());
- ui->visitCustomURL->setToolTip(mod()->parseCustomURL().toString());
+ mod().setCustomURL(ui->customURL->text());
+ ui->visitCustomURL->setToolTip(mod().parseCustomURL().toString());
}
void NexusTab::onVisitCustomURL()
{
- const auto url = mod()->parseCustomURL();
+ const auto url = mod().parseCustomURL();
if (url.isValid()) {
shell::OpenLink(url);
}
diff --git a/src/modinfodialognexus.h b/src/modinfodialognexus.h
index 930c1ffc..6478375b 100644
--- a/src/modinfodialognexus.h
+++ b/src/modinfodialognexus.h
@@ -33,9 +33,7 @@ signals:
class NexusTab : public ModInfoDialogTab
{
public:
- NexusTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id);
+ NexusTab(ModInfoDialogTabContext cx);
~NexusTab();
diff --git a/src/modinfodialogtab.cpp b/src/modinfodialogtab.cpp
index 0468b405..554df6df 100644
--- a/src/modinfodialogtab.cpp
+++ b/src/modinfodialogtab.cpp
@@ -3,11 +3,9 @@
#include "texteditor.h"
#include "directoryentry.h"
-ModInfoDialogTab::ModInfoDialogTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id) :
- ui(ui), m_core(oc), m_plugin(plugin), m_parent(parent),
- m_origin(nullptr), m_tabID(id), m_hasData(false), m_firstActivation(true)
+ModInfoDialogTab::ModInfoDialogTab(ModInfoDialogTabContext cx) :
+ ui(cx.ui), m_core(cx.core), m_plugin(cx.plugin), m_parent(cx.parent),
+ m_origin(cx.origin), m_tabID(cx.id), m_hasData(false), m_firstActivation(true)
{
}
@@ -82,8 +80,15 @@ void ModInfoDialogTab::setMod(ModInfo::Ptr mod, MOShared::FilesOrigin* origin)
m_origin = origin;
}
-ModInfo::Ptr ModInfoDialogTab::mod() const
+ModInfo& ModInfoDialogTab::mod() const
{
+ Q_ASSERT(m_mod);
+ return *m_mod;
+}
+
+ModInfo::Ptr ModInfoDialogTab::modPtr() const
+{
+ Q_ASSERT(m_mod);
return m_mod;
}
@@ -143,10 +148,8 @@ void ModInfoDialogTab::setFocus()
}
-NotesTab::NotesTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int index)
- : ModInfoDialogTab(oc, plugin, parent, ui, index)
+NotesTab::NotesTab(ModInfoDialogTabContext cx)
+ : ModInfoDialogTab(std::move(cx))
{
connect(ui->comments, &QLineEdit::editingFinished, [&]{ onComments(); });
connect(ui->notes, &HTMLEditor::editingFinished, [&]{ onNotes(); });
@@ -161,8 +164,8 @@ void NotesTab::clear()
void NotesTab::update()
{
- const auto comments = mod()->comments();
- const auto notes = mod()->notes();
+ const auto comments = mod().comments();
+ const auto notes = mod().notes();
ui->comments->setText(comments);
ui->notes->setText(notes);
@@ -176,7 +179,7 @@ bool NotesTab::canHandleSeparators() const
void NotesTab::onComments()
{
- mod()->setComments(ui->comments->text());
+ mod().setComments(ui->comments->text());
checkHasData();
}
@@ -184,9 +187,9 @@ void NotesTab::onNotes()
{
// Avoid saving html stub if notes field is empty.
if (ui->notes->toPlainText().isEmpty()) {
- mod()->setNotes({});
+ mod().setNotes({});
} else {
- mod()->setNotes(ui->notes->toHtml());
+ mod().setNotes(ui->notes->toHtml());
}
checkHasData();
diff --git a/src/modinfodialogtab.h b/src/modinfodialogtab.h
index 3f98314a..eb574de0 100644
--- a/src/modinfodialogtab.h
+++ b/src/modinfodialogtab.h
@@ -10,6 +10,33 @@ namespace Ui { class ModInfoDialog; }
class Settings;
class OrganizerCore;
+// helper struct to avoid passing too much stuff to tab constructors
+//
+struct ModInfoDialogTabContext
+{
+ OrganizerCore& core;
+ PluginContainer& plugin;
+ QWidget* parent;
+ Ui::ModInfoDialog* ui;
+ int id;
+ ModInfo::Ptr mod;
+ MOShared::FilesOrigin* origin;
+
+ ModInfoDialogTabContext(
+ OrganizerCore& core,
+ PluginContainer& plugin,
+ QWidget* parent,
+ Ui::ModInfoDialog* ui,
+ int id,
+ ModInfo::Ptr mod,
+ MOShared::FilesOrigin* origin) :
+ core(core), plugin(plugin), parent(parent), ui(ui), id(id),
+ mod(mod), origin(origin)
+ {
+ }
+};
+
+
// base class for all tabs in the mod info dialog
//
// when the dialog is opened or when next/previous is clicked, the sequence is:
@@ -38,7 +65,7 @@ class OrganizerCore;
// tabs can call emitModOpen() to request showing a different mod
//
// hasDataChanged() should be called when a tab goes from having data to being
-// empty or vice versa; this will update the tab text color
+// empty or vice versa; this will update the tab text colour
//
class ModInfoDialogTab : public QObject
{
@@ -107,20 +134,75 @@ public:
//
virtual void firstActivation();
+ // called when closing the dialog, can return false to stop the dialog from
+ // closing
+ //
+ // this is typically used by tabs that require manual saving, like text files;
+ // tabs that refuse to close should focus themselves before showing whatever
+ // confirmation they have
//
virtual bool canClose();
+
+
+ // called after the dialog is closed, tabs should save whatever UI state they
+ // want
+ //
virtual void saveState(Settings& s);
+
+ // called before the is shown, tabs should restore whatever UI state they
+ // saved in saveState()
+ //
virtual void restoreState(const Settings& s);
+
+ // called on the selected tab when the Delete key is pressed on the keyboard;
+ // tabs _must_ check which widget currently has focus to decide whether this
+ // should be handled or not; do not blindly delete stuff when this is called
+ //
+ // if the delete request was handled, this should return true
+ //
virtual bool deleteRequested();
+
+ // return true if this tab can handle a separator mod, defaults to false;
+ // when this returns false, the tab is removed from the widget entirely
+ //
+ // if a tab can show meaningful information about a separator (like
+ // categories or notes), it should return true
+ //
virtual bool canHandleSeparators() const;
+
+ // return true if this tab can handle unmanaged mods, defaults to false;
+ // when this returns false, the tab is removed from the widget entirely
+ //
virtual bool canHandleUnmanaged() const;
+
+ // return true if this tab uses the files from the mod's origin, defaults to
+ // false
+ //
+ // tabs that do not care about the files inside a mod should return false,
+ // such as the notes or categories tab
+ //
+ // mods that return true will be updated anytime a tab calls
+ // emitOriginModifed()
+ //
virtual bool usesOriginFiles() const;
- ModInfo::Ptr mod() const;
+
+ // returns the currently selected mod
+ //
+ ModInfo& mod() const;
+
+ // returns the currently selected mod, can never be empty
+ //
+ ModInfo::Ptr modPtr() const;
+
+ // returns the origin of the selected mod; this can be null for mods that
+ // don't have an origin, like deactivated mods
+ //
MOShared::FilesOrigin* origin() const;
+
int tabID() const;
bool hasData() const;
@@ -133,9 +215,7 @@ signals:
protected:
Ui::ModInfoDialog* ui;
- ModInfoDialogTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id);
+ ModInfoDialogTab(ModInfoDialogTabContext cx);
OrganizerCore& core();
PluginContainer& plugin();
@@ -186,9 +266,7 @@ private:
class NotesTab : public ModInfoDialogTab
{
public:
- NotesTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int index);
+ NotesTab(ModInfoDialogTabContext cx);
void clear() override;
void update() override;
diff --git a/src/modinfodialogtextfiles.cpp b/src/modinfodialogtextfiles.cpp
index bc44ee3e..7a09fa4e 100644
--- a/src/modinfodialogtextfiles.cpp
+++ b/src/modinfodialogtextfiles.cpp
@@ -99,10 +99,10 @@ private:
GenericFilesTab::GenericFilesTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id,
- QListView* list, QSplitter* sp, TextEditor* e, QLineEdit* filter) :
- ModInfoDialogTab(oc, plugin, parent, ui, id),
+ ModInfoDialogTabContext cx,
+ QListView* list, QSplitter* sp,
+ TextEditor* e, QLineEdit* filter) :
+ ModInfoDialogTab(std::move(cx)),
m_list(list), m_editor(e), m_splitter(sp), m_model(new FileListModel)
{
m_list->setModel(m_model);
@@ -208,13 +208,10 @@ void GenericFilesTab::select(const QModelIndex& index)
}
-TextFilesTab::TextFilesTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id)
- : GenericFilesTab(
- oc, plugin, parent, ui, id,
- ui->textFileList, ui->tabTextSplitter,
- ui->textFileEditor, ui->textFileFilter)
+TextFilesTab::TextFilesTab(ModInfoDialogTabContext cx)
+ : GenericFilesTab(cx,
+ cx.ui->textFileList, cx.ui->tabTextSplitter,
+ cx.ui->textFileEditor, cx.ui->textFileFilter)
{
}
@@ -231,13 +228,10 @@ bool TextFilesTab::wantsFile(const QString& rootPath, const QString& fullPath) c
return false;
}
-IniFilesTab::IniFilesTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id)
- : GenericFilesTab(
- oc, plugin, parent, ui, id,
- ui->iniFileList, ui->tabIniSplitter,
- ui->iniFileEditor, ui->iniFileFilter)
+IniFilesTab::IniFilesTab(ModInfoDialogTabContext cx)
+ : GenericFilesTab(cx,
+ cx.ui->iniFileList, cx.ui->tabIniSplitter,
+ cx.ui->iniFileEditor, cx.ui->iniFileFilter)
{
}
diff --git a/src/modinfodialogtextfiles.h b/src/modinfodialogtextfiles.h
index ffe49904..725ac999 100644
--- a/src/modinfodialogtextfiles.h
+++ b/src/modinfodialogtextfiles.h
@@ -30,9 +30,9 @@ protected:
FilterWidget m_filter;
GenericFilesTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id,
- QListView* list, QSplitter* splitter, TextEditor* editor, QLineEdit* filter);
+ ModInfoDialogTabContext cx,
+ QListView* list, QSplitter* splitter,
+ TextEditor* editor, QLineEdit* filter);
virtual bool wantsFile(const QString& rootPath, const QString& fullPath) const = 0;
@@ -45,9 +45,7 @@ private:
class TextFilesTab : public GenericFilesTab
{
public:
- TextFilesTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id);
+ TextFilesTab(ModInfoDialogTabContext cx);
protected:
bool wantsFile(const QString& rootPath, const QString& fullPath) const override;
@@ -57,9 +55,7 @@ protected:
class IniFilesTab : public GenericFilesTab
{
public:
- IniFilesTab(
- OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id);
+ IniFilesTab(ModInfoDialogTabContext cx);
protected:
bool wantsFile(const QString& rootPath, const QString& fullPath) const override;