1 /***************************************************************************
2 * Copyright (C) 2005-09 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "desktopnotificationbackend.h"
23 #include <QTextDocument>
26 #include "clientsettings.h"
27 #include "networkmodel.h"
29 DesktopNotificationBackend::DesktopNotificationBackend(QObject *parent)
30 : AbstractNotificationBackend(parent),
33 _dbusInterface = new org::freedesktop::Notifications(
34 "org.freedesktop.Notifications",
35 "/org/freedesktop/Notifications",
36 QDBusConnection::sessionBus(), this);
38 if(!_dbusInterface->isValid()) {
39 qWarning() << "DBus notification service not available!";
43 QStringList desktopCapabilities = _dbusInterface->GetCapabilities();
44 _daemonSupportsMarkup = desktopCapabilities.contains("body-markup");
46 connect(_dbusInterface, SIGNAL(NotificationClosed(uint, uint)), SLOT(desktopNotificationClosed(uint, uint)));
47 connect(_dbusInterface, SIGNAL(ActionInvoked(uint, const QString &)), SLOT(desktopNotificationInvoked(uint, const QString&)));
49 NotificationSettings notificationSettings;
50 _enabled = notificationSettings.value("DesktopNotification/Enabled", false).toBool();
51 _useHints = notificationSettings.value("DesktopNotification/UseHints", false).toBool();
52 _xHint = notificationSettings.value("DesktopNotification/XHint", 0).toInt();
53 _yHint = notificationSettings.value("DesktopNotification/YHint", 0).toInt();
54 _queueNotifications = notificationSettings.value("DesktopNotification/QueueNotifications", true).toBool();
55 _timeout = notificationSettings.value("DesktopNotification/Timeout", 10000).toInt();
56 _useTimeout = notificationSettings.value("DesktopNotification/UseTimeout", true).toBool();
58 notificationSettings.notify("DesktopNotification/Enabled", this, SLOT(enabledChanged(const QVariant &)));
59 notificationSettings.notify("DesktopNotification/UseHints", this, SLOT(useHintsChanged(const QVariant &)));
60 notificationSettings.notify("DesktopNotification/XHint", this, SLOT(xHintChanged(const QVariant &)));
61 notificationSettings.notify("DesktopNotification/YHint", this, SLOT(yHintChanged(const QVariant &)));
62 notificationSettings.notify("DesktopNotification/Timeout", this, SLOT(timeoutChanged(const QVariant &)));
63 notificationSettings.notify("DesktopNotification/UseTimeout", this, SLOT(useTimeoutChanged(const QVariant &)));
64 notificationSettings.notify("DesktopNotification/QueueNotifications", this, SLOT(queueNotificationsChanged(const QVariant &)));
67 void DesktopNotificationBackend::enabledChanged(const QVariant &v) {
68 _enabled = v.toBool();
71 void DesktopNotificationBackend::useHintsChanged(const QVariant &v) {
72 _useHints = v.toBool();
75 void DesktopNotificationBackend::xHintChanged(const QVariant &v) {
79 void DesktopNotificationBackend::yHintChanged(const QVariant &v) {
83 void DesktopNotificationBackend::queueNotificationsChanged(const QVariant &v) {
84 _queueNotifications = v.toBool();
87 void DesktopNotificationBackend::timeoutChanged(const QVariant &v) {
91 void DesktopNotificationBackend::useTimeoutChanged(const QVariant &v) {
92 _useTimeout = v.toBool();
95 void DesktopNotificationBackend::notify(const Notification &n) {
96 if(_enabled && _dbusInterface->isValid() && (n.type == Highlight || n.type == PrivMsg)) {
98 QMap<QString, QVariant> hints;
101 hints["x"] = _xHint; // Standard hint: x location for the popup to show up
102 hints["y"] = _yHint; // Standard hint: y location for the popup to show up
105 uint oldId = _queueNotifications ? 0 : _lastDbusId;
107 actions << "activate" << "View";
109 QString title = Client::networkModel()->networkName(n.bufferId) + " - " + Client::networkModel()->bufferName(n.bufferId);
110 QString message = QString("<%1> %2").arg(n.sender, n.message);
112 if(_daemonSupportsMarkup)
113 message = Qt::escape(message);
115 QDBusReply<uint> reply = _dbusInterface->Notify(
116 "Quassel IRC", // Application name
117 oldId, // ID of previous notification to replace
118 "quassel", // Icon to display
119 title, // Summary / Header of the message to display
120 message, // Body of the message to display
121 actions, // Actions from which the user may choose
122 hints, // Hints to the server displaying the message
123 _useTimeout? _timeout : 0 // Timeout in milliseconds
126 if(!reply.isValid()) {
128 // could also happen if no notification service runs, so... whatever :)
129 // qDebug() << "Error on sending notification..." << reply.error();
132 uint dbusid = reply.value();
133 _idMap.insert(n.notificationId, dbusid);
134 _lastDbusId = dbusid;
138 void DesktopNotificationBackend::close(uint notificationId) {
139 uint dbusId = _idMap.value(notificationId, 0);
141 _idMap.remove(notificationId);
142 _dbusInterface->CloseNotification(dbusId);
147 void DesktopNotificationBackend::desktopNotificationClosed(uint id, uint reason) {
149 _idMap.remove(_idMap.key(id));
154 void DesktopNotificationBackend::desktopNotificationInvoked(uint id, const QString & action) {
156 foreach(uint ourid, _idMap.keys()) {
157 if(_idMap.value(ourid) != id)
159 emit activated(ourid);
166 SettingsPage *DesktopNotificationBackend::createConfigWidget() const {
167 return new ConfigWidget();
170 /***************************************************************************/
172 DesktopNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent) : SettingsPage("Internal", "DesktopNotification", parent) {
175 connect(ui.enabled, SIGNAL(toggled(bool)), SLOT(widgetChanged()));
176 connect(ui.useHints, SIGNAL(toggled(bool)), SLOT(widgetChanged()));
177 connect(ui.xHint, SIGNAL(valueChanged(int)), SLOT(widgetChanged()));
178 connect(ui.yHint, SIGNAL(valueChanged(int)), SLOT(widgetChanged()));
179 connect(ui.queueNotifications, SIGNAL(toggled(bool)), SLOT(widgetChanged()));
180 connect(ui.useTimeout, SIGNAL(toggled(bool)), SLOT(widgetChanged()));
181 connect(ui.timeout, SIGNAL(valueChanged(int)), SLOT(widgetChanged()));
184 void DesktopNotificationBackend::ConfigWidget::widgetChanged() {
186 enabled != ui.enabled->isChecked()
187 || useHints != ui.useHints->isChecked()
188 || xHint != ui.xHint->value()
189 || yHint != ui.yHint->value()
190 || queueNotifications != ui.queueNotifications->isChecked()
191 || timeout/1000 != ui.timeout->value()
192 || useTimeout != ui.useTimeout->isChecked();
193 if(changed != hasChanged()) setChangedState(changed);
196 bool DesktopNotificationBackend::ConfigWidget::hasDefaults() const {
200 void DesktopNotificationBackend::ConfigWidget::defaults() {
201 ui.enabled->setChecked(false);
202 ui.useTimeout->setChecked(true);
203 ui.timeout->setValue(10);
204 ui.useHints->setChecked(false);
205 ui.xHint->setValue(0);
206 ui.yHint->setValue(0);
207 ui.queueNotifications->setChecked(true);
211 void DesktopNotificationBackend::ConfigWidget::load() {
212 NotificationSettings s;
213 enabled = s.value("DesktopNotification/Enabled", false).toBool();
214 useTimeout = s.value("DesktopNotification/UseTimeout", true).toBool();
215 timeout = s.value("DesktopNotification/Timeout", 10000).toInt();
216 useHints = s.value("DesktopNotification/UseHints", false).toBool();
217 xHint = s.value("DesktopNotification/XHint", 0).toInt();
218 yHint = s.value("DesktopNotification/YHint", 0).toInt();
219 queueNotifications = s.value("DesktopNotification/QueueNotifications", true).toBool();
221 ui.enabled->setChecked(enabled);
222 ui.useTimeout->setChecked(useTimeout);
223 ui.timeout->setValue(timeout/1000);
224 ui.useHints->setChecked(useHints);
225 ui.xHint->setValue(xHint);
226 ui.yHint->setValue(yHint);
227 ui.queueNotifications->setChecked(queueNotifications);
229 setChangedState(false);
232 void DesktopNotificationBackend::ConfigWidget::save() {
233 NotificationSettings s;
234 s.setValue("DesktopNotification/Enabled", ui.enabled->isChecked());
235 s.setValue("DesktopNotification/UseTimeout", ui.useTimeout->isChecked());
236 s.setValue("DesktopNotification/Timeout", ui.timeout->value() * 1000);
237 s.setValue("DesktopNotification/UseHints", ui.useHints->isChecked());
238 s.setValue("DesktopNotification/XHint", ui.xHint->value());
239 s.setValue("DesktopNotification/YHint", ui.yHint->value());
240 s.setValue("DesktopNotification/QueueNotifications", ui.queueNotifications->isChecked());