summaryrefslogtreecommitdiff
path: root/src/pluginlist.cpp
diff options
context:
space:
mode:
authorTannin <devnull@localhost>2014-04-05 15:14:37 +0200
committerTannin <devnull@localhost>2014-04-05 15:14:37 +0200
commitc017f4a0d50b67a44e276bd5ae8929ed3990c62c (patch)
treebe504af55ffc99b657eca9938a4a76864e41454f /src/pluginlist.cpp
parentb1f1682790072fbfb45bd9eaa3c6890edfb81a22 (diff)
- added buttons to backup and restore the modlist and pluginlist
- replaced boss integration with loot
Diffstat (limited to 'src/pluginlist.cpp')
-rw-r--r--src/pluginlist.cpp224
1 files changed, 1 insertions, 223 deletions
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index af6f42da..1f4ed9b1 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -78,7 +78,6 @@ PluginList::PluginList(QObject *parent)
: QAbstractItemModel(parent)
, m_FontMetrics(QFont())
, m_SaveTimer(this)
- , m_BOSS(NULL)
{
m_SaveTimer.setSingleShot(true);
connect(&m_SaveTimer, SIGNAL(timeout()), this, SIGNAL(saveTimer()));
@@ -95,11 +94,6 @@ PluginList::PluginList(QObject *parent)
PluginList::~PluginList()
{
- if (m_BOSS != NULL) {
- m_BOSS->CleanUpAPI();
- delete m_BOSS;
- m_BOSS = NULL;
- }
}
@@ -595,225 +589,9 @@ void PluginList::refreshLoadOrder()
}
-class boss_exception : public std::runtime_error {
-public:
- boss_exception(const std::string &message) : std::runtime_error(message) {}
-};
-
-#define THROW_BOSS_ERROR(obj) \
- uint8_t *message; \
- obj->GetLastErrorDetails(&message); \
- throw boss_exception(std::string(reinterpret_cast<char*>(message)));
-
-#define U8(text) reinterpret_cast<const uint8_t*>(text)
-
-
-void outputBossLog(const QString &filename)
-{
- QFile file(filename);
- if (file.open(QIODevice::ReadOnly)) {
- while (!file.atEnd()) {
- QByteArray line = file.readLine().trimmed();
- if (line.length() < 1)
- continue;
-
- int endFirstWord = line.indexOf(':');
- if (endFirstWord < 0) {
- endFirstWord = 0;
- }
- QString firstWord = line.mid(0, endFirstWord);
- if (firstWord == "DEBUG") {
- qDebug("(boss) %s", line.mid(endFirstWord + 2).constData());
- } else {
- qWarning("(boss) %s", line.mid(endFirstWord + 2).constData());
- }
- }
- }
- file.resize(0);
-}
-
-
-boss_db PluginList::initBoss()
-{
- boss_db result;
- bool firstRun = (m_BOSS == nullptr);
- if (firstRun) {
- m_BOSS = new BossDLL(TEXT("dlls\\boss.dll"));
-
- if (!m_BOSS->IsCompatibleVersion(2,1,1)) {
- throw MyException(tr("BOSS dll incompatible"));
- }
- uint8_t *versionString;
- if (m_BOSS->GetVersionString(&versionString) != BossDLL::RESULT_OK) {
- THROW_BOSS_ERROR(m_BOSS)
- }
- qDebug("using boss version %s", versionString);
-
- m_TempFile.open(); m_TempFile.close(); // yeah, stupid, but open is required to generate the name
- m_BOSS->SetLoggerOutput(m_TempFile.fileName().toLocal8Bit().constData(), 4);
- }
-
- if (m_BOSS->CreateBossDb(&result, BossDLL::SKYRIM, NULL) != BossDLL::RESULT_OK) {
- uint8_t *message;
- m_BOSS->GetLastErrorDetails(&message);
- std::string messageCopy(reinterpret_cast<const char*>(message));
- delete m_BOSS;
- m_BOSS = NULL;
- throw boss_exception(messageCopy);
- }
- qApp->processEvents();
-
- QString masterlistName = QDir::toNativeSeparators(qApp->applicationDirPath() + "/boss/masterlist.txt");
-
- if (firstRun) {
- uint32_t res = m_BOSS->UpdateMasterlist(result, U8(masterlistName.toUtf8().constData()));
- qApp->processEvents();
- if (res == BossDLL::RESULT_OK) {
- qDebug("boss masterlist updated");
- } else if (res == BossDLL::RESULT_NO_UPDATE_NECESSARY) {
- qDebug("boss masterlist already up-to-date");
- } else {
- THROW_BOSS_ERROR(m_BOSS)
- }
- }
- if (m_BOSS->Load(result,
- U8(masterlistName.toUtf8().constData()),
- U8(QDir::toNativeSeparators(qApp->applicationDirPath() + "/boss/userlist.txt").toUtf8().constData())) != BossDLL::RESULT_OK) {
- THROW_BOSS_ERROR(m_BOSS)
- }
- return result;
-}
-
-void PluginList::convertPluginListForBoss(boss_db db, boost::ptr_vector<uint8_t> &inputPlugins, std::vector<uint8_t*> &activePlugins)
-{
- foreach (int idx, m_ESPsByPriority) {
- QString fileName = m_ESPs[idx].m_Name;
- QByteArray name = fileName.toUtf8();
-
- uint8_t *nameU8 = new uint8_t[name.length() + 1];
- memcpy(nameU8, name.constData(), name.length() + 1);
- if (m_ESPs[idx].m_Enabled) {
- activePlugins.push_back(nameU8);
- }
- inputPlugins.push_back(nameU8);
- }
- if (m_BOSS->SetActivePluginsDumb(db, &activePlugins[0], activePlugins.size()) != BossDLL::RESULT_OK) {
- THROW_BOSS_ERROR(m_BOSS)
- }
-}
-
-void PluginList::applyBOSSSorting(boss_db db, std::map<int, QString> &lockedLoadOrder, uint8_t **pluginList, size_t size,
- int &priority, int &loadOrder, bool recognized, const char *extension)
-{
- for (size_t i = 0; i < size; ++i) {
- QString name = QString::fromUtf8(reinterpret_cast<const char*>(pluginList[i])).toLower();
- if (name.endsWith(extension)) {
- auto iter = m_ESPsByName.find(name);
- if (iter == m_ESPsByName.end()) {
- // boss seems to report plugins from userlist as sorted that aren't even installed
- continue;
- }
-
- BossMessage *message;
- size_t numMessages = 0;
- m_BOSS->GetPluginMessages(db, pluginList[i], &message, &numMessages);
- BossInfo newInfo;
- for (size_t im = 0; im < numMessages; ++im) {
- newInfo.m_BOSSMessages.append(QString::fromUtf8(reinterpret_cast<const char*>(message[im].message)));
- }
- newInfo.m_BOSSUnrecognized = !recognized;
- m_BossInfo[name] = newInfo;
-
- // locked order plugins are not inserted by boss sorting ...
- if (m_LockedOrder.find(name) != m_LockedOrder.end()) {
- continue;
- }
-
- // ... but by their enforced priority
- while (lockedLoadOrder.find(loadOrder) != lockedLoadOrder.end()) {
- auto lloIter = lockedLoadOrder.find(loadOrder);
- auto nameIter = m_ESPsByName.find(lloIter->second);
- if (nameIter != m_ESPsByName.end()) {
- m_ESPs[nameIter->second].m_Priority = priority++;
- if (m_ESPs[nameIter->second].m_Enabled) {
- m_ESPs[nameIter->second].m_LoadOrder = loadOrder++;
- } else {
- m_ESPs[nameIter->second].m_LoadOrder = -1;
- }
- }
- lockedLoadOrder.erase(lloIter);
- }
-
- m_ESPs[iter->second].m_Priority = priority++;
- if (m_ESPs[iter->second].m_Enabled) {
- m_ESPs[iter->second].m_LoadOrder = loadOrder++;
- } else {
- m_ESPs[iter->second].m_LoadOrder = -1;
- }
- }
- }
-}
-
-void PluginList::bossSort()
+void PluginList::lootSort()
{
- boss_db db = initBoss();
- ON_BLOCK_EXIT([&] { m_BOSS->DestroyBossDb(db); });
-
- // create a boss-compatible representation of our current mod list.
- boost::ptr_vector<uint8_t> inputPlugins;
- std::vector<uint8_t*> activePlugins;
- convertPluginListForBoss(db, inputPlugins, activePlugins);
-
- // sort mods in-memory
- uint8_t **sortedPlugins;
- uint8_t **unrecognizedPlugins;
- size_t sizeSorted, sizeUnrecognized;
- if (m_BOSS->SortCustomMods(db,
- inputPlugins.c_array(), inputPlugins.size(),
- &sortedPlugins, &sizeSorted,
- &unrecognizedPlugins, &sizeUnrecognized) != BossDLL::RESULT_OK) {
- THROW_BOSS_ERROR(m_BOSS)
- }
-
- // output the log from boss to our own log to make it visible
- outputBossLog(m_TempFile.fileName());
-
- qDebug("%d sorted, %d unrecognized", sizeSorted, sizeUnrecognized);
- ChangeBracket<PluginList> layoutChange(this);
-
- std::map<int, QString> lockedLoadOrder;
- std::for_each(m_LockedOrder.begin(), m_LockedOrder.end(),
- [&lockedLoadOrder] (const std::pair<QString, int> &ele) { lockedLoadOrder[ele.second] = ele.first; });
-
- int priority = 0;
- int loadOrder = 0;
- applyBOSSSorting(db, lockedLoadOrder, sortedPlugins, sizeSorted, priority, loadOrder, true, "esm");
- applyBOSSSorting(db, lockedLoadOrder, unrecognizedPlugins, sizeUnrecognized, priority, loadOrder, false, "esm");
- applyBOSSSorting(db, lockedLoadOrder, sortedPlugins, sizeSorted, priority, loadOrder, true, "esp");
- applyBOSSSorting(db, lockedLoadOrder, unrecognizedPlugins, sizeUnrecognized, priority, loadOrder, false, "esp");
-
- // applyBOSSSorting removed entries from lockedLoadOrder when they were inserted so everything that's left is plugins
- // locked to the end of the list. Now this inserts the rest in the ascending priority order. If the list is too short
- // to place the plugins in their intended position then this guarantees plugins are kept in the correct relative order
- // but it doesn't minimize the number of misplaced plugins.
- for (auto iter = lockedLoadOrder.begin(); iter != lockedLoadOrder.end(); ++iter) {
- auto nameIter = m_ESPsByName.find(iter->second);
- if (nameIter != m_ESPsByName.end()) {
- m_ESPs[nameIter->second].m_Priority = priority++;
- if (m_ESPs[nameIter->second].m_Enabled) {
- m_ESPs[nameIter->second].m_LoadOrder = loadOrder++;
- } else {
- m_ESPs[nameIter->second].m_LoadOrder = -1;
- }
- }
- }
-
- // inform view of the changed data
- updateIndices();
- layoutChange.finish();
- emit dataChanged(this->index(0, 0), this->index(m_ESPs.size(), columnCount()));
- m_Refreshed();
}
IPluginList::PluginState PluginList::state(const QString &name) const