From 55de581ee9829c5fcb5bae37504fad4e89cac721 Mon Sep 17 00:00:00 2001 From: Jonathan Feenstra <26406078+JonathanFeenstra@users.noreply.github.com> Date: Fri, 15 May 2026 09:23:09 +0200 Subject: Add setting to show notifications when downloads complete or fail (#2338) --- 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 | 11 ++++++++--- src/systemtraymanager.h | 6 ++++++ 13 files changed, 97 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 4e667e0f..2d9cdd45 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 @@ -1403,7 +1404,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); @@ -1817,6 +1822,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); } @@ -2392,6 +2402,12 @@ void DownloadManager::finishDownload(DownloadID id) 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 9c8e391d..876978b2 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -759,6 +759,8 @@ private: DownloadInfo* downloadInfoByID(DownloadID id); + QString displayNameByInfo(const DownloadInfo* info) const; + void removePending(QString gameName, int modID, int fileID); /** diff --git a/src/iuserinterface.h b/src/iuserinterface.h index 7ddc545d..ae5ed880 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 @@ public: 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 0a4fba2e..6a662173 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -142,6 +142,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include #include #include @@ -2266,6 +2267,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 d3e1d480..cc7e3366 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 @@ public: 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 68ccd2ff..27ab9713 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -541,6 +542,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 80f340b6..d7810e1b 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -360,6 +361,10 @@ public: 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 849f64ec..a7c46458 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2302,6 +2302,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 28eeb1fd..5b2c6ee7 100644 --- a/src/settings.h +++ b/src/settings.h @@ -654,6 +654,11 @@ public: 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 9e335909..9a7ce3bc 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 + + + @@ -191,10 +204,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 374eb621..ab68b3f2 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()); // connect MODL button QObject::connect(ui->associateModlButton, &QPushButton::clicked, [&] { @@ -69,6 +71,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 d885f1eb..afbd598d 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,12 @@ 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 43a3b0e4..e7e03c09 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 @@ public: 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; -- cgit v1.3.1