From cf1bbdd13e0db8856df672c367d3ec1610f6c556 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Mon, 25 May 2020 19:53:21 +0200 Subject: Switch to using the ModDataContent feature from the game plugin. --- src/filterlist.cpp | 12 ++++----- src/filterlist.h | 4 ++- src/mainwindow.cpp | 6 +++-- src/modinfo.cpp | 27 ------------------- src/modinfo.h | 40 ++++++++--------------------- src/modinforegular.cpp | 57 +++++------------------------------------ src/modinforegular.h | 2 +- src/modinfowithconflictinfo.cpp | 7 ++++- src/modinfowithconflictinfo.h | 15 ++++++++--- src/modlist.cpp | 39 ++++++++++------------------ src/modlist.h | 12 ++++----- src/modlistsortproxy.cpp | 19 ++------------ src/organizercore.cpp | 10 ++++++++ src/organizercore.h | 8 ++++++ 14 files changed, 88 insertions(+), 170 deletions(-) (limited to 'src') diff --git a/src/filterlist.cpp b/src/filterlist.cpp index 57bc740a..142751f0 100644 --- a/src/filterlist.cpp +++ b/src/filterlist.cpp @@ -3,6 +3,7 @@ #include "categories.h" #include "categoriesdialog.h" #include "settings.h" +#include "organizercore.h" #include using namespace MOBase; @@ -180,8 +181,8 @@ private: }; -FilterList::FilterList(Ui::MainWindow* ui, CategoryFactory& factory) - : ui(ui), m_factory(factory) +FilterList::FilterList(Ui::MainWindow* ui, OrganizerCore* organizer, CategoryFactory& factory) + : ui(ui), m_Organizer(organizer), m_factory(factory) { auto* eventFilter = new CriteriaItemFilter( ui->filters, [&](auto* item, int dir){ return cycleItem(item, dir); }); @@ -233,11 +234,10 @@ QTreeWidgetItem* FilterList::addCriteriaItem( void FilterList::addContentCriteria() { - for (unsigned i = 0; i < ModInfo::NUM_CONTENT_TYPES; ++i) { - QString filterName = tr("Contains %1").arg(ModInfo::getContentTypeName(i)); + for (auto &content: m_Organizer->modDataContents()) { addCriteriaItem( - nullptr, QString("<%1>").arg(filterName), - i, ModListSortProxy::TypeContent); + nullptr, QString("<%1>").arg(tr("Contains %1").arg(content.name())), + content.id(), ModListSortProxy::TypeContent); } } diff --git a/src/filterlist.h b/src/filterlist.h index b0ebc9a4..ba9dc71c 100644 --- a/src/filterlist.h +++ b/src/filterlist.h @@ -7,13 +7,14 @@ namespace Ui { class MainWindow; }; class CategoryFactory; class Settings; +class OrganizerCore; class FilterList : public QObject { Q_OBJECT; public: - FilterList(Ui::MainWindow* ui, CategoryFactory& factory); + FilterList(Ui::MainWindow* ui, OrganizerCore *organizer, CategoryFactory& factory); void restoreState(const Settings& s); void saveState(Settings& s) const; @@ -31,6 +32,7 @@ private: class CriteriaItem; Ui::MainWindow* ui; + OrganizerCore* m_Organizer; CategoryFactory& m_factory; bool onClick(QMouseEvent* e); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index de4a6b39..a720b621 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -311,7 +311,7 @@ MainWindow::MainWindow(Settings &settings ui->statusBar->setAPI(ni->getAPIStats(), ni->getAPIUserAccount()); } - m_Filters.reset(new FilterList(ui, m_CategoryFactory)); + m_Filters.reset(new FilterList(ui, &m_OrganizerCore, m_CategoryFactory)); connect( m_Filters.get(), &FilterList::criteriaChanged, @@ -5950,7 +5950,9 @@ void MainWindow::onFiltersCriteria(const std::vector const auto& c = criteria[0]; if (c.type == ModListSortProxy::TypeContent) { - label = ModInfo::getContentTypeName(c.id); + auto& contents = m_OrganizerCore.modDataContents(); + auto it = std::find_if(std::begin(contents), std::end(contents), [&c](auto const& content) { return content.id() == c.id; }); + label = it != std::end(contents) ? it->name() : QString(); } else { label = m_CategoryFactory.getCategoryNameByID(c.id); } diff --git a/src/modinfo.cpp b/src/modinfo.cpp index 15fa71da..a8e6a55b 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -108,27 +108,6 @@ ModInfo::Ptr ModInfo::createFromPlugin(const QString &modName, return result; } -QString ModInfo::getContentTypeName(int contentType) -{ - switch (contentType) { - case CONTENT_PLUGIN: return tr("Plugins"); - case CONTENT_TEXTURE: return tr("Textures"); - case CONTENT_MESH: return tr("Meshes"); - case CONTENT_BSA: return tr("Bethesda Archive"); - case CONTENT_INTERFACE: return tr("UI Changes"); - case CONTENT_SOUND: return tr("Sound Effects"); - case CONTENT_SCRIPT: return tr("Scripts"); - case CONTENT_SKSE: return tr("Script Extender"); - case CONTENT_SKSEFILES: return tr("Script Extender Files"); - case CONTENT_SKYPROC: return tr("SkyProc Tools"); - case CONTENT_MCM: return tr("MCM Data"); - case CONTENT_INI: return tr("INI files"); - case CONTENT_MODGROUP: return tr("ModGroup files"); - - default: throw MyException(tr("invalid content type: %1").arg(contentType)); - } -} - void ModInfo::createFromOverwrite(PluginContainer *pluginContainer, const MOBase::IPluginGame* game, MOShared::DirectoryEntry **directoryStructure) @@ -515,12 +494,6 @@ bool ModInfo::hasAnyOfTheseFlags(std::vector flags) const return false; } -bool ModInfo::hasContent(ModInfo::EContent content) const -{ - std::vector contents = getContents(); - return std::find(contents.begin(), contents.end(), content) != contents.end(); -} - bool ModInfo::categorySet(int categoryID) const { for (std::set::const_iterator iter = m_Categories.begin(); iter != m_Categories.end(); ++iter) { diff --git a/src/modinfo.h b/src/modinfo.h index 29e6124d..c5b1cfca 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -87,24 +87,6 @@ public: FLAG_TRACKED, }; - enum EContent { - CONTENT_PLUGIN, - CONTENT_TEXTURE, - CONTENT_MESH, - CONTENT_BSA, - CONTENT_INTERFACE, - CONTENT_SOUND, - CONTENT_SCRIPT, - CONTENT_SKSE, - CONTENT_SKSEFILES, - CONTENT_SKYPROC, - CONTENT_MCM, - CONTENT_INI, - CONTENT_MODGROUP - }; - - static const int NUM_CONTENT_TYPES = CONTENT_MODGROUP + 1; - enum EHighlight { HIGHLIGHT_NONE = 0, HIGHLIGHT_INVALID = 1, @@ -248,13 +230,6 @@ public: // static bool isRegularName(const QString& name); - /** - * @brief retieve a name for one of the CONTENT_ enums - * @param contentType the content value - * @return a display string - */ - static QString getContentTypeName(int contentType); - virtual bool isRegular() const { return false; } virtual bool isEmpty() const { return false; } @@ -546,7 +521,10 @@ public: /** * @return a list of content types contained in a mod */ - virtual std::vector getContents() const { return std::vector(); } + virtual const std::vector& getContents() const { + static std::vector dummy; + return dummy; + } /** * @brief test if the specified flag is set for this mod @@ -563,11 +541,13 @@ public: bool hasAnyOfTheseFlags(std::vector flags) const; /** - * @brief test if the mods contains the specified content - * @param content the content to test - * @return true if the content is there, false otherwise + * @brief Test if the mod contains the specified content. + * + * @param content ID of the content to test. + * + * @return true if the content is there, false otherwise. */ - bool hasContent(ModInfo::EContent content) const; + virtual bool hasContent(int content) const = 0; /** * @return an indicator if and how this mod should be highlighted by the UI diff --git a/src/modinforegular.cpp b/src/modinforegular.cpp index a1f1a04d..8ad7ffe5 100644 --- a/src/modinforegular.cpp +++ b/src/modinforegular.cpp @@ -3,7 +3,7 @@ #include "categories.h" #include "messagedialog.h" #include "report.h" -#include "scriptextender.h" +#include "moddatacontent.h" #include "settings.h" #include @@ -653,60 +653,15 @@ std::vector ModInfoRegular::getFlags() const } -std::vector ModInfoRegular::doGetContents() const +std::vector ModInfoRegular::doGetContents() const { - auto tree = contentFileTree(); - std::vector contents; + ModDataContent* contentFeature = m_GamePlugin->feature(); - for (auto e : *tree) { - if (e->isFile()) { - auto suffix = e->suffix().toLower(); - if (suffix == "esp" || suffix == "esm" || suffix == "esl") { - contents.push_back(CONTENT_PLUGIN); - } - else if (suffix == "bsa" || suffix == "ba2") { - contents.push_back(CONTENT_BSA); - } - else if (suffix == "ini" && e->compare("meta.ini") != 0) { - contents.push_back(CONTENT_INI); - } - else if (suffix == "modgroups") { - contents.push_back(CONTENT_MODGROUP); - } - } - else { - if (e->compare("textures") == 0 || e->compare("icons") == 0 || e->compare("bookart") == 0) - contents.push_back(CONTENT_TEXTURE); - if (e->compare("meshes") == 0) - contents.push_back(CONTENT_MESH); - if (e->compare("interface") == 0 || e->compare("menus") == 0) - contents.push_back(CONTENT_INTERFACE); - if (e->compare("music") == 0 || e->compare("sound") == 0) - contents.push_back(CONTENT_SOUND); - if (e->compare("scripts") == 0) - contents.push_back(CONTENT_SCRIPT); - if (e->compare("SkyProc Patchers") == 0) - contents.push_back(CONTENT_SKYPROC); - if (e->compare("MCM") == 0) - contents.push_back(CONTENT_MCM); - } - } - - ScriptExtender* extender = m_GamePlugin->feature(); - if (extender != nullptr) { - auto e = tree->findDirectory(extender->PluginPath()); - if (e) { - contents.push_back(CONTENT_SKSEFILES); - for (auto f : *e) { - if (f->hasSuffix("dll")) { - contents.push_back(CONTENT_SKSE); - break; - } - } - } + if (contentFeature) { + return contentFeature->getContentsFor(contentFileTree()); } - return contents; + return {}; } diff --git a/src/modinforegular.h b/src/modinforegular.h index e63e7570..b09dcd98 100644 --- a/src/modinforegular.h +++ b/src/modinforegular.h @@ -416,7 +416,7 @@ private slots: protected: - virtual std::vector doGetContents() const override; + virtual std::vector doGetContents() const override; ModInfoRegular(PluginContainer *pluginContainer, const MOBase::IPluginGame *game, const QDir &path, MOShared::DirectoryEntry **directoryStructure); diff --git a/src/modinfowithconflictinfo.cpp b/src/modinfowithconflictinfo.cpp index b0edf581..14b341d2 100644 --- a/src/modinfowithconflictinfo.cpp +++ b/src/modinfowithconflictinfo.cpp @@ -331,6 +331,11 @@ bool ModInfoWithConflictInfo::isValid() const { return m_Valid.value(); } -std::vector ModInfoWithConflictInfo::getContents() const { +const std::vector& ModInfoWithConflictInfo::getContents() const { return m_Contents.value(); } + +bool ModInfoWithConflictInfo::hasContent(int content) const { + auto& contents = m_Contents.value(); + return std::find(std::begin(contents), std::end(contents), content) != std::end(contents); +} diff --git a/src/modinfowithconflictinfo.h b/src/modinfowithconflictinfo.h index abc9f223..b66a7444 100644 --- a/src/modinfowithconflictinfo.h +++ b/src/modinfowithconflictinfo.h @@ -24,7 +24,16 @@ public: /** * @return a list of content types contained in a mod */ - virtual std::vector getContents() const override; + virtual const std::vector& getContents() const override; + + /** + * @brief Test if the mod contains the specified content. + * + * @param content ID of the content to test. + * + * @return true if the content is there, false otherwise. + */ + virtual bool hasContent(int content) const override; /** * @brief clear all caches held for this mod @@ -66,7 +75,7 @@ protected: * * @return the contents for this mod. **/ - virtual std::vector doGetContents() const { return {}; } + virtual std::vector doGetContents() const { return {}; } /** * @brief Retrieve a file tree corresponding to the underlying disk content @@ -137,7 +146,7 @@ private: MOShared::MemoizedLocked> m_FileTree; MOShared::MemoizedLocked m_Valid; - MOShared::MemoizedLocked> m_Contents; + MOShared::MemoizedLocked> m_Contents; MOShared::DirectoryEntry **m_DirectoryStructure; diff --git a/src/modlist.cpp b/src/modlist.cpp index e8c14434..3ace0ed0 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -25,6 +25,7 @@ along with Mod Organizer. If not, see . #include "modlistsortproxy.h" #include "pluginlist.h" #include "settings.h" +#include "organizercore.h" #include "modinforegular.h" #include "shared/directoryentry.h" #include "shared/fileentry.h" @@ -59,8 +60,9 @@ along with Mod Organizer. If not, see . using namespace MOBase; -ModList::ModList(PluginContainer *pluginContainer, QObject *parent) - : QAbstractItemModel(parent) +ModList::ModList(PluginContainer *pluginContainer, OrganizerCore *organizer) + : QAbstractItemModel(organizer) + , m_Organizer(organizer) , m_Profile(nullptr) , m_NexusInterface(nullptr) , m_Modified(false) @@ -69,19 +71,6 @@ ModList::ModList(PluginContainer *pluginContainer, QObject *parent) , m_DropOnItems(false) , m_PluginContainer(pluginContainer) { - m_ContentIcons[ModInfo::CONTENT_PLUGIN] = std::make_tuple(":/MO/gui/content/plugin", QT_TR_NOOP("Game Plugins (ESP/ESM/ESL)")); - m_ContentIcons[ModInfo::CONTENT_INTERFACE] = std::make_tuple(":/MO/gui/content/interface", QT_TR_NOOP("Interface")); - m_ContentIcons[ModInfo::CONTENT_MESH] = std::make_tuple(":/MO/gui/content/mesh", QT_TR_NOOP("Meshes")); - m_ContentIcons[ModInfo::CONTENT_BSA] = std::make_tuple(":/MO/gui/content/bsa", QT_TR_NOOP("Bethesda Archive")); - m_ContentIcons[ModInfo::CONTENT_SCRIPT] = std::make_tuple(":/MO/gui/content/script", QT_TR_NOOP("Scripts (Papyrus)")); - m_ContentIcons[ModInfo::CONTENT_SKSE] = std::make_tuple(":/MO/gui/content/skse", QT_TR_NOOP("Script Extender Plugin")); - m_ContentIcons[ModInfo::CONTENT_SKYPROC] = std::make_tuple(":/MO/gui/content/skyproc", QT_TR_NOOP("SkyProc Patcher")); - m_ContentIcons[ModInfo::CONTENT_SOUND] = std::make_tuple(":/MO/gui/content/sound", QT_TR_NOOP("Sound or Music")); - m_ContentIcons[ModInfo::CONTENT_TEXTURE] = std::make_tuple(":/MO/gui/content/texture", QT_TR_NOOP("Textures")); - m_ContentIcons[ModInfo::CONTENT_MCM] = std::make_tuple(":/MO/gui/content/menu", QT_TR_NOOP("MCM Configuration")); - m_ContentIcons[ModInfo::CONTENT_INI] = std::make_tuple(":/MO/gui/content/inifile", QT_TR_NOOP("INI files")); - m_ContentIcons[ModInfo::CONTENT_MODGROUP] = std::make_tuple(":/MO/gui/content/modgroup", QT_TR_NOOP("ModGroup files")); - m_LastCheck.start(); } @@ -188,13 +177,13 @@ QString ModList::getConflictFlagText(ModInfo::EConflictFlag flag, ModInfo::Ptr m } -QVariantList ModList::contentsToIcons(const std::vector &contents) const +QVariantList ModList::contentsToIcons(const std::vector &contents) const { QVariantList result; - std::set contentsSet(contents.begin(), contents.end()); - for (auto iter = m_ContentIcons.begin(); iter != m_ContentIcons.end(); ++iter) { - if (contentsSet.find(iter->first) != contentsSet.end()) { - result.append(std::get<0>(iter->second)); + std::set contentsSet(contents.begin(), contents.end()); + for (auto &content: m_Organizer->modDataContents()) { + if (contentsSet.find(content.id()) != contentsSet.end()) { + result.append(content.icon()); } else { result.append(QString()); } @@ -202,16 +191,16 @@ QVariantList ModList::contentsToIcons(const std::vector &cont return result; } -QString ModList::contentsToToolTip(const std::vector &contents) const +QString ModList::contentsToToolTip(const std::vector &contents) const { QString result(""); - std::set contentsSet(contents.begin(), contents.end()); - for (auto iter = m_ContentIcons.begin(); iter != m_ContentIcons.end(); ++iter) { - if (contentsSet.find(iter->first) != contentsSet.end()) { + std::set contentsSet(contents.begin(), contents.end()); + for (auto& content : m_Organizer->modDataContents()) { + if (contentsSet.find(content.id()) != contentsSet.end()) { result.append(QString("" "") - .arg(std::get<0>(iter->second)).arg(tr(std::get<1>(iter->second).toStdString().c_str()))); + .arg(content.icon()).arg(content.name())); } } result.append("
%2
"); diff --git a/src/modlist.h b/src/modlist.h index 4d456a9a..2abda076 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -20,7 +20,7 @@ along with Mod Organizer. If not, see . #ifndef MODLIST_H #define MODLIST_H - +#include "moddatacontent.h" #include "categories.h" #include "nexusinterface.h" #include "modinfo.h" @@ -42,6 +42,7 @@ along with Mod Organizer. If not, see . class QSortFilterProxyModel; class PluginContainer; +class OrganizerCore; /** * Model presenting an overview of the installed mod @@ -78,7 +79,7 @@ public: * @brief constructor * @todo ensure this view works without a profile set, otherwise there are intransparent dependencies on the initialisation order **/ - ModList(PluginContainer *pluginContainer, QObject *parent = nullptr); + ModList(PluginContainer *pluginContainer, OrganizerCore *parent = nullptr); ~ModList(); @@ -284,9 +285,9 @@ private: static QString getColumnToolTip(int column); - QVariantList contentsToIcons(const std::vector &content) const; + QVariantList contentsToIcons(const std::vector &contentIds) const; - QString contentsToToolTip(const std::vector &contents) const; + QString contentsToToolTip(const std::vector &contentsIds) const; ModList::EColumn getEnabledColumn(int index) const; @@ -328,6 +329,7 @@ private: private: + OrganizerCore *m_Organizer; Profile *m_Profile; NexusInterface *m_NexusInterface; @@ -352,8 +354,6 @@ private: SignalModStateChanged m_ModStateChanged; SignalModMoved m_ModMoved; - std::map > m_ContentIcons; - QElapsedTimer m_LastCheck; PluginContainer *m_PluginContainer; diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 018b9760..99dba913 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -177,22 +177,7 @@ bool ModListSortProxy::lessThan(const QModelIndex &left, } } break; case ModList::COL_CONTENT: { - std::vector lContent = leftMod->getContents(); - std::vector rContent = rightMod->getContents(); - if (lContent.size() != rContent.size()) { - lt = lContent.size() < rContent.size(); - } - - int lValue = 0; - int rValue = 0; - for (ModInfo::EContent content : lContent) { - lValue += 2 << (unsigned int)content; - } - for (ModInfo::EContent content : rContent) { - rValue += 2 << (unsigned int)content; - } - - lt = lValue < rValue; + lt = leftMod->getContents() < rightMod->getContents(); } break; case ModList::COL_NAME: { int comp = QString::compare(leftMod->name(), rightMod->name(), Qt::CaseInsensitive); @@ -449,7 +434,7 @@ bool ModListSortProxy::categoryMatchesMod( bool ModListSortProxy::contentMatchesMod(ModInfo::Ptr info, bool enabled, int content) const { - return info->hasContent(static_cast(content)); + return info->hasContent(content); } bool ModListSortProxy::filterMatchesMod(ModInfo::Ptr info, bool enabled) const diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 6e4b3fbf..45fe5220 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -135,6 +135,16 @@ OrganizerCore::OrganizerCore(Settings &settings) connect(this, SIGNAL(managedGameChanged(MOBase::IPluginGame const *)), &m_PluginList, SLOT(managedGameChanged(MOBase::IPluginGame const *))); + connect(this, &OrganizerCore::managedGameChanged, [this](IPluginGame const* gamePlugin) { + ModDataContent* contentFeature = gamePlugin->feature(); + if (contentFeature) { + m_Contents = contentFeature->getAllContents(); + } + else { + m_Contents = {}; + } + }); + connect(&m_PluginList, &PluginList::writePluginsList, &m_PluginListsWriter, &DelayedFileWriterBase::write); diff --git a/src/organizercore.h b/src/organizercore.h index a4d1a799..af741964 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -19,6 +19,7 @@ #include #include #include "executableinfo.h" +#include "moddatacontent.h" #include #include @@ -122,6 +123,12 @@ public: MOBase::IPluginGame const *managedGame() const; + /** + * @return the list of contents for the currently managed game, or an empty vector + * if the game plugin does not implement the ModDataContent feature. + */ + const std::vector& modDataContents() const { return m_Contents; } + bool isArchivesInit() const { return m_ArchivesInit; } bool saveCurrentLists(); @@ -305,6 +312,7 @@ private: PluginContainer *m_PluginContainer; QString m_GameName; MOBase::IPluginGame *m_GamePlugin; + std::vector m_Contents; Profile *m_CurrentProfile; -- cgit v1.3.1 From 36b81b4a7ca4d9760c4fbe79d67c9aed7e0ab6fe Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Mon, 25 May 2020 20:17:21 +0200 Subject: Use ModDataContent to display the tooltip in the header. --- src/modlist.cpp | 40 +++++++++++++++++++++------------------- src/modlist.h | 2 +- 2 files changed, 22 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/modlist.cpp b/src/modlist.cpp index 3ace0ed0..e71bff14 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -19,6 +19,7 @@ along with Mod Organizer. If not, see . #include "modlist.h" +#include "widgetutility.h" #include "messagedialog.h" #include "qtgroupingproxy.h" #include "viewmarkingscrollbar.h" @@ -670,6 +671,13 @@ QVariant ModList::headerData(int section, Qt::Orientation orientation, return getColumnToolTip(section); } else if (role == Qt::TextAlignmentRole) { return QVariant(Qt::AlignCenter); + } else if (role == MOBase::EnabledColumnRole) { + if (section == COL_CONTENT) { + return !m_Organizer->modDataContents().empty(); + } + else { + return true; + } } } return QAbstractItemModel::headerData(section, orientation, role); @@ -1298,7 +1306,7 @@ QString ModList::getColumnName(int column) } -QString ModList::getColumnToolTip(int column) +QString ModList::getColumnToolTip(int column) const { switch (column) { case COL_NAME: return tr("Name of your mods"); @@ -1310,24 +1318,18 @@ QString ModList::getColumnToolTip(int column) case COL_MODID: return tr("Id of the mod as used on Nexus."); case COL_CONFLICTFLAGS: return tr("Indicators of file conflicts between mods."); case COL_FLAGS: return tr("Emblems to highlight things that might require attention."); - case COL_CONTENT: return tr("Depicts the content of the mod:
" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - - "
Game plugins (esp/esm/esl)
Interface
Meshes
BSA
Textures
Sounds
Music
Strings
Scripts (Papyrus)
Script Extender plugins
SkyProc Patcher
Mod Configuration Menu
INI files
ModGroup files
"); + case COL_CONTENT: { + auto& contents = m_Organizer->modDataContents(); + if (contents.empty()) { + return QString(); + } + QString result = tr("Depicts the content of the mod:") + "
" + ""; + for (auto& content : contents) { + result += QString("") + .arg(content.icon()).arg(content.name()); + } + return result + "
%2
"; + }; case COL_INSTALLTIME: return tr("Time this mod was installed"); case COL_NOTES: return tr("User notes about the mod"); default: return tr("unknown"); diff --git a/src/modlist.h b/src/modlist.h index 2abda076..4e2e86d2 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -283,7 +283,7 @@ private: QString getConflictFlagText(ModInfo::EConflictFlag flag, ModInfo::Ptr modInfo) const; - static QString getColumnToolTip(int column); + QString getColumnToolTip(int column) const; QVariantList contentsToIcons(const std::vector &contentIds) const; -- cgit v1.3.1 From 7c7631d40997b895291827fdc03a1a2e158a9189 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Tue, 26 May 2020 20:20:47 +0200 Subject: Replace usage of MakeVector with initializer lists. --- src/categories.cpp | 116 ++++++++++++++++++++++++++--------------------------- 1 file changed, 58 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/categories.cpp b/src/categories.cpp index aea99532..b1e08a3a 100644 --- a/src/categories.cpp +++ b/src/categories.cpp @@ -113,7 +113,7 @@ void CategoryFactory::reset() // 43 = Savegames (makes no sense to install them through MO) // 45 = Videos and trailers // 87 = Miscelanous - addCategory(0, "None", MakeVector(4, 28, 43, 45, 87), 0); + addCategory(0, "None", { 4, 28, 43, 45, 87 }, 0); } @@ -206,63 +206,63 @@ void CategoryFactory::loadDefaultCategories() { // the order here is relevant as it defines the order in which the // mods appear in the combo box - addCategory(1, "Animations", MakeVector(2, 4, 51), 0); - addCategory(52, "Poses", MakeVector(1, 29), 1); - addCategory(2, "Armour", MakeVector(2, 5, 54), 0); - addCategory(53, "Power Armor", MakeVector(1, 53), 2); - addCategory(3, "Audio", MakeVector(3, 33, 35, 106), 0); - addCategory(38, "Music", MakeVector(2, 34, 61), 0); - addCategory(39, "Voice", MakeVector(2, 36, 107), 0); - addCategory(5, "Clothing", MakeVector(2, 9, 60), 0); - addCategory(41, "Jewelry", MakeVector(1, 102), 5); - addCategory(42, "Backpacks", MakeVector(1, 49), 5); - addCategory(6, "Collectables", MakeVector(2, 10, 92), 0); - addCategory(28, "Companions", MakeVector(3, 11, 66, 96), 0); - addCategory(7, "Creatures, Mounts, & Vehicles", MakeVector(4, 12, 65, 83, 101), 0); - addCategory(8, "Factions", MakeVector(2, 16, 25), 0); - addCategory(9, "Gameplay", MakeVector(2, 15, 24), 0); - addCategory(27, "Combat", MakeVector(1, 77), 9); - addCategory(43, "Crafting", MakeVector(2, 50, 100), 9); - addCategory(48, "Overhauls", MakeVector(2, 24, 79), 9); - addCategory(49, "Perks", MakeVector(1, 27), 9); - addCategory(54, "Radio", MakeVector(1, 31), 9); - addCategory(55, "Shouts", MakeVector(1, 104), 9); - addCategory(22, "Skills & Levelling", MakeVector(2, 46, 73), 9); - addCategory(58, "Weather & Lighting", MakeVector(1, 56), 9); - addCategory(44, "Equipment", MakeVector(1, 44), 43); - addCategory(45, "Home/Settlement", MakeVector(1, 45), 43); - addCategory(10, "Body, Face, & Hair", MakeVector(2, 17, 26), 0); - addCategory(39, "Tattoos", MakeVector(1, 57), 10); - addCategory(40, "Character Presets", MakeVector(1, 58), 0); - addCategory(11, "Items", MakeVector(2, 27, 85), 0); - addCategory(32, "Mercantile", MakeVector(2, 23, 69), 0); - addCategory(37, "Ammo", MakeVector(1, 3), 11); - addCategory(19, "Weapons", MakeVector(2, 41, 55), 11); - addCategory(36, "Weapon & Armour Sets", MakeVector(1, 42), 11); - addCategory(23, "Player Homes", MakeVector(2, 28, 67), 0); - addCategory(25, "Castles & Mansions", MakeVector(1, 68), 23); - addCategory(51, "Settlements", MakeVector(1, 48), 23); - addCategory(12, "Locations", MakeVector(10, 20, 21, 22, 30, 47, 70, 88, 89, 90, 91), 0); - addCategory(4, "Cities", MakeVector(1, 53), 12); - addCategory(31, "Landscape Changes", MakeVector(1, 58), 0); - addCategory(29, "Environment", MakeVector(2, 14, 74), 0); - addCategory(30, "Immersion", MakeVector(2, 51, 78), 0); - addCategory(20, "Magic", MakeVector(3, 75, 93, 94), 0); - addCategory(21, "Models & Textures", MakeVector(2, 19, 29), 0); - addCategory(33, "Modders resources", MakeVector(2, 18, 82), 0); - addCategory(13, "NPCs", MakeVector(3, 22, 33, 99), 0); - addCategory(24, "Bugfixes", MakeVector(2, 6, 95), 0); - addCategory(14, "Patches", MakeVector(2, 25, 84), 24); - addCategory(35, "Utilities", MakeVector(2, 38, 39), 0); - addCategory(26, "Cheats", MakeVector(1, 8), 0); - addCategory(15, "Quests", MakeVector(2, 30, 35), 0); - addCategory(16, "Races & Classes", MakeVector(1, 34), 0); - addCategory(34, "Stealth", MakeVector(1, 76), 0); - addCategory(17, "UI", MakeVector(2, 37, 42), 0); - addCategory(18, "Visuals", MakeVector(2, 40, 62), 0); - addCategory(50, "Pip-Boy", MakeVector(1, 52), 18); - addCategory(46, "Shader Presets", MakeVector(3, 13, 97, 105), 0); - addCategory(47, "Miscellaneous", MakeVector(2, 2, 28), 0); + addCategory(1, "Animations", { 2, 4, 51 }, 0); + addCategory(52, "Poses", { 1, 29 }, 1); + addCategory(2, "Armour", { 2, 5, 54 }, 0); + addCategory(53, "Power Armor", { 1, 53 }, 2); + addCategory(3, "Audio", { 3, 33, 35, 106 }, 0); + addCategory(38, "Music", { 2, 34, 61 }, 0); + addCategory(39, "Voice", { 2, 36, 107 }, 0); + addCategory(5, "Clothing", { 2, 9, 60 }, 0); + addCategory(41, "Jewelry", { 1, 102 }, 5); + addCategory(42, "Backpacks", { 1, 49 }, 5); + addCategory(6, "Collectables", { 2, 10, 92 }, 0); + addCategory(28, "Companions", { 3, 11, 66, 96 }, 0); + addCategory(7, "Creatures, Mounts, & Vehicles", { 4, 12, 65, 83, 101 }, 0); + addCategory(8, "Factions", { 2, 16, 25 }, 0); + addCategory(9, "Gameplay", { 2, 15, 24 }, 0); + addCategory(27, "Combat", { 1, 77 }, 9); + addCategory(43, "Crafting", { 2, 50, 100 }, 9); + addCategory(48, "Overhauls", { 2, 24, 79 }, 9); + addCategory(49, "Perks", { 1, 27 }, 9); + addCategory(54, "Radio", { 1, 31 }, 9); + addCategory(55, "Shouts", { 1, 104 }, 9); + addCategory(22, "Skills & Levelling", { 2, 46, 73 }, 9); + addCategory(58, "Weather & Lighting", { 1, 56 }, 9); + addCategory(44, "Equipment", { 1, 44 }, 43); + addCategory(45, "Home/Settlement", { 1, 45 }, 43); + addCategory(10, "Body, Face, & Hair", { 2, 17, 26 }, 0); + addCategory(39, "Tattoos", { 1, 57 }, 10); + addCategory(40, "Character Presets", { 1, 58 }, 0); + addCategory(11, "Items", { 2, 27, 85 }, 0); + addCategory(32, "Mercantile", { 2, 23, 69 }, 0); + addCategory(37, "Ammo", { 1, 3 }, 11); + addCategory(19, "Weapons", { 2, 41, 55 }, 11); + addCategory(36, "Weapon & Armour Sets", { 1, 42 }, 11); + addCategory(23, "Player Homes", { 2, 28, 67 }, 0); + addCategory(25, "Castles & Mansions", { 1, 68 }, 23); + addCategory(51, "Settlements", { 1, 48 }, 23); + addCategory(12, "Locations", { 10, 20, 21, 22, 30, 47, 70, 88, 89, 90, 91 }, 0); + addCategory(4, "Cities", { 1, 53 }, 12); + addCategory(31, "Landscape Changes", { 1, 58 }, 0); + addCategory(29, "Environment", { 2, 14, 74 }, 0); + addCategory(30, "Immersion", { 2, 51, 78 }, 0); + addCategory(20, "Magic", { 3, 75, 93, 94 }, 0); + addCategory(21, "Models & Textures", { 2, 19, 29 }, 0); + addCategory(33, "Modders resources", { 2, 18, 82 }, 0); + addCategory(13, "NPCs", { 3, 22, 33, 99 }, 0); + addCategory(24, "Bugfixes", { 2, 6, 95 }, 0); + addCategory(14, "Patches", { 2, 25, 84 }, 24); + addCategory(35, "Utilities", { 2, 38, 39 }, 0); + addCategory(26, "Cheats", { 1, 8 }, 0); + addCategory(15, "Quests", { 2, 30, 35 }, 0); + addCategory(16, "Races & Classes", { 1, 34 }, 0); + addCategory(34, "Stealth", { 1, 76 }, 0); + addCategory(17, "UI", { 2, 37, 42 }, 0); + addCategory(18, "Visuals", { 2, 40, 62 }, 0); + addCategory(50, "Pip-Boy", { 1, 52 }, 18); + addCategory(46, "Shader Presets", { 3, 13, 97, 105 }, 0); + addCategory(47, "Miscellaneous", { 2, 2, 28 }, 0); } -- cgit v1.3.1 From c31c79c61df46614aa19ea47c7fedcafd560dce4 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Wed, 27 May 2020 14:56:49 +0200 Subject: Add temporary icon for material content. --- src/resources.qrc | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/resources.qrc b/src/resources.qrc index c54d5bfc..c240ecb2 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -106,6 +106,7 @@ resources/contents/config.png resources/contents/feather-and-scroll.png resources/contents/xedit.png + resources/contents/locked-chest.png qt.conf -- cgit v1.3.1 From 70f1e8bdf63e0471d0ccde41926383536f247dcb Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Wed, 27 May 2020 14:58:32 +0200 Subject: Make ModInfo::getContents() pure virtual. --- src/modinfo.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/modinfo.h b/src/modinfo.h index c5b1cfca..5f2d7ba7 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -521,10 +521,7 @@ public: /** * @return a list of content types contained in a mod */ - virtual const std::vector& getContents() const { - static std::vector dummy; - return dummy; - } + virtual const std::vector& getContents() const = 0; /** * @brief test if the specified flag is set for this mod -- cgit v1.3.1 From 9c3ddb53c9042ead731fcbfcf9daf9fec60dbbf7 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Wed, 27 May 2020 21:29:17 +0200 Subject: Fix sorting for the Content column. --- src/modlistsortproxy.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 99dba913..87db4fed 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -177,7 +177,15 @@ bool ModListSortProxy::lessThan(const QModelIndex &left, } } break; case ModList::COL_CONTENT: { - lt = leftMod->getContents() < rightMod->getContents(); + unsigned int lValue = 0; + unsigned int rValue = 0; + for (int content : leftMod->getContents()) { + lValue += 2U << static_cast(content); + } + for (int content : rightMod->getContents()) { + rValue += 2U << static_cast(content); + } + lt = lValue < rValue; } break; case ModList::COL_NAME: { int comp = QString::compare(leftMod->name(), rightMod->name(), Qt::CaseInsensitive); -- cgit v1.3.1 From 6f22a77cdac588abcb60ac4c45d795b74872c626 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Wed, 27 May 2020 22:01:36 +0200 Subject: Do not show Content with isOnlyForFilter() in the column. --- src/modlist.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/modlist.cpp b/src/modlist.cpp index e71bff14..7fa63b54 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -183,10 +183,13 @@ QVariantList ModList::contentsToIcons(const std::vector &contents) const QVariantList result; std::set contentsSet(contents.begin(), contents.end()); for (auto &content: m_Organizer->modDataContents()) { - if (contentsSet.find(content.id()) != contentsSet.end()) { - result.append(content.icon()); - } else { - result.append(QString()); + if (!content.isOnlyForFilter()) { + if (contentsSet.find(content.id()) != contentsSet.end()) { + result.append(content.icon()); + } + else { + result.append(QString()); + } } } return result; @@ -198,7 +201,7 @@ QString ModList::contentsToToolTip(const std::vector &contents) const std::set contentsSet(contents.begin(), contents.end()); for (auto& content : m_Organizer->modDataContents()) { - if (contentsSet.find(content.id()) != contentsSet.end()) { + if (!content.isOnlyForFilter() && contentsSet.find(content.id()) != contentsSet.end()) { result.append(QString("" "%2") .arg(content.icon()).arg(content.name())); @@ -1325,8 +1328,10 @@ QString ModList::getColumnToolTip(int column) const } QString result = tr("Depicts the content of the mod:") + "
" + ""; for (auto& content : contents) { - result += QString("") - .arg(content.icon()).arg(content.name()); + if (!content.isOnlyForFilter()) { + result += QString("") + .arg(content.icon()).arg(content.name()); + } } return result + "
%2
%2
"; }; -- cgit v1.3.1 From 700c5fb16c1c4e39fd757998e95ead4a25ecc6da Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Wed, 27 May 2020 22:45:42 +0200 Subject: Store contents as a set instead of a vector. --- src/modinfo.h | 2 +- src/modinforegular.cpp | 5 +++-- src/modinforegular.h | 2 +- src/modinfowithconflictinfo.cpp | 2 +- src/modinfowithconflictinfo.h | 7 ++++--- src/modlist.cpp | 11 ++++------- src/modlist.h | 6 +++--- 7 files changed, 17 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/modinfo.h b/src/modinfo.h index 5f2d7ba7..a6c8ea65 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -521,7 +521,7 @@ public: /** * @return a list of content types contained in a mod */ - virtual const std::vector& getContents() const = 0; + virtual const std::set& getContents() const = 0; /** * @brief test if the specified flag is set for this mod diff --git a/src/modinforegular.cpp b/src/modinforegular.cpp index 8ad7ffe5..8ef8e007 100644 --- a/src/modinforegular.cpp +++ b/src/modinforegular.cpp @@ -653,12 +653,13 @@ std::vector ModInfoRegular::getFlags() const } -std::vector ModInfoRegular::doGetContents() const +std::set ModInfoRegular::doGetContents() const { ModDataContent* contentFeature = m_GamePlugin->feature(); if (contentFeature) { - return contentFeature->getContentsFor(contentFileTree()); + auto result = contentFeature->getContentsFor(contentFileTree()); + return std::set(std::begin(result), std::end(result)); } return {}; diff --git a/src/modinforegular.h b/src/modinforegular.h index b09dcd98..7e70631e 100644 --- a/src/modinforegular.h +++ b/src/modinforegular.h @@ -416,7 +416,7 @@ private slots: protected: - virtual std::vector doGetContents() const override; + virtual std::set doGetContents() const override; ModInfoRegular(PluginContainer *pluginContainer, const MOBase::IPluginGame *game, const QDir &path, MOShared::DirectoryEntry **directoryStructure); diff --git a/src/modinfowithconflictinfo.cpp b/src/modinfowithconflictinfo.cpp index 14b341d2..227ee12e 100644 --- a/src/modinfowithconflictinfo.cpp +++ b/src/modinfowithconflictinfo.cpp @@ -331,7 +331,7 @@ bool ModInfoWithConflictInfo::isValid() const { return m_Valid.value(); } -const std::vector& ModInfoWithConflictInfo::getContents() const { +const std::set& ModInfoWithConflictInfo::getContents() const { return m_Contents.value(); } diff --git a/src/modinfowithconflictinfo.h b/src/modinfowithconflictinfo.h index b66a7444..7109b83d 100644 --- a/src/modinfowithconflictinfo.h +++ b/src/modinfowithconflictinfo.h @@ -6,6 +6,7 @@ #include "thread_utils.h" #include "modinfo.h" +#include #include class ModInfoWithConflictInfo : public ModInfo @@ -24,7 +25,7 @@ public: /** * @return a list of content types contained in a mod */ - virtual const std::vector& getContents() const override; + virtual const std::set& getContents() const override; /** * @brief Test if the mod contains the specified content. @@ -75,7 +76,7 @@ protected: * * @return the contents for this mod. **/ - virtual std::vector doGetContents() const { return {}; } + virtual std::set doGetContents() const { return {}; } /** * @brief Retrieve a file tree corresponding to the underlying disk content @@ -146,7 +147,7 @@ private: MOShared::MemoizedLocked> m_FileTree; MOShared::MemoizedLocked m_Valid; - MOShared::MemoizedLocked> m_Contents; + MOShared::MemoizedLocked> m_Contents; MOShared::DirectoryEntry **m_DirectoryStructure; diff --git a/src/modlist.cpp b/src/modlist.cpp index 7fa63b54..614588db 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -178,13 +178,12 @@ QString ModList::getConflictFlagText(ModInfo::EConflictFlag flag, ModInfo::Ptr m } -QVariantList ModList::contentsToIcons(const std::vector &contents) const +QVariantList ModList::contentsToIcons(const std::set &contents) const { QVariantList result; - std::set contentsSet(contents.begin(), contents.end()); for (auto &content: m_Organizer->modDataContents()) { if (!content.isOnlyForFilter()) { - if (contentsSet.find(content.id()) != contentsSet.end()) { + if (contents.find(content.id()) != contents.end()) { result.append(content.icon()); } else { @@ -195,13 +194,11 @@ QVariantList ModList::contentsToIcons(const std::vector &contents) const return result; } -QString ModList::contentsToToolTip(const std::vector &contents) const +QString ModList::contentsToToolTip(const std::set &contents) const { QString result(""); - - std::set contentsSet(contents.begin(), contents.end()); for (auto& content : m_Organizer->modDataContents()) { - if (!content.isOnlyForFilter() && contentsSet.find(content.id()) != contentsSet.end()) { + if (!content.isOnlyForFilter() && contents.find(content.id()) != contents.end()) { result.append(QString("" "") .arg(content.icon()).arg(content.name())); diff --git a/src/modlist.h b/src/modlist.h index 4e2e86d2..8c29300d 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -79,7 +79,7 @@ public: * @brief constructor * @todo ensure this view works without a profile set, otherwise there are intransparent dependencies on the initialisation order **/ - ModList(PluginContainer *pluginContainer, OrganizerCore *parent = nullptr); + ModList(PluginContainer *pluginContainer, OrganizerCore *parent); ~ModList(); @@ -285,9 +285,9 @@ private: QString getColumnToolTip(int column) const; - QVariantList contentsToIcons(const std::vector &contentIds) const; + QVariantList contentsToIcons(const std::set &contentIds) const; - QString contentsToToolTip(const std::vector &contentsIds) const; + QString contentsToToolTip(const std::set &contentsIds) const; ModList::EColumn getEnabledColumn(int index) const; -- cgit v1.3.1 From 4791569790e9695512248a9acdfbcd1c96f13967 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Wed, 27 May 2020 22:46:03 +0200 Subject: Ignore filter-only content when sorting. --- src/modlistsortproxy.cpp | 23 ++++++++++++++++------- src/modlistsortproxy.h | 5 ++++- 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 87db4fed..321722f5 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -22,6 +22,8 @@ along with Mod Organizer. If not, see . #include "profile.h" #include "messagedialog.h" #include "qtgroupingproxy.h" +#include "organizercore.h" + #include #include #include @@ -33,8 +35,9 @@ along with Mod Organizer. If not, see . using namespace MOBase; -ModListSortProxy::ModListSortProxy(Profile* profile, QObject *parent) - : QSortFilterProxyModel(parent) +ModListSortProxy::ModListSortProxy(Profile* profile, OrganizerCore * organizer) + : QSortFilterProxyModel(organizer) + , m_Organizer(organizer) , m_Profile(profile) , m_FilterActive(false) , m_FilterMode(FilterAnd) @@ -177,13 +180,19 @@ bool ModListSortProxy::lessThan(const QModelIndex &left, } } break; case ModList::COL_CONTENT: { + auto& lContents = leftMod->getContents(); + auto& rContents = rightMod->getContents(); unsigned int lValue = 0; unsigned int rValue = 0; - for (int content : leftMod->getContents()) { - lValue += 2U << static_cast(content); - } - for (int content : rightMod->getContents()) { - rValue += 2U << static_cast(content); + for (auto& content : m_Organizer->modDataContents()) { + if (!content.isOnlyForFilter()) { + if (std::find(std::begin(lContents), std::end(lContents), content.id()) != std::end(lContents)) { + lValue += 2U << static_cast(content.id()); + } + if (std::find(std::begin(rContents), std::end(rContents), content.id()) != std::end(rContents)) { + rValue += 2U << static_cast(content.id()); + } + } } lt = lValue < rValue; } break; diff --git a/src/modlistsortproxy.h b/src/modlistsortproxy.h index 3a29b7f7..bf5c077a 100644 --- a/src/modlistsortproxy.h +++ b/src/modlistsortproxy.h @@ -25,6 +25,7 @@ along with Mod Organizer. If not, see . #include "modlist.h" class Profile; +class OrganizerCore; class ModListSortProxy : public QSortFilterProxyModel { @@ -72,7 +73,7 @@ public: public: - explicit ModListSortProxy(Profile *profile, QObject *parent = 0); + explicit ModListSortProxy(Profile *profile, OrganizerCore * organizer); void setProfile(Profile *profile); @@ -154,6 +155,8 @@ private slots: void postDataChanged(); private: + OrganizerCore* m_Organizer; + Profile* m_Profile; std::vector m_Criteria; QString m_Filter; -- cgit v1.3.1 From d2b7a1a321d5cf496860f717eccdfb9487621169 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Thu, 28 May 2020 19:48:21 +0200 Subject: Expose ModDataContentHolder from OrganizerCore instead of vector of Content. --- src/filterlist.cpp | 4 +- src/mainwindow.cpp | 5 +-- src/modlist.cpp | 38 ++++++----------- src/modlistsortproxy.cpp | 16 +++---- src/organizercore.cpp | 4 +- src/organizercore.h | 108 ++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 132 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/filterlist.cpp b/src/filterlist.cpp index 142751f0..2b72c152 100644 --- a/src/filterlist.cpp +++ b/src/filterlist.cpp @@ -234,11 +234,11 @@ QTreeWidgetItem* FilterList::addCriteriaItem( void FilterList::addContentCriteria() { - for (auto &content: m_Organizer->modDataContents()) { + m_Organizer->modDataContents().forEachContent([this](auto const& content) { addCriteriaItem( nullptr, QString("<%1>").arg(tr("Contains %1").arg(content.name())), content.id(), ModListSortProxy::TypeContent); - } + }, true); } void FilterList::addCategoryCriteria(QTreeWidgetItem *root, const std::set &categoriesUsed, int targetID) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a720b621..35e31e61 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -5950,9 +5950,8 @@ void MainWindow::onFiltersCriteria(const std::vector const auto& c = criteria[0]; if (c.type == ModListSortProxy::TypeContent) { - auto& contents = m_OrganizerCore.modDataContents(); - auto it = std::find_if(std::begin(contents), std::end(contents), [&c](auto const& content) { return content.id() == c.id; }); - label = it != std::end(contents) ? it->name() : QString(); + const auto *content = m_OrganizerCore.modDataContents().findById(c.id); + label = content ? content->name() : QString(); } else { label = m_CategoryFactory.getCategoryNameByID(c.id); } diff --git a/src/modlist.cpp b/src/modlist.cpp index 614588db..06e5e9bf 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -181,29 +181,21 @@ QString ModList::getConflictFlagText(ModInfo::EConflictFlag flag, ModInfo::Ptr m QVariantList ModList::contentsToIcons(const std::set &contents) const { QVariantList result; - for (auto &content: m_Organizer->modDataContents()) { - if (!content.isOnlyForFilter()) { - if (contents.find(content.id()) != contents.end()) { - result.append(content.icon()); - } - else { - result.append(QString()); - } - } - } + m_Organizer->modDataContents().forEachContentInOrOut( + contents, + [&result](auto const& content) { result.append(content.icon()); }, + [&result](auto const&) { result.append(QString()); }); return result; } QString ModList::contentsToToolTip(const std::set &contents) const { QString result("
%2
"); - for (auto& content : m_Organizer->modDataContents()) { - if (!content.isOnlyForFilter() && contents.find(content.id()) != contents.end()) { - result.append(QString("" - "") - .arg(content.icon()).arg(content.name())); - } - } + m_Organizer->modDataContents().forEachContentIn(contents, [&result](auto const& content) { + result.append(QString("" + "") + .arg(content.icon()).arg(content.name())); + }); result.append("
%2
%2
"); return result; } @@ -1320,16 +1312,14 @@ QString ModList::getColumnToolTip(int column) const case COL_FLAGS: return tr("Emblems to highlight things that might require attention."); case COL_CONTENT: { auto& contents = m_Organizer->modDataContents(); - if (contents.empty()) { + if (m_Organizer->modDataContents().empty()) { return QString(); } QString result = tr("Depicts the content of the mod:") + "
" + ""; - for (auto& content : contents) { - if (!content.isOnlyForFilter()) { - result += QString("") - .arg(content.icon()).arg(content.name()); - } - } + m_Organizer->modDataContents().forEachContent([&result](auto const& content) { + result += QString("") + .arg(content.icon()).arg(content.name()); + }); return result + "
%2
%2
"; }; case COL_INSTALLTIME: return tr("Time this mod was installed"); diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 321722f5..b56dff78 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -184,16 +184,12 @@ bool ModListSortProxy::lessThan(const QModelIndex &left, auto& rContents = rightMod->getContents(); unsigned int lValue = 0; unsigned int rValue = 0; - for (auto& content : m_Organizer->modDataContents()) { - if (!content.isOnlyForFilter()) { - if (std::find(std::begin(lContents), std::end(lContents), content.id()) != std::end(lContents)) { - lValue += 2U << static_cast(content.id()); - } - if (std::find(std::begin(rContents), std::end(rContents), content.id()) != std::end(rContents)) { - rValue += 2U << static_cast(content.id()); - } - } - } + m_Organizer->modDataContents().forEachContentIn(lContents, [&lValue](auto const& content) { + lValue += 2U << static_cast(content.id()); + }); + m_Organizer->modDataContents().forEachContentIn(rContents, [&rValue](auto const& content) { + rValue += 2U << static_cast(content.id()); + }); lt = lValue < rValue; } break; case ModList::COL_NAME: { diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 45fe5220..14f85ac0 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -138,10 +138,10 @@ OrganizerCore::OrganizerCore(Settings &settings) connect(this, &OrganizerCore::managedGameChanged, [this](IPluginGame const* gamePlugin) { ModDataContent* contentFeature = gamePlugin->feature(); if (contentFeature) { - m_Contents = contentFeature->getAllContents(); + m_Contents = ModDataContentHolder(contentFeature->getAllContents()); } else { - m_Contents = {}; + m_Contents = ModDataContentHolder(); } }); diff --git a/src/organizercore.h b/src/organizercore.h index af741964..c08a1495 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -83,6 +83,110 @@ private: typedef boost::signals2::signal SignalModInstalled; public: + + /** + * Small holder for the game content returned by the ModDataContent feature (the + * list of all possible contents, not the per-mod content). + */ + struct ModDataContentHolder { + + using Content = ModDataContent::Content; + + /** + * @return true if the hold list of contents is empty, false otherwise. + */ + bool empty() const { return m_Contents.empty(); } + + /** + * @param id ID of the content to retrieve. + * + * @return the content with the given ID, or a null pointer if it is not found. + */ + const Content* findById(int id) const { + auto it = std::find_if(std::begin(m_Contents), std::end(m_Contents), [&id](auto const& content) { return content.id() == id; }); + return it == std::end(m_Contents) ? nullptr : &(*it); + } + + /** + * Apply the given function to each content whose ID is in the given set. + * + * @param ids The set of content IDs. + * @param fn The function to apply. + * @param includeFilter true to also apply the function to filter-only contents, false otherwise. + */ + template + void forEachContentIn(std::set const& ids, Fn const& fn, bool includeFilter = false) const { + for (const auto& content : m_Contents) { + if ((includeFilter || !content.isOnlyForFilter()) + && ids.find(content.id()) != ids.end()) { + fn(content); + } + } + } + + /** + * Apply fnIn to each content whose ID is in the given set, and fnOut to each content not in the + * given set, excluding filter-only content (from both cases) unless includeFilter is true.. + * + * @param ids The set of content IDs. + * @param fnIn Function to apply to content whose IDs are in ids. + * @param fnOut Function to apply to content whose IDs are not in ids. + * @param includeFilter true to also apply the function to filter-only contents, false otherwise. + */ + template + void forEachContentInOrOut(std::set const& ids, FnIn const& fnIn, FnOut const& fnOut, bool includeFilter = false) const { + for (const auto& content : m_Contents) { + if ((includeFilter || !content.isOnlyForFilter())) { + if (ids.find(content.id()) != ids.end()) { + fnIn(content); + } + else { + fnOut(content); + } + } + } + } + + /** + * Apply the given function to each content. + * + * @param fn The function to apply. + * @param includeFilter true to also apply the function to filter-only contents, false otherwise. + */ + template + void forEachContent(Fn const& fn, bool includeFilter = false) const { + for (const auto& content : m_Contents) { + if (includeFilter || !content.isOnlyForFilter()) { + fn(content); + } + } + } + + + ModDataContentHolder& operator=(ModDataContentHolder const&) = delete; + ModDataContentHolder& operator=(ModDataContentHolder&&) = default; + + private: + + std::vector m_Contents; + + /** + * @brief Construct a ModDataContentHolder without any contents (e.g., if the feature is + * missing). + */ + ModDataContentHolder() { } + + /** + * @brief Construct a ModDataContentHold holding the given list of contents. + */ + ModDataContentHolder(std::vector contents) : + m_Contents(std::move(contents)) { } + + friend class OrganizerCore; + }; + +public: + static bool isNxmLink(const QString &link) { return link.startsWith("nxm://", Qt::CaseInsensitive); } OrganizerCore(Settings &settings); @@ -127,7 +231,7 @@ public: * @return the list of contents for the currently managed game, or an empty vector * if the game plugin does not implement the ModDataContent feature. */ - const std::vector& modDataContents() const { return m_Contents; } + const ModDataContentHolder& modDataContents() const { return m_Contents; } bool isArchivesInit() const { return m_ArchivesInit; } @@ -312,7 +416,7 @@ private: PluginContainer *m_PluginContainer; QString m_GameName; MOBase::IPluginGame *m_GamePlugin; - std::vector m_Contents; + ModDataContentHolder m_Contents; Profile *m_CurrentProfile; -- cgit v1.3.1 From 7f42698f4c733269a1b2b74d993186b362a9208a Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Thu, 28 May 2020 19:50:39 +0200 Subject: Change auto& to const auto&. --- src/modlistsortproxy.cpp | 4 ++-- src/organizercore.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index b56dff78..ab6dd852 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -180,8 +180,8 @@ bool ModListSortProxy::lessThan(const QModelIndex &left, } } break; case ModList::COL_CONTENT: { - auto& lContents = leftMod->getContents(); - auto& rContents = rightMod->getContents(); + const auto& lContents = leftMod->getContents(); + const auto& rContents = rightMod->getContents(); unsigned int lValue = 0; unsigned int rValue = 0; m_Organizer->modDataContents().forEachContentIn(lContents, [&lValue](auto const& content) { diff --git a/src/organizercore.h b/src/organizercore.h index c08a1495..00765694 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -125,8 +125,8 @@ public: } /** - * Apply fnIn to each content whose ID is in the given set, and fnOut to each content not in the - * given set, excluding filter-only content (from both cases) unless includeFilter is true.. + * @brief Apply fnIn to each content whose ID is in the given set, and fnOut to each content not in the + * given set, excluding filter-only content (from both cases) unless includeFilter is true. * * @param ids The set of content IDs. * @param fnIn Function to apply to content whose IDs are in ids. -- cgit v1.3.1 From 78143598db7db03c865498229420596f2cc6d1b1 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Thu, 28 May 2020 19:51:20 +0200 Subject: Remove space. --- src/modlistsortproxy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/modlistsortproxy.h b/src/modlistsortproxy.h index bf5c077a..90b6251e 100644 --- a/src/modlistsortproxy.h +++ b/src/modlistsortproxy.h @@ -73,7 +73,7 @@ public: public: - explicit ModListSortProxy(Profile *profile, OrganizerCore * organizer); + explicit ModListSortProxy(Profile *profile, OrganizerCore *organizer); void setProfile(Profile *profile); -- cgit v1.3.1 From 0a5790b333883c7c4ef07bb44f0a411ce8ba79b5 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Thu, 28 May 2020 21:58:59 +0200 Subject: Add icon for FO4 material (courtesy of @twizz0r). --- src/resources.qrc | 2 +- src/resources/contents/f4-nuclear.png | Bin 0 -> 1733 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/resources/contents/f4-nuclear.png (limited to 'src') diff --git a/src/resources.qrc b/src/resources.qrc index c240ecb2..8e4d9156 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -106,7 +106,7 @@ resources/contents/config.png resources/contents/feather-and-scroll.png resources/contents/xedit.png - resources/contents/locked-chest.png + resources/contents/f4-nuclear.png
qt.conf diff --git a/src/resources/contents/f4-nuclear.png b/src/resources/contents/f4-nuclear.png new file mode 100644 index 00000000..c9d3c2e5 Binary files /dev/null and b/src/resources/contents/f4-nuclear.png differ -- cgit v1.3.1