summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/filterlist.cpp4
-rw-r--r--src/mainwindow.cpp5
-rw-r--r--src/modlist.cpp38
-rw-r--r--src/modlistsortproxy.cpp16
-rw-r--r--src/organizercore.cpp4
-rw-r--r--src/organizercore.h108
6 files changed, 132 insertions, 43 deletions
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<int> &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<ModListSortProxy::Criteria>
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<int> &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<int> &contents) const
{
QString result("<table cellspacing=7>");
- for (auto& content : m_Organizer->modDataContents()) {
- if (!content.isOnlyForFilter() && contents.find(content.id()) != contents.end()) {
- result.append(QString("<tr><td><img src=\"%1\" width=32/></td>"
- "<td valign=\"middle\">%2</td></tr>")
- .arg(content.icon()).arg(content.name()));
- }
- }
+ m_Organizer->modDataContents().forEachContentIn(contents, [&result](auto const& content) {
+ result.append(QString("<tr><td><img src=\"%1\" width=32/></td>"
+ "<td valign=\"middle\">%2</td></tr>")
+ .arg(content.icon()).arg(content.name()));
+ });
result.append("</table>");
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:") + "<br>" + "<table cellspacing=7>";
- for (auto& content : contents) {
- if (!content.isOnlyForFilter()) {
- result += QString("<tr><td><img src=\"%1\" width=32/></td><td>%2</td></tr>")
- .arg(content.icon()).arg(content.name());
- }
- }
+ m_Organizer->modDataContents().forEachContent([&result](auto const& content) {
+ result += QString("<tr><td><img src=\"%1\" width=32/></td><td>%2</td></tr>")
+ .arg(content.icon()).arg(content.name());
+ });
return result + "</table>";
};
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<unsigned int>(content.id());
- }
- if (std::find(std::begin(rContents), std::end(rContents), content.id()) != std::end(rContents)) {
- rValue += 2U << static_cast<unsigned int>(content.id());
- }
- }
- }
+ m_Organizer->modDataContents().forEachContentIn(lContents, [&lValue](auto const& content) {
+ lValue += 2U << static_cast<unsigned int>(content.id());
+ });
+ m_Organizer->modDataContents().forEachContentIn(rContents, [&rValue](auto const& content) {
+ rValue += 2U << static_cast<unsigned int>(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<ModDataContent>();
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<void (const QString&)> 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 <class Fn>
+ void forEachContentIn(std::set<int> 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 <class FnIn, class FnOut>
+ void forEachContentInOrOut(std::set<int> 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 <class Fn>
+ 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<Content> 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<ModDataContent::Content> 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<ModDataContent::Content>& 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<ModDataContent::Content> m_Contents;
+ ModDataContentHolder m_Contents;
Profile *m_CurrentProfile;