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