From c6101e34e1e142a3442c3a4543ea22dabd31fa33 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 18 Nov 2013 20:17:14 +0100 Subject: - archive.dll now supports querying the crc value of files - esptk now determines if a esp is a dummy (without records) - hook.dll no longer creates a log file if noone wrote to it - nexus id and installtime columns are now hidden by default - modlist can now be refreshed without saving first (so plugins can replace the modlist.txt as a whole) - plugins can now query more details about virtualised files - added style options "plastique" and "cleanlooks" - "overwrite" is no longer listed with a creation time - a warning will now be displayed if the user has too many plugins active - a warning will now be displayed if mods with scripts have an installation order that doesn't match the corresponding esp load order - nmm importer now has select all/deselect all buttons - nmm importer no longer tries to unpack missing files from archives (won't work anyway) - initial support for importing from nmm 0.5 alpha - removed some broken warning suppresions - python runner now works with bundled python - extended qbs build system (still fails to build the main gui application) - implemented a nsis-based installer --- src/installationmanager.cpp | 2 -- src/main.cpp | 2 +- src/mainwindow.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++--- src/mainwindow.h | 5 ++++- src/moapplication.cpp | 29 ++++++++++++++++++-------- src/moapplication.h | 2 ++ src/modinfodialog.ui | 33 ++++++++++-------------------- src/modlist.cpp | 7 ++++++- src/modlist.h | 4 ++++ src/organizer.qbs | 44 ++++++++++++++++++++++++++++----------- src/pluginlist.cpp | 21 +++++++++++++++++++ src/pluginlist.h | 7 +++++++ src/settings.cpp | 3 +++ src/shared/shared.qbs | 14 ++++++++----- 14 files changed, 167 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp index 6b430eea..a8571ec9 100644 --- a/src/installationmanager.cpp +++ b/src/installationmanager.cpp @@ -506,7 +506,6 @@ bool InstallationManager::ensureValidModName(GuessedValue &name) const return true; } - bool InstallationManager::doInstall(GuessedValue &modName, int modID, const QString &version, const QString &newestVersion, int categoryID) { @@ -528,7 +527,6 @@ bool InstallationManager::doInstall(GuessedValue &modName, int modID, m_InstallationProgress.setValue(0); m_InstallationProgress.setWindowModality(Qt::WindowModal); m_InstallationProgress.show(); - if (!m_CurrentArchive->extract(ToWString(QDir::toNativeSeparators(targetDirectory)).c_str(), new MethodCallback(this, &InstallationManager::updateProgress), new MethodCallback(this, &InstallationManager::updateProgressFile), diff --git a/src/main.cpp b/src/main.cpp index 5053d21d..8b74ba83 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,7 +60,6 @@ along with Mod Organizer. If not, see . #include "selectiondialog.h" #include "moapplication.h" #include "tutorialmanager.h" -#include #include #include #include @@ -156,6 +155,7 @@ bool bootstrap() // verify the hook-dll exists QString dllName = qApp->applicationDirPath() + "/" + ToQString(AppConfig::hookDLLName()); + HMODULE dllMod = ::LoadLibraryW(ToWString(dllName).c_str()); if (dllMod == NULL) { throw windows_error("hook.dll is missing or invalid"); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f726757c..a8026b68 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -188,8 +188,13 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget ui->modList->header()->installEventFilter(&m_ModList); if (initSettings.contains("mod_list_state")) { ui->modList->header()->restoreState(initSettings.value("mod_list_state").toByteArray()); + } else { + // hide these columns by default + ui->modList->header()->setSectionHidden(ModList::COL_MODID, true); + ui->modList->header()->setSectionHidden(ModList::COL_INSTALLTIME, true); } - ui->modList->header()->setSectionHidden(0, false); // prevent the name-column from being hidden + + ui->modList->header()->setSectionHidden(ModList::COL_NAME, false); // prevent the name-column from being hidden ui->modList->installEventFilter(&m_ModList); // set up plugin list @@ -1364,10 +1369,12 @@ void MainWindow::startExeAction() } -void MainWindow::refreshModList() +void MainWindow::refreshModList(bool saveChanges) { // don't lose changes! - m_CurrentProfile->writeModlistNow(true); + if (saveChanges) { + m_CurrentProfile->writeModlistNow(true); + } ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure); m_CurrentProfile->refreshModStatus(); @@ -2096,6 +2103,32 @@ QStringList MainWindow::findFiles(const QString &path, const std::function MainWindow::findFileInfos(const QString &path, const std::function &filter) const +{ + QList result; + DirectoryEntry *dir = m_DirectoryStructure->findSubDirectoryRecursive(ToWString(path)); + if (dir != NULL) { + std::vector files = dir->getFiles(); + foreach (FileEntry::Ptr file, files) { + FileInfo info; + info.filePath = ToQString(file->getFullPath()); + bool fromArchive = false; + info.origins.append(ToQString(m_DirectoryStructure->getOriginByID(file->getOrigin(fromArchive)).getName())); + info.archive = fromArchive ? ToQString(file->getArchive()) : ""; + foreach (int idx, file->getAlternatives()) { + info.origins.append(ToQString(m_DirectoryStructure->getOriginByID(idx).getName())); + } + + if (filter(info)) { + result.append(info); + } + } + } else { + qWarning("directory %s not found", qPrintable(path)); + } + return result; +} + IDownloadManager *MainWindow::downloadManager() { return &m_DownloadManager; @@ -2161,6 +2194,9 @@ std::vector MainWindow::activeProblems() const if (m_UnloadedPlugins.size() != 0) { problems.push_back(PROBLEM_PLUGINSNOTLOADED); } + if (m_PluginList.enabledCount() > 256) { + problems.push_back(PROBLEM_TOOMANYPLUGINS); + } return problems; } @@ -2170,6 +2206,9 @@ QString MainWindow::shortDescription(unsigned int key) const case PROBLEM_PLUGINSNOTLOADED: { return tr("Some plugins could not be loaded"); } break; + case PROBLEM_TOOMANYPLUGINS: { + return tr("Too many esps and esms enabled"); + } break; default: { return tr("Description missing"); } break; @@ -2187,6 +2226,10 @@ QString MainWindow::fullDescription(unsigned int key) const result += "
    "; return result; } break; + case PROBLEM_TOOMANYPLUGINS: { + return tr("The game doesn't allow more than 256 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or " + "merge some plugins into one. You can find a guide here: http://wiki.step-project.com/Guide:Merging_Plugins"); + } break; default: { return tr("Description missing"); } break; @@ -3195,6 +3238,7 @@ void MainWindow::syncOverwrite() modInfo->testValid(); refreshDirectoryStructure(); } + } void MainWindow::createModFromOverwrite() diff --git a/src/mainwindow.h b/src/mainwindow.h index cf97d4f9..dfd2e571 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -98,7 +98,6 @@ public: void refreshBSAList(); void refreshDataTree(); void refreshSaveList(); - void refreshModList(); void setExecutablesList(const ExecutablesList &executablesList); @@ -135,11 +134,14 @@ public: virtual QString resolvePath(const QString &fileName) const; virtual QStringList listDirectories(const QString &directoryName) const; virtual QStringList findFiles(const QString &path, const std::function &filter) const; + virtual QList findFileInfos(const QString &path, const std::function &filter) const; + virtual MOBase::IDownloadManager *downloadManager(); virtual MOBase::IPluginList *pluginList(); virtual MOBase::IModList *modList(); virtual HANDLE startApplication(const QString &executable, const QStringList &args = QStringList(), const QString &cwd = "", const QString &profile = ""); virtual bool onAboutToRun(const std::function &func); + virtual void refreshModList(bool saveChanges = true); virtual std::vector activeProblems() const; virtual QString shortDescription(unsigned int key) const; @@ -274,6 +276,7 @@ private: private: static const unsigned int PROBLEM_PLUGINSNOTLOADED = 1; + static const unsigned int PROBLEM_TOOMANYPLUGINS = 2; private: diff --git a/src/moapplication.cpp b/src/moapplication.cpp index ba23808b..7e3104db 100644 --- a/src/moapplication.cpp +++ b/src/moapplication.cpp @@ -23,12 +23,15 @@ along with Mod Organizer. If not, see . #include #include #include +#include +#include MOApplication::MOApplication(int argc, char **argv) : QApplication(argc, argv) { connect(&m_StyleWatcher, SIGNAL(fileChanged(QString)), SLOT(updateStyle(QString))); + m_DefaultStyle = style()->objectName(); } @@ -42,11 +45,12 @@ bool MOApplication::setStyleFile(const QString &styleName) // set new stylesheet or clear it if (styleName.length() != 0) { QString styleSheetName = applicationDirPath() + "/" + MOBase::ToQString(AppConfig::stylesheetsPath()) + "/" + styleName; - if (!QFile::exists(styleSheetName)) { - return false; + if (QFile::exists(styleSheetName)) { + m_StyleWatcher.addPath(styleSheetName); + updateStyle(styleSheetName); + } else { + updateStyle(styleName); } - m_StyleWatcher.addPath(styleSheetName); - updateStyle(styleSheetName); } else { setStyleSheet(""); } @@ -74,11 +78,18 @@ bool MOApplication::notify(QObject *receiver, QEvent *event) void MOApplication::updateStyle(const QString &fileName) { - QFile file(fileName); - if (file.open(QFile::ReadOnly)) { - setStyleSheet(file.readAll()); + if (fileName == "Plastique") { + setStyle(new QPlastiqueStyle); + setStyleSheet(""); + } else if (fileName == "Cleanlooks") { + setStyle(new QCleanlooksStyle); + setStyleSheet(""); } else { - qDebug("no stylesheet"); + setStyle(m_DefaultStyle); + if (QFile::exists(fileName)) { + setStyleSheet(QString("file:///%1").arg(fileName)); + } else { + qWarning("invalid stylesheet: %s", qPrintable(fileName)); + } } - file.close(); } diff --git a/src/moapplication.h b/src/moapplication.h index dd7f5eab..645b9144 100644 --- a/src/moapplication.h +++ b/src/moapplication.h @@ -43,6 +43,8 @@ private slots: private: QFileSystemWatcher m_StyleWatcher; + QString m_DefaultStyle; + }; diff --git a/src/modinfodialog.ui b/src/modinfodialog.ui index 2fdbe5f3..d0039a95 100644 --- a/src/modinfodialog.ui +++ b/src/modinfodialog.ui @@ -209,7 +209,7 @@ 0 0 - 668 + 676 126 @@ -223,16 +223,7 @@ 0 - - 0 - - - 0 - - - 0 - - + 0 @@ -293,7 +284,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e - + :/MO/gui/resources/go-up.png:/MO/gui/resources/go-up.png @@ -322,7 +313,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e - + :/MO/gui/resources/go-down.png:/MO/gui/resources/go-down.png @@ -525,9 +516,9 @@ Most mods do not have optional esps, so chances are good you are looking at an e - + - + Primary Category @@ -542,7 +533,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e - + :/MO/gui/resources/internet-web-browser.png:/MO/gui/resources/internet-web-browser.png @@ -634,7 +625,7 @@ p, li { white-space: pre-wrap; } - + :/MO/gui/refresh:/MO/gui/refresh @@ -660,7 +651,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> @@ -696,7 +687,7 @@ p, li { white-space: pre-wrap; } Endorse - + :/MO/gui/icon_favorite:/MO/gui/icon_favorite @@ -791,8 +782,6 @@ p, li { white-space: pre-wrap; } - - - + diff --git a/src/modlist.cpp b/src/modlist.cpp index eac02372..b35d6ad2 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -186,7 +186,12 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const return QVariant(); } } else if (column == COL_INSTALLTIME) { - return modInfo->creationTime(); + // display installation time for mods that can be updated + if (modInfo->canBeUpdated()) { + return modInfo->creationTime(); + } else { + return QVariant(); + } } else { return tr("invalid"); } diff --git a/src/modlist.h b/src/modlist.h index 8cab7f3e..cc5955d0 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -275,6 +275,10 @@ private: SignalModStateChanged m_ModStateChanged; + + // QAbstractItemModel interface + + // IModList interface }; #endif // MODLIST_H diff --git a/src/organizer.qbs b/src/organizer.qbs index fdfb914c..2b7f45fc 100644 --- a/src/organizer.qbs +++ b/src/organizer.qbs @@ -3,21 +3,41 @@ import qbs.base 1.0 Application { name: 'Organizer' - Depends { name: 'Qt.core' } - Depends { name: 'Qt.gui' } - Depends { name: 'Qt.network' } - Depends { name: 'Qt.declarative' } - Depends { name: 'UIBase' } + Depends { name: "Qt"; submodules: ["core", "gui", "network", "declarative"] } Depends { name: 'Shared' } + Depends { name: 'UIBase' } Depends { name: 'cpp' } - cpp.defines: [] - cpp.includePaths: [ '../shared', '../archive', '../uibase', qbs.getenv("BOOSTPATH") ] + cpp.defines: [ 'UNICODE', '_UNICODE' ] + cpp.libraryPaths: [ qbs.getenv('BOOSTPATH') + '/stage/lib' ] + cpp.includePaths: [ '../shared', '../archive', '../bsatk', '../esptk', '../uibase', qbs.getenv("BOOSTPATH") ] // '../bsatk', '../esptk', - files: [ - '*.cpp', - '*.h', - '*.ui' - ] + cpp.staticLibraries: [ 'shell32', 'user32', 'Version', 'shlwapi' ] + //LIBS += -lmo_shared -luibase -lshell32 -lole32 -luser32 -ladvapi32 -lgdi32 -lPsapi -lVersion -lbsatk -lshlwapi + + Group { + name: 'Headers' + files: [ '*.h' ] + } + + Group { + name: 'Sources' + files: [ '*.cpp' ] + } + + Group { + name: 'UI Files' + files: [ '*.ui' ] + } + + Group { + name: 'ESP Toolkit' + files: [ '../esptk/*.h', '../esptk/*.cpp' ] + } } + +// /nologo /c + + +// /Zi -GR -W3 diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index b0228849..8eeed76e 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -499,6 +499,17 @@ bool PluginList::saveLoadOrder(DirectoryEntry &directoryStructure) return true; } +int PluginList::enabledCount() const +{ + int enabled = 0; + foreach (auto info, m_ESPs) { + if (info.m_Enabled) { + ++enabled; + } + } + return enabled; +} + bool PluginList::isESPLocked(int index) const { return m_LockedOrder.find(m_ESPs.at(index).m_Name.toLower()) != m_LockedOrder.end(); @@ -713,6 +724,8 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const return QIcon(":/MO/gui/warning"); } else if (m_LockedOrder.find(m_ESPs[index].m_Name.toLower()) != m_LockedOrder.end()) { return QIcon(":/MO/gui/locked"); + } else if (m_ESPs[index].m_IsDummy && m_ESPs[index].m_Enabled) { + return QIcon(":/MO/gui/edit_clear"); } else { return QVariant(); } @@ -723,6 +736,8 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const if (m_ESPs[index].m_IsMaster) { result.setItalic(true); result.setWeight(QFont::Bold); + } else if (m_ESPs[index].m_IsDummy) { + result.setItalic(true); } return result; } else if (role == Qt::TextAlignmentRole) { @@ -744,6 +759,10 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const m_ESPs[index].m_MasterUnset.begin(), m_ESPs[index].m_MasterUnset.end(), std::inserter(enabledMasters, enabledMasters.end())); text += "
    " + tr("Enabled Masters") + ": " + SetJoin(enabledMasters, ", "); + if (m_ESPs[index].m_IsDummy) { + text += "
    This file is a dummy! It exists only so the bsa with the same name gets loaded. With MO you don't need this: " + "If you enable the archive with the same name in the \"Archive\" tab you can disable this plugin."; + } return text; } } else { @@ -1009,6 +1028,7 @@ PluginList::ESPInfo::ESPInfo(const QString &name, bool enabled, FILETIME time, c try { ESP::File file(ToWString(fullPath)); m_IsMaster = file.isMaster(); + m_IsDummy = file.isDummy(); std::set masters = file.masters(); for (auto iter = masters.begin(); iter != masters.end(); ++iter) { m_Masters.insert(QString(iter->c_str())); @@ -1016,5 +1036,6 @@ PluginList::ESPInfo::ESPInfo(const QString &name, bool enabled, FILETIME time, c } catch (const std::exception &e) { qCritical("failed to parse esp file %s: %s", qPrintable(fullPath), e.what()); m_IsMaster = false; + m_IsDummy = false; } } diff --git a/src/pluginlist.h b/src/pluginlist.h index 2af5a0df..2f1a3f5f 100644 --- a/src/pluginlist.h +++ b/src/pluginlist.h @@ -126,6 +126,12 @@ public: **/ bool saveLoadOrder(MOShared::DirectoryEntry &directoryStructure); + /** + * @return number of enabled plugins in the list + */ + int enabledCount() const; + + QString getName(int index) const { return m_ESPs.at(index).m_Name; } int getPriority(int index) const { return m_ESPs.at(index).m_Priority; } bool isESPLocked(int index) const; @@ -198,6 +204,7 @@ private: FILETIME m_Time; QString m_OriginName; bool m_IsMaster; + bool m_IsDummy; std::set m_Masters; mutable std::set m_MasterUnset; }; diff --git a/src/settings.cpp b/src/settings.cpp index 36a4f1f8..144049aa 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -422,6 +422,9 @@ void Settings::addLanguages(QComboBox *languageBox) void Settings::addStyles(QComboBox *styleBox) { styleBox->addItem("None", ""); + styleBox->addItem("Plastique", "Plastique"); + styleBox->addItem("Cleanlooks", "Cleanlooks"); + QDirIterator langIter(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::stylesheetsPath()), QStringList("*.qss"), QDir::Files); while (langIter.hasNext()) { langIter.next(); diff --git a/src/shared/shared.qbs b/src/shared/shared.qbs index 44b7539f..1fa471a0 100644 --- a/src/shared/shared.qbs +++ b/src/shared/shared.qbs @@ -1,16 +1,20 @@ import qbs.base 1.0 -Application { - name: 'Shared' +StaticLibrary { + name: { + print(qbs.getenv("BOOSTPATH") + "/stage/lib") + return 'Shared' + } Depends { name: 'cpp' } Depends { name: 'BSAToolkit' } cpp.defines: [] - cpp.libraryPaths: [ qbs.getenv("BOOSTPATH") ] - cpp.includePaths: [ 'bsatk', qbs.getenv("BOOSTPATH") ] + cpp.libraryPaths: [ qbs.getenv("BOOSTPATH") + "/stage/lib" ] + cpp.includePaths: [ '../bsatk', qbs.getenv("BOOSTPATH") ] files: [ '*.h', - '*.cpp' + '*.cpp', + '*.inc' ] } -- cgit v1.3.1