From 4656ba9447d9bd0ebe5540a54892ec41abda047b Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Sun, 17 Dec 2017 22:31:46 +0200 Subject: Increase mo_interface log to help diagnose problems --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 90c15ccd..17ef5eba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -587,7 +587,7 @@ int main(int argc, char *argv[]) // initialize dump collection only after "dataPath" since the crashes are stored under it prevUnhandledExceptionFilter = SetUnhandledExceptionFilter(MyUnhandledExceptionFilter); - LogBuffer::init(100, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log"); + LogBuffer::init(1000, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log"); QString splash = dataPath + "/splash.png"; if (!QFile::exists(dataPath + "/splash.png")) { -- cgit v1.3.1 From 90421277e7ed0044b499d81f06df95bf62111ce9 Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Mon, 18 Dec 2017 00:26:59 +0200 Subject: Ensure all mostlist writing is done through the DelayedFileWriter --- src/mainwindow.cpp | 8 ++++---- src/modlist.cpp | 4 ++-- src/organizercore.cpp | 10 +++++----- src/profile.cpp | 23 +++++++++++++++++++---- src/profile.h | 9 +++++++-- 5 files changed, 37 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 22e99e37..3782b034 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1958,7 +1958,7 @@ void MainWindow::modorder_changed() } } m_OrganizerCore.refreshBSAList(); - m_OrganizerCore.currentProfile()->modlistWriter().write(); + m_OrganizerCore.currentProfile()->writeModlist(); m_ArchiveListWriter.write(); m_OrganizerCore.directoryStructure()->getFileRegister()->sortOrigins(); @@ -2264,7 +2264,7 @@ void MainWindow::restoreBackup_clicked() void MainWindow::modlistChanged(const QModelIndex&, int) { - m_OrganizerCore.currentProfile()->modlistWriter().write(); + m_OrganizerCore.currentProfile()->writeModlist(); } void MainWindow::modlistSelectionChanged(const QModelIndex ¤t, const QModelIndex&) @@ -3307,7 +3307,7 @@ void MainWindow::fixMods_clicked(SaveGameInfo::MissingAssets const &missingAsset } } - m_OrganizerCore.currentProfile()->modlistWriter().write(); + m_OrganizerCore.currentProfile()->writeModlist(); m_OrganizerCore.refreshLists(); std::set espsToActivate = dialog.getESPsToActivate(); @@ -4678,7 +4678,7 @@ void MainWindow::on_restoreButton_clicked() void MainWindow::on_saveModsButton_clicked() { - m_OrganizerCore.currentProfile()->modlistWriter().writeImmediately(true); + m_OrganizerCore.currentProfile()->writeModlistNow(true); QDateTime now = QDateTime::currentDateTime(); if (createBackup(m_OrganizerCore.currentProfile()->getModlistFileName(), now)) { MessageDialog::showMessage(tr("Backup of modlist created"), this); diff --git a/src/modlist.cpp b/src/modlist.cpp index 3afa94b5..c028432c 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -940,12 +940,12 @@ void ModList::removeRowForce(int row, const QModelIndex &parent) m_Profile->setModEnabled(row, false); - m_Profile->modlistWriter().cancel(); + m_Profile->cancelModlistWrite(); beginRemoveRows(parent, row, row); ModInfo::removeMod(row); endRemoveRows(); m_Profile->refreshModStatus(); // removes the mod from the status list - m_Profile->modlistWriter().write(); // this ensures the modified list gets written back before new mods can be installed + m_Profile->writeModlist(); // this ensures the modified list gets written back before new mods can be installed if (wasEnabled) { emit removeOrigin(modInfo->name()); diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 98920479..3be9559a 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -1181,7 +1181,7 @@ HANDLE OrganizerCore::spawnBinaryProcess(const QFileInfo &binary, // need to make sure all data is saved before we start the application if (m_CurrentProfile != nullptr) { - m_CurrentProfile->modlistWriter().writeImmediately(true); + m_CurrentProfile->writeModlistNow(true); } // TODO: should also pass arguments @@ -1438,7 +1438,7 @@ void OrganizerCore::refreshModList(bool saveChanges) { // don't lose changes! if (saveChanges) { - m_CurrentProfile->modlistWriter().writeImmediately(true); + m_CurrentProfile->writeModlistNow(true); } ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign(), managedGame()); @@ -1460,7 +1460,7 @@ void OrganizerCore::refreshESPList() }); return; } - m_CurrentProfile->modlistWriter().write(); + m_CurrentProfile->writeModlist(); // clear list try { @@ -1670,7 +1670,7 @@ std::vector OrganizerCore::enabledArchives() void OrganizerCore::refreshDirectoryStructure() { if (!m_DirectoryUpdate) { - m_CurrentProfile->modlistWriter().writeImmediately(true); + m_CurrentProfile->writeModlistNow(true); m_DirectoryUpdate = true; std::vector> activeModList @@ -1925,7 +1925,7 @@ void OrganizerCore::prepareStart() if (m_CurrentProfile == nullptr) { return; } - m_CurrentProfile->modlistWriter().write(); + m_CurrentProfile->writeModlist(); m_CurrentProfile->createTweakedIniFile(); saveCurrentLists(); m_Settings.setupLoadMechanism(); diff --git a/src/profile.cpp b/src/profile.cpp index 6382a15c..3383ffee 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -66,7 +66,7 @@ void Profile::touchFile(QString fileName) } Profile::Profile(const QString &name, IPluginGame const *gamePlugin, bool useDefaultSettings) - : m_ModListWriter(std::bind(&Profile::writeModlistNow, this)) + : m_ModListWriter(std::bind(&Profile::doWriteModlist, this)) , m_GamePlugin(gamePlugin) { QString profilesDir = Settings::instance().getProfileDirectory(); @@ -111,7 +111,7 @@ Profile::Profile(const QString &name, IPluginGame const *gamePlugin, bool useDef Profile::Profile(const QDir &directory, IPluginGame const *gamePlugin) : m_Directory(directory) , m_GamePlugin(gamePlugin) - , m_ModListWriter(std::bind(&Profile::writeModlistNow, this)) + , m_ModListWriter(std::bind(&Profile::doWriteModlist, this)) { assert(gamePlugin != nullptr); @@ -133,7 +133,7 @@ Profile::Profile(const QDir &directory, IPluginGame const *gamePlugin) Profile::Profile(const Profile &reference) : m_Directory(reference.m_Directory) - , m_ModListWriter(std::bind(&Profile::writeModlistNow, this)) + , m_ModListWriter(std::bind(&Profile::doWriteModlist, this)) , m_GamePlugin(reference.m_GamePlugin) { @@ -154,7 +154,22 @@ bool Profile::exists() const return m_Directory.exists(); } -void Profile::writeModlistNow() +void Profile::writeModlist() +{ + m_ModListWriter.write(); +} + +void Profile::writeModlistNow(bool onlyIfPending) +{ + m_ModListWriter.writeImmediately(onlyIfPending); +} + +void Profile::cancelModlistWrite() +{ + m_ModListWriter.cancel(); +} + +void Profile::doWriteModlist() { if (!m_Directory.exists()) return; diff --git a/src/profile.h b/src/profile.h index 996e561f..edbbffe7 100644 --- a/src/profile.h +++ b/src/profile.h @@ -89,7 +89,11 @@ public: **/ static Profile *createPtrFrom(const QString &name, const Profile &reference, MOBase::IPluginGame const *gamePlugin); - MOBase::DelayedFileWriter &modlistWriter() { return m_ModListWriter; } + void writeModlist(); + + void writeModlistNow(bool onlyIfPending=false); + + void cancelModlistWrite(); /** * @brief test if this profile uses archive invalidation @@ -297,7 +301,8 @@ signals: public slots: - void writeModlistNow(); + // should only be called by DelayedFileWriter, use writeModlist() and writeModlistNow() instead + void doWriteModlist(); private: -- cgit v1.3.1 From ff31ce636b68a19949d6e4049d20f7cf88e29f99 Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Sun, 17 Dec 2017 21:05:18 +0200 Subject: Fix mod rename with custom profiles path --- src/mainwindow.cpp | 64 +-------------------------------------------- src/mainwindow.h | 2 -- src/modlist.cpp | 10 +++---- src/profile.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/profile.h | 5 ++++ 5 files changed, 87 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 3782b034..6f156269 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2019,71 +2019,9 @@ void MainWindow::installMod_clicked() installMod(); } -void MainWindow::renameModInList(QFile &modList, const QString &oldName, const QString &newName) -{ - //TODO this code needs to be merged with ModList::readFrom - if (!modList.open(QIODevice::ReadWrite)) { - reportError(tr("failed to open %1").arg(modList.fileName())); - return; - } - - QBuffer outBuffer; - outBuffer.open(QIODevice::WriteOnly); - - while (!modList.atEnd()) { - QByteArray line = modList.readLine(); - - if (line.length() == 0) { - // ignore empty lines - qWarning("mod list contained invalid data: empty line"); - continue; - } - - char spec = line.at(0); - if (spec == '#') { - // don't touch comments - outBuffer.write(line); - continue; - } - - QString modName = QString::fromUtf8(line).mid(1).trimmed(); - - if (modName.isEmpty()) { - // file broken? - qWarning("mod list contained invalid data: missing mod name"); - continue; - } - - outBuffer.write(QByteArray(1, spec)); - if (modName == oldName) { - modName = newName; - } - outBuffer.write(modName.toUtf8().constData()); - outBuffer.write("\r\n"); - } - - modList.resize(0); - modList.write(outBuffer.buffer()); - modList.close(); -} - - void MainWindow::modRenamed(const QString &oldName, const QString &newName) { - // fix the profiles directly on disc - for (int i = 0; i < ui->profileBox->count(); ++i) { - QString profileName = ui->profileBox->itemText(i); - - //TODO this functionality should be in the Profile class - QString modlistName = QString("%1/%2/modlist.txt") - .arg(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath())) - .arg(profileName); - - QFile modList(modlistName); - if (modList.exists()) { - renameModInList(modList, oldName, newName); - } - } + Profile::renameModInAllProfiles(oldName, newName); // immediately refresh the active profile because the data in memory is invalid m_OrganizerCore.currentProfile()->refreshModStatus(); diff --git a/src/mainwindow.h b/src/mainwindow.h index 45a41137..a4ded688 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -220,8 +220,6 @@ private: void writeDataToFile(QFile &file, const QString &directory, const MOShared::DirectoryEntry &directoryEntry); - void renameModInList(QFile &modList, const QString &oldName, const QString &newName); - void refreshFilters(); /** diff --git a/src/modlist.cpp b/src/modlist.cpp index c028432c..046e2280 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -424,13 +424,13 @@ bool ModList::renameMod(int index, const QString &newName) return false; } - // before we rename, write back the current profile so we don't lose changes and to ensure - // there is no scheduled asynchronous rewrite anytime soon - m_Profile->writeModlistNow(); - ModInfo::Ptr modInfo = ModInfo::getByIndex(index); QString oldName = modInfo->name(); - if (modInfo->setName(nameFixed)) { + if (newName != oldName && modInfo->setName(nameFixed)) { + // before we rename, write back the current profile so we don't lose changes and to ensure + // there is no scheduled asynchronous rewrite anytime soon + m_Profile->writeModlistNow(); + // this just disabled the mod in all profiles. The recipient of modRenamed must fix that emit modRenamed(oldName, nameFixed); } diff --git a/src/profile.cpp b/src/profile.cpp index 3383ffee..00509ef7 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -39,6 +39,8 @@ along with Mod Organizer. If not, see . #include // for QStringList #include // for qDebug, qWarning, etc #include // for qPrintable +#include +#include #include @@ -242,9 +244,83 @@ void Profile::createTweakedIniFile() qDebug("%s saved", qPrintable(QDir::toNativeSeparators(tweakedIni))); } +// static +void Profile::renameModInAllProfiles(const QString& oldName, const QString& newName) +{ + QDir profilesDir(Settings::instance().getProfileDirectory()); + profilesDir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot); + QDirIterator profileIter(profilesDir); + while (profileIter.hasNext()) { + profileIter.next(); + QFile modList(profileIter.filePath() + "/modlist.txt"); + if (modList.exists()) + renameModInList(modList, oldName, newName); + else + qWarning("Profile has no modlist.txt : %s", qPrintable(profileIter.filePath())); + } +} + +// static +void Profile::renameModInList(QFile &modList, const QString &oldName, const QString &newName) +{ + if (!modList.open(QIODevice::ReadOnly)) { + reportError(tr("failed to open %1").arg(modList.fileName())); + return; + } + + QBuffer outBuffer; + outBuffer.open(QIODevice::WriteOnly); + + int renamed = 0; + while (!modList.atEnd()) { + QByteArray line = modList.readLine(); + + if (line.length() == 0) { + // ignore empty lines + qWarning("mod list contained invalid data: empty line"); + continue; + } + + char spec = line.at(0); + if (spec == '#') { + // don't touch comments + outBuffer.write(line); + continue; + } + + QString modName = QString::fromUtf8(line).mid(1).trimmed(); + + if (modName.isEmpty()) { + // file broken? + qWarning("mod list contained invalid data: missing mod name"); + continue; + } + + outBuffer.write(QByteArray(1, spec)); + if (modName == oldName) { + modName = newName; + ++renamed; + } + outBuffer.write(modName.toUtf8().constData()); + outBuffer.write("\r\n"); + } + modList.close(); + + if (renamed) { + modList.open(QIODevice::WriteOnly); + modList.write(outBuffer.buffer()); + modList.close(); + } + + if (renamed) + qDebug("Renamed %d \"%s\" mod to \"%s\" in %s", + renamed, qPrintable(oldName), qPrintable(newName), qPrintable(modList.fileName())); +} void Profile::refreshModStatus() { + writeModlistNow(true); // if there are pending changes write them first + QFile file(getModlistFileName()); if (!file.open(QIODevice::ReadOnly)) { throw MyException(tr("\"%1\" is missing or inaccessible").arg(getModlistFileName())); diff --git a/src/profile.h b/src/profile.h index edbbffe7..3e620b3c 100644 --- a/src/profile.h +++ b/src/profile.h @@ -89,6 +89,9 @@ public: **/ static Profile *createPtrFrom(const QString &name, const Profile &reference, MOBase::IPluginGame const *gamePlugin); + + static void renameModInAllProfiles(const QString& oldName, const QString& newName); + void writeModlist(); void writeModlistNow(bool onlyIfPending=false); @@ -331,6 +334,8 @@ private: void touchFile(QString fileName); void finishChangeStatus() const; + static void renameModInList(QFile &modList, const QString &oldName, const QString &newName); + private: QDir m_Directory; -- cgit v1.3.1 From 302a9b744d1f8edbae5cad910b0153f3c717bd2b Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Mon, 18 Dec 2017 01:47:03 +0200 Subject: Ensure clearing currentInstance reg key when selecting portable install --- src/instancemanager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp index 1b0d0e5b..b1b85cc6 100644 --- a/src/instancemanager.cpp +++ b/src/instancemanager.cpp @@ -189,6 +189,7 @@ QString InstanceManager::determineDataPath() if (instanceId.isEmpty() || !QFileInfo::exists(dataPath)) { instanceId = chooseInstance(instances()); + setCurrentInstance(instanceId); if (!instanceId.isEmpty()) { dataPath = QDir::fromNativeSeparators( QStandardPaths::writableLocation(QStandardPaths::DataLocation) @@ -199,8 +200,6 @@ QString InstanceManager::determineDataPath() if (instanceId.isEmpty()) { return qApp->applicationDirPath(); } else { - setCurrentInstance(instanceId); - createDataPath(dataPath); return dataPath; -- cgit v1.3.1 From 7dad8bcb282ac385267087961b29af608f81593d Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Mon, 18 Dec 2017 02:09:21 +0200 Subject: avoid splash screen when running a shortcut --- src/main.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 17ef5eba..4cf47a3c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -367,8 +367,6 @@ int runApplication(MOApplication &application, SingleInstance &instance, const QString &splashPath) { qDebug("start main application"); - QPixmap pixmap(splashPath); - QSplashScreen splash(pixmap); QString dataPath = application.property("dataPath").toString(); qDebug("data path: %s", qPrintable(dataPath)); @@ -382,13 +380,7 @@ int runApplication(MOApplication &application, SingleInstance &instance, try { qDebug("Working directory: %s", qPrintable(QDir::toNativeSeparators(QDir::currentPath()))); - splash.show(); - } catch (const std::exception &e) { - reportError(e.what()); - return 1; - } - try { QSettings settings(dataPath + "/" + QString::fromStdWString(AppConfig::iniFileName()), QSettings::IniFormat); @@ -488,6 +480,10 @@ int runApplication(MOApplication &application, SingleInstance &instance, } } + QPixmap pixmap(splashPath); + QSplashScreen splash(pixmap); + splash.show(); + NexusInterface::instance()->getAccessManager()->startLoginCheck(); qDebug("initializing tutorials"); -- cgit v1.3.1 From cb1c9f5e83e98039d38f548c80d4b95442163cf2 Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Tue, 19 Dec 2017 00:44:18 +0200 Subject: Tie moshortcuts to a specific instance --- src/CMakeLists.txt | 2 ++ src/executableslist.cpp | 2 +- src/instancemanager.cpp | 17 ++++++++++++++--- src/instancemanager.h | 8 ++++++-- src/main.cpp | 16 +++++++++++----- src/mainwindow.cpp | 3 ++- src/moshortcut.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/moshortcut.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/organizercore.cpp | 15 +++++++++++---- src/organizercore.h | 6 ++---- 10 files changed, 134 insertions(+), 20 deletions(-) create mode 100644 src/moshortcut.cpp create mode 100644 src/moshortcut.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 914bdd12..0c70fe57 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -88,6 +88,7 @@ SET(organizer_SRCS instancemanager.cpp usvfsconnector.cpp eventfilter.cpp + moshortcut.cpp shared/windows_error.cpp shared/error_report.cpp @@ -179,6 +180,7 @@ SET(organizer_HDRS usvfsconnector.h eventfilter.h descriptionpage.h + moshortcut.h shared/windows_error.h shared/error_report.h diff --git a/src/executableslist.cpp b/src/executableslist.cpp index b1890ac9..21cb6ed4 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -86,7 +86,7 @@ Executable &ExecutablesList::find(const QString &title) return exe; } } - throw std::runtime_error(QString("invalid name %1").arg(title).toLocal8Bit().constData()); + throw std::runtime_error(QString("invalid executable name %1").arg(title).toLocal8Bit().constData()); } diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp index b1b85cc6..34e23d7b 100644 --- a/src/instancemanager.cpp +++ b/src/instancemanager.cpp @@ -47,9 +47,19 @@ InstanceManager &InstanceManager::instance() return s_Instance; } +void InstanceManager::overrideInstance(const QString& instanceName) +{ + m_overrideInstanceName = instanceName; + m_overrideInstance = true; +} + + QString InstanceManager::currentInstance() const { - return m_AppSettings.value(INSTANCE_KEY, "").toString(); + if (m_overrideInstance) + return m_overrideInstanceName; + else + return m_AppSettings.value(INSTANCE_KEY, "").toString(); } void InstanceManager::clearCurrentInstance() @@ -177,7 +187,8 @@ void InstanceManager::createDataPath(const QString &dataPath) const QString InstanceManager::determineDataPath() { QString instanceId = currentInstance(); - if (instanceId.isEmpty() && portableInstall() && !m_Reset) { + if (instanceId.isEmpty() && !m_Reset && (m_overrideInstance || portableInstall())) + { // startup, apparently using portable mode before return qApp->applicationDirPath(); } @@ -187,7 +198,7 @@ QString InstanceManager::determineDataPath() + "/" + instanceId); - if (instanceId.isEmpty() || !QFileInfo::exists(dataPath)) { + if (!m_overrideInstance && (instanceId.isEmpty() || !QFileInfo::exists(dataPath))) { instanceId = chooseInstance(instances()); setCurrentInstance(instanceId); if (!instanceId.isEmpty()) { diff --git a/src/instancemanager.h b/src/instancemanager.h index a0a5df09..2782c71d 100644 --- a/src/instancemanager.h +++ b/src/instancemanager.h @@ -34,11 +34,14 @@ public: QString determineDataPath(); void clearCurrentInstance(); + void overrideInstance(const QString& instanceName); + + QString currentInstance() const; + private: InstanceManager(); - QString currentInstance() const; QString instancePath() const; QStringList instances() const; @@ -55,5 +58,6 @@ private: QSettings m_AppSettings; bool m_Reset {false}; - + bool m_overrideInstance{false}; + QString m_overrideInstanceName; }; diff --git a/src/main.cpp b/src/main.cpp index 4cf47a3c..3d315f1d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -45,6 +45,7 @@ along with Mod Organizer. If not, see . #include "tutorialmanager.h" #include "nxmaccessmanager.h" #include "instancemanager.h" +#include "moshortcut.h" #include #include @@ -450,9 +451,9 @@ int runApplication(MOApplication &application, SingleInstance &instance, // if we have a command line parameter, it is either a nxm link or // a binary to start if (arguments.size() > 1) { - if (OrganizerCore::isMoShortcut(arguments.at(1))) { + if (MOShortcut shortcut{ arguments.at(1) }) { try { - organizer.runShortcut(OrganizerCore::moShortcutName(arguments.at(1))); + organizer.runShortcut(shortcut); return 0; } catch (const std::exception &e) { reportError( @@ -552,10 +553,12 @@ int main(int argc, char *argv[]) forcePrimary = true; } + MOShortcut moshortcut{ arguments.size() > 1 ? arguments.at(1) : "" }; + SingleInstance instance(forcePrimary); if (!instance.primaryInstance()) { - if ((arguments.size() == 2) - && (OrganizerCore::isMoShortcut(arguments.at(1)) || OrganizerCore::isNxmLink(arguments.at(1)))) + if (moshortcut || + arguments.size() > 1 && OrganizerCore::isNxmLink(arguments.at(1))) { qDebug("not primary instance, sending shortcut/download message"); instance.sendMessage(arguments.at(1)); @@ -572,7 +575,10 @@ int main(int argc, char *argv[]) QString dataPath; try { - dataPath = InstanceManager::instance().determineDataPath(); + InstanceManager& instanceManager = InstanceManager::instance(); + if (moshortcut && moshortcut.hasInstance()) + instanceManager.overrideInstance(moshortcut.instance()); + dataPath = instanceManager.determineDataPath(); } catch (const std::exception &e) { if (strcmp(e.what(),"Canceled")) QMessageBox::critical(nullptr, QObject::tr("Failed to set up instance"), e.what()); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6f156269..1c5e321d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3331,7 +3331,8 @@ void MainWindow::addWindowsLink(const ShortcutType mapping) QString executable = QDir::toNativeSeparators(selectedExecutable.m_BinaryInfo.absoluteFilePath()); std::wstring targetFile = ToWString(exeInfo.absoluteFilePath()); - std::wstring parameter = ToWString(QString("\"moshortcut://%1\"").arg(selectedExecutable.m_Title)); + std::wstring parameter = ToWString( + QString("\"moshortcut://%1:%2\"").arg(InstanceManager::instance().currentInstance(),selectedExecutable.m_Title)); std::wstring description = ToWString(QString("Run %1 with ModOrganizer").arg(selectedExecutable.m_Title)); std::wstring iconFile = ToWString(executable); std::wstring currentDirectory = ToWString(QDir::toNativeSeparators(qApp->applicationDirPath())); diff --git a/src/moshortcut.cpp b/src/moshortcut.cpp new file mode 100644 index 00000000..c8c2ef6f --- /dev/null +++ b/src/moshortcut.cpp @@ -0,0 +1,39 @@ +/* +Copyright (C) 2016 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see . +*/ + + +#include "moshortcut.h" + + +MOShortcut::MOShortcut(const QString& link) + : m_valid(link.startsWith("moshortcut://")) + , m_hasInstance(false) +{ + if (m_valid) { + int start = (int)strlen("moshortcut://"); + int sep = link.indexOf(':', start); + if (sep >= 0) { + m_hasInstance = true; + m_instance = link.mid(start, sep - start); + m_executable = link.mid(sep + 1); + } + else + m_executable = link.mid(start); + } +} diff --git a/src/moshortcut.h b/src/moshortcut.h new file mode 100644 index 00000000..7b7574b9 --- /dev/null +++ b/src/moshortcut.h @@ -0,0 +1,46 @@ +/* +Copyright (C) 2016 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see . +*/ + + +#pragma once + + +#include + + +class MOShortcut { + +public: + MOShortcut(const QString& link); + + /// true iff intialized using a valid moshortcut link + operator bool() const { return m_valid; } + + bool hasInstance() const { return m_hasInstance; } + + const QString& instance() const { return m_instance; } + + const QString& executable() const { return m_executable; } + +private: + QString m_instance; + QString m_executable; + bool m_valid; + bool m_hasInstance; +}; diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 3be9559a..7668485c 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -32,6 +32,7 @@ #include #include #include "lockeddialog.h" +#include "instancemanager.h" #include #include @@ -578,8 +579,8 @@ void OrganizerCore::downloadRequestedNXM(const QString &url) void OrganizerCore::externalMessage(const QString &message) { - if (isMoShortcut(message)) { - runShortcut(moShortcutName(message)); + if (MOShortcut moshortcut{ message }) { + runShortcut(moshortcut); } else if (isNxmLink(message)) { MessageDialog::showMessage(tr("Download started"), qApp->activeWindow()); @@ -1228,9 +1229,15 @@ HANDLE OrganizerCore::spawnBinaryProcess(const QFileInfo &binary, } } -HANDLE OrganizerCore::runShortcut(const QString &title) +HANDLE OrganizerCore::runShortcut(const MOShortcut& shortcut) { - Executable& exe = m_ExecutablesList.find(title); + if (shortcut.hasInstance() && shortcut.instance() != InstanceManager::instance().currentInstance()) + throw std::runtime_error( + QString("Refusing to run executable from different instance %1:%2") + .arg(shortcut.instance(),shortcut.executable()) + .toLocal8Bit().constData()); + + Executable& exe = m_ExecutablesList.find(shortcut.executable()); return spawnBinaryDirect( exe.m_BinaryInfo, exe.m_Arguments, diff --git a/src/organizercore.h b/src/organizercore.h index decb3d01..f98e9d0a 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -13,6 +13,7 @@ #include "downloadmanager.h" #include "executableslist.h" #include "usvfsconnector.h" +#include "moshortcut.h" #include #include #include @@ -86,9 +87,6 @@ private: public: static bool isNxmLink(const QString &link) { return link.startsWith("nxm://", Qt::CaseInsensitive); } - static bool isMoShortcut(const QString &link) { return link.startsWith("moshortcut://", Qt::CaseInsensitive); } - static QString moShortcutName(const QString &link) { return link.mid(strlen("moshortcut://")); } - OrganizerCore(const QSettings &initSettings); @@ -203,7 +201,7 @@ public: DownloadManager *downloadManager(); PluginList *pluginList(); ModList *modList(); - HANDLE runShortcut(const QString &title); + HANDLE runShortcut(const MOShortcut& shortcut); HANDLE startApplication(const QString &executable, const QStringList &args, const QString &cwd, const QString &profile); bool waitForApplication(HANDLE processHandle, LPDWORD exitCode = nullptr); HANDLE findAndOpenAUSVFSProcess(); -- cgit v1.3.1 From 80fc71327397ba5b85fb9739d299d2e4ec542828 Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Sat, 16 Dec 2017 12:41:57 +0200 Subject: fix usvfs includes (following usvfs VS project) --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0c70fe57..5e58a313 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -284,7 +284,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/bsatk/src ${project_path}/esptk/src ${project_path}/archive/src - ${project_path}/../usvfs/usvfs + ${project_path}/../usvfs/include ${project_path}/game_gamebryo/src ${project_path}/game_features/src ${project_path}/githubpp/src) -- cgit v1.3.1 From 5c192fb8c577a4ec25c93bdcab80292fc4bfe0fb Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Tue, 19 Dec 2017 15:20:28 +0200 Subject: Use Qt deploy also for Qt plugins (cherry picking only the ones we need) --- src/CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5e58a313..db86392d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -344,7 +344,7 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dlls.manifest.qt5 RENAME dlls.manifest) # use windeployqt.exe to install all required libraries -SET(windeploy_parameters --no-translations --no-plugins --libdir dlls --release-with-debug-info --no-compiler-runtime) +SET(windeploy_parameters "--no-translations --plugindir qtplugins --libdir dlls --release-with-debug-info --no-compiler-runtime") INSTALL( CODE "EXECUTE_PROCESS( @@ -353,7 +353,10 @@ INSTALL( COMMAND ${qt5bin}/windeployqt.exe uibase.dll ${windeploy_parameters} WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin - )" + ) + file(RENAME ${CMAKE_INSTALL_PREFIX}/bin/qtplugins/platforms ${CMAKE_INSTALL_PREFIX}/bin/platforms) + file(RENAME ${CMAKE_INSTALL_PREFIX}/bin/qtplugins/imageformats ${CMAKE_INSTALL_PREFIX}/bin/dlls/imageformats) + file(REMOVE_RECURSE ${CMAKE_INSTALL_PREFIX}/bin/qtplugins)" ) INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/stylesheets -- cgit v1.3.1 From 0c75ff1836804dc312824009e68c8eb97dc32ea1 Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Wed, 20 Dec 2017 02:00:56 +0200 Subject: Fix modorganizer staging --- src/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index db86392d..f0ad2fe1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -337,7 +337,7 @@ FIND_PROGRAM(WINDEPLOYQT_COMMAND windeployqt PATHS ${qt5bin} NO_DEFAULT_PATH) INSTALL(TARGETS ModOrganizer RUNTIME DESTINATION bin) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/ModOrganizer.pdb +INSTALL(FILES $ DESTINATION pdb) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dlls.manifest.qt5 DESTINATION bin/dlls @@ -354,6 +354,8 @@ INSTALL( ${qt5bin}/windeployqt.exe uibase.dll ${windeploy_parameters} WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin ) + file(REMOVE_RECURSE ${CMAKE_INSTALL_PREFIX}/bin/platforms) + file(REMOVE_RECURSE ${CMAKE_INSTALL_PREFIX}/bin/dlls/imageformats) file(RENAME ${CMAKE_INSTALL_PREFIX}/bin/qtplugins/platforms ${CMAKE_INSTALL_PREFIX}/bin/platforms) file(RENAME ${CMAKE_INSTALL_PREFIX}/bin/qtplugins/imageformats ${CMAKE_INSTALL_PREFIX}/bin/dlls/imageformats) file(REMOVE_RECURSE ${CMAKE_INSTALL_PREFIX}/bin/qtplugins)" -- cgit v1.3.1 From a24a1cbf257f49fa31263e2f6115c378714a64d3 Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Wed, 20 Dec 2017 02:14:14 +0200 Subject: Hide boost compiler version warnings --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0ad2fe1..7a339180 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -301,7 +301,7 @@ EXECUTE_PROCESS( OUTPUT_STRIP_TRAILING_WHITESPACE ) -ADD_DEFINITIONS(-D_UNICODE -DUNICODE -DNOMINMAX -D_CRT_SECURE_NO_WARNINGS -DGITID="${GIT_COMMIT_HASH}") +ADD_DEFINITIONS(-D_UNICODE -DUNICODE -DNOMINMAX -D_CRT_SECURE_NO_WARNINGS -DBOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE -DGITID="${GIT_COMMIT_HASH}") IF("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") SET(usvfs_name usvfs_x64) -- cgit v1.3.1