diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mainwindow.cpp | 4 | ||||
| -rw-r--r-- | src/modinfodialog.cpp | 40 | ||||
| -rw-r--r-- | src/modinfodialog.h | 36 | ||||
| -rw-r--r-- | src/modinfodialogcategories.cpp | 14 | ||||
| -rw-r--r-- | src/modinfodialogcategories.h | 4 | ||||
| -rw-r--r-- | src/modinfodialogconflicts.cpp | 12 | ||||
| -rw-r--r-- | src/modinfodialogconflicts.h | 4 | ||||
| -rw-r--r-- | src/modinfodialogesps.cpp | 8 | ||||
| -rw-r--r-- | src/modinfodialogesps.h | 4 | ||||
| -rw-r--r-- | src/modinfodialogfiletree.cpp | 14 | ||||
| -rw-r--r-- | src/modinfodialogfiletree.h | 4 | ||||
| -rw-r--r-- | src/modinfodialogimages.cpp | 9 | ||||
| -rw-r--r-- | src/modinfodialogimages.h | 4 | ||||
| -rw-r--r-- | src/modinfodialognexus.cpp | 85 | ||||
| -rw-r--r-- | src/modinfodialognexus.h | 4 | ||||
| -rw-r--r-- | src/modinfodialogtab.cpp | 33 | ||||
| -rw-r--r-- | src/modinfodialogtab.h | 94 | ||||
| -rw-r--r-- | src/modinfodialogtextfiles.cpp | 30 | ||||
| -rw-r--r-- | src/modinfodialogtextfiles.h | 14 |
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; |
