2 #include "notificationsinterface.h"
4 #include <QCoreApplication>
5 #include <QDBusConnection>
6 #include <QDBusPendingReply>
9 #include <QMutexLocker>
39 static QMutex pendingNotificationsMutex;
41 static std::map<uint, DBusNotification *> pendingNotifications;
42 OrgFreedesktopNotificationsInterface *DBusNotification::s_dbusInterface =
nullptr;
52 inline SwappedImage::SwappedImage(
const QImage &image)
53 : QImage(image.rgbSwapped())
84 argument.beginStructure();
86 argument.endStructure();
92 argument.beginStructure();
94 argument.endStructure();
109 : width(image.width())
110 , height(image.height())
111 , rowstride(image.bytesPerLine())
112 , hasAlpha(image.hasAlphaChannel())
113 , channels(image.isGrayscale() ? 1 : hasAlpha ? 4 : 3)
114 , bitsPerSample(image.depth() / channels)
115 #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
116 , data(reinterpret_cast<const char *>(image.bits()), static_cast<int>(image.sizeInBytes()))
118 , data(reinterpret_cast<const char *>(image.bits()), image.byteCount())
120 , isValid(!image.isNull())
131 return isValid ? QImage(
reinterpret_cast<const uchar *
>(
data.constData()),
width,
height,
hasAlpha ? QImage::Format_ARGB32 : QImage::Format_RGB32)
138 return QVariant::fromValue(*
this);
183 void DBusNotification::initInterface()
185 if (!s_dbusInterface) {
186 qDBusRegisterMetaType<NotificationImage>();
187 s_dbusInterface =
new OrgFreedesktopNotificationsInterface(
188 QStringLiteral(
"org.freedesktop.Notifications"), QStringLiteral(
"/org/freedesktop/Notifications"), QDBusConnection::sessionBus());
189 connect(s_dbusInterface, &OrgFreedesktopNotificationsInterface::ActionInvoked, &DBusNotification::handleActionInvoked);
190 connect(s_dbusInterface, &OrgFreedesktopNotificationsInterface::NotificationClosed, &DBusNotification::handleNotificationClosed);
200 QMutexLocker lock(&pendingNotificationsMutex);
201 auto i = pendingNotifications.find(m_id);
202 if (i != pendingNotifications.end()) {
203 pendingNotifications.erase(i);
215 return s_dbusInterface->isValid();
225 m_icon = QStringLiteral(
"dialog-information");
228 m_icon = QStringLiteral(
"dialog-warning");
231 m_icon = QStringLiteral(
"dialog-critical");
276 if (!s_dbusInterface->isValid()) {
283 =
new QDBusPendingCallWatcher(s_dbusInterface->Notify(m_applicationName.isEmpty() ? QCoreApplication::applicationName() : m_applicationName,
284 m_id, m_icon, m_title, m_msg, m_actions, m_hints, m_timeout),
286 connect(m_watcher, &QDBusPendingCallWatcher::finished,
this, &DBusNotification::handleNotifyResult);
320 if (!m_msg.startsWith(QStringLiteral(
"•"))) {
321 m_msg.insert(0, QStringLiteral(
"• "));
323 m_msg.append(QStringLiteral(
"\n• "));
333 if (!s_dbusInterface->isValid()) {
338 const auto *
const watcher =
new QDBusPendingCallWatcher(s_dbusInterface->GetCapabilities());
339 connect(watcher, &QDBusPendingCallWatcher::finished, [&callback](QDBusPendingCallWatcher *watcher) {
340 watcher->deleteLater();
341 const QDBusPendingReply<QStringList> returnValue(*watcher);
342 if (returnValue.isError()) {
359 s_dbusInterface->CloseNotification(m_id);
368 void DBusNotification::handleNotifyResult(QDBusPendingCallWatcher *watcher)
370 if (watcher != m_watcher) {
374 watcher->deleteLater();
377 QDBusPendingReply<uint> returnValue = *watcher;
378 if (returnValue.isError()) {
384 QMutexLocker lock(&pendingNotificationsMutex);
385 pendingNotifications[m_id = returnValue.argumentAt<0>()] =
this;
393 void DBusNotification::handleNotificationClosed(uint
id, uint reason)
395 QMutexLocker lock(&pendingNotificationsMutex);
396 auto i = pendingNotifications.find(
id);
397 if (i != pendingNotifications.end()) {
399 notification->m_id = 0;
401 pendingNotifications.erase(i);
408 void DBusNotification::handleActionInvoked(uint
id,
const QString &action)
410 QMutexLocker lock(&pendingNotificationsMutex);
411 auto i = pendingNotifications.find(
id);
412 if (i != pendingNotifications.end()) {
414 emit notification->actionInvoked(action);
419 notification->m_id = 0;
420 pendingNotifications.erase(i);
423 s_dbusInterface->CloseNotification(i->first);