From 6a606b6674849b80c4771504e9d9dc15d47dfef1 Mon Sep 17 00:00:00 2001
From: Jonathan Feenstra <26406078+JonathanFeenstra@users.noreply.github.com>
Date: Sun, 15 Feb 2026 19:24:12 +0100
Subject: [PATCH 1/2] Add setting to show notifications when downloads complete
or fail
---
src/downloadmanager.cpp | 16 ++++++++++++++++
src/downloadmanager.h | 2 ++
src/iuserinterface.h | 5 +++++
src/mainwindow.cpp | 7 +++++++
src/mainwindow.h | 5 +++++
src/organizercore.cpp | 9 +++++++++
src/organizercore.h | 5 +++++
src/settings.cpp | 10 ++++++++++
src/settings.h | 5 +++++
src/settingsdialog.ui | 17 +++++++++++++++--
src/settingsdialoggeneral.cpp | 4 ++++
src/systemtraymanager.cpp | 12 +++++++++---
src/systemtraymanager.h | 6 ++++++
13 files changed, 98 insertions(+), 5 deletions(-)
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp
index ce6ba665d..33be6a6ec 100644
--- a/src/downloadmanager.cpp
+++ b/src/downloadmanager.cpp
@@ -42,6 +42,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
#include
#include
@@ -1365,7 +1366,11 @@ QString DownloadManager::getDisplayName(int index) const
}
DownloadInfo* info = m_ActiveDownloads.at(index);
+ return displayNameByInfo(info);
+}
+QString DownloadManager::displayNameByInfo(const DownloadInfo* info) const
+{
QTextDocument doc;
if (!info->m_FileInfo->name.isEmpty()) {
doc.setHtml(info->m_FileInfo->name);
@@ -1789,6 +1794,11 @@ void DownloadManager::nxmDescriptionAvailable(QString, int, QVariant userData,
info->m_FileInfo->modName = doc.toPlainText();
if (info->m_FileInfo->fileID != 0) {
setState(info, STATE_READY);
+ if (m_OrganizerCore->settings().interface().showDownloadNotifications()) {
+ m_OrganizerCore->showNotification(
+ tr("Download complete"),
+ tr("%1 is ready to be installed.").arg(displayNameByInfo(info)));
+ }
} else {
setState(info, STATE_FETCHINGFILEINFO);
}
@@ -2278,6 +2288,12 @@ void DownloadManager::downloadFinished(int index)
emit showMessage(tr("Download failed: %1 (%2)")
.arg(reply->errorString())
.arg(reply->error()));
+ if (m_OrganizerCore->settings().interface().showDownloadNotifications()) {
+ m_OrganizerCore->showNotification(
+ tr("Download failed"),
+ tr("%1 failed to download.").arg(displayNameByInfo(info)),
+ QSystemTrayIcon::MessageIcon::Critical);
+ }
}
error = true;
setState(info, STATE_ERROR);
diff --git a/src/downloadmanager.h b/src/downloadmanager.h
index abf909c86..0cdeae7f0 100644
--- a/src/downloadmanager.h
+++ b/src/downloadmanager.h
@@ -588,6 +588,8 @@ private slots:
DownloadInfo* downloadInfoByID(unsigned int id);
+ QString displayNameByInfo(const DownloadInfo* info) const;
+
void removePending(QString gameName, int modID, int fileID);
static QString getFileTypeString(int fileType);
diff --git a/src/iuserinterface.h b/src/iuserinterface.h
index 7ddc545d0..ae5ed880a 100644
--- a/src/iuserinterface.h
+++ b/src/iuserinterface.h
@@ -4,6 +4,7 @@
#include "modinfodialogfwd.h"
#include
#include
+#include
#include
#include
#include
@@ -27,6 +28,10 @@ class IUserInterface
virtual MOBase::DelayedFileWriterBase& archivesWriter() = 0;
virtual QMainWindow* mainWindow() = 0;
+
+ virtual void showNotification(const QString& title, const QString& message,
+ QSystemTrayIcon::MessageIcon icon =
+ QSystemTrayIcon::MessageIcon::Information) = 0;
};
#endif // IUSERINTERFACE_H
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 5d5a88cec..f3f1bba0f 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -139,6 +139,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
#include
#include
#include
@@ -2259,6 +2260,12 @@ QMainWindow* MainWindow::mainWindow()
return this;
}
+void MainWindow::showNotification(const QString& title, const QString& message,
+ QSystemTrayIcon::MessageIcon icon)
+{
+ m_SystemTrayManager->showNotification(title, message, icon);
+}
+
void MainWindow::on_tabWidget_currentChanged(int index)
{
QWidget* currentWidget = ui->tabWidget->widget(index);
diff --git a/src/mainwindow.h b/src/mainwindow.h
index d3e1d480e..cc7e3366e 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -78,6 +78,7 @@ class DirectoryEntry;
#include
#include
#include
+#include
#include
#include
#include
@@ -156,6 +157,10 @@ class MainWindow : public QMainWindow, public IUserInterface
return m_ArchiveListWriter;
}
+ void showNotification(const QString& title, const QString& message,
+ QSystemTrayIcon::MessageIcon icon =
+ QSystemTrayIcon::MessageIcon::Information) override;
+
public slots:
void refresherProgress(const DirectoryRefreshProgress* p);
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index a8fc67c27..53375ac13 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -46,6 +46,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -539,6 +540,14 @@ std::wstring OrganizerCore::getGlobalCoreDumpPath()
return {};
}
+void OrganizerCore::showNotification(const QString& message, const QString& title,
+ QSystemTrayIcon::MessageIcon icon)
+{
+ if (m_UserInterface) {
+ m_UserInterface->showNotification(message, title, icon);
+ }
+}
+
void OrganizerCore::setCurrentProfile(const QString& profileName)
{
if ((m_CurrentProfile != nullptr) && (profileName == m_CurrentProfile->name())) {
diff --git a/src/organizercore.h b/src/organizercore.h
index 80f340b68..d7810e1b6 100644
--- a/src/organizercore.h
+++ b/src/organizercore.h
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include
#include
@@ -360,6 +361,10 @@ class OrganizerCore : public QObject, public MOBase::IPluginDiagnose
static void setGlobalCoreDumpType(env::CoreDumpTypes type);
static std::wstring getGlobalCoreDumpPath();
+ void showNotification(
+ const QString& title, const QString& message,
+ QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::MessageIcon::Information);
+
public:
MOBase::IModRepositoryBridge* createNexusBridge() const;
QString profileName() const;
diff --git a/src/settings.cpp b/src/settings.cpp
index ef1785b16..0356cf944 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -2263,6 +2263,16 @@ void InterfaceSettings::setHideDownloadsAfterInstallation(bool b)
set(m_Settings, "Settings", "autohide_downloads", b);
}
+bool InterfaceSettings::showDownloadNotifications() const
+{
+ return get(m_Settings, "Settings", "download_notifications", false);
+}
+
+void InterfaceSettings::setShowDownloadNotifications(bool b)
+{
+ set(m_Settings, "Settings", "download_notifications", b);
+}
+
bool InterfaceSettings::hideAPICounter() const
{
return get(m_Settings, "Settings", "hide_api_counter", false);
diff --git a/src/settings.h b/src/settings.h
index edc1d6445..1f5d2bc26 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -653,6 +653,11 @@ class InterfaceSettings
bool hideDownloadsAfterInstallation() const;
void setHideDownloadsAfterInstallation(bool b);
+ // whether to show notifications when downloads complete or fail
+ //
+ bool showDownloadNotifications() const;
+ void setShowDownloadNotifications(bool b);
+
// whether the API counter should be hidden
//
bool hideAPICounter() const;
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index 6011b1588..f1ff4f7d1 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -166,6 +166,19 @@
+ -
+
+
+ Show notifications when downloads complete or fail.
+
+
+ Show notifications when downloads complete or fail.
+
+
+ Show notifications for completed or failed downloads
+
+
+
@@ -178,10 +191,10 @@
-
- Check for Mod Organizer updates on Github on startup.
+ Check for Mod Organizer updates on GitHub on startup.
- Check for Mod Organizer updates on Github on startup.
+ Check for Mod Organizer updates on GitHub on startup.
Check for updates
diff --git a/src/settingsdialoggeneral.cpp b/src/settingsdialoggeneral.cpp
index 265c9db90..8daef5827 100644
--- a/src/settingsdialoggeneral.cpp
+++ b/src/settingsdialoggeneral.cpp
@@ -20,6 +20,8 @@ GeneralSettingsTab::GeneralSettingsTab(Settings& s, SettingsDialog& d)
ui->showMetaBox->setChecked(settings().interface().metaDownloads());
ui->hideDownloadInstallBox->setChecked(
settings().interface().hideDownloadsAfterInstallation());
+ ui->showDownloadNotificationsBox->setChecked(
+ settings().interface().showDownloadNotifications());
// updates
ui->checkForUpdates->setChecked(settings().checkForUpdates());
@@ -64,6 +66,8 @@ void GeneralSettingsTab::update()
settings().interface().setMetaDownloads(ui->showMetaBox->isChecked());
settings().interface().setHideDownloadsAfterInstallation(
ui->hideDownloadInstallBox->isChecked());
+ settings().interface().setShowDownloadNotifications(
+ ui->showDownloadNotificationsBox->isChecked());
// updates
settings().setCheckForUpdates(ui->checkForUpdates->isChecked());
diff --git a/src/systemtraymanager.cpp b/src/systemtraymanager.cpp
index d885f1ebd..6bc349596 100644
--- a/src/systemtraymanager.cpp
+++ b/src/systemtraymanager.cpp
@@ -24,6 +24,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
#include
SystemTrayManager::SystemTrayManager(QMainWindow* parent, QDockWidget* logDock)
@@ -42,11 +43,11 @@ SystemTrayManager::SystemTrayManager(QMainWindow* parent, QDockWidget* logDock)
trayMenu->addAction(exitAction);
m_SystemTrayIcon->setContextMenu(trayMenu);
+ m_SystemTrayIcon->show();
}
void SystemTrayManager::minimizeToSystemTray()
{
- m_SystemTrayIcon->show();
m_Parent->hide();
if (m_LogDock->isFloating() && m_LogDock->isVisible()) {
@@ -56,8 +57,6 @@ void SystemTrayManager::minimizeToSystemTray()
void SystemTrayManager::restoreFromSystemTray()
{
- m_SystemTrayIcon->hide();
-
m_Parent->showNormal();
m_Parent->raise();
m_Parent->activateWindow();
@@ -67,6 +66,13 @@ void SystemTrayManager::restoreFromSystemTray()
}
}
+void SystemTrayManager::showNotification(
+ const QString& title, const QString& message,
+ QSystemTrayIcon::MessageIcon icon)
+{
+ m_SystemTrayIcon->showMessage(title, message, icon);
+}
+
void SystemTrayManager::on_systemTrayIcon_activated(
QSystemTrayIcon::ActivationReason reason)
{
diff --git a/src/systemtraymanager.h b/src/systemtraymanager.h
index 43a3b0e48..e7e03c093 100644
--- a/src/systemtraymanager.h
+++ b/src/systemtraymanager.h
@@ -21,8 +21,10 @@ along with Mod Organizer. If not, see .
#define SYSTEMTRAYMANAGER_H
#include
+#include
#include
#include
+#include
#include
class SystemTrayManager : public QObject
@@ -35,6 +37,10 @@ class SystemTrayManager : public QObject
void minimizeToSystemTray();
void restoreFromSystemTray();
+ void showNotification(
+ const QString& title, const QString& message,
+ QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::MessageIcon::Information);
+
private:
QMainWindow* m_Parent;
QDockWidget* m_LogDock;
From 6c37c79ca176a07e81c74d0e660c2d2cc7390ac2 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Sun, 15 Feb 2026 18:40:00 +0000
Subject: [PATCH 2/2] [pre-commit.ci] Auto fixes from pre-commit.com hooks.
---
src/systemtraymanager.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/systemtraymanager.cpp b/src/systemtraymanager.cpp
index 6bc349596..afbd598de 100644
--- a/src/systemtraymanager.cpp
+++ b/src/systemtraymanager.cpp
@@ -66,9 +66,8 @@ void SystemTrayManager::restoreFromSystemTray()
}
}
-void SystemTrayManager::showNotification(
- const QString& title, const QString& message,
- QSystemTrayIcon::MessageIcon icon)
+void SystemTrayManager::showNotification(const QString& title, const QString& message,
+ QSystemTrayIcon::MessageIcon icon)
{
m_SystemTrayIcon->showMessage(title, message, icon);
}