From da6b3eb8f44f9257aa7f7eb1b0e6a1b2f20cd0a5 Mon Sep 17 00:00:00 2001 From: Loren Burkholder <55629213+LorenDB@users.noreply.github.com> Date: Mon, 18 Apr 2022 12:50:15 -0400 Subject: [PATCH] D-Bus fixes (#1048) According to LorenDB's First Law of Software Development, once a developer has committed or merged a new feature, he will find at least one problem with the implementation. I realized that I was constructing the room info items with some parameters out of order, which required a rather urgent fix. Furthermore, I fixed the image decoding algorithms in the QDBusArgument operator. Finally, I switched the API version parameter back to QString, since passing it as a QVersionNumber would create a problem for non-Qt API users. On the general improvements side of things, I added some handy wrappers for D-Bus calls so that other devs that copy the NhekoDBusApi files to use for their own applications won't have to go to the effort of making the D-Bus calls themselves. --- src/dbus/NhekoDBusApi.cpp | 93 +++++++++++++++++++++++++---------- src/dbus/NhekoDBusApi.h | 27 +++++++--- src/dbus/NhekoDBusBackend.cpp | 6 +-- src/dbus/NhekoDBusBackend.h | 8 +-- 4 files changed, 95 insertions(+), 39 deletions(-) diff --git a/src/dbus/NhekoDBusApi.cpp b/src/dbus/NhekoDBusApi.cpp index 201cdac1..e55757e9 100644 --- a/src/dbus/NhekoDBusApi.cpp +++ b/src/dbus/NhekoDBusApi.cpp @@ -5,7 +5,9 @@ #include "NhekoDBusApi.h" +#include #include +#include namespace nheko::dbus { void @@ -14,18 +16,17 @@ init() qDBusRegisterMetaType(); qDBusRegisterMetaType>(); qDBusRegisterMetaType(); - qDBusRegisterMetaType(); } bool apiVersionIsCompatible(const QVersionNumber &clientAppVersion) { - if (clientAppVersion.majorVersion() != nheko::dbus::apiVersion.majorVersion()) + if (clientAppVersion.majorVersion() != nheko::dbus::dbusApiVersion.majorVersion()) return false; - if (clientAppVersion.minorVersion() > nheko::dbus::apiVersion.minorVersion()) + if (clientAppVersion.minorVersion() > nheko::dbus::dbusApiVersion.minorVersion()) return false; - if (clientAppVersion.minorVersion() == nheko::dbus::apiVersion.minorVersion() && - clientAppVersion.microVersion() < nheko::dbus::apiVersion.microVersion()) + if (clientAppVersion.minorVersion() == nheko::dbus::dbusApiVersion.minorVersion() && + clientAppVersion.microVersion() < nheko::dbus::dbusApiVersion.microVersion()) return false; return true; @@ -87,6 +88,61 @@ operator>>(const QDBusArgument &arg, RoomInfoItem &item) arg.endStructure(); return arg; } + +QString +apiVersion() +{ + if (QDBusInterface interface{QStringLiteral(NHEKO_DBUS_SERVICE_NAME), QStringLiteral("/")}; + interface.isValid()) + return QDBusReply{interface.call(QStringLiteral("apiVersion"))}.value(); + else + return {}; +} + +QString +nhekoVersion() +{ + if (QDBusInterface interface{QStringLiteral(NHEKO_DBUS_SERVICE_NAME), QStringLiteral("/")}; + interface.isValid()) + return QDBusReply{interface.call(QStringLiteral("nhekoVersion"))}.value(); + else + return {}; +} + +QVector +rooms() +{ + if (QDBusInterface interface{QStringLiteral(NHEKO_DBUS_SERVICE_NAME), QStringLiteral("/")}; + interface.isValid()) + return QDBusReply>{interface.call(QStringLiteral("rooms"))} + .value(); + else + return {}; +} + +void +activateRoom(const QString &alias) +{ + if (QDBusInterface interface{QStringLiteral(NHEKO_DBUS_SERVICE_NAME), QStringLiteral("/")}; + interface.isValid()) + interface.call(QDBus::NoBlock, QStringLiteral("activateRoom"), alias); +} + +void +joinRoom(const QString &alias) +{ + if (QDBusInterface interface{QStringLiteral(NHEKO_DBUS_SERVICE_NAME), QStringLiteral("/")}; + interface.isValid()) + interface.call(QDBus::NoBlock, QStringLiteral("joinRoom"), alias); +} + +void +directChat(const QString &userId) +{ + if (QDBusInterface interface{QStringLiteral(NHEKO_DBUS_SERVICE_NAME), QStringLiteral("/")}; + interface.isValid()) + interface.call(QDBus::NoBlock, QStringLiteral("directChat"), userId); +} } // nheko::dbus /** @@ -140,27 +196,12 @@ operator>>(const QDBusArgument &arg, QImage &image) arg >> width >> height >> garbage >> garbage >> garbage >> garbage >> bits; arg.endStructure(); - image = QImage(reinterpret_cast(bits.data()), width, height, QImage::Format_RGBA8888); + // Unfortunately, this copy-and-detach is necessary to ensure that the source buffer + // is copied properly. If anybody finds a better solution, please implement it. + auto temp = + QImage(reinterpret_cast(bits.data()), width, height, QImage::Format_RGBA8888); + image = temp; + image.detach(); return arg; } - -QDBusArgument & -operator<<(QDBusArgument &arg, const QVersionNumber &v) -{ - arg.beginStructure(); - arg << v.toString(); - arg.endStructure(); - return arg; -} - -const QDBusArgument & -operator>>(const QDBusArgument &arg, QVersionNumber &v) -{ - arg.beginStructure(); - QString temp; - arg >> temp; - v = QVersionNumber::fromString(temp); - arg.endStructure(); - return arg; -} diff --git a/src/dbus/NhekoDBusApi.h b/src/dbus/NhekoDBusApi.h index d2754f24..984ac763 100644 --- a/src/dbus/NhekoDBusApi.h +++ b/src/dbus/NhekoDBusApi.h @@ -18,7 +18,7 @@ init(); //! The nheko D-Bus API version provided by this file. The API version number follows semantic //! versioning as defined by https://semver.org. -const QVersionNumber apiVersion{0, 0, 1}; +const QVersionNumber dbusApiVersion{0, 0, 1}; //! Compare the installed Nheko API to the version that your client app targets to see if they //! are compatible. @@ -58,6 +58,26 @@ private: int unreadNotifications_; }; +//! Get the nheko D-Bus API version. +QString +apiVersion(); +//! Get the nheko version. +QString +nhekoVersion(); +//! Call this function to get a list of all joined rooms. +QVector +rooms(); +//! Activates a currently joined room. +void +activateRoom(const QString &alias); +//! Joins a room. It is your responsibility to ask for confirmation (if desired). +void +joinRoom(const QString &alias); +//! Starts or activates a direct chat. It is your responsibility to ask for confirmation (if +//! desired). +void +directChat(const QString &userId); + QDBusArgument & operator<<(QDBusArgument &arg, const RoomInfoItem &item); const QDBusArgument & @@ -70,11 +90,6 @@ operator<<(QDBusArgument &arg, const QImage &image); const QDBusArgument & operator>>(const QDBusArgument &arg, QImage &); -QDBusArgument & -operator<<(QDBusArgument &arg, const QVersionNumber &v); -const QDBusArgument & -operator>>(const QDBusArgument &arg, QVersionNumber &v); - #define NHEKO_DBUS_SERVICE_NAME "im.nheko.Nheko" #endif // NHEKODBUSAPI_H diff --git a/src/dbus/NhekoDBusBackend.cpp b/src/dbus/NhekoDBusBackend.cpp index 7c1c77f8..f0ed9df1 100644 --- a/src/dbus/NhekoDBusBackend.cpp +++ b/src/dbus/NhekoDBusBackend.cpp @@ -19,7 +19,7 @@ NhekoDBusBackend::NhekoDBusBackend(RoomlistModel *parent) {} QVector -NhekoDBusBackend::getRooms(const QDBusMessage &message) +NhekoDBusBackend::rooms(const QDBusMessage &message) { const auto roomListModel = m_parent->models; QSharedPointer> model{ @@ -39,7 +39,7 @@ NhekoDBusBackend::getRooms(const QDBusMessage &message) } model->push_back(nheko::dbus::RoomInfoItem{ - room->roomId(), room->roomName(), alias, image, room->notificationCount()}); + room->roomId(), alias, room->roomName(), image, room->notificationCount()}); if (model->length() == roomListModelSize) { auto reply = message.createReply(); @@ -81,7 +81,7 @@ NhekoDBusBackend::joinRoom(const QString &alias) const } void -NhekoDBusBackend::startDirectChat(const QString &userId) const +NhekoDBusBackend::directChat(const QString &userId) const { bringWindowToTop(); ChatPage::instance()->startChat(userId); diff --git a/src/dbus/NhekoDBusBackend.h b/src/dbus/NhekoDBusBackend.h index 02fd87d5..05d686ca 100644 --- a/src/dbus/NhekoDBusBackend.h +++ b/src/dbus/NhekoDBusBackend.h @@ -23,18 +23,18 @@ public: public slots: //! Get the nheko D-Bus API version. - Q_SCRIPTABLE QVersionNumber apiVersion() const { return nheko::dbus::apiVersion; } + Q_SCRIPTABLE QString apiVersion() const { return nheko::dbus::dbusApiVersion.toString(); } //! Get the nheko version. - Q_SCRIPTABLE QString nhekoVersionString() const { return nheko::version; } + Q_SCRIPTABLE QString nhekoVersion() const { return nheko::version; } //! Call this function to get a list of all joined rooms. - Q_SCRIPTABLE QVector getRooms(const QDBusMessage &message); + Q_SCRIPTABLE QVector rooms(const QDBusMessage &message); //! Activates a currently joined room. Q_SCRIPTABLE void activateRoom(const QString &alias) const; //! Joins a room. It is your responsibility to ask for confirmation (if desired). Q_SCRIPTABLE void joinRoom(const QString &alias) const; //! Starts or activates a direct chat. It is your responsibility to ask for confirmation (if //! desired). - Q_SCRIPTABLE void startDirectChat(const QString &userId) const; + Q_SCRIPTABLE void directChat(const QString &userId) const; private: void bringWindowToTop() const;