diff options
| author | Jonathan Feenstra <26406078+JonathanFeenstra@users.noreply.github.com> | 2026-01-03 15:48:06 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-03 15:48:06 +0100 |
| commit | e5ac1cc82d832f0515364fdb3f02f03bdea8870e (patch) | |
| tree | 16c7499b254b75380fc9248be6a749cddf15dd04 | |
| parent | d5bd9603c6ce4117cf98508616c72b702a760440 (diff) | |
Add executable setting to minimize MO2 to the system tray while running (#2313)
| -rw-r--r-- | src/editexecutablesdialog.cpp | 13 | ||||
| -rw-r--r-- | src/editexecutablesdialog.ui | 13 | ||||
| -rw-r--r-- | src/executableslist.cpp | 25 | ||||
| -rw-r--r-- | src/executableslist.h | 8 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 20 | ||||
| -rw-r--r-- | src/mainwindow.h | 3 | ||||
| -rw-r--r-- | src/systemtraymanager.cpp | 77 | ||||
| -rw-r--r-- | src/systemtraymanager.h | 48 |
8 files changed, 195 insertions, 12 deletions
diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index 8a01b9f0..f4a602c3 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -118,6 +118,9 @@ EditExecutablesDialog::EditExecutablesDialog(OrganizerCore& oc, int sel, connect(ui->useApplicationIcon, &QCheckBox::toggled, [&] { save(); }); + connect(ui->minimizeToSystemTray, &QCheckBox::toggled, [&] { + save(); + }); connect(ui->hide, &QCheckBox::toggled, [&] { save(); }); @@ -382,6 +385,8 @@ void EditExecutablesDialog::clearEdits() ui->configureLibraries->setEnabled(false); ui->useApplicationIcon->setEnabled(false); ui->useApplicationIcon->setChecked(false); + ui->minimizeToSystemTray->setEnabled(false); + ui->minimizeToSystemTray->setChecked(false); ui->hide->setEnabled(false); ui->hide->setChecked(false); @@ -398,6 +403,7 @@ void EditExecutablesDialog::setEdits(const Executable& e) ui->steamAppID->setEnabled(!e.steamAppID().isEmpty()); ui->steamAppID->setText(e.steamAppID()); ui->useApplicationIcon->setChecked(e.usesOwnIcon()); + ui->minimizeToSystemTray->setChecked(e.minimizeToSystemTray()); ui->hide->setChecked(e.hide()); m_lastGoodTitle = e.title(); @@ -443,6 +449,7 @@ void EditExecutablesDialog::setEdits(const Executable& e) ui->useApplicationIcon->setEnabled(true); ui->createFilesInMod->setEnabled(true); ui->forceLoadLibraries->setEnabled(true); + ui->minimizeToSystemTray->setEnabled(true); ui->hide->setEnabled(true); } @@ -503,6 +510,12 @@ void EditExecutablesDialog::save() e->flags(e->flags() & (~Executable::UseApplicationIcon)); } + if (ui->minimizeToSystemTray->isChecked()) { + e->flags(e->flags() | Executable::MinimizeToSystemTray); + } else { + e->flags(e->flags() & (~Executable::MinimizeToSystemTray)); + } + if (ui->hide->isChecked()) { e->flags(e->flags() | Executable::Hide); } else { diff --git a/src/editexecutablesdialog.ui b/src/editexecutablesdialog.ui index d90fd8d4..005f3a19 100644 --- a/src/editexecutablesdialog.ui +++ b/src/editexecutablesdialog.ui @@ -438,6 +438,19 @@ Right now the only case I know of where this needs to be overwritten is for the </property>
</widget>
</item>
+ <item>
+ <widget class="QCheckBox" name="minimizeToSystemTray">
+ <property name="toolTip">
+ <string>Mod Organizer will minimize to the system tray while this executable is running. It will reappear after it finishes.</string>
+ </property>
+ <property name="whatsThis">
+ <string>Mod Organizer will minimize to the system tray while this executable is running. It will reappear after it finishes.</string>
+ </property>
+ <property name="text">
+ <string>Minimize to system tray while running</string>
+ </property>
+ </widget>
+ </item>
<item>
<widget class="QCheckBox" name="hide">
<property name="toolTip">
diff --git a/src/executableslist.cpp b/src/executableslist.cpp index c683bdcb..c4563f90 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -82,6 +82,9 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, const Settings& s) if (map["ownicon"].toBool()) flags |= Executable::UseApplicationIcon; + if (map["minimizeToSystemTray"].toBool()) + flags |= Executable::MinimizeToSystemTray; + if (map["hide"].toBool()) flags |= Executable::Hide; @@ -114,14 +117,15 @@ void ExecutablesList::store(Settings& s) for (const auto& item : *this) { std::map<QString, QVariant> map; - map["title"] = item.title(); - map["toolbar"] = item.isShownOnToolbar(); - map["ownicon"] = item.usesOwnIcon(); - map["hide"] = item.hide(); - map["binary"] = item.binaryInfo().filePath(); - map["arguments"] = item.arguments(); - map["workingDirectory"] = item.workingDirectory(); - map["steamAppID"] = item.steamAppID(); + map["title"] = item.title(); + map["toolbar"] = item.isShownOnToolbar(); + map["ownicon"] = item.usesOwnIcon(); + map["hide"] = item.hide(); + map["binary"] = item.binaryInfo().filePath(); + map["arguments"] = item.arguments(); + map["workingDirectory"] = item.workingDirectory(); + map["steamAppID"] = item.steamAppID(); + map["minimizeToSystemTray"] = item.minimizeToSystemTray(); v.push_back(std::move(map)); } @@ -464,6 +468,11 @@ bool Executable::usesOwnIcon() const return m_flags.testFlag(UseApplicationIcon); } +bool Executable::minimizeToSystemTray() const +{ + return m_flags.testFlag(MinimizeToSystemTray); +} + bool Executable::hide() const { return m_flags.testFlag(Hide); diff --git a/src/executableslist.h b/src/executableslist.h index 21a30056..d3d31f92 100644 --- a/src/executableslist.h +++ b/src/executableslist.h @@ -43,9 +43,10 @@ class Executable public: enum Flag { - ShowInToolbar = 0x02, - UseApplicationIcon = 0x04, - Hide = 0x08 + ShowInToolbar = 0x02, + UseApplicationIcon = 0x04, + Hide = 0x08, + MinimizeToSystemTray = 0x16 }; Q_DECLARE_FLAGS(Flags, Flag); @@ -74,6 +75,7 @@ public: bool isShownOnToolbar() const; void setShownOnToolbar(bool state); bool usesOwnIcon() const; + bool minimizeToSystemTray() const; bool hide() const; void mergeFrom(const Executable& other); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ce432196..cd74165e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -67,6 +67,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "shared/appconfig.h" #include "spawn.h" #include "statusbar.h" +#include "systemtraymanager.h" #include <bsainvalidation.h> #include <dataarchives.h> #include <safewritefile.h> @@ -238,7 +239,8 @@ MainWindow::MainWindow(Settings& settings, OrganizerCore& organizerCore, m_PluginContainer(pluginContainer), m_ArchiveListWriter(std::bind(&MainWindow::saveArchiveList, this)), m_LinkToolbar(nullptr), m_LinkDesktop(nullptr), m_LinkStartMenu(nullptr), - m_NumberOfProblems(0), m_ProblemsCheckRequired(false) + m_SystemTrayManager(nullptr), m_NumberOfProblems(0), + m_ProblemsCheckRequired(false) { // disables incredibly slow menu fade in effect that looks and feels like crap. // this was only happening to users with the windows @@ -265,6 +267,8 @@ MainWindow::MainWindow(Settings& settings, OrganizerCore& organizerCore, languageChange(settings.interface().language()); ui->statusBar->setup(ui, settings); + m_SystemTrayManager = new SystemTrayManager(this, ui->logDock); + { auto& ni = NexusInterface::instance(); @@ -477,6 +481,12 @@ MainWindow::MainWindow(Settings& settings, OrganizerCore& organizerCore, m_Tutorial.expose("espList", m_OrganizerCore.pluginList()); m_OrganizerCore.setUserInterface(this); + m_OrganizerCore.onFinishedRun([=](const QString, unsigned int) { + if (isHidden()) { + m_SystemTrayManager->restoreFromSystemTray(); + } + }); + connect(m_OrganizerCore.modList(), &ModList::showMessage, [=](auto&& message) { showMessage(message); }); @@ -1697,6 +1707,10 @@ void MainWindow::startExeAction() action->setEnabled(true); }); + if (itor->minimizeToSystemTray()) { + m_SystemTrayManager->minimizeToSystemTray(); + } + m_OrganizerCore.processRunner() .setFromExecutable(*itor) .setWaitForCompletion(ProcessRunner::TriggerRefresh) @@ -2271,6 +2285,10 @@ void MainWindow::on_startButton_clicked() ui->startButton->setEnabled(true); }); + if (selectedExecutable->minimizeToSystemTray()) { + m_SystemTrayManager->minimizeToSystemTray(); + } + m_OrganizerCore.processRunner() .setFromExecutable(*selectedExecutable) .setWaitForCompletion(ProcessRunner::TriggerRefresh) diff --git a/src/mainwindow.h b/src/mainwindow.h index 45a7ab2a..d3e1d480 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -34,6 +34,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "modlistsortproxy.h" #include "plugincontainer.h" #include "shared/fileregisterfwd.h" +#include "systemtraymanager.h" class Executable; class CategoryFactory; @@ -310,6 +311,8 @@ private: QAction* m_LinkDesktop; QAction* m_LinkStartMenu; + SystemTrayManager* m_SystemTrayManager; + // icon set by the stylesheet, used to remember its original appearance // when painting the count QIcon m_originalNotificationIcon; diff --git a/src/systemtraymanager.cpp b/src/systemtraymanager.cpp new file mode 100644 index 00000000..d885f1eb --- /dev/null +++ b/src/systemtraymanager.cpp @@ -0,0 +1,77 @@ +/* +Copyright (C) 2012 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 <http://www.gnu.org/licenses/>. +*/ + +#include "systemtraymanager.h" + +#include <QAction> +#include <QDockWidget> +#include <QIcon> +#include <QMainWindow> +#include <QMenu> +#include <QSystemTrayIcon> + +SystemTrayManager::SystemTrayManager(QMainWindow* parent, QDockWidget* logDock) + : m_Parent(parent), m_LogDock(logDock), + m_SystemTrayIcon(new QSystemTrayIcon(QIcon(":/MO/gui/app_icon"), m_Parent)) +{ + m_SystemTrayIcon->setToolTip(tr("Mod Organizer")); + + connect(m_SystemTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, + SLOT(on_systemTrayIcon_activated(QSystemTrayIcon::ActivationReason))); + + auto* exitAction = new QAction(tr("Exit"), m_SystemTrayIcon); + connect(exitAction, &QAction::triggered, m_Parent, &QMainWindow::close); + + auto* trayMenu = new QMenu(m_Parent); + trayMenu->addAction(exitAction); + + m_SystemTrayIcon->setContextMenu(trayMenu); +} + +void SystemTrayManager::minimizeToSystemTray() +{ + m_SystemTrayIcon->show(); + m_Parent->hide(); + + if (m_LogDock->isFloating() && m_LogDock->isVisible()) { + m_LogDock->hide(); + } +} + +void SystemTrayManager::restoreFromSystemTray() +{ + m_SystemTrayIcon->hide(); + + m_Parent->showNormal(); + m_Parent->raise(); + m_Parent->activateWindow(); + + if (m_LogDock->isFloating() && m_LogDock->isHidden()) { + m_LogDock->show(); + } +} + +void SystemTrayManager::on_systemTrayIcon_activated( + QSystemTrayIcon::ActivationReason reason) +{ + if (m_Parent->isHidden() && reason == QSystemTrayIcon::Trigger) { + // left click + restoreFromSystemTray(); + } +} diff --git a/src/systemtraymanager.h b/src/systemtraymanager.h new file mode 100644 index 00000000..43a3b0e4 --- /dev/null +++ b/src/systemtraymanager.h @@ -0,0 +1,48 @@ +/* +Copyright (C) 2012 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 <http://www.gnu.org/licenses/>. +*/ + +#ifndef SYSTEMTRAYMANAGER_H +#define SYSTEMTRAYMANAGER_H + +#include <QDockWidget> +#include <QMainWindow> +#include <QObject> +#include <QSystemTrayIcon> + +class SystemTrayManager : public QObject +{ + Q_OBJECT + +public: + explicit SystemTrayManager(QMainWindow* parent, QDockWidget* logDock); + + void minimizeToSystemTray(); + void restoreFromSystemTray(); + +private: + QMainWindow* m_Parent; + QDockWidget* m_LogDock; + + QSystemTrayIcon* m_SystemTrayIcon; + +private slots: + void on_systemTrayIcon_activated(QSystemTrayIcon::ActivationReason reason); +}; + +#endif // SYSTEMTRAYMANAGER_H |
