File indexing completed on 2025-01-12 04:20:11

0001 #include "freedesktopnotification_backend.h"
0002 
0003 #include "libsnore/notification/notification.h"
0004 #include "libsnore/notification/notification_p.h"
0005 #include "libsnore/snore.h"
0006 #include "libsnore/snore_p.h"
0007 #include "libsnore/utils.h"
0008 
0009 #include "fredesktopnotification.h"
0010 
0011 SnorePlugin::Freedesktop::Freedesktop()
0012 {
0013     m_interface = new org::freedesktop::Notifications(QStringLiteral("org.freedesktop.Notifications"),
0014             QStringLiteral("/org/freedesktop/Notifications"),
0015             QDBusConnection::sessionBus(), this);
0016     QDBusPendingReply<QStringList> reply = m_interface->GetCapabilities();
0017     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
0018     connect(watcher, &QDBusPendingCallWatcher::finished, [reply, watcher, this]() {
0019         m_supportsRichtext = reply.value().contains(QStringLiteral("body-markup"));
0020         watcher->deleteLater();
0021     });
0022     connect(this, &Freedesktop::enabledChanged, [this](bool enabled) {
0023         if (enabled) {
0024             connect(m_interface, &org::freedesktop::Notifications::ActionInvoked, this, &Freedesktop::slotActionInvoked);
0025             connect(m_interface, &org::freedesktop::Notifications::NotificationClosed, this , &Freedesktop::slotNotificationClosed);
0026         } else {
0027             disconnect(m_interface, &org::freedesktop::Notifications::ActionInvoked, this, &Freedesktop::slotActionInvoked);
0028             disconnect(m_interface, &org::freedesktop::Notifications::NotificationClosed, this , &Freedesktop::slotNotificationClosed);
0029 
0030         }
0031     });
0032 }
0033 
0034 bool SnorePlugin::Freedesktop::canCloseNotification() const
0035 {
0036     return true;
0037 }
0038 
0039 bool SnorePlugin::Freedesktop::canUpdateNotification() const
0040 {
0041     return true;
0042 }
0043 
0044 void  SnorePlugin::Freedesktop::slotNotify(Snore::Notification noti)
0045 {
0046     if (noti.data()->sourceAndTargetAreSimilar(this)) {
0047         return;
0048     }
0049 
0050     QStringList actions;
0051     foreach(int k, noti.actions().keys()) {
0052         actions << QString::number(k) << noti.actions()[k].name();
0053     }
0054     QVariantMap hints;
0055 
0056     FreedesktopImageHint image(noti.icon().pixmap(QSize(128, 128)).toImage());
0057     hints.insert(QStringLiteral("image_data"), QVariant::fromValue(image));
0058 
0059     char urgency = 1;
0060     if (noti.priority() < 0) {
0061         urgency = 0;
0062     } else if (noti.priority() > 2) {
0063         urgency = 2;
0064     }
0065     hints.insert(QStringLiteral("urgency"), urgency);
0066 
0067     if (noti.application().constHints().contains("desktop-entry")) {
0068         hints.insert(QStringLiteral("desktop-entry"), noti.application().constHints().value("desktop-entry"));
0069     }
0070 
0071     hints.insert(QStringLiteral("suppress-sound"), noti.constHints().value("silent").toBool());
0072 
0073     uint updateId = 0;
0074     if (noti.isUpdate()) {
0075         updateId = noti.old().hints().privateValue(this, "id").toUInt();
0076         m_dbusIdMap.take(updateId);
0077     }
0078 
0079     QString title = noti.application().name() + QLatin1String(" - ") + noti.title(m_supportsRichtext ? Snore::Utils::AllMarkup : Snore::Utils::NoMarkup);
0080     QString body(noti.text(m_supportsRichtext ? Snore::Utils::AllMarkup : Snore::Utils::NoMarkup));
0081     //TODO: add app icon hint?
0082     QDBusPendingReply<uint>  id = m_interface->Notify(noti.application().name(), updateId, QString(), title,
0083                                   body, actions, hints, noti.isSticky() ? -1 : noti.timeout() * 1000);
0084 
0085     id.waitForFinished();
0086     noti.hints().setPrivateValue(this, "id", id.value());
0087     m_dbusIdMap[id.value()] = noti;
0088     slotNotificationDisplayed(noti);
0089 
0090     qCDebug(SNORE) << noti.id() << "|" << id.value();
0091 }
0092 
0093 void SnorePlugin::Freedesktop::slotActionInvoked(const uint id, const QString &actionID)
0094 {
0095     qCDebug(SNORE) << id << m_dbusIdMap[id];
0096     Snore::Notification noti = m_dbusIdMap[id];
0097     if (!noti.isValid()) {
0098         return;
0099     }
0100     slotNotificationActionInvoked(noti, noti.actions().value(actionID.toInt()));;
0101 }
0102 
0103 void SnorePlugin::Freedesktop::slotCloseNotification(Snore::Notification notification)
0104 {
0105     uint id = notification.hints().privateValue(this, "id").toUInt();
0106     qCDebug(SNORE) << notification.id() << id;
0107     m_interface->CloseNotification(id);
0108 }
0109 
0110 void SnorePlugin::Freedesktop::slotNotificationClosed(const uint id, const uint reason)
0111 {
0112     /*
0113      *
0114      *  The reason the notification was closed.
0115      *
0116      *  1 - The notification expired.
0117      *
0118      *  2 - The notification was dismissed by the user.
0119      *
0120      *  3 - The notification was closed by a call to CloseNotification.
0121      *
0122      *  4 - Undefined/reserved reasons.
0123     */
0124     Snore::Notification::CloseReasons closeReason;
0125     switch (reason) {
0126     case (1):
0127         closeReason = Snore::Notification::TimedOut;
0128         break;
0129     case (2):
0130         closeReason = Snore::Notification::Dismissed;
0131         break;
0132     case (3):
0133         closeReason = Snore::Notification::Closed;
0134         break;
0135     default:
0136         closeReason = Snore::Notification::None;
0137     }
0138 
0139     qCDebug(SNORE) << id << "|" << closeReason << reason;
0140     if (id == 0) {
0141         return;
0142     }
0143     Snore::Notification noti =  m_dbusIdMap.take(id);
0144     if (noti.isValid()) {
0145         closeNotification(noti, closeReason);
0146     }
0147 }
0148