diff options
Diffstat (limited to 'src/pluginlist.cpp')
| -rw-r--r-- | src/pluginlist.cpp | 262 |
1 files changed, 186 insertions, 76 deletions
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 3812143a..28e0af51 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -43,7 +43,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QDir>
#include <QFile>
#include <QFileInfo>
-#include <QTextCodec>
#include <QFileInfo>
#include <QListWidgetItem>
#include <QRegularExpression>
@@ -62,27 +61,6 @@ using namespace MOBase; using namespace MOShared;
-static bool ByName(const PluginList::ESPInfo& LHS, const PluginList::ESPInfo& RHS)
-{
- return LHS.name.toUpper() < RHS.name.toUpper();
-}
-
-static bool ByPriority(const PluginList::ESPInfo& LHS, const PluginList::ESPInfo& RHS)
-{
- if (LHS.isMaster && !RHS.isMaster) {
- return true;
- } else if (!LHS.isMaster && RHS.isMaster) {
- return false;
- } else {
- return LHS.priority < RHS.priority;
- }
-}
-
-static bool ByDate(const PluginList::ESPInfo& LHS, const PluginList::ESPInfo& RHS)
-{
- return QFileInfo(LHS.fullPath).lastModified() < QFileInfo(RHS.fullPath).lastModified();
-}
-
static QString TruncateString(const QString& text)
{
QString new_text = text;
@@ -272,6 +250,9 @@ void PluginList::refresh(const QString &profileName gamePlugins->readPluginLists(m_Organizer.managedGameOrganizer()->pluginList());
}
+ fixPrimaryPlugins();
+ fixPluginRelationships();
+
testMasters();
updateIndices();
@@ -287,6 +268,84 @@ void PluginList::refresh(const QString &profileName m_Refreshed();
}
+void PluginList::fixPrimaryPlugins()
+{
+ if (!m_Organizer.settings().game().forceEnableCoreFiles()) {
+ return;
+ }
+
+ // This function ensures that the primary plugins are first and in the correct order
+ QStringList primaryPlugins = m_Organizer.managedGame()->primaryPlugins();
+ int prio = 0;
+ bool somethingChanged = false;
+ for (QString plugin : primaryPlugins) {
+ std::map<QString, int>::iterator iter = m_ESPsByName.find(plugin);
+ // Plugin is present?
+ if (iter != m_ESPsByName.end()) {
+ if (prio != m_ESPs[iter->second].priority) {
+ // Priority is wrong! Fix it!
+ int newPrio = prio;
+ setPluginPriority(iter->second, newPrio, true /* isForced */);
+ somethingChanged = true;
+ }
+ prio++;
+ }
+ }
+
+ if (somethingChanged) {
+ writePluginsList();
+ }
+}
+
+void PluginList::fixPluginRelationships()
+{
+ TimeThis timer("PluginList::fixPluginRelationships");
+
+ // Count the types of plugins
+ int masterCount = 0;
+ for (auto plugin : m_ESPs) {
+ if (plugin.hasLightExtension ||
+ plugin.hasMasterExtension ||
+ plugin.isMasterFlagged) {
+ masterCount++;
+ }
+ }
+
+ // Ensure masters are up top and normal plugins are down below
+ for (int i = 0; i < m_ESPs.size(); i++) {
+ ESPInfo& plugin = m_ESPs[i];
+ if (plugin.hasLightExtension ||
+ plugin.hasMasterExtension ||
+ plugin.isMasterFlagged) {
+ if (plugin.priority > masterCount) {
+ int newPriority = masterCount + 1;
+ setPluginPriority(i, newPriority);
+ }
+ }
+ else {
+ if (plugin.priority < masterCount) {
+ int newPriority = masterCount + 1;
+ setPluginPriority(i, newPriority);
+ }
+ }
+ }
+
+ // Ensure master/child relationships are observed
+ for (int i = 0; i < m_ESPs.size(); i++) {
+ ESPInfo& plugin = m_ESPs[i];
+ int newPriority = plugin.priority;
+ for (auto master : plugin.masters) {
+ auto iter = m_ESPsByName.find(master);
+ if (iter != m_ESPsByName.end()) {
+ newPriority = std::max(newPriority, m_ESPs[iter->second].priority);
+ }
+ }
+ if (newPriority != plugin.priority) {
+ setPluginPriority(i, newPriority);
+ }
+ }
+}
+
void PluginList::fixPriorities()
{
std::vector<std::pair<int, int>> espPrios;
@@ -846,57 +905,71 @@ int PluginList::loadOrder(const QString &name) const }
}
-bool PluginList::isMaster(const QString &name) const
+QStringList PluginList::masters(const QString &name) const
{
auto iter = m_ESPsByName.find(name);
if (iter == m_ESPsByName.end()) {
- return false;
+ return QStringList();
+ } else {
+ QStringList result;
+ for (const QString &master : m_ESPs[iter->second].masters) {
+ result.append(master);
+ }
+ return result;
+ }
+}
+
+QString PluginList::origin(const QString &name) const
+{
+ auto iter = m_ESPsByName.find(name);
+ if (iter == m_ESPsByName.end()) {
+ return QString();
} else {
- return m_ESPs[iter->second].isMaster;
+ return m_ESPs[iter->second].originName;
}
}
-bool PluginList::isLight(const QString &name) const
+bool PluginList::hasMasterExtension(const QString& name) const
{
auto iter = m_ESPsByName.find(name);
if (iter == m_ESPsByName.end()) {
return false;
- } else {
- return m_ESPs[iter->second].isLight;
+ }
+ else {
+ return m_ESPs[iter->second].hasMasterExtension;
}
}
-bool PluginList::isLightFlagged(const QString &name) const
+bool PluginList::hasLightExtension(const QString& name) const
{
auto iter = m_ESPsByName.find(name);
if (iter == m_ESPsByName.end()) {
return false;
- } else {
- return m_ESPs[iter->second].isLightFlagged;
+ }
+ else {
+ return m_ESPs[iter->second].hasLightExtension;
}
}
-QStringList PluginList::masters(const QString &name) const
+bool PluginList::isMasterFlagged(const QString& name) const
{
auto iter = m_ESPsByName.find(name);
if (iter == m_ESPsByName.end()) {
- return QStringList();
- } else {
- QStringList result;
- for (const QString &master : m_ESPs[iter->second].masters) {
- result.append(master);
- }
- return result;
+ return false;
+ }
+ else {
+ return m_ESPs[iter->second].isMasterFlagged;
}
}
-QString PluginList::origin(const QString &name) const
+bool PluginList::isLightFlagged(const QString& name) const
{
auto iter = m_ESPsByName.find(name);
if (iter == m_ESPsByName.end()) {
- return QString();
- } else {
- return m_ESPs[iter->second].originName;
+ return false;
+ }
+ else {
+ return m_ESPs[iter->second].isLightFlagged;
}
}
@@ -961,7 +1034,7 @@ void PluginList::generatePluginIndexes() ++numSkipped;
continue;
}
- if (lightPluginsSupported && (m_ESPs[i].isLight || m_ESPs[i].isLightFlagged)) {
+ if (lightPluginsSupported && (m_ESPs[i].hasLightExtension || m_ESPs[i].isLightFlagged)) {
int ESLpos = 254 + ((numESLs + 1) / 4096);
m_ESPs[i].index = QString("%1:%2").arg(ESLpos, 2, 16, QChar('0')).arg((numESLs) % 4096, 3, 16, QChar('0')).toUpper();
++numESLs;
@@ -1090,10 +1163,12 @@ QVariant PluginList::fontData(const QModelIndex &modelIndex) const QFont result;
- if (m_ESPs[index].isMaster) {
+ if (m_ESPs[index].hasMasterExtension ||
+ m_ESPs[index].isMasterFlagged ||
+ m_ESPs[index].hasLightExtension) {
result.setItalic(true);
result.setWeight(QFont::Bold);
- } else if (m_ESPs[index].isLight || m_ESPs[index].isLightFlagged) {
+ } else if (m_ESPs[index].isLightFlagged) {
result.setItalic(true);
}
@@ -1175,7 +1250,7 @@ QVariant PluginList::tooltipData(const QModelIndex &modelIndex) const "be added to your game settings, overwriting in case of conflicts.");
}
- if (esp.isLightFlagged && !esp.isLight) {
+ if (esp.isLightFlagged && !esp.hasLightExtension) {
toolTip +=
"<br><br>" + tr(
"This ESP is flagged as an ESL. It will adhere to the ESP load "
@@ -1297,7 +1372,7 @@ QVariant PluginList::iconData(const QModelIndex &modelIndex) const result.append(":/MO/gui/archive_conflict_neutral");
}
- if (esp.isLightFlagged && !esp.isLight) {
+ if (esp.isLightFlagged && !esp.hasLightExtension) {
result.append(":/MO/gui/awaiting");
}
@@ -1423,7 +1498,7 @@ Qt::ItemFlags PluginList::flags(const QModelIndex &modelIndex) const return result;
}
-void PluginList::setPluginPriority(int row, int &newPriority)
+void PluginList::setPluginPriority(int row, int &newPriority, bool isForced)
{
int newPriorityTemp = newPriority;
@@ -1433,18 +1508,22 @@ void PluginList::setPluginPriority(int row, int &newPriority) else if (newPriorityTemp >= static_cast<int>(m_ESPsByPriority.size()))
newPriorityTemp = static_cast<int>(m_ESPsByPriority.size()) - 1;
- if (!m_ESPs[row].isMaster && !m_ESPs[row].isLight) {
+ if (!m_ESPs[row].isMasterFlagged &&
+ !m_ESPs[row].hasLightExtension &&
+ !m_ESPs[row].hasMasterExtension) {
// don't allow esps to be moved above esms
while ((newPriorityTemp < static_cast<int>(m_ESPsByPriority.size() - 1)) &&
- (m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).isMaster ||
- m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).isLight)) {
+ (m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).isMasterFlagged ||
+ m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).hasLightExtension ||
+ m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).hasMasterExtension)) {
++newPriorityTemp;
}
} else {
// don't allow esms to be moved below esps
while ((newPriorityTemp > 0) &&
- !m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).isMaster &&
- !m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).isLight) {
+ !m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).isMasterFlagged &&
+ !m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).hasLightExtension &&
+ !m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).hasMasterExtension) {
--newPriorityTemp;
}
// also don't allow "regular" esms to be moved above primary plugins
@@ -1454,25 +1533,54 @@ void PluginList::setPluginPriority(int row, int &newPriority) }
}
- try {
- int oldPriority = m_ESPs.at(row).priority;
- if (newPriorityTemp > oldPriority) {
- // priority is higher than the old, so the gap we left is in lower priorities
- for (int i = oldPriority + 1; i <= newPriorityTemp; ++i) {
- --m_ESPs.at(m_ESPsByPriority.at(i)).priority;
+ int oldPriority = m_ESPs.at(row).priority;
+ if (newPriorityTemp < oldPriority) { // moving up
+ // don't allow plugins to be moved above their masters
+ for (auto master : m_ESPs[row].masters) {
+ auto iter = m_ESPsByName.find(master);
+ if (iter != m_ESPsByName.end()) {
+ int masterPriority = m_ESPs[iter->second].priority;
+ if (masterPriority >= newPriorityTemp)
+ {
+ newPriorityTemp = masterPriority + 1;
+ }
}
- emit dataChanged(index(oldPriority + 1, 0), index(newPriorityTemp, columnCount()));
- } else {
- for (int i = newPriorityTemp; i < oldPriority; ++i) {
- ++m_ESPs.at(m_ESPsByPriority.at(i)).priority;
+ }
+ }
+ else if (newPriorityTemp > oldPriority) { // moving down
+ // don't allow masters to be moved below their children
+ for (int i = oldPriority + 1; i <= newPriorityTemp; i++) {
+ PluginList::ESPInfo* otherInfo = &m_ESPs.at(m_ESPsByPriority[i]);
+ for (auto master : otherInfo->masters) {
+ if (master.compare(m_ESPs[row].name, Qt::CaseInsensitive) == 0) {
+ newPriorityTemp = otherInfo->priority - 1;
+ break;
+ }
}
- emit dataChanged(index(newPriorityTemp, 0), index(oldPriority - 1, columnCount()));
- ++newPriority;
}
+ }
+
+ try {
+ if (newPriorityTemp != oldPriority) {
+ if (newPriorityTemp > oldPriority) {
+ // priority is higher than the old, so the gap we left is in lower priorities
+ for (int i = oldPriority + 1; i <= newPriorityTemp; ++i) {
+ --m_ESPs.at(m_ESPsByPriority.at(i)).priority;
+ }
+ emit dataChanged(index(oldPriority + 1, 0), index(newPriorityTemp, columnCount()));
+ }
+ else {
+ for (int i = newPriorityTemp; i < oldPriority; ++i) {
+ ++m_ESPs.at(m_ESPsByPriority.at(i)).priority;
+ }
+ emit dataChanged(index(newPriorityTemp, 0), index(oldPriority - 1, columnCount()));
+ ++newPriority;
+ }
- m_ESPs.at(row).priority = newPriorityTemp;
- emit dataChanged(index(row, 0), index(row, columnCount()));
- m_PluginMoved(m_ESPs[row].name, oldPriority, newPriorityTemp);
+ m_ESPs.at(row).priority = newPriorityTemp;
+ emit dataChanged(index(row, 0), index(row, columnCount()));
+ m_PluginMoved(m_ESPs[row].name, oldPriority, newPriorityTemp);
+ }
} catch (const std::out_of_range&) {
reportError(tr("failed to restore load order for %1").arg(m_ESPs[row].name));
}
@@ -1490,11 +1598,11 @@ void PluginList::changePluginPriority(std::vector<int> rows, int newPriority) // don't try to move plugins before force-enabled plugins
for (std::vector<ESPInfo>::const_iterator iter = m_ESPs.begin();
- iter != m_ESPs.end(); ++iter) {
+ iter != m_ESPs.end(); ++iter) {
if (iter->forceEnabled) {
- newPriority = std::max(newPriority, iter->priority+1);
+ newPriority = std::max(newPriority, iter->priority + 1);
}
- maxPriority = std::max(maxPriority, iter->priority+1);
+ maxPriority = std::max(maxPriority, iter->priority + 1);
minPriority = std::min(minPriority, iter->priority);
}
@@ -1586,9 +1694,10 @@ PluginList::ESPInfo::ESPInfo(const QString &name, bool enabled, {
try {
ESP::File file(ToWString(fullPath));
- isMaster = file.isMaster();
auto extension = name.right(3).toLower();
- isLight = lightPluginsAreSupported && (extension == "esl");
+ hasMasterExtension = (extension == "esm");
+ hasLightExtension = lightPluginsAreSupported && (extension == "esl");
+ isMasterFlagged = file.isMaster();
isLightFlagged = lightPluginsAreSupported && file.isLight();
author = QString::fromLatin1(file.author().c_str());
@@ -1599,8 +1708,9 @@ PluginList::ESPInfo::ESPInfo(const QString &name, bool enabled, }
} catch (const std::exception &e) {
log::error("failed to parse plugin file {}: {}", fullPath, e.what());
- isMaster = false;
- isLight = false;
+ hasMasterExtension = false;
+ hasLightExtension = false;
+ isMasterFlagged = false;
isLightFlagged = false;
}
}
|
