File indexing completed on 2024-04-14 04:54:21

0001 // SPDX-FileCopyrightText: 2022 Nicolas Fella <nicolas.fella@gmx.de>
0002 // SPDX-License-Identifier: GPL-2.0-or-later
0003 
0004 #pragma once
0005 
0006 #include <QDBusContext>
0007 #include <QObject>
0008 
0009 #include <QDBusArgument>
0010 #include <QList>
0011 #include <QString>
0012 #include <QVariantMap>
0013 
0014 #include "models/roomlistmodel.h"
0015 #include "models/sortfilterroomlistmodel.h"
0016 
0017 /**
0018  * The type of match. Value is important here as it is used for sorting
0019  *
0020  * Copied from KRunner/QueryMatch
0021  *
0022  * @sa KRunner/QueryMatch
0023  */
0024 enum MatchType {
0025     NoMatch = 0, /**< Null match */
0026     CompletionMatch = 10, /**< Possible completion for the data of the query */
0027     PossibleMatch = 30, /**< Something that may match the query */
0028     InformationalMatch = 50, /**< A purely informational, non-runnable match,
0029                                 such as the answer to a question or calculation.
0030                                 The data of the match will be converted to a string
0031                                 and set in the search field */
0032     HelperMatch = 70, /**< A match that represents an action not directly related
0033                             to activating the given search term, such as a search
0034                             in an external tool or a command learning trigger. Helper
0035                             matches tend to be generic to the query and should not
0036                             be autoactivated just because the user hits "Enter"
0037                             while typing. They must be explicitly selected to
0038                             be activated, but unlike InformationalMatch cause
0039                             an action to be triggered. */
0040     ExactMatch = 100, /**< An exact match to the query */
0041 };
0042 
0043 struct RemoteMatch {
0044     // sssuda{sv}
0045     QString id;
0046     QString text;
0047     QString iconName;
0048     MatchType type = MatchType::NoMatch;
0049     qreal relevance = 0;
0050     QVariantMap properties;
0051 };
0052 
0053 typedef QList<RemoteMatch> RemoteMatches;
0054 
0055 struct RemoteAction {
0056     QString id;
0057     QString text;
0058     QString iconName;
0059 };
0060 
0061 typedef QList<RemoteAction> RemoteActions;
0062 
0063 struct RemoteImage {
0064     // iiibiiay (matching notification spec image-data attribute)
0065     int width;
0066     int height;
0067     qsizetype rowStride;
0068     bool hasAlpha;
0069     int bitsPerSample;
0070     int channels;
0071     QByteArray data;
0072 };
0073 
0074 inline QDBusArgument &operator<<(QDBusArgument &argument, const RemoteMatch &match)
0075 {
0076     argument.beginStructure();
0077     argument << match.id;
0078     argument << match.text;
0079     argument << match.iconName;
0080     argument << match.type;
0081     argument << match.relevance;
0082     argument << match.properties;
0083     argument.endStructure();
0084     return argument;
0085 }
0086 
0087 inline const QDBusArgument &operator>>(const QDBusArgument &argument, RemoteMatch &match)
0088 {
0089     argument.beginStructure();
0090     argument >> match.id;
0091     argument >> match.text;
0092     argument >> match.iconName;
0093     uint type;
0094     argument >> type;
0095     match.type = static_cast<MatchType>(type);
0096     argument >> match.relevance;
0097     argument >> match.properties;
0098     argument.endStructure();
0099 
0100     return argument;
0101 }
0102 
0103 inline QDBusArgument &operator<<(QDBusArgument &argument, const RemoteAction &action)
0104 {
0105     argument.beginStructure();
0106     argument << action.id;
0107     argument << action.text;
0108     argument << action.iconName;
0109     argument.endStructure();
0110     return argument;
0111 }
0112 
0113 inline const QDBusArgument &operator>>(const QDBusArgument &argument, RemoteAction &action)
0114 {
0115     argument.beginStructure();
0116     argument >> action.id;
0117     argument >> action.text;
0118     argument >> action.iconName;
0119     argument.endStructure();
0120     return argument;
0121 }
0122 
0123 inline QDBusArgument &operator<<(QDBusArgument &argument, const RemoteImage &image)
0124 {
0125     argument.beginStructure();
0126     argument << image.width;
0127     argument << image.height;
0128     argument << image.rowStride;
0129     argument << image.hasAlpha;
0130     argument << image.bitsPerSample;
0131     argument << image.channels;
0132     argument << image.data;
0133     argument.endStructure();
0134     return argument;
0135 }
0136 
0137 inline const QDBusArgument &operator>>(const QDBusArgument &argument, RemoteImage &image)
0138 {
0139     argument.beginStructure();
0140     argument >> image.width;
0141     argument >> image.height;
0142     argument >> image.rowStride;
0143     argument >> image.hasAlpha;
0144     argument >> image.bitsPerSample;
0145     argument >> image.channels;
0146     argument >> image.data;
0147     argument.endStructure();
0148     return argument;
0149 }
0150 
0151 Q_DECLARE_METATYPE(RemoteMatch)
0152 Q_DECLARE_METATYPE(RemoteMatches)
0153 Q_DECLARE_METATYPE(RemoteAction)
0154 Q_DECLARE_METATYPE(RemoteActions)
0155 Q_DECLARE_METATYPE(RemoteImage)
0156 
0157 /**
0158  * @class Runner
0159  *
0160  * A class to define the NeoChat KRunner plugin.
0161  *
0162  * @sa KRunner
0163  */
0164 class Runner : public QObject, protected QDBusContext
0165 {
0166     Q_OBJECT
0167     Q_CLASSINFO("D-Bus Interface", "org.kde.krunner1")
0168     QML_ELEMENT
0169     QML_SINGLETON
0170 
0171     Q_PROPERTY(RoomListModel *roomListModel READ roomListModel WRITE setRoomListModel NOTIFY roomListModelChanged)
0172 public:
0173     static Runner *create(QQmlEngine *engine, QJSEngine *)
0174     {
0175         static Runner instance;
0176         engine->setObjectOwnership(&instance, QQmlEngine::CppOwnership);
0177         return &instance;
0178     }
0179 
0180     /**
0181      * @brief Return a list of KRunner actions.
0182      *
0183      * @note It's always empty; nothing is broken.
0184      */
0185     Q_SCRIPTABLE RemoteActions Actions();
0186 
0187     /**
0188      * @brief Return a list of room matches for a search.
0189      */
0190     Q_SCRIPTABLE RemoteMatches Match(const QString &searchTerm);
0191 
0192     /**
0193      * @brief Handle action calls.
0194      */
0195     Q_SCRIPTABLE void Run(const QString &id, const QString &actionId);
0196 
0197     void setRoomListModel(RoomListModel *roomListModel);
0198     RoomListModel *roomListModel() const;
0199 
0200 Q_SIGNALS:
0201     void roomListModelChanged();
0202 
0203 private:
0204     RemoteImage serializeImage(const QImage &image);
0205 
0206     SortFilterRoomListModel m_model;
0207     RoomListModel m_sourceModel;
0208     Runner();
0209 };