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/modlist.cpp | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) (limited to 'src/modlist.cpp') 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
"); -- 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/modlist.cpp') 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 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/modlist.cpp') 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/modlist.cpp') 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 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/modlist.cpp') 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