From 0c498574d2f26bae581bc8f9a01e739e1f9c3872 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Sun, 12 Oct 2008 18:48:09 +0200 Subject: [PATCH] Complete and pimp DesktopNotificationBackend. You'll need to reset your notification settings, as things have moved around in the settings files. Thanks to TerrorBite for providing the patches in BR #278, this information was very valuable! --- src/qtui/CMakeLists.txt | 1 + src/qtui/desktopnotificationbackend.cpp | 149 +++++++++++++++-- src/qtui/desktopnotificationbackend.h | 41 ++++- src/qtui/mainwin.cpp | 2 +- .../ui/desktopnotificationconfigwidget.ui | 157 ++++++++++++++++++ 5 files changed, 334 insertions(+), 16 deletions(-) create mode 100644 src/qtui/ui/desktopnotificationconfigwidget.ui diff --git a/src/qtui/CMakeLists.txt b/src/qtui/CMakeLists.txt index 59d3837a..0bf28eee 100644 --- a/src/qtui/CMakeLists.txt +++ b/src/qtui/CMakeLists.txt @@ -111,6 +111,7 @@ set(FORMS IF(HAVE_DBUS) set(SOURCES ${SOURCES} desktopnotificationbackend.cpp) set(MOC_HDRS ${MOC_HDRS} desktopnotificationbackend.h) + set(FORMS ${FORMS} desktopnotificationconfigwidget.ui) qt4_add_dbus_interface(DBUS ../../interfaces/org.freedesktop.Notifications.xml desktopnotificationinterface) ENDIF(HAVE_DBUS) diff --git a/src/qtui/desktopnotificationbackend.cpp b/src/qtui/desktopnotificationbackend.cpp index de87344d..45d18b59 100644 --- a/src/qtui/desktopnotificationbackend.cpp +++ b/src/qtui/desktopnotificationbackend.cpp @@ -20,36 +20,57 @@ #include "desktopnotificationbackend.h" +#include + #include "client.h" #include "clientsettings.h" #include "networkmodel.h" DesktopNotificationBackend::DesktopNotificationBackend(QObject *parent) : AbstractNotificationBackend(parent) { + _configWidget = new ConfigWidget(); + _dbusInterface = new org::freedesktop::Notifications( "org.freedesktop.Notifications", "/org/freedesktop/Notifications", QDBusConnection::sessionBus(), this); - _dbusNotificationId = 0; + + QStringList desktopCapabilities = _dbusInterface->GetCapabilities(); + _daemonSupportsMarkup = desktopCapabilities.contains("body-markup"); + + _lastDbusId = 0; connect(_dbusInterface, SIGNAL(NotificationClosed(uint, uint)), SLOT(desktopNotificationClosed(uint, uint))); connect(_dbusInterface, SIGNAL(ActionInvoked(uint, const QString &)), SLOT(desktopNotificationInvoked(uint, const QString&))); NotificationSettings notificationSettings; _enabled = notificationSettings.value("DesktopNotification/Enabled", false).toBool(); + _useHints = notificationSettings.value("DesktopNotification/UseHints", false).toBool(); _xHint = notificationSettings.value("DesktopNotification/XHint", 0).toInt(); _yHint = notificationSettings.value("DesktopNotification/YHint", 0).toInt(); + _queueNotifications = notificationSettings.value("DesktopNotification/QueueNotifications", true).toBool(); + _timeout = notificationSettings.value("DesktopNotification/Timeout", 10000).toInt(); + _useTimeout = notificationSettings.value("DesktopNotification/UseTimeout", true).toBool(); + notificationSettings.notify("DesktopNotification/Enabled", this, SLOT(enabledChanged(const QVariant &))); + notificationSettings.notify("DesktopNotification/UseHints", this, SLOT(useHintsChanged(const QVariant &))); notificationSettings.notify("DesktopNotification/XHint", this, SLOT(xHintChanged(const QVariant &))); notificationSettings.notify("DesktopNotification/YHint", this, SLOT(yHintChanged(const QVariant &))); + notificationSettings.notify("DesktopNotification/Timeout", this, SLOT(timeoutChanged(const QVariant &))); + notificationSettings.notify("DesktopNotification/UseTimeout", this, SLOT(useTimeoutChanged(const QVariant &))); + notificationSettings.notify("DesktopNotification/QueueNotifications", this, SLOT(queueNotificationsChanged(const QVariant &))); } DesktopNotificationBackend::~DesktopNotificationBackend() { - + delete _configWidget; } void DesktopNotificationBackend::enabledChanged(const QVariant &v) { _enabled = v.toBool(); } +void DesktopNotificationBackend::useHintsChanged(const QVariant &v) { + _useHints = v.toBool(); +} + void DesktopNotificationBackend::xHintChanged(const QVariant &v) { _xHint = v.toInt(); } @@ -58,54 +79,156 @@ void DesktopNotificationBackend::yHintChanged(const QVariant &v) { _yHint = v.toInt(); } +void DesktopNotificationBackend::queueNotificationsChanged(const QVariant &v) { + _queueNotifications = v.toBool(); +} + +void DesktopNotificationBackend::timeoutChanged(const QVariant &v) { + _timeout = v.toInt(); +} + +void DesktopNotificationBackend::useTimeoutChanged(const QVariant &v) { + _useTimeout = v.toBool(); +} + void DesktopNotificationBackend::notify(const Notification &n) { if(_enabled) { QStringList actions; QMap hints; - hints["x"] = _xHint; // Standard hint: x location for the popup to show up - hints["y"] = _yHint; // Standard hint: y location for the popup to show up + if(_useHints) { + hints["x"] = _xHint; // Standard hint: x location for the popup to show up + hints["y"] = _yHint; // Standard hint: y location for the popup to show up + } + + uint oldId = _queueNotifications ? 0 : _lastDbusId; // actions << "click" << "Click Me!"; QString title = Client::networkModel()->networkName(n.bufferId) + " - " + Client::networkModel()->bufferName(n.bufferId); QString message = QString("<%1> %2").arg(n.sender, n.message); + if(_daemonSupportsMarkup) + message = Qt::escape(message); + QDBusReply reply = _dbusInterface->Notify( "Quassel IRC", // Application name - _dbusNotificationId, // ID of previous notification to replace + oldId, // ID of previous notification to replace "quassel", // Icon to display title, // Summary / Header of the message to display message, // Body of the message to display actions, // Actions from which the user may choose hints, // Hints to the server displaying the message - 5000 // Timeout in milliseconds + _useTimeout? _timeout : 0 // Timeout in milliseconds ); if(!reply.isValid()) { /* ERROR */ // could also happen if no notification service runs, so... whatever :) - //qDebug() << "Error on sending notification..." << reply.error(); + // qDebug() << "Error on sending notification..." << reply.error(); return; } - _dbusNotificationId = reply.value(); + uint dbusid = reply.value(); + _idMap.insert(n.notificationId, dbusid); + _lastDbusId = dbusid; } } void DesktopNotificationBackend::close(uint notificationId) { - Q_UNUSED(notificationId); + uint dbusId = _idMap.value(notificationId, 0); + if(dbusId) { + _idMap.remove(notificationId); + _dbusInterface->CloseNotification(dbusId); + } + _lastDbusId = 0; } void DesktopNotificationBackend::desktopNotificationClosed(uint id, uint reason) { - Q_UNUSED(id); Q_UNUSED(reason); - // qDebug() << "OID: " << notificationId << " ID: " << id << " Reason: " << reason << " Time: " << QTime::currentTime().toString(); - _dbusNotificationId = 0; + Q_UNUSED(reason); + _idMap.remove(_idMap.key(id)); + _lastDbusId = 0; } void DesktopNotificationBackend::desktopNotificationInvoked(uint id, const QString & action) { Q_UNUSED(id); Q_UNUSED(action); - // qDebug() << "OID: " << notificationId << " ID: " << id << " Action: " << action << " Time: " << QTime::currentTime().toString(); } +SettingsPage *DesktopNotificationBackend::configWidget() const { + return _configWidget; +} + +/***************************************************************************/ + +DesktopNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent) : SettingsPage("Internal", "DesktopNotification", parent) { + ui.setupUi(this); + + connect(ui.enabled, SIGNAL(toggled(bool)), SLOT(widgetChanged())); + connect(ui.useHints, SIGNAL(toggled(bool)), SLOT(widgetChanged())); + connect(ui.xHint, SIGNAL(valueChanged(int)), SLOT(widgetChanged())); + connect(ui.yHint, SIGNAL(valueChanged(int)), SLOT(widgetChanged())); + connect(ui.queueNotifications, SIGNAL(toggled(bool)), SLOT(widgetChanged())); + connect(ui.useTimeout, SIGNAL(toggled(bool)), SLOT(widgetChanged())); + connect(ui.timeout, SIGNAL(valueChanged(int)), SLOT(widgetChanged())); +} + +void DesktopNotificationBackend::ConfigWidget::widgetChanged() { + bool changed = + enabled != ui.enabled->isChecked() + || useHints != ui.useHints->isChecked() + || xHint != ui.xHint->value() + || yHint != ui.yHint->value() + || queueNotifications != ui.queueNotifications->isChecked() + || timeout/1000 != ui.timeout->value() + || useTimeout != ui.useTimeout->isChecked(); + if(changed != hasChanged()) setChangedState(changed); +} + +bool DesktopNotificationBackend::ConfigWidget::hasDefaults() const { + return true; +} + +void DesktopNotificationBackend::ConfigWidget::defaults() { + ui.enabled->setChecked(false); + ui.useTimeout->setChecked(true); + ui.timeout->setValue(10); + ui.useHints->setChecked(false); + ui.xHint->setValue(0); + ui.yHint->setValue(0); + ui.queueNotifications->setChecked(true); + widgetChanged(); +} + +void DesktopNotificationBackend::ConfigWidget::load() { + NotificationSettings s; + enabled = s.value("DesktopNotification/Enabled", false).toBool(); + useTimeout = s.value("DesktopNotification/UseTimeout", true).toBool(); + timeout = s.value("DesktopNotification/Timeout", 10).toInt(); + useHints = s.value("DesktopNotification/UseHints", false).toBool(); + xHint = s.value("DesktopNotification/XHint", 0).toInt(); + yHint = s.value("DesktopNotification/YHint", 0).toInt(); + queueNotifications = s.value("DesktopNotification/QueueNotifications", true).toBool(); + + ui.enabled->setChecked(enabled); + ui.useTimeout->setChecked(useTimeout); + ui.timeout->setValue(timeout/1000); + ui.useHints->setChecked(useHints); + ui.xHint->setValue(xHint); + ui.yHint->setValue(yHint); + ui.queueNotifications->setChecked(queueNotifications); + + setChangedState(false); +} +void DesktopNotificationBackend::ConfigWidget::save() { + NotificationSettings s; + s.setValue("DesktopNotification/Enabled", ui.enabled->isChecked()); + s.setValue("DesktopNotification/UseTimeout", ui.useTimeout->isChecked()); + s.setValue("DesktopNotification/Timeout", ui.timeout->value() * 1000); + s.setValue("DesktopNotification/UseHints", ui.useHints->isChecked()); + s.setValue("DesktopNotification/XHint", ui.xHint->value()); + s.setValue("DesktopNotification/YHint", ui.yHint->value()); + s.setValue("DesktopNotification/QueueNotifications", ui.queueNotifications->isChecked()); + + load(); +} diff --git a/src/qtui/desktopnotificationbackend.h b/src/qtui/desktopnotificationbackend.h index 0c06b70d..4427afe9 100644 --- a/src/qtui/desktopnotificationbackend.h +++ b/src/qtui/desktopnotificationbackend.h @@ -21,11 +21,14 @@ #ifndef DESKTOPNOTIFICATIONBACKEND_H_ #define DESKTOPNOTIFICATIONBACKEND_H_ +#include + #include "abstractnotificationbackend.h" #include "settingspage.h" #include "desktopnotificationinterface.h" +#include "ui_desktopnotificationconfigwidget.h" //! Implements the freedesktop.org notifications specification (via D-Bus) /** @@ -49,15 +52,49 @@ private slots: void desktopNotificationInvoked(uint id, const QString &action); void enabledChanged(const QVariant &); + void useHintsChanged(const QVariant &); void xHintChanged(const QVariant &); void yHintChanged(const QVariant &); + void queueNotificationsChanged(const QVariant &); + void timeoutChanged(const QVariant &); + void useTimeoutChanged(const QVariant &); private: + class ConfigWidget; + SettingsPage *_configWidget; + org::freedesktop::Notifications *_dbusInterface; - quint32 _dbusNotificationId; + bool _daemonSupportsMarkup; + quint32 _lastDbusId; + QHash _idMap; ///< Maps our own notification Id to the D-Bus one - bool _enabled; + bool _enabled, _queueNotifications, _useHints; int _xHint, _yHint; + int _timeout; + bool _useTimeout; + +}; + +class DesktopNotificationBackend::ConfigWidget : public SettingsPage { + Q_OBJECT + + public: + ConfigWidget(QWidget *parent = 0); + void save(); + void load(); + bool hasDefaults() const; + void defaults(); + + private slots: + void widgetChanged(); + + private: + Ui::DesktopNotificationConfigWidget ui; + int xHint, yHint; + bool useHints, queueNotifications; + int timeout; + bool useTimeout; + bool enabled; }; #endif diff --git a/src/qtui/mainwin.cpp b/src/qtui/mainwin.cpp index 3485cca6..9cc1c3e0 100644 --- a/src/qtui/mainwin.cpp +++ b/src/qtui/mainwin.cpp @@ -89,7 +89,7 @@ MainWin::MainWin(QWidget *parent) QtUi::registerNotificationBackend(new SystrayNotificationBackend(this)); #ifdef HAVE_DBUS - //QtUi::registerNotificationBackend(new DesktopNotificationBackend(this)); + QtUi::registerNotificationBackend(new DesktopNotificationBackend(this)); #endif QtUiApplication* app = qobject_cast qApp; diff --git a/src/qtui/ui/desktopnotificationconfigwidget.ui b/src/qtui/ui/desktopnotificationconfigwidget.ui new file mode 100644 index 00000000..e641282c --- /dev/null +++ b/src/qtui/ui/desktopnotificationconfigwidget.ui @@ -0,0 +1,157 @@ + + DesktopNotificationConfigWidget + + + + 0 + 0 + 435 + 144 + + + + Form + + + + + + Desktop Notification (via D-Bus) + + + true + + + false + + + + + + + + Timeout: + + + true + + + + + + + + + + s + + + 1 + + + 10 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Position hint: + + + + + + + false + + + px + + + X: + + + 9999 + + + + + + + false + + + px + + + Y: + + + 9999 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Queue unread notifications + + + true + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + -- 2.20.1