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); }