void Profile::writeModlistNow() { if (!m_Directory.exists()) return; try { QString fileName = getModlistFileName(); SafeWriteFile file(fileName); file->write(QString("# This file was automatically generated by Mod Organizer.\r\n").toUtf8()); if (m_ModStatus.empty()) { return; } for (int i = m_ModStatus.size() - 1; i >= 0; --i) { // the priority order was inverted on load so it has to be inverted again unsigned int index = m_ModIndexByPriority[i]; if (index != UINT_MAX) { ModInfo::Ptr modInfo = ModInfo::getByIndex(index); std::vector<ModInfo::EFlag> flags = modInfo->getFlags(); if ((modInfo->getFixedPriority() == INT_MIN)) { if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_FOREIGN) != flags.end()) { file->write("*"); } else if (m_ModStatus[index].m_Enabled) { file->write("+"); } else { file->write("-"); } file->write(modInfo->name().toUtf8()); file->write("\r\n"); } } } if (file.commitIfDifferent(m_LastModlistHash)) { qDebug("%s saved", QDir::toNativeSeparators(fileName).toUtf8().constData()); } } catch (const std::exception &e) { reportError(tr("failed to write mod list: %1").arg(e.what())); return; } }
void Profile::refreshModStatus() { QFile file(getModlistFileName()); if (!file.open(QIODevice::ReadOnly)) { throw MyException(tr("\"%1\" is missing or inaccessible").arg(getModlistFileName())); } bool modStatusModified = false; m_ModStatus.clear(); m_ModStatus.resize(ModInfo::getNumMods()); std::set<QString> namesRead; // load mods from file and update enabled state and priority for them int index = 0; while (!file.atEnd()) { QByteArray line = file.readLine().trimmed(); bool enabled = true; QString modName; if (line.length() == 0) { // empty line continue; } else if (line.at(0) == '#') { // comment line continue; } else if (line.at(0) == '-') { enabled = false; modName = QString::fromUtf8(line.mid(1).trimmed().constData()); } else if ((line.at(0) == '+') || (line.at(0) == '*')) { modName = QString::fromUtf8(line.mid(1).trimmed().constData()); } else { modName = QString::fromUtf8(line.trimmed().constData()); } if (modName.size() > 0) { QString lookupName = modName; if (namesRead.find(lookupName) != namesRead.end()) { continue; } else { namesRead.insert(lookupName); } unsigned int modIndex = ModInfo::getIndex(lookupName); if (modIndex != UINT_MAX) { ModInfo::Ptr info = ModInfo::getByIndex(modIndex); if ((modIndex < m_ModStatus.size()) && (info->getFixedPriority() == INT_MIN)) { m_ModStatus[modIndex].m_Enabled = enabled; if (m_ModStatus[modIndex].m_Priority == -1) { if (static_cast<size_t>(index) >= m_ModStatus.size()) { throw MyException(tr("invalid index %1").arg(index)); } m_ModStatus[modIndex].m_Priority = index++; } } else { qWarning("no mod state for \"%s\" (profile \"%s\")", qPrintable(modName), m_Directory.path().toUtf8().constData()); // need to rewrite the modlist to fix this modStatusModified = true; } } else { qDebug("mod \"%s\" (profile \"%s\") not found", qPrintable(modName), m_Directory.path().toUtf8().constData()); // need to rewrite the modlist to fix this modStatusModified = true; } } } int numKnownMods = index; int topInsert = 0; // invert priority order to match that of the pluginlist. Also // give priorities to mods not referenced in the profile for (size_t i = 0; i < m_ModStatus.size(); ++i) { ModInfo::Ptr modInfo = ModInfo::getByIndex(i); if (modInfo->alwaysEnabled()) { m_ModStatus[i].m_Enabled = true; } if (modInfo->getFixedPriority() == INT_MAX) { continue; } if (m_ModStatus[i].m_Priority != -1) { m_ModStatus[i].m_Priority = numKnownMods - m_ModStatus[i].m_Priority - 1; } else { if (static_cast<size_t>(index) >= m_ModStatus.size()) { throw MyException(tr("invalid index %1").arg(index)); } if (modInfo->hasFlag(ModInfo::FLAG_FOREIGN)) { m_ModStatus[i].m_Priority = --topInsert; } else { m_ModStatus[i].m_Priority = index++; } // also, mark the mod-list as changed modStatusModified = true; } } // to support insertion of new mods at the top we may now have mods with negative priority. shift them all up // to align priority with 0 if (topInsert < 0) { int offset = topInsert * -1; for (size_t i = 0; i < m_ModStatus.size(); ++i) { ModInfo::Ptr modInfo = ModInfo::getByIndex(i); if (modInfo->getFixedPriority() == INT_MAX) { continue; } m_ModStatus[i].m_Priority += offset; } } file.close(); updateIndices(); if (modStatusModified) { m_ModListWriter.write(); } }