Improve D-Bus notifications handling

Make notifications clickable on Linux by assigning "default" action.
Don't react to unrelated notifications clicked by keeping track of qBittorrent notifications IDs and filter out unrelated ones.
Make D-Bus Notifications interface proxy class to be maintained manually and fix coding style in it.
Closes #9084.
PR #17282.
This commit is contained in:
Vladimir Golovnev
2022-07-01 11:27:16 +03:00
committed by GitHub
parent 7f5271ae7c
commit b760f37093
11 changed files with 336 additions and 172 deletions

View File

@@ -48,9 +48,8 @@
#include <QtGlobal>
#include <QTimer>
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) && defined(QT_DBUS_LIB)
#include <QDBusConnection>
#include "qtnotify/notifications.h"
#ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
#include "notifications/dbusnotifier.h"
#endif
#include "base/bittorrent/session.h"
@@ -128,7 +127,7 @@ MainWindow::MainWindow(QWidget *parent)
, m_storeNotificationEnabled(NOTIFICATIONS_SETTINGS_KEY("Enabled"))
, m_storeNotificationTorrentAdded(NOTIFICATIONS_SETTINGS_KEY("TorrentAdded"))
, m_storeExecutionLogTypes(EXECUTIONLOG_SETTINGS_KEY("Types"), Log::MsgType::ALL)
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) && defined(QT_DBUS_LIB)
#ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
, m_storeNotificationTimeOut(NOTIFICATIONS_SETTINGS_KEY("Timeout"))
#endif
{
@@ -182,6 +181,14 @@ MainWindow::MainWindow(QWidget *parent)
m_ui->actionLock->setVisible(true);
});
#ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
if (isNotificationsEnabled())
{
m_notifier = new DBusNotifier(this);
connect(m_notifier, &DBusNotifier::messageClicked, this, &MainWindow::balloonClicked);
}
#endif
// Creating Bittorrent session
updateAltSpeedsBtn(BitTorrent::Session::instance()->isAltGlobalSpeedLimitEnabled());
@@ -508,9 +515,25 @@ bool MainWindow::isNotificationsEnabled() const
return m_storeNotificationEnabled.get(true);
}
void MainWindow::setNotificationsEnabled(bool value)
void MainWindow::setNotificationsEnabled(const bool value)
{
if (m_storeNotificationEnabled == value)
return;
m_storeNotificationEnabled = value;
#ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
if (value)
{
m_notifier = new DBusNotifier(this);
connect(m_notifier, &DBusNotifier::messageClicked, this, &MainWindow::balloonClicked);
}
else
{
delete m_notifier;
m_notifier = nullptr;
}
#endif
}
bool MainWindow::isTorrentAddedNotificationsEnabled() const
@@ -1646,27 +1669,8 @@ void MainWindow::showNotificationBalloon(const QString &title, const QString &ms
if (!isNotificationsEnabled())
return;
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) && defined(QT_DBUS_LIB)
OrgFreedesktopNotificationsInterface notifications(QLatin1String("org.freedesktop.Notifications")
, QLatin1String("/org/freedesktop/Notifications")
, QDBusConnection::sessionBus());
// Testing for 'notifications.isValid()' isn't helpful here.
// If the notification daemon is configured to run 'as needed'
// the above check can be false if the daemon wasn't started
// by another application. In this case DBus will be able to
// start the notification daemon and complete our request. Such
// a daemon is xfce4-notifyd, DBus autostarts it and after
// some inactivity shuts it down. Other DEs, like GNOME, choose
// to start their daemons at the session startup and have it sit
// idling for the whole session.
const QVariantMap hints {{QLatin1String("desktop-entry"), QLatin1String("org.qbittorrent.qBittorrent")}};
QDBusPendingReply<uint> reply = notifications.Notify(QLatin1String("qBittorrent"), 0
, QLatin1String("qbittorrent"), title, msg, {}, hints, getNotificationTimeout());
reply.waitForFinished();
if (!reply.isError())
return;
#ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
m_notifier->showMessage(title, msg, getNotificationTimeout());
#elif defined(Q_OS_MACOS)
MacUtils::displayNotification(title, msg);
#else
@@ -1713,7 +1717,9 @@ void MainWindow::createTrayIcon(const int retries)
m_systrayIcon->setContextMenu(m_trayIconMenu);
connect(m_systrayIcon, &QSystemTrayIcon::activated, this, &MainWindow::toggleVisibility);
#ifndef QBT_USES_CUSTOMDBUSNOTIFICATIONS
connect(m_systrayIcon, &QSystemTrayIcon::messageClicked, this, &MainWindow::balloonClicked);
#endif
m_systrayIcon->show();
emit systemTrayIconCreated();