pgiovanni

Untitled

Jul 22nd, 2021
1,101
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * SPDX-FileCopyrightText: 2013 Albert Vaca <albertvaka@gmail.com>
  3.  *
  4.  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
  5.  */
  6.  
  7. #include "notificationsplugin.h"
  8.  
  9. #include "plugin_notification_debug.h"
  10. #include "sendreplydialog.h"
  11. #include <dbushelper.h>
  12.  
  13. #include <KPluginFactory>
  14. #include <KStartupInfo>
  15.  
  16. #if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
  17. #include <QX11Info>
  18. #endif
  19.  
  20. K_PLUGIN_CLASS_WITH_JSON(NotificationsPlugin, "kdeconnect_notifications.json")
  21.  
  22. NotificationsPlugin::NotificationsPlugin(QObject* parent, const QVariantList& args)
  23.     : KdeConnectPlugin(parent, args)
  24. {
  25. }
  26.  
  27. void NotificationsPlugin::connected()
  28. {
  29.     NetworkPacket np(PACKET_TYPE_NOTIFICATION_REQUEST, {{QStringLiteral("request"), true}});
  30.     sendPacket(np);
  31. }
  32.  
  33. bool NotificationsPlugin::receivePacket(const NetworkPacket& np)
  34. {
  35.     if (np.get<bool>(QStringLiteral("request"))) return false;
  36.  
  37.     if (np.get<bool>(QStringLiteral("isCancel"))) {
  38.         QString id = np.get<QString>(QStringLiteral("id"));
  39.         // cut off kdeconnect-android's prefix if there:
  40.         if (id.startsWith(QLatin1String("org.kde.kdeconnect_tp::")))
  41.             id = id.mid(id.indexOf(QLatin1String("::")) + 2);
  42.         removeNotification(id);
  43.         return true;
  44.     }
  45.  
  46.     QString id = np.get<QString>(QStringLiteral("id"));
  47.  
  48.     Notification* noti = nullptr;
  49.  
  50.     if (!m_internalIdToPublicId.contains(id)) {
  51.         noti = new Notification(np, device(), this);
  52.  
  53.         if (noti->isReady()) {
  54.             addNotification(noti);
  55.         } else {
  56.             connect(noti, &Notification::ready, this, &NotificationsPlugin::notificationReady);
  57.         }
  58.     } else {
  59.         QString pubId = m_internalIdToPublicId.value(id);
  60.         noti = m_notifications.value(pubId);
  61.         noti->update(np);
  62.     }
  63.  
  64.     return true;
  65. }
  66.  
  67. void NotificationsPlugin::clearNotifications()
  68. {
  69.     qDeleteAll(m_notifications);
  70.     m_notifications.clear();
  71.     Q_EMIT allNotificationsRemoved();
  72. }
  73.  
  74. QStringList NotificationsPlugin::activeNotifications()
  75. {
  76.     return m_notifications.keys();
  77. }
  78.  
  79. void NotificationsPlugin::notificationReady()
  80. {
  81.     Notification* noti = static_cast<Notification*>(sender());
  82.     disconnect(noti, &Notification::ready, this, &NotificationsPlugin::notificationReady);
  83.     addNotification(noti);
  84. }
  85.  
  86. void NotificationsPlugin::addNotification(Notification* noti)
  87. {
  88.     const QString& internalId = noti->internalId();
  89.  
  90.     if (m_internalIdToPublicId.contains(internalId)) {
  91.         removeNotification(internalId);
  92.     }
  93.  
  94.     //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "addNotification" << internalId;
  95.  
  96.     connect(noti, &Notification::dismissRequested,
  97.             this, &NotificationsPlugin::dismissRequested);
  98.  
  99.     connect(noti, &Notification::replyRequested, this, [this,noti]{
  100.         replyRequested(noti);
  101.     });
  102.  
  103.     connect(noti, &Notification::actionTriggered, this, &NotificationsPlugin::sendAction);
  104.     connect(noti, &Notification::replied, this, [this, noti](const QString& message){
  105.         sendReply(noti->replyId(), message);
  106.     });
  107.  
  108.     const QString& publicId = newId();
  109.     m_notifications[publicId] = noti;
  110.     m_internalIdToPublicId[internalId] = publicId;
  111.  
  112.     DBusHelper::sessionBus().registerObject(device()->dbusPath() + QStringLiteral("/notifications/") + publicId, noti, QDBusConnection::ExportScriptableContents);
  113.     Q_EMIT notificationPosted(publicId);
  114. }
  115.  
  116. void NotificationsPlugin::removeNotification(const QString& internalId)
  117. {
  118.     //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "removeNotification" << internalId;
  119.  
  120.     if (!m_internalIdToPublicId.contains(internalId)) {
  121.         qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Not found noti by internal Id: " << internalId;
  122.         return;
  123.     }
  124.  
  125.     QString publicId = m_internalIdToPublicId.take(internalId);
  126.  
  127.     Notification* noti = m_notifications.take(publicId);
  128.     if (!noti) {
  129.         qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Not found noti by public Id: " << publicId;
  130.         return;
  131.     }
  132.  
  133.     //Deleting the notification will unregister it automatically
  134.     noti->deleteLater();
  135.  
  136.     Q_EMIT notificationRemoved(publicId);
  137. }
  138.  
  139. void NotificationsPlugin::dismissRequested(const QString& internalId)
  140. {
  141.     NetworkPacket np(PACKET_TYPE_NOTIFICATION_REQUEST);
  142.     np.set<QString>(QStringLiteral("cancel"), internalId);
  143.     sendPacket(np);
  144.  
  145.     //Workaround: we erase notifications without waiting a response from the
  146.     //phone because we won't receive a response if we are out of sync and this
  147.     //notification no longer exists. Ideally, each time we reach the phone
  148.     //after some time disconnected we should re-sync all the notifications.
  149.     removeNotification(internalId);
  150. }
  151.  
  152. void NotificationsPlugin::replyRequested(Notification* noti)
  153. {
  154.     QString replyId = noti->replyId();
  155.     QString appName = noti->appName();
  156.     QString originalMessage = noti->ticker();
  157.     SendReplyDialog* dialog = new SendReplyDialog(originalMessage, replyId, appName);
  158.     connect(dialog, &SendReplyDialog::sendReply, this, &NotificationsPlugin::sendReply);
  159.     dialog->show();
  160. #if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
  161.     auto window = qobject_cast<QWindow*>(dialog->windowHandle());
  162.     if (window && QX11Info::isPlatformX11()) {
  163.         KStartupInfo::setNewStartupId(window, QX11Info::nextStartupId());
  164.     }
  165. #endif
  166.     dialog->raise();
  167. }
  168.  
  169. void NotificationsPlugin::sendReply(const QString& replyId, const QString& message)
  170. {
  171.     NetworkPacket np(PACKET_TYPE_NOTIFICATION_REPLY);
  172.     np.set<QString>(QStringLiteral("requestReplyId"), replyId);
  173.     np.set<QString>(QStringLiteral("message"), message);
  174.     sendPacket(np);
  175. }
  176.  
  177. void NotificationsPlugin::sendAction(const QString& key, const QString& action)
  178. {
  179.     NetworkPacket np(PACKET_TYPE_NOTIFICATION_ACTION);
  180.     np.set<QString>(QStringLiteral("key"), key);
  181.     np.set<QString>(QStringLiteral("action"), action);
  182.     sendPacket(np);
  183. }
  184.  
  185. QString NotificationsPlugin::newId()
  186. {
  187.     return QString::number(++m_lastId);
  188. }
  189.  
  190. QString NotificationsPlugin::dbusPath() const
  191. {
  192.     return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/notifications");
  193. }
  194.  
  195. #include "notificationsplugin.moc"
  196.  
RAW Paste Data