From 58cc25f3227dd82011c809b50bbedbeec039ccc4 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 5 Sep 2023 13:25:01 -0500 Subject: Implement 'override' plugin support --- src/pluginlist.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'src/pluginlist.cpp') diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 6e54b46d..311f05ec 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -179,6 +179,8 @@ void PluginList::refresh(const QString& profileName, GamePlugins* gamePlugins = m_GamePlugin->feature(); const bool lightPluginsAreSupported = gamePlugins ? gamePlugins->lightPluginsAreSupported() : false; + const bool overridePluginsAreSupported = + gamePlugins ? gamePlugins->overridePluginsAreSupported() : false; m_CurrentProfile = profileName; @@ -233,7 +235,7 @@ void PluginList::refresh(const QString& profileName, m_ESPs.push_back(ESPInfo(filename, forceEnabled, originName, ToQString(current->getFullPath()), hasIni, - loadedArchives, lightPluginsAreSupported)); + loadedArchives, lightPluginsAreSupported, overridePluginsAreSupported)); m_ESPs.rbegin()->priority = -1; } catch (const std::exception& e) { reportError( @@ -990,6 +992,16 @@ bool PluginList::isLightFlagged(const QString& name) const } } +bool PluginList::isOverrideFlagged(const QString& name) const +{ + auto iter = m_ESPsByName.find(name); + if (iter == m_ESPsByName.end()) { + return false; + } else { + return m_ESPs[iter->second].isOverrideFlagged; + } +} + boost::signals2::connection PluginList::onPluginStateChanged( const std::function&)>& func) { @@ -1049,6 +1061,8 @@ void PluginList::generatePluginIndexes() GamePlugins* gamePlugins = m_GamePlugin->feature(); const bool lightPluginsSupported = gamePlugins ? gamePlugins->lightPluginsAreSupported() : false; + const bool overridePluginsSupported = + gamePlugins ? gamePlugins->overridePluginsAreSupported() : false; for (int l = 0; l < m_ESPs.size(); ++l) { int i = m_ESPsByPriority.at(l); @@ -1065,6 +1079,8 @@ void PluginList::generatePluginIndexes() .arg((numESLs) % 4096, 3, 16, QChar('0')) .toUpper(); ++numESLs; + } else if (overridePluginsSupported && m_ESPs[i].isOverrideFlagged) { + m_ESPs[i].index = QString(""); } else { m_ESPs[i].index = QString("%1").arg(l - numESLs - numSkipped, 2, 16, QChar('0')).toUpper(); @@ -1705,7 +1721,7 @@ QModelIndex PluginList::parent(const QModelIndex&) const PluginList::ESPInfo::ESPInfo(const QString& name, bool enabled, const QString& originName, const QString& fullPath, bool hasIni, std::set archives, - bool lightPluginsAreSupported) + bool lightSupported, bool overrideSupported) : name(name), fullPath(fullPath), enabled(enabled), forceEnabled(enabled), priority(0), loadOrder(-1), originName(originName), hasIni(hasIni), archives(archives.begin(), archives.end()), modSelected(false) @@ -1714,9 +1730,10 @@ PluginList::ESPInfo::ESPInfo(const QString& name, bool enabled, ESP::File file(ToWString(fullPath)); auto extension = name.right(3).toLower(); hasMasterExtension = (extension == "esm"); - hasLightExtension = lightPluginsAreSupported && (extension == "esl"); + hasLightExtension = lightSupported && (extension == "esl"); isMasterFlagged = file.isMaster(); - isLightFlagged = lightPluginsAreSupported && file.isLight(); + isOverrideFlagged = overrideSupported && file.isOverride(); + isLightFlagged = lightSupported && !isOverrideFlagged && file.isLight(overrideSupported); author = QString::fromLatin1(file.author().c_str()); description = QString::fromLatin1(file.description().c_str()); @@ -1729,6 +1746,7 @@ PluginList::ESPInfo::ESPInfo(const QString& name, bool enabled, hasMasterExtension = false; hasLightExtension = false; isMasterFlagged = false; + isOverrideFlagged = false; isLightFlagged = false; } } -- cgit v1.3.1 From 94455c2dabea121274d6190f1f0845731f0e3800 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 9 Sep 2023 04:37:03 -0500 Subject: Add 'None' LoadOrderMechanism which disables managed plugins - Primary plugins are still marked as loaded --- src/pluginlist.cpp | 30 +++++++++++++++++++++--------- src/pluginlist.h | 7 ++++--- 2 files changed, 25 insertions(+), 12 deletions(-) (limited to 'src/pluginlist.cpp') diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 311f05ec..d3987e4d 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -205,6 +205,9 @@ void PluginList::refresh(const QString& profileName, bool forceEnabled = Settings::instance().game().forceEnableCoreFiles() && primaryPlugins.contains(filename, Qt::CaseInsensitive); + bool forceDisabled = + m_GamePlugin->loadOrderMechanism() == IPluginGame::LoadOrderMechanism::None && + !forceEnabled; bool archive = false; try { @@ -233,9 +236,10 @@ void PluginList::refresh(const QString& profileName, originName = modInfo->name(); } - m_ESPs.push_back(ESPInfo(filename, forceEnabled, originName, + m_ESPs.push_back(ESPInfo(filename, forceEnabled, forceDisabled, originName, ToQString(current->getFullPath()), hasIni, - loadedArchives, lightPluginsAreSupported, overridePluginsAreSupported)); + loadedArchives, lightPluginsAreSupported, + overridePluginsAreSupported)); m_ESPs.rbegin()->priority = -1; } catch (const std::exception& e) { reportError( @@ -390,7 +394,8 @@ void PluginList::enableESP(const QString& name, bool enable) if (iter != m_ESPsByName.end()) { auto enabled = m_ESPs[iter->second].enabled; - m_ESPs[iter->second].enabled = enable || m_ESPs[iter->second].forceEnabled; + m_ESPs[iter->second].enabled = (enable && !m_ESPs[iter->second].forceDisabled) || + m_ESPs[iter->second].forceEnabled; emit writePluginsList(); if (enabled != m_ESPs[iter->second].enabled) { @@ -856,7 +861,8 @@ void PluginList::setState(const QString& name, PluginStates state) auto iter = m_ESPsByName.find(name); if (iter != m_ESPsByName.end()) { m_ESPs[iter->second].enabled = - (state == IPluginList::STATE_ACTIVE) || m_ESPs[iter->second].forceEnabled; + (state == IPluginList::STATE_ACTIVE && !m_ESPs[iter->second].forceDisabled) || + m_ESPs[iter->second].forceEnabled; } else { log::warn("Plugin not found: {}", name); } @@ -1171,7 +1177,7 @@ QVariant PluginList::checkstateData(const QModelIndex& modelIndex) const { const int index = modelIndex.row(); - if (m_ESPs[index].forceEnabled) { + if (m_ESPs[index].forceEnabled || m_ESPs[index].forceDisabled) { return {}; } @@ -1295,6 +1301,11 @@ QVariant PluginList::tooltipData(const QModelIndex& modelIndex) const tr("This ESP is flagged as an ESL. It will adhere to the ESP load " "order but the records will be loaded in ESL space."); } + + if (esp.forceDisabled) { + toolTip += "

" + tr("This game does not currently permit custom plugin " + "loading. There may be manual workarounds."); + } } // additional info @@ -1718,13 +1729,13 @@ QModelIndex PluginList::parent(const QModelIndex&) const return QModelIndex(); } -PluginList::ESPInfo::ESPInfo(const QString& name, bool enabled, +PluginList::ESPInfo::ESPInfo(const QString& name, bool enabled, bool forceDisabled, const QString& originName, const QString& fullPath, bool hasIni, std::set archives, bool lightSupported, bool overrideSupported) : name(name), fullPath(fullPath), enabled(enabled), forceEnabled(enabled), - priority(0), loadOrder(-1), originName(originName), hasIni(hasIni), - archives(archives.begin(), archives.end()), modSelected(false) + forceDisabled(forceDisabled), priority(0), loadOrder(-1), originName(originName), + hasIni(hasIni), archives(archives.begin(), archives.end()), modSelected(false) { try { ESP::File file(ToWString(fullPath)); @@ -1733,7 +1744,8 @@ PluginList::ESPInfo::ESPInfo(const QString& name, bool enabled, hasLightExtension = lightSupported && (extension == "esl"); isMasterFlagged = file.isMaster(); isOverrideFlagged = overrideSupported && file.isOverride(); - isLightFlagged = lightSupported && !isOverrideFlagged && file.isLight(overrideSupported); + isLightFlagged = + lightSupported && !isOverrideFlagged && file.isLight(overrideSupported); author = QString::fromLatin1(file.author().c_str()); description = QString::fromLatin1(file.description().c_str()); diff --git a/src/pluginlist.h b/src/pluginlist.h index 56f9e1a9..0c53fc25 100644 --- a/src/pluginlist.h +++ b/src/pluginlist.h @@ -313,14 +313,15 @@ signals: private: struct ESPInfo { - ESPInfo(const QString& name, bool enabled, const QString& originName, - const QString& fullPath, bool hasIni, std::set archives, - bool lightSupported, bool overrideSupported); + ESPInfo(const QString& name, bool enabled, bool forceDisabled, + const QString& originName, const QString& fullPath, bool hasIni, + std::set archives, bool lightSupported, bool overrideSupported); QString name; QString fullPath; bool enabled; bool forceEnabled; + bool forceDisabled; int priority; QString index; int loadOrder; -- cgit v1.3.1 From 3dc00922ed528659b577116014289ad1c4bd9c8d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 12 Sep 2023 15:08:21 -0500 Subject: Changes for None-type plugin sorting * Display checkboxes for all plugins * Disable checkboxes for force enabled/disabled plugins * Display tooltip data for all plugins regardless of force status --- src/pluginlist.cpp | 113 +++++++++++++++++++++++++++++------------------------ 1 file changed, 61 insertions(+), 52 deletions(-) (limited to 'src/pluginlist.cpp') diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index d3987e4d..a6361791 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -1178,7 +1178,9 @@ QVariant PluginList::checkstateData(const QModelIndex& modelIndex) const const int index = modelIndex.row(); if (m_ESPs[index].forceEnabled || m_ESPs[index].forceDisabled) { - return {}; + return Qt::Checked; + } else if (m_ESPs[index].forceDisabled) { + return Qt::Unchecked; } return m_ESPs[index].enabled ? Qt::Checked : Qt::Unchecked; @@ -1246,61 +1248,68 @@ QVariant PluginList::tooltipData(const QModelIndex& modelIndex) const if (esp.forceEnabled) { toolTip += "
" + tr("This plugin can't be disabled (enforced by the game).") + ""; - } else { - if (!esp.author.isEmpty()) { - toolTip += "
" + tr("Author") + ": " + TruncateString(esp.author); - } - - if (esp.description.size() > 0) { - toolTip += - "
" + tr("Description") + ": " + TruncateString(esp.description); - } + } - if (esp.masterUnset.size() > 0) { - toolTip += - "
" + tr("Missing Masters") + ": " + "" + - TruncateString( - QStringList(esp.masterUnset.begin(), esp.masterUnset.end()).join(", ")) + - ""; - } + if (!esp.author.isEmpty()) { + toolTip += "
" + tr("Author") + ": " + TruncateString(esp.author); + } - std::set enabledMasters; - std::set_difference(esp.masters.begin(), esp.masters.end(), esp.masterUnset.begin(), - esp.masterUnset.end(), - std::inserter(enabledMasters, enabledMasters.end())); + if (esp.description.size() > 0) { + toolTip += + "
" + tr("Description") + ": " + TruncateString(esp.description); + } - if (!enabledMasters.empty()) { - toolTip += "
" + tr("Enabled Masters") + - ": " + TruncateString(SetJoin(enabledMasters, ", ")); - } + if (esp.masterUnset.size() > 0) { + toolTip += + "
" + tr("Missing Masters") + ": " + "" + + TruncateString( + QStringList(esp.masterUnset.begin(), esp.masterUnset.end()).join(", ")) + + ""; + } + + std::set enabledMasters; + std::set_difference(esp.masters.begin(), esp.masters.end(), esp.masterUnset.begin(), + esp.masterUnset.end(), + std::inserter(enabledMasters, enabledMasters.end())); + + if (!enabledMasters.empty()) { + toolTip += "
" + tr("Enabled Masters") + + ": " + TruncateString(SetJoin(enabledMasters, ", ")); + } + + if (!esp.archives.empty() && esp.archives.size() < 6) { + QString archiveString = + esp.archives.size() < 6 + ? TruncateString( + QStringList(esp.archives.begin(), esp.archives.end()).join(", ")) + + "
" + : ""; + toolTip += "
" + tr("Loads Archives") + ": " + + archiveString + + tr("There are Archives connected to this plugin. Their assets will be " + "added to your game, overwriting in case of conflicts following the " + "plugin order. Loose files will always overwrite assets from " + "Archives. (This flag only checks for Archives from the same mod as " + "the plugin)"); + } - if (!esp.archives.empty()) { - toolTip += - "
" + tr("Loads Archives") + ": " + - TruncateString( - QStringList(esp.archives.begin(), esp.archives.end()).join(", ")) + - "
" + - tr("There are Archives connected to this plugin. Their assets will be " - "added to your game, overwriting in case of conflicts following the " - "plugin order. Loose files will always overwrite assets from " - "Archives. (This flag only checks for Archives from the same mod as " - "the plugin)"); - } + if (esp.hasIni) { + toolTip += "
" + tr("Loads INI settings") + + ": " + "
" + + tr("There is an ini file connected to this plugin. Its settings will " + "be added to your game settings, overwriting in case of conflicts."); + } - if (esp.hasIni) { - toolTip += - "
" + tr("Loads INI settings") + - ": " - "
" + - tr("There is an ini file connected to this plugin. Its settings will " - "be added to your game settings, overwriting in case of conflicts."); - } + if (esp.isLightFlagged && !esp.hasLightExtension) { + toolTip += + "

" + tr("This ESP is flagged as an ESL. It will adhere to the ESP load " + "order but the records will be loaded in ESL space."); + } - if (esp.isLightFlagged && !esp.hasLightExtension) { - toolTip += "

" + - tr("This ESP is flagged as an ESL. It will adhere to the ESP load " - "order but the records will be loaded in ESL space."); - } + if (esp.forceDisabled) { + toolTip += "

" + tr("This game does not currently permit custom plugin " + "loading. There may be manual workarounds."); if (esp.forceDisabled) { toolTip += "

" + tr("This game does not currently permit custom plugin " @@ -1530,8 +1539,8 @@ Qt::ItemFlags PluginList::flags(const QModelIndex& modelIndex) const Qt::ItemFlags result = QAbstractItemModel::flags(modelIndex); if (modelIndex.isValid()) { - if (!m_ESPs[index].forceEnabled) { - result |= Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled; + if (!m_ESPs[index].forceEnabled && !m_ESPs[index].forceDisabled) { + result |= Qt::ItemIsDragEnabled; } if (modelIndex.column() == COL_PRIORITY) { result |= Qt::ItemIsEditable; -- cgit v1.3.1 From b1f3c7ea510317dc45074f4b930bc15d77b0f03c Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 12 Sep 2023 16:53:45 -0500 Subject: Fix merge issues and small plugin display corrections --- src/pluginlist.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'src/pluginlist.cpp') diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index a6361791..b31d60bf 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -1177,7 +1177,7 @@ QVariant PluginList::checkstateData(const QModelIndex& modelIndex) const { const int index = modelIndex.row(); - if (m_ESPs[index].forceEnabled || m_ESPs[index].forceDisabled) { + if (m_ESPs[index].forceEnabled) { return Qt::Checked; } else if (m_ESPs[index].forceDisabled) { return Qt::Unchecked; @@ -1194,6 +1194,10 @@ QVariant PluginList::foregroundData(const QModelIndex& modelIndex) const return QBrush(Qt::gray); } + if ((modelIndex.column() == COL_NAME) && m_ESPs[index].forceDisabled) { + return QBrush(Qt::darkRed); + } + return {}; } @@ -1277,15 +1281,14 @@ QVariant PluginList::tooltipData(const QModelIndex& modelIndex) const ": " + TruncateString(SetJoin(enabledMasters, ", ")); } - if (!esp.archives.empty() && esp.archives.size() < 6) { + if (!esp.archives.empty()) { QString archiveString = esp.archives.size() < 6 ? TruncateString( QStringList(esp.archives.begin(), esp.archives.end()).join(", ")) + "
" : ""; - toolTip += "
" + tr("Loads Archives") + ": " + - archiveString + + toolTip += "
" + tr("Loads Archives") + ": " + archiveString + tr("There are Archives connected to this plugin. Their assets will be " "added to your game, overwriting in case of conflicts following the " "plugin order. Loose files will always overwrite assets from " @@ -1302,19 +1305,15 @@ QVariant PluginList::tooltipData(const QModelIndex& modelIndex) const } if (esp.isLightFlagged && !esp.hasLightExtension) { + QString type = esp.hasMasterExtension ? "ESM" : "ESP"; toolTip += - "

" + tr("This ESP is flagged as an ESL. It will adhere to the ESP load " - "order but the records will be loaded in ESL space."); + "

" + tr("This %1 is flagged as an ESL. It will adhere to the %1 load " + "order but the records will be loaded in ESL space.").arg(type); } if (esp.forceDisabled) { toolTip += "

" + tr("This game does not currently permit custom plugin " "loading. There may be manual workarounds."); - - if (esp.forceDisabled) { - toolTip += "

" + tr("This game does not currently permit custom plugin " - "loading. There may be manual workarounds."); - } } // additional info -- cgit v1.3.1 From d15a87b0e646e2bffc0605ce8fdae4909e41995c Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Sep 2023 03:23:47 -0500 Subject: Fix lint issues --- src/pluginlist.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/pluginlist.cpp') diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index b31d60bf..cb3face6 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -1308,7 +1308,8 @@ QVariant PluginList::tooltipData(const QModelIndex& modelIndex) const QString type = esp.hasMasterExtension ? "ESM" : "ESP"; toolTip += "

" + tr("This %1 is flagged as an ESL. It will adhere to the %1 load " - "order but the records will be loaded in ESL space.").arg(type); + "order but the records will be loaded in ESL space.") + .arg(type); } if (esp.forceDisabled) { -- cgit v1.3.1 From 800c2ea084235a09e3f55e38c768b14da40099b3 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 15 Sep 2023 21:30:07 -0500 Subject: Context menu fix Prevent changing the status of force disabled or enabled plugins via the context menu --- src/pluginlist.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/pluginlist.cpp') diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index cb3face6..a50f242c 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -421,6 +421,8 @@ void PluginList::setEnabled(const QModelIndexList& indices, bool enabled) { QStringList dirty; for (auto& idx : indices) { + if (m_ESPs[idx.row()].forceEnabled || m_ESPs[idx.row()].forceDisabled) + continue; if (m_ESPs[idx.row()].enabled != enabled) { m_ESPs[idx.row()].enabled = enabled; dirty.append(m_ESPs[idx.row()].name); @@ -437,6 +439,8 @@ void PluginList::setEnabledAll(bool enabled) { QStringList dirty; for (ESPInfo& info : m_ESPs) { + if (info.forceEnabled || info.forceDisabled) + continue; if (info.enabled != enabled) { info.enabled = enabled; dirty.append(info.name); -- cgit v1.3.1 From f2a784ed70ef75954a4b9ba5b317794532116619 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 16 Sep 2023 03:21:18 -0500 Subject: Allow unforced plugins to be checkable again --- src/pluginlist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/pluginlist.cpp') diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index a50f242c..efa51ac7 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -1544,7 +1544,7 @@ Qt::ItemFlags PluginList::flags(const QModelIndex& modelIndex) const if (modelIndex.isValid()) { if (!m_ESPs[index].forceEnabled && !m_ESPs[index].forceDisabled) { - result |= Qt::ItemIsDragEnabled; + result |= Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled; } if (modelIndex.column() == COL_PRIORITY) { result |= Qt::ItemIsEditable; -- cgit v1.3.1