From f92e2c376d36132a9676b30f0b08543f27a13064 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Thu, 19 Sep 2019 16:27:41 -0400 Subject: TaskDialog for restarting as admin for steam added a parent widget parameter to a bunch of places fixed paths still getting changed even if folders can't be created made private the member variables that were temporarily public during rework --- src/settingsdialog.cpp | 44 ++++++++++------ src/settingsdialog.h | 20 +++---- src/settingsdialoggeneral.cpp | 7 ++- src/settingsdialognexus.cpp | 14 ++--- src/settingsdialogpaths.cpp | 6 ++- src/settingsdialogworkarounds.cpp | 6 ++- src/spawn.cpp | 106 ++++++++++++++++++++------------------ src/spawn.h | 7 ++- 8 files changed, 121 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp index 1d3d4a39..8fb25b1c 100644 --- a/src/settingsdialog.cpp +++ b/src/settingsdialog.cpp @@ -33,8 +33,8 @@ SettingsDialog::SettingsDialog(PluginContainer *pluginContainer, Settings& setti : TutorableDialog("SettingsDialog", parent) , ui(new Ui::SettingsDialog) , m_settings(settings) - , m_PluginContainer(pluginContainer) - , m_keyChanged(false) + , m_pluginContainer(pluginContainer) + , m_restartNeeded(false) { ui->setupUi(this); @@ -47,6 +47,25 @@ SettingsDialog::SettingsDialog(PluginContainer *pluginContainer, Settings& setti m_tabs.push_back(std::unique_ptr(new WorkaroundsSettingsTab(settings, *this))); } +PluginContainer* SettingsDialog::pluginContainer() +{ + return m_pluginContainer; +} + +QWidget* SettingsDialog::parentWidgetForDialogs() +{ + if (isVisible()) { + return this; + } else { + return parentWidget(); + } +} + +void SettingsDialog::setRestartNeeded() +{ + m_restartNeeded = true; +} + int SettingsDialog::exec() { GeometrySaver gs(m_settings, this); @@ -68,13 +87,8 @@ int SettingsDialog::exec() } } - bool restartNeeded = false; - if (getApiKeyChanged()) { - restartNeeded = true; - } - - if (restartNeeded) { - if (QMessageBox::question(nullptr, + if (m_restartNeeded) { + if (QMessageBox::question(parentWidgetForDialogs(), tr("Restart Mod Organizer?"), tr("In order to finish configuration changes, MO must be restarted.\n" "Restart it now?"), @@ -111,7 +125,7 @@ void SettingsDialog::accept() QDir::fromNativeSeparators( Settings::instance().paths().mods(true))) && (QMessageBox::question( - nullptr, tr("Confirm"), + parentWidgetForDialogs(), tr("Confirm"), tr("Changing the mod directory affects all your profiles! " "Mods not present (or named differently) in the new location " "will be disabled in all profiles. " @@ -124,11 +138,6 @@ void SettingsDialog::accept() TutorableDialog::accept(); } -bool SettingsDialog::getApiKeyChanged() -{ - return m_keyChanged; -} - SettingsTab::SettingsTab(Settings& s, SettingsDialog& d) : ui(d.ui), m_settings(s), m_dialog(d) @@ -146,3 +155,8 @@ SettingsDialog& SettingsTab::dialog() { return m_dialog; } + +QWidget* SettingsTab::parentWidget() +{ + return m_dialog.parentWidgetForDialogs(); +} diff --git a/src/settingsdialog.h b/src/settingsdialog.h index 6a99cb8d..e89da665 100644 --- a/src/settingsdialog.h +++ b/src/settingsdialog.h @@ -42,6 +42,7 @@ protected: Settings& settings(); SettingsDialog& dialog(); + QWidget* parentWidget(); private: Settings& m_settings; @@ -56,11 +57,12 @@ private: **/ class SettingsDialog : public MOBase::TutorableDialog { - Q_OBJECT + Q_OBJECT; + friend class SettingsTab; public: explicit SettingsDialog( - PluginContainer *pluginContainer, Settings& settings, QWidget *parent = 0); + PluginContainer* pluginContainer, Settings& settings, QWidget* parent = 0); ~SettingsDialog(); @@ -70,23 +72,21 @@ public: */ QString getColoredButtonStyleSheet() const; - // temp - Ui::SettingsDialog *ui; - bool m_keyChanged; - PluginContainer *m_PluginContainer; + PluginContainer* pluginContainer(); + QWidget* parentWidgetForDialogs(); + void setRestartNeeded(); int exec() override; public slots: virtual void accept(); -public: - bool getApiKeyChanged(); - private: Settings& m_settings; std::vector> m_tabs; - + Ui::SettingsDialog* ui; + bool m_restartNeeded; + PluginContainer* m_pluginContainer; }; #endif // SETTINGSDIALOG_H diff --git a/src/settingsdialoggeneral.cpp b/src/settingsdialoggeneral.cpp index 3f7ece38..8ecdcbb9 100644 --- a/src/settingsdialoggeneral.cpp +++ b/src/settingsdialoggeneral.cpp @@ -238,8 +238,11 @@ void GeneralSettingsTab::on_resetColorsBtn_clicked() void GeneralSettingsTab::on_resetDialogsButton_clicked() { - if (QMessageBox::question(&dialog(), QObject::tr("Confirm?"), - QObject::tr("This will make all dialogs show up again where you checked the \"Remember selection\"-box. Continue?"), + if (QMessageBox::question( + parentWidget(), QObject::tr("Confirm?"), + QObject::tr( + "This will reset all the choices you made to dialogs and make them all " + "visible again. Continue?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { resetDialogs(); } diff --git a/src/settingsdialognexus.cpp b/src/settingsdialognexus.cpp index 0b08f13f..826075c0 100644 --- a/src/settingsdialognexus.cpp +++ b/src/settingsdialognexus.cpp @@ -226,7 +226,7 @@ void NexusSettingsTab::on_nexusDisconnect_clicked() void NexusSettingsTab::on_clearCacheButton_clicked() { QDir(Settings::instance().paths().cache()).removeRecursively(); - NexusInterface::instance(dialog().m_PluginContainer)->clearCache(); + NexusInterface::instance(dialog().pluginContainer())->clearCache(); } void NexusSettingsTab::on_associateButton_clicked() @@ -238,7 +238,7 @@ void NexusSettingsTab::validateKey(const QString& key) { if (!m_nexusValidator) { m_nexusValidator.reset(new NexusKeyValidator( - *NexusInterface::instance(dialog().m_PluginContainer)->getAccessManager())); + *NexusInterface::instance(dialog().pluginContainer())->getAccessManager())); m_nexusValidator->stateChanged = [&](auto&& s, auto&& e){ onValidatorStateChanged(s, e); @@ -294,7 +294,7 @@ void NexusSettingsTab::onValidatorStateChanged( void NexusSettingsTab::onValidatorFinished(const APIUserAccount& user) { - NexusInterface::instance(dialog().m_PluginContainer)->setUserAccount(user); + NexusInterface::instance(dialog().pluginContainer())->setUserAccount(user); if (!user.apiKey().isEmpty()) { if (setKey(user.apiKey())) { @@ -311,7 +311,7 @@ void NexusSettingsTab::addNexusLog(const QString& s) bool NexusSettingsTab::setKey(const QString& key) { - dialog().m_keyChanged = true; + dialog().setRestartNeeded(); const bool ret = settings().nexus().setApiKey(key); updateNexusState(); return ret; @@ -319,10 +319,10 @@ bool NexusSettingsTab::setKey(const QString& key) bool NexusSettingsTab::clearKey() { - dialog().m_keyChanged = true; + dialog().setRestartNeeded(); const auto ret = settings().nexus().clearApiKey(); - NexusInterface::instance(dialog().m_PluginContainer)->getAccessManager()->clearApiKey(); + NexusInterface::instance(dialog().pluginContainer())->getAccessManager()->clearApiKey(); updateNexusState(); return ret; @@ -371,7 +371,7 @@ void NexusSettingsTab::updateNexusButtons() void NexusSettingsTab::updateNexusData() { - const auto user = NexusInterface::instance(dialog().m_PluginContainer) + const auto user = NexusInterface::instance(dialog().pluginContainer()) ->getAPIUserAccount(); if (user.isValid()) { diff --git a/src/settingsdialogpaths.cpp b/src/settingsdialogpaths.cpp index aeb4dd5d..c6fd40a7 100644 --- a/src/settingsdialogpaths.cpp +++ b/src/settingsdialogpaths.cpp @@ -68,10 +68,12 @@ void PathsSettingsTab::update() if (!QDir(realPath).exists()) { if (!QDir().mkpath(realPath)) { - QMessageBox::warning(qApp->activeWindow(), QObject::tr("Error"), + QMessageBox::warning(parentWidget(), QObject::tr("Error"), QObject::tr("Failed to create \"%1\", you may not have the " - "necessary permission. path remains unchanged.") + "necessary permissions. Path remains unchanged.") .arg(realPath)); + + continue; } } diff --git a/src/settingsdialogworkarounds.cpp b/src/settingsdialogworkarounds.cpp index ccbfcbfe..5e70e5a6 100644 --- a/src/settingsdialogworkarounds.cpp +++ b/src/settingsdialogworkarounds.cpp @@ -83,7 +83,9 @@ void WorkaroundsSettingsTab::on_bsaDateBtn_clicked() const auto* game = qApp->property("managed_game").value(); QDir dir = game->dataDirectory(); - helper::backdateBSAs(qApp->applicationDirPath().toStdWString(), + helper::backdateBSAs( + parentWidget(), + qApp->applicationDirPath().toStdWString(), dir.absolutePath().toStdWString()); } @@ -95,7 +97,7 @@ void WorkaroundsSettingsTab::on_resetGeometryBtn_clicked() "Restart now?"); const auto res = QMessageBox::question( - nullptr, caption, text, QMessageBox::Yes | QMessageBox::Cancel); + parentWidget(), caption, text, QMessageBox::Yes | QMessageBox::Cancel); if (res == QMessageBox::Yes) { settings().geometry().requestReset(); diff --git a/src/spawn.cpp b/src/spawn.cpp index e18e6bb3..a0cf9fb6 100644 --- a/src/spawn.cpp +++ b/src/spawn.cpp @@ -215,7 +215,7 @@ QMessageBox::StandardButton startSteamFailed( .exec(); } -void spawnFailed(const SpawnParameters& sp, DWORD code) +void spawnFailed(QWidget* parent, const SpawnParameters& sp, DWORD code) { const auto details = makeDetails(sp, code); log::error("{}", details); @@ -225,12 +225,7 @@ void spawnFailed(const SpawnParameters& sp, DWORD code) const auto mainText = QObject::tr("Cannot start %1") .arg(sp.binary.fileName()); - QWidget *window = qApp->activeWindow(); - if ((window != nullptr) && (!window->isVisible())) { - window = nullptr; - } - - MOBase::TaskDialog(window, title) + MOBase::TaskDialog(parent, title) .main(mainText) .content(makeContent(sp, code)) .details(details) @@ -239,7 +234,7 @@ void spawnFailed(const SpawnParameters& sp, DWORD code) } void helperFailed( - DWORD code, const QString& why, const std::wstring& binary, + QWidget* parent, DWORD code, const QString& why, const std::wstring& binary, const std::wstring& cwd, const std::wstring& args) { SpawnParameters sp; @@ -255,12 +250,7 @@ void helperFailed( const auto mainText = QObject::tr("Cannot start %1") .arg(sp.binary.fileName()); - QWidget *window = qApp->activeWindow(); - if ((window != nullptr) && (!window->isVisible())) { - window = nullptr; - } - - MOBase::TaskDialog(window, title) + MOBase::TaskDialog(parent, title) .main(mainText) .content(makeContent(sp, code)) .details(details) @@ -268,7 +258,7 @@ void helperFailed( .exec(); } -bool confirmRestartAsAdmin(const SpawnParameters& sp) +bool confirmRestartAsAdmin(QWidget* parent, const SpawnParameters& sp) { const auto details = makeDetails(sp, ERROR_ELEVATION_REQUIRED); @@ -287,15 +277,9 @@ bool confirmRestartAsAdmin(const SpawnParameters& sp) "You can restart Mod Organizer as administrator and try launching the " "program again."); - - QWidget *window = qApp->activeWindow(); - if ((window != nullptr) && (!window->isVisible())) { - window = nullptr; - } - log::debug("asking user to restart MO as administrator"); - const auto r = MOBase::TaskDialog(window, title) + const auto r = MOBase::TaskDialog(parent, title) .main(mainText) .content(content) .details(details) @@ -313,7 +297,7 @@ bool confirmRestartAsAdmin(const SpawnParameters& sp) } QMessageBox::StandardButton confirmStartSteam( - QWidget* window, const SpawnParameters& sp, const QString& details) + QWidget* parent, const SpawnParameters& sp, const QString& details) { const auto title = QObject::tr("Launch Steam"); const auto mainText = QObject::tr("This program requires Steam"); @@ -321,7 +305,7 @@ QMessageBox::StandardButton confirmStartSteam( "Mod Organizer has detected that this program likely requires Steam to be " "running to function properly."); - return MOBase::TaskDialog(window, title) + return MOBase::TaskDialog(parent, title) .main(mainText) .content(content) .details(details) @@ -340,17 +324,35 @@ QMessageBox::StandardButton confirmStartSteam( .exec(); } -QuestionBoxMemory::Button confirmRestartAsAdminForSteam(QWidget* parent, const SpawnParameters& sp) +QMessageBox::StandardButton confirmRestartAsAdminForSteam( + QWidget* parent, const SpawnParameters& sp) { - return QuestionBoxMemory::query( - parent, "steamAdminQuery", sp.binary.fileName(), - QObject::tr("Steam: Access Denied"), - QObject::tr("MO was denied access to the Steam process. This normally indicates that " - "Steam is being run as administrator while MO is not. This can cause issues " - "launching the game. It is recommended to not run Steam as administrator unless " - "absolutely necessary.\n\n" - "Restart MO as administrator?"), - QDialogButtonBox::Yes | QDialogButtonBox::No | QDialogButtonBox::Cancel); + const auto title = QObject::tr("Elevation required"); + const auto mainText = QObject::tr("Steam is running as administrator"); + const auto content = QObject::tr( + "Running Steam as administrator is typically unnecessary and can cause " + "problems when Mod Organizer is not running as administrato\r\n\r\n" + "You can restart Mod Organizer as administrator and try launching the " + "program again."); + + return MOBase::TaskDialog(parent, title) + .main(mainText) + .content(content) + .details("") + .icon(QMessageBox::Question) + .button({ + QObject::tr("Restart Mod Organizer as administrator"), + QObject::tr("You must allow \"helper.exe\" to make changes to the system."), + QMessageBox::Yes}) + .button({ + QObject::tr("Continue"), + QObject::tr("The program might fail to run."), + QMessageBox::No}) + .button({ + QObject::tr("Cancel"), + QMessageBox::Cancel}) + .remember("steamAdminQuery", sp.binary.fileName()) + .exec(); } bool eventLogNotRunning( @@ -447,7 +449,7 @@ DWORD spawn(const SpawnParameters& sp, HANDLE& processHandle, HANDLE& threadHand return ERROR_SUCCESS; } -bool restartAsAdmin() +bool restartAsAdmin(QWidget* parent) { WCHAR cwd[MAX_PATH] = {}; if (!GetCurrentDirectory(MAX_PATH, cwd)) { @@ -455,6 +457,7 @@ bool restartAsAdmin() } if (!helper::adminLaunch( + parent, qApp->applicationDirPath().toStdWString(), qApp->applicationFilePath().toStdWString(), std::wstring(cwd))) @@ -469,21 +472,21 @@ bool restartAsAdmin() return true; } -void startBinaryAdmin(const SpawnParameters& sp) +void startBinaryAdmin(QWidget* parent, const SpawnParameters& sp) { - if (!dialogs::confirmRestartAsAdmin(sp)) { + if (!dialogs::confirmRestartAsAdmin(parent, sp)) { log::debug("user declined"); return; } log::info("restarting MO as administrator"); - restartAsAdmin(); + restartAsAdmin(parent); } bool checkBinary(QWidget* parent, const SpawnParameters& sp) { if (!sp.binary.exists()) { - dialogs::spawnFailed(sp, ERROR_FILE_NOT_FOUND); + dialogs::spawnFailed(parent, sp, ERROR_FILE_NOT_FOUND); return false; } @@ -660,7 +663,7 @@ bool checkSteam( const auto c = dialogs::confirmRestartAsAdminForSteam(parent, sp); if (c == QDialogButtonBox::Yes) { - restartAsAdmin(); + restartAsAdmin(parent); return false; } else if (c == QDialogButtonBox::No) { log::debug("user declined to restart MO, continuing"); @@ -720,13 +723,13 @@ HANDLE startBinary(QWidget* parent, const SpawnParameters& sp) case ERROR_ELEVATION_REQUIRED: { - startBinaryAdmin(sp); + startBinaryAdmin(parent, sp); return INVALID_HANDLE_VALUE; } default: { - dialogs::spawnFailed(sp, e); + dialogs::spawnFailed(parent, sp, e); return INVALID_HANDLE_VALUE; } } @@ -740,6 +743,7 @@ namespace helper { bool helperExec( + QWidget* parent, const std::wstring& moDirectory, const std::wstring& commandLine, BOOL async) { const std::wstring fileName = moDirectory + L"\\helper.exe"; @@ -766,7 +770,7 @@ bool helperExec( const auto e = GetLastError(); spawn::dialogs::helperFailed( - e, "ShellExecuteExW()", fileName, moDirectory, commandLine); + parent, e, "ShellExecuteExW()", fileName, moDirectory, commandLine); return false; } @@ -788,7 +792,8 @@ bool helperExec( ERROR_ABANDONED_WAIT_0 : GetLastError()); spawn::dialogs::helperFailed( - code, "WaitForSingleObject()", fileName, moDirectory, commandLine); + parent, code, "WaitForSingleObject()", + fileName, moDirectory, commandLine); return false; } @@ -798,7 +803,7 @@ bool helperExec( const auto e = GetLastError(); spawn::dialogs::helperFailed( - e, "GetExitCodeProcess()", fileName, moDirectory, commandLine); + parent, e, "GetExitCodeProcess()", fileName, moDirectory, commandLine); return false; } @@ -806,21 +811,24 @@ bool helperExec( return (exitCode == 0); } -bool backdateBSAs(const std::wstring &moPath, const std::wstring &dataPath) +bool backdateBSAs( + QWidget* parent, const std::wstring &moPath, const std::wstring &dataPath) { const std::wstring commandLine = fmt::format( L"backdateBSA \"{}\"", dataPath); - return helperExec(moPath, commandLine, FALSE); + return helperExec(parent, moPath, commandLine, FALSE); } -bool adminLaunch(const std::wstring &moPath, const std::wstring &moFile, const std::wstring &workingDir) +bool adminLaunch( + QWidget* parent, const std::wstring &moPath, + const std::wstring &moFile, const std::wstring &workingDir) { const std::wstring commandLine = fmt::format( L"adminLaunch {} \"{}\" \"{}\"", ::GetCurrentProcessId(), moFile, workingDir); - return helperExec(moPath, commandLine, true); + return helperExec(parent, moPath, commandLine, true); } } // namespace diff --git a/src/spawn.h b/src/spawn.h index da626329..9e1e2539 100644 --- a/src/spawn.h +++ b/src/spawn.h @@ -84,7 +84,8 @@ namespace helper * @param moPath absolute path to the modOrganizer base directory * @param dataPath the path taht contains the .bsa-files, usually the data directory of the game **/ -bool backdateBSAs(const std::wstring &moPath, const std::wstring &dataPath); +bool backdateBSAs( + QWidget* parent, const std::wstring &moPath, const std::wstring &dataPath); /** * @brief waits for the current process to exit and restarts it as an administrator @@ -92,7 +93,9 @@ bool backdateBSAs(const std::wstring &moPath, const std::wstring &dataPath); * @param moFile file name of modOrganizer * @param workingDir current working directory **/ -bool adminLaunch(const std::wstring &moPath, const std::wstring &moFile, const std::wstring &workingDir); +bool adminLaunch( + QWidget* parent, const std::wstring &moPath, + const std::wstring &moFile, const std::wstring &workingDir); } // namespace -- cgit v1.3.1