From 7ab98cb451153c541245641b984e7904bc9c575d Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Sun, 10 Dec 2017 21:34:19 +0200 Subject: move crash dumps to their own folder --- src/organizercore.cpp | 2 +- src/settingsdialog.ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 91330d3a..30f96caf 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -670,7 +670,7 @@ std::wstring OrganizerCore::crashDumpsPath() { wchar_t appDataLocal[MAX_PATH]{ 0 }; ::SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, appDataLocal); std::wstring dumpPath{ appDataLocal }; - dumpPath += L"\\modorganizer"; + dumpPath += L"\\modorganizer\\crashDumps"; return dumpPath; } diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui index 632dc6c9..6d462cfa 100644 --- a/src/settingsdialog.ui +++ b/src/settingsdialog.ui @@ -486,7 +486,7 @@ If you use pre-releases, never contact me directly by e-mail or via private mess - Dumps are stored in <a href="%LOCALAPPDATA%\modorganizer">%LOCALAPPDATA%\modorganizer</a>. + Dumps are stored in <a href="%LOCALAPPDATA%\modorganizer\crashDumps">%LOCALAPPDATA%\modorganizer\crashDumps</a>. Sending such dumps to the developers can help solve crashes caused by MO. It is recommended to compress the dumps before sending, especially on the larger settings. -- cgit v1.3.1 From db973f7422258399726f8e5223079b6919535fd5 Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Sun, 10 Dec 2017 23:32:29 +0200 Subject: Allow copying an executable without changing details --- src/editexecutablesdialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index f76323e8..89605016 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -228,7 +228,8 @@ bool EditExecutablesDialog::executableChanged() QString storedCustomOverwrite = m_Profile->setting("custom_overwrites", selectedExecutable.m_Title).toString(); - return selectedExecutable.m_Arguments != ui->argumentsEdit->text() + return selectedExecutable.m_Title != ui->titleEdit->text() + || selectedExecutable.m_Arguments != ui->argumentsEdit->text() || selectedExecutable.m_SteamAppID != ui->appIDOverwriteEdit->text() || !storedCustomOverwrite.isEmpty() != ui->newFilesModCheckBox->isChecked() || !storedCustomOverwrite.isEmpty() && (storedCustomOverwrite != ui->newFilesModBox->currentText()) -- cgit v1.3.1 From d43f35f56bc2d9164b6fe9aa5591eef287bebe07 Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Sun, 10 Dec 2017 23:33:01 +0200 Subject: Run shortcuts using moshortcut:// to avoid command line problems --- src/main.cpp | 21 ++++++++++- src/mainwindow.cpp | 7 ++-- src/organizercore.cpp | 96 +++++++++++++++++++++++++++++---------------------- src/organizercore.h | 10 +++++- 4 files changed, 87 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 40224170..9b2afecc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -126,6 +126,16 @@ bool isNxmLink(const QString &link) return link.startsWith("nxm://", Qt::CaseInsensitive); } +bool isMoShortcut(const QString &link) +{ + return link.startsWith("moshortcut://", Qt::CaseInsensitive); +} + +QString moShortcutName(const QString &link) +{ + return link.mid(strlen("moshortcut://")); +} + static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs) { if ((exceptionPtrs->ExceptionRecord->ExceptionCode < 0x80000000) // non-critical @@ -467,7 +477,16 @@ 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 (isNxmLink(arguments.at(1))) { + if (isMoShortcut(arguments.at(1))) { + try { + organizer.runShortcut(moShortcutName(arguments.at(1))); + return 0; + } catch (const std::exception &e) { + reportError( + QObject::tr("failed to start shortcut: %1").arg(e.what())); + return 1; + } + } else if (isNxmLink(arguments.at(1))) { qDebug("starting download from command line: %s", qPrintable(arguments.at(1))); organizer.externalMessage(arguments.at(1)); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 1db895fc..632b64e9 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3199,11 +3199,10 @@ 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("\"%1\" %2").arg(executable) - .arg(selectedExecutable.m_Arguments)); - std::wstring description = ToWString(selectedExecutable.m_BinaryInfo.fileName()); + std::wstring parameter = ToWString(QString("\"moshortcut://%1\"").arg(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(exeInfo.absolutePath())); + std::wstring currentDirectory = ToWString(QDir::toNativeSeparators(qApp->applicationDirPath())); if (CreateShortcut(targetFile.c_str() , parameter.c_str() diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 30f96caf..116552df 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -1068,19 +1068,9 @@ QStringList OrganizerCore::modsSortedByProfilePriority() const void OrganizerCore::spawnBinary(const QFileInfo &binary, const QString &arguments, const QDir ¤tDirectory, const QString &steamAppID, const QString &customOverwrite) { - ILockedWaitingForProcess* uilock = nullptr; - if (m_UserInterface != nullptr) { - uilock = m_UserInterface->lock(); - } - ON_BLOCK_EXIT([&] () { - if (m_UserInterface != nullptr) { m_UserInterface->unlock(); } - }); - - HANDLE processHandle = spawnBinaryDirect(binary, arguments, m_CurrentProfile->name(), currentDirectory, steamAppID, customOverwrite); + DWORD processExitCode = 0; + HANDLE processHandle = spawnBinaryDirect(binary, arguments, m_CurrentProfile->name(), currentDirectory, steamAppID, customOverwrite, &processExitCode); if (processHandle != INVALID_HANDLE_VALUE) { - DWORD processExitCode; - (void)waitForProcessCompletion(processHandle, &processExitCode, uilock); - refreshDirectoryStructure(); // need to remove our stored load order because it may be outdated if a foreign tool changed the // file time. After removing that file, refreshESPList will use the file time as the order @@ -1092,7 +1082,6 @@ void OrganizerCore::spawnBinary(const QFileInfo &binary, const QString &argument refreshESPList(); savePluginList(); - cycleDiagnostics(); //These callbacks should not fiddle with directoy structure and ESPs. m_FinishedRun(binary.absoluteFilePath(), processExitCode); @@ -1104,7 +1093,45 @@ HANDLE OrganizerCore::spawnBinaryDirect(const QFileInfo &binary, const QString &profileName, const QDir ¤tDirectory, const QString &steamAppID, - const QString &customOverwrite) + const QString &customOverwrite, + LPDWORD exitCode) +{ + HANDLE processHandle = spawnBinaryProcess(binary, arguments, profileName, currentDirectory, steamAppID, customOverwrite); + if (processHandle != INVALID_HANDLE_VALUE) { + std::unique_ptr dlg; + ILockedWaitingForProcess* uilock = nullptr; + + if (m_UserInterface != nullptr) { + uilock = m_UserInterface->lock(); + } + else { + // i.e. when running command line shortcuts there is no m_UserInterface + dlg.reset(new LockedDialog); + dlg->show(); + dlg->setEnabled(true); + uilock = dlg.get(); + } + + ON_BLOCK_EXIT([&]() { + if (m_UserInterface != nullptr) { + m_UserInterface->unlock(); + } }); + + DWORD ignoreExitCode; + waitForProcessCompletion(processHandle, exitCode ? exitCode : &ignoreExitCode, uilock); + cycleDiagnostics(); + } + + return processHandle; +} + + +HANDLE OrganizerCore::spawnBinaryProcess(const QFileInfo &binary, + const QString &arguments, + const QString &profileName, + const QDir ¤tDirectory, + const QString &steamAppID, + const QString &customOverwrite) { prepareStart(); @@ -1199,6 +1226,19 @@ HANDLE OrganizerCore::spawnBinaryDirect(const QFileInfo &binary, } } +HANDLE OrganizerCore::runShortcut(const QString &title) +{ + Executable& exe = m_ExecutablesList.find(title); + + return spawnBinaryDirect( + exe.m_BinaryInfo, exe.m_Arguments, + m_CurrentProfile->name(), + exe.m_WorkingDirectory.length() != 0 + ? exe.m_WorkingDirectory + : exe.m_BinaryInfo.absolutePath(), + exe.m_SteamAppID, ""); +} + HANDLE OrganizerCore::startApplication(const QString &executable, const QStringList &args, const QString &cwd, @@ -1260,33 +1300,7 @@ HANDLE OrganizerCore::startApplication(const QString &executable, } } - HANDLE processHandle = spawnBinaryDirect(binary, arguments, profileName, currentDirectory, steamAppID, customOverwrite); - if (processHandle != INVALID_HANDLE_VALUE) { - std::unique_ptr dlg; - ILockedWaitingForProcess* uilock = nullptr; - - if (m_UserInterface != nullptr) { - uilock = m_UserInterface->lock(); - } - else { - // i.e. when running command line shortcuts there is no m_UserInterface - dlg.reset(new LockedDialog); - dlg->show(); - dlg->setEnabled(true); - uilock = dlg.get(); - } - - ON_BLOCK_EXIT([&]() { - if (m_UserInterface != nullptr) { - m_UserInterface->unlock(); - } }); - - DWORD processExitCode; - waitForProcessCompletion(processHandle, &processExitCode, uilock); - cycleDiagnostics(); - } - - return processHandle; + return spawnBinaryDirect(binary, arguments, profileName, currentDirectory, steamAppID, customOverwrite); } bool OrganizerCore::waitForApplication(HANDLE handle, LPDWORD exitCode) diff --git a/src/organizercore.h b/src/organizercore.h index 0927c88e..901780a1 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -145,7 +145,14 @@ public: const QString &profileName, const QDir ¤tDirectory, const QString &steamAppID, - const QString &customOverwrite); + const QString &customOverwrite, + LPDWORD exitCode = nullptr); + + HANDLE spawnBinaryProcess(const QFileInfo &binary, const QString &arguments, + const QString &profileName, + const QDir ¤tDirectory, + const QString &steamAppID, + const QString &customOverwrite); void loginSuccessfulUpdate(bool necessary); void loginFailedUpdate(const QString &message); @@ -192,6 +199,7 @@ public: DownloadManager *downloadManager(); PluginList *pluginList(); ModList *modList(); + HANDLE runShortcut(const QString &title); HANDLE startApplication(const QString &executable, const QStringList &args, const QString &cwd, const QString &profile); bool waitForApplication(HANDLE processHandle, LPDWORD exitCode = nullptr); bool onModInstalled(const std::function &func); -- cgit v1.3.1 From ebf378cda0bd6832d9070cf1597d5ea12b206155 Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Sun, 10 Dec 2017 23:45:20 +0200 Subject: Turn on application icon for executables by default --- src/executableslist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 9fe4596c..b1890ac9 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -192,7 +192,7 @@ void ExecutablesList::addExecutableInternal(const QString &title, const QString newExe.m_Arguments = arguments; newExe.m_WorkingDirectory = workingDirectory; newExe.m_SteamAppID = steamAppID; - newExe.m_Flags = 0; + newExe.m_Flags = Executable::UseApplicationIcon; m_Executables.push_back(newExe); } } -- cgit v1.3.1 From ad702537bd6dc4eff40dd6b6d51536b2758dca6c Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Mon, 11 Dec 2017 00:11:17 +0200 Subject: Use single instance also for MO shortcuts --- src/main.cpp | 27 +++++++-------------------- src/organizercore.cpp | 5 ++++- src/organizercore.h | 4 ++++ 3 files changed, 15 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 9b2afecc..dbf41afb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -121,21 +121,6 @@ bool bootstrap() } -bool isNxmLink(const QString &link) -{ - return link.startsWith("nxm://", Qt::CaseInsensitive); -} - -bool isMoShortcut(const QString &link) -{ - return link.startsWith("moshortcut://", Qt::CaseInsensitive); -} - -QString moShortcutName(const QString &link) -{ - return link.mid(strlen("moshortcut://")); -} - static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs) { if ((exceptionPtrs->ExceptionRecord->ExceptionCode < 0x80000000) // non-critical @@ -477,16 +462,16 @@ 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 (isMoShortcut(arguments.at(1))) { + if (OrganizerCore::isMoShortcut(arguments.at(1))) { try { - organizer.runShortcut(moShortcutName(arguments.at(1))); + organizer.runShortcut(OrganizerCore::moShortcutName(arguments.at(1))); return 0; } catch (const std::exception &e) { reportError( QObject::tr("failed to start shortcut: %1").arg(e.what())); return 1; } - } else if (isNxmLink(arguments.at(1))) { + } else if (OrganizerCore::isNxmLink(arguments.at(1))) { qDebug("starting download from command line: %s", qPrintable(arguments.at(1))); organizer.externalMessage(arguments.at(1)); @@ -579,8 +564,10 @@ int main(int argc, char *argv[]) SingleInstance instance(forcePrimary); if (!instance.primaryInstance()) { - if ((arguments.size() == 2) && isNxmLink(arguments.at(1))) { - qDebug("not primary instance, sending download message"); + if ((arguments.size() == 2) + && (OrganizerCore::isMoShortcut(arguments.at(1)) || OrganizerCore::isNxmLink(arguments.at(1)))) + { + qDebug("not primary instance, sending shortcut/download message"); instance.sendMessage(arguments.at(1)); return 0; } else if (arguments.size() == 1) { diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 116552df..bc0578b3 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -578,7 +578,10 @@ void OrganizerCore::downloadRequestedNXM(const QString &url) void OrganizerCore::externalMessage(const QString &message) { - if (message.left(6).toLower() == "nxm://") { + if (isMoShortcut(message)) { + runShortcut(moShortcutName(message)); + } + else if (isNxmLink(message)) { MessageDialog::showMessage(tr("Download started"), qApp->activeWindow()); downloadRequestedNXM(message); } diff --git a/src/organizercore.h b/src/organizercore.h index 901780a1..f8806289 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -85,6 +85,10 @@ private: typedef boost::signals2::signal SignalModInstalled; 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); -- cgit v1.3.1