[OpenDocString] kdeconnect-kde (cpp)
notificationsplugin.cpp
NotificationsPlugin::NotificationsPlugin(QObject *parent, const QVariantList &args)
    : KdeConnectPlugin(parent, args)
{
}
Constructs a KdeConnectPlugin object and assigns args to it.
void NotificationsPlugin::connected()
{
    NetworkPacket np(PACKET_TYPE_NOTIFICATION_REQUEST, {{QStringLiteral("request"), true}});
    sendPacket(np);
}
This sends a network packet that requests a notification of a type from the plugin.
bool NotificationsPlugin::receivePacket(const NetworkPacket &np)
{
    if (np.get(QStringLiteral("request")))
        return false;

    if (np.get(QStringLiteral("isCancel"))) {
        QString id = np.get(QStringLiteral("id"));
        // cut off kdeconnect-android's prefix if there:
        if (id.startsWith(QLatin1String("org.kde.kdeconnect_tp::")))
            id = id.mid(id.indexOf(QLatin1String("::")) + 2);
        removeNotification(id);
        return true;
    }

    QString id = np.get(QStringLiteral("id"));

    Notification *noti = nullptr;

    if (!m_internalIdToPublicId.contains(id)) {
        noti = new Notification(np, device(), this);

        if (noti->isReady()) {
            addNotification(noti);
        } else {
            connect(noti, &Notification::ready, this, &NotificationsPlugin::notificationReady);
        }
    } else {
        QString pubId = m_internalIdToPublicId.value(id);
        noti = m_notifications.value(pubId);
        noti->update(np);
    }

    return true;
}
This creates a Notification object, if it doesn't exist, and updates it. It returns true on the first successful attempt. If the isCancel flag is set, the method returns true. If the id is not present, the method creates one and connects the notification to the device's public id. If the id is not present, the method creates it and sets the signal isReady.
void NotificationsPlugin::clearNotifications()
{
    qDeleteAll(m_notifications);
    m_notifications.clear();
    Q_EMIT allNotificationsRemoved();
}
This removes all notifications from the internal list and emits the allNotificationsRemoved signal.
QStringList NotificationsPlugin::activeNotifications()
{
    return m_notifications.keys();
}
Returns the list of active notifications.
void NotificationsPlugin::notificationReady()
{
    Notification *noti = static_cast(sender());
    disconnect(noti, &Notification::ready, this, &NotificationsPlugin::notificationReady);
    addNotification(noti);
}
This creates a notification object from the sender of the plugin, and disconnects from the sender, and adds it to the list of notices.
void NotificationsPlugin::addNotification(Notification *noti)
{
    const QString &internalId = noti->internalId();

    if (m_internalIdToPublicId.contains(internalId)) {
        removeNotification(internalId);
    }

    // qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "addNotification" << internalId;

    connect(noti, &Notification::dismissRequested, this, &NotificationsPlugin::dismissRequested);

    connect(noti, &Notification::replyRequested, this, [this, noti] {
        replyRequested(noti);
    });

    connect(noti, &Notification::actionTriggered, this, &NotificationsPlugin::sendAction);
    connect(noti, &Notification::replied, this, [this, noti](const QString &message) {
        sendReply(noti->replyId(), message);
    });

    const QString &publicId = newId();
    m_notifications[publicId] = noti;
    m_internalIdToPublicId[internalId] = publicId;

    QDBusConnection::sessionBus().registerObject(device()->dbusPath() + QStringLiteral("/notifications/") + publicId,
                                                 noti,
                                                 QDBusConnection::ExportScriptableContents);
    Q_EMIT notificationPosted(publicId);
}
This adds a notification object to the internal list of notifiers. It removes the notification from the internal list, and sets up signal/slot connections for the public id, as well creates a new one. It also emits the signal notificationPosted.
void NotificationsPlugin::removeNotification(const QString &internalId)
{
    // qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "removeNotification" << internalId;

    if (!m_internalIdToPublicId.contains(internalId)) {
        qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Not found noti by internal Id: " << internalId;
        return;
    }

    QString publicId = m_internalIdToPublicId.take(internalId);

    Notification *noti = m_notifications.take(publicId);
    if (!noti) {
        qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Not found noti by public Id: " << publicId;
        return;
    }

    // Deleting the notification will unregister it automatically
    noti->deleteLater();

    Q_EMIT notificationRemoved(publicId);
}
This removes the notification of the given internal id, if it exists. It first checks if the internal id list contains the internal id, then checks if the list contains the notification of the given internal id. Then it gets the notification of the given public id, and if it exists, it deletes the notification and emits the notificationRemoved signal.
void NotificationsPlugin::dismissRequested(const QString &internalId)
{
    NetworkPacket np(PACKET_TYPE_NOTIFICATION_REQUEST);
    np.set(QStringLiteral("cancel"), internalId);
    sendPacket(np);

    // Workaround: we erase notifications without waiting a response from the
    // phone because we won't receive a response if we are out of sync and this
    // notification no longer exists. Ideally, each time we reach the phone
    // after some time disconnected we should re-sync all the notifications.
    removeNotification(internalId);
}
This sends a network packet and removes the notification of the given internal id.
void NotificationsPlugin::replyRequested(Notification *noti)
{
    QString replyId = noti->replyId();
    QString appName = noti->appName();
    QString originalMessage = noti->ticker();
    SendReplyDialog *dialog = new SendReplyDialog(originalMessage, replyId, appName);
    connect(dialog, &SendReplyDialog::sendReply, this, &NotificationsPlugin::sendReply);
    dialog->show();
#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
    auto window = qobject_cast(dialog->windowHandle());
    if (window && QX11Info::isPlatformX11()) {
        KStartupInfo::setNewStartupId(window, QX11Info::nextStartupId());
    }
#endif
    dialog->raise();
}
This sends a reply to the given notification. It takes the reply id and app name, and creates a send reply dialog. It also sets the new startup id for the window if possible.
void NotificationsPlugin::sendReply(const QString &replyId, const QString &message)
{
    NetworkPacket np(PACKET_TYPE_NOTIFICATION_REPLY);
    np.set(QStringLiteral("requestReplyId"), replyId);
    np.set(QStringLiteral("message"), message);
    sendPacket(np);
}
This sends a reply to a specific reply id and a message.
void NotificationsPlugin::sendAction(const QString &key, const QString &action)
{
    NetworkPacket np(PACKET_TYPE_NOTIFICATION_ACTION);
    np.set(QStringLiteral("key"), key);
    np.set(QStringLiteral("action"), action);
    sendPacket(np);
}
This sends a notification action packet to the server.
QString NotificationsPlugin::newId()
{
    return QString::number(++m_lastId);
}
Returns a new id.
QString NotificationsPlugin::dbusPath() const
{
    return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/notifications");
}
Returns the dbus path as a QString.