Qt Utilities  5.7.1
Common Qt related C++ classes and routines used by my applications such as dialogs, widgets and models
dbusnotification.cpp
Go to the documentation of this file.
1 #include "./dbusnotification.h"
2 #include "notificationsinterface.h"
3 
4 #include <QCoreApplication>
5 #include <QDBusConnection>
6 #include <QDBusPendingReply>
7 
8 #include <map>
9 
10 using namespace std;
11 
12 namespace MiscUtils {
13 
36 static std::map<uint, DBusNotification *> pendingNotifications;
38 OrgFreedesktopNotificationsInterface *DBusNotification::m_dbusInterface = nullptr;
40 
44 DBusNotification::DBusNotification(const QString &title, NotificationIcon icon, int timeout, QObject *parent)
45  : QObject(parent)
46  , m_id(0)
47  , m_watcher(nullptr)
48  , m_title(title)
49  , m_timeout(timeout)
50 {
51  initInterface();
52  setIcon(icon);
53 }
54 
58 DBusNotification::DBusNotification(const QString &title, const QString &icon, int timeout, QObject *parent)
59  : QObject(parent)
60  , m_id(0)
61  , m_watcher(nullptr)
62  , m_title(title)
63  , m_icon(icon)
64  , m_timeout(timeout)
65 {
66  initInterface();
67 }
68 
72 void DBusNotification::initInterface()
73 {
74  if (!m_dbusInterface) {
75  m_dbusInterface = new OrgFreedesktopNotificationsInterface(
76  QStringLiteral("org.freedesktop.Notifications"), QStringLiteral("/org/freedesktop/Notifications"), QDBusConnection::sessionBus());
77  connect(m_dbusInterface, &OrgFreedesktopNotificationsInterface::ActionInvoked, &DBusNotification::handleActionInvoked);
78  connect(m_dbusInterface, &OrgFreedesktopNotificationsInterface::NotificationClosed, &DBusNotification::handleNotificationClosed);
79  }
80 }
81 
86 {
87  auto i = pendingNotifications.find(m_id);
88  if (i != pendingNotifications.end()) {
89  pendingNotifications.erase(i);
90  }
91  hide();
92 }
93 
98 {
99  initInterface();
100  return m_dbusInterface->isValid();
101 }
102 
107 {
108  switch (icon) {
110  m_icon = QStringLiteral("dialog-information");
111  break;
113  m_icon = QStringLiteral("dialog-warning");
114  break;
116  m_icon = QStringLiteral("dialog-critical");
117  break;
118  default:;
119  }
120 }
121 
127 {
128  connect(this, &DBusNotification::closed, this, &DBusNotification::deleteLater);
129  connect(this, &DBusNotification::error, this, &DBusNotification::deleteLater);
130 }
131 
140 {
141  if (!m_dbusInterface->isValid()) {
142  emit error();
143  return false;
144  }
145 
146  delete m_watcher;
147  m_watcher = new QDBusPendingCallWatcher(
148  m_dbusInterface->Notify(QCoreApplication::applicationName(), m_id, m_icon, m_title, m_msg, m_actions, m_hints, m_timeout), this);
149  connect(m_watcher, &QDBusPendingCallWatcher::finished, this, &DBusNotification::handleNotifyResult);
150  return true;
151 }
152 
160 bool DBusNotification::show(const QString &message)
161 {
162  m_msg = message;
163  return show();
164 }
165 
178 bool DBusNotification::update(const QString &line)
179 {
180  if (!isVisible() || m_msg.isEmpty()) {
181  m_msg = line;
182  } else {
183  if (!m_msg.startsWith(QStringLiteral("•"))) {
184  m_msg.insert(0, QStringLiteral("• "));
185  }
186  m_msg.append(QStringLiteral("\n• "));
187  m_msg.append(line);
188  }
189  return show();
190 }
191 
198 {
199  if (m_id) {
200  m_dbusInterface->CloseNotification(m_id);
201  }
202 }
203 
207 void DBusNotification::handleNotifyResult(QDBusPendingCallWatcher *watcher)
208 {
209  if (watcher != m_watcher) {
210  return;
211  }
212 
213  watcher->deleteLater();
214  m_watcher = nullptr;
215 
216  QDBusPendingReply<uint> returnValue = *watcher;
217  if (returnValue.isError()) {
218  deleteLater();
219  emit error();
220  } else {
221  pendingNotifications[m_id = returnValue.argumentAt<0>()] = this;
222  emit shown();
223  }
224 }
225 
229 void DBusNotification::handleNotificationClosed(uint id, uint reason)
230 {
231  auto i = pendingNotifications.find(id);
232  if (i != pendingNotifications.end()) {
233  DBusNotification *notification = i->second;
234  notification->m_id = 0;
235  emit notification->closed(reason >= 1 && reason <= 3 ? static_cast<NotificationCloseReason>(reason) : NotificationCloseReason::Undefined);
236  pendingNotifications.erase(i);
237  }
238 }
239 
243 void DBusNotification::handleActionInvoked(uint id, const QString &action)
244 {
245  auto i = pendingNotifications.find(id);
246  if (i != pendingNotifications.end()) {
247  DBusNotification *notification = i->second;
248  emit notification->actionInvoked(action);
249  // Plasma 5 also closes the notification but doesn't emit the
250  // NotificationClose signal
251  // -> just consider the notification closed
253  notification->m_id = 0;
254  pendingNotifications.erase(i);
255  // however, lxqt-notificationd does not close the notification
256  // -> close manually for consistent behaviour
257  m_dbusInterface->CloseNotification(i->first);
258  }
259 }
260 
312 }
void setIcon(const QString &icon)
Sets the icon name.
void closed(NotificationCloseReason reason)
Emitted when the notification has been closed.
const QString & title() const
bool update(const QString &line)
Updates the message and shows/updates the notification.
STL namespace.
void hide()
Hides the notification (if still visible).
void shown()
Emitted when the notification could be shown successful.
static bool isAvailable()
Returns whether the notification D-Bus daemon is running.
bool isVisible() const
Returns whether the notification is (still) visible.
DBusNotification(const QString &title, NotificationIcon icon=NotificationIcon::Information, int timeout=10000, QObject *parent=nullptr)
Creates a new notification (which is not shown instantly).
bool show()
Shows the notification.
void error()
Emitted when the notification couldn&#39;t be shown.
void actionInvoked(const QString &action)
Emitted when action has been invoked.
~DBusNotification()
Closes the notification if still shown and delete the object.
The DBusNotification class emits D-Bus notifications.
void deleteOnCloseOrError()
Makes the notification object delete itself when the notification has been closed or an error occured...
const QString & icon() const
const QString & message() const