From eca077cfdb9d92a3f2fa29d65e71ae6c213923f4 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 26 Jan 2018 10:37:44 +0900 Subject: CreateRoomJob: Update to the latest Spec version --- jobs/generated/create_room.cpp | 3 ++- jobs/generated/create_room.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/jobs/generated/create_room.cpp b/jobs/generated/create_room.cpp index be06873a..de7807b5 100644 --- a/jobs/generated/create_room.cpp +++ b/jobs/generated/create_room.cpp @@ -74,7 +74,7 @@ class CreateRoomJob::Private QString roomId; }; -CreateRoomJob::CreateRoomJob(const QString& visibility, const QString& roomAliasName, const QString& name, const QString& topic, const QVector& invite, const QVector& invite3pid, const QJsonObject& creationContent, const QVector& initialState, const QString& preset, bool isDirect) +CreateRoomJob::CreateRoomJob(const QString& visibility, const QString& roomAliasName, const QString& name, const QString& topic, const QVector& invite, const QVector& invite3pid, const QJsonObject& creationContent, const QVector& initialState, const QString& preset, bool isDirect, bool guestCanJoin) : BaseJob(HttpVerb::Post, "CreateRoomJob", basePath % "/createRoom") , d(new Private) @@ -95,6 +95,7 @@ CreateRoomJob::CreateRoomJob(const QString& visibility, const QString& roomAlias if (!preset.isEmpty()) _data.insert("preset", toJson(preset)); _data.insert("is_direct", toJson(isDirect)); + _data.insert("guest_can_join", toJson(guestCanJoin)); setRequestData(_data); } diff --git a/jobs/generated/create_room.h b/jobs/generated/create_room.h index 13c9d2c0..b479615a 100644 --- a/jobs/generated/create_room.h +++ b/jobs/generated/create_room.h @@ -40,7 +40,7 @@ namespace QMatrixClient // End of inner data structures - explicit CreateRoomJob(const QString& visibility = {}, const QString& roomAliasName = {}, const QString& name = {}, const QString& topic = {}, const QVector& invite = {}, const QVector& invite3pid = {}, const QJsonObject& creationContent = {}, const QVector& initialState = {}, const QString& preset = {}, bool isDirect = {}); + explicit CreateRoomJob(const QString& visibility = {}, const QString& roomAliasName = {}, const QString& name = {}, const QString& topic = {}, const QVector& invite = {}, const QVector& invite3pid = {}, const QJsonObject& creationContent = {}, const QVector& initialState = {}, const QString& preset = {}, bool isDirect = {}, bool guestCanJoin = {}); ~CreateRoomJob() override; const QString& roomId() const; -- cgit v1.2.3 From 2393ea6a1c43f2e7ac7bcb5d7fb4915cec09f2e3 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 26 Jan 2018 20:53:01 +0900 Subject: Connection class cleanup createRoom and createUser renamed to roomFactory and userFactory (because createRoom will mean a different thing); unneeded #include moved to the cpp file. --- connection.cpp | 9 +++++---- connection.h | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/connection.cpp b/connection.cpp index c515e5a4..51a73e8d 100644 --- a/connection.cpp +++ b/connection.cpp @@ -24,6 +24,7 @@ #include "jobs/generated/login.h" #include "jobs/generated/logout.h" #include "jobs/generated/receipts.h" +#include "jobs/generated/leaving.h" #include "jobs/sendeventjob.h" #include "jobs/joinroomjob.h" #include "jobs/roommessagesjob.h" @@ -437,7 +438,7 @@ User* Connection::user(const QString& userId) { if( d->userMap.contains(userId) ) return d->userMap.value(userId); - auto* user = createUser(this, userId); + auto* user = userFactory(this, userId); d->userMap.insert(userId, user); return user; } @@ -515,7 +516,7 @@ Room* Connection::provideRoom(const QString& id, JoinState joinState) } else { - room = createRoom(this, id, joinState); + room = roomFactory(this, id, joinState); if (!room) { qCCritical(MAIN) << "Failed to create a room" << id; @@ -550,11 +551,11 @@ Room* Connection::provideRoom(const QString& id, JoinState joinState) return room; } -Connection::room_factory_t Connection::createRoom = +Connection::room_factory_t Connection::roomFactory = [](Connection* c, const QString& id, JoinState joinState) { return new Room(c, id, joinState); }; -Connection::user_factory_t Connection::createUser = +Connection::user_factory_t Connection::userFactory = [](Connection* c, const QString& id) { return new User(id, c); }; QByteArray Connection::generateTxnId() diff --git a/connection.h b/connection.h index 79d7d658..b9aa328b 100644 --- a/connection.h +++ b/connection.h @@ -18,7 +18,6 @@ #pragma once -#include "jobs/generated/leaving.h" #include "joinstate.h" #include @@ -39,6 +38,7 @@ namespace QMatrixClient class SyncData; class RoomMessagesJob; class PostReceiptJob; + class ForgetRoomJob; class MediaThumbnailJob; class JoinRoomJob; class UploadContentJob; @@ -145,7 +145,7 @@ namespace QMatrixClient template static void setRoomType() { - createRoom = + roomFactory = [](Connection* c, const QString& id, JoinState joinState) { return new T(c, id, joinState); }; } @@ -153,7 +153,7 @@ namespace QMatrixClient template static void setUserType() { - createUser = + userFactory = [](Connection* c, const QString& id) { return new T(id, c); }; } @@ -186,15 +186,15 @@ namespace QMatrixClient int requestedHeight) const; // QIODevice* should already be open - virtual UploadContentJob* uploadContent(QIODevice* contentSource, + UploadContentJob* uploadContent(QIODevice* contentSource, const QString& filename = {}, const QString& contentType = {}) const; - virtual UploadContentJob* uploadFile(const QString& fileName, - const QString& contentType = {}); - virtual GetContentJob* getContent(const QString& mediaId) const; + UploadContentJob* uploadFile(const QString& fileName, + const QString& contentType = {}); + GetContentJob* getContent(const QString& mediaId) const; GetContentJob* getContent(const QUrl& url) const; // If localFilename is empty, a temporary file will be created - virtual DownloadFileJob* downloadFile(const QUrl& url, + DownloadFileJob* downloadFile(const QUrl& url, const QString& localFilename = {}) const; virtual JoinRoomJob* joinRoom(const QString& roomAlias); @@ -310,7 +310,7 @@ namespace QMatrixClient * the server; in particular, does not automatically create rooms * on the server. * @return a pointer to a Room object with the specified id; nullptr - * if roomId is empty if createRoom() failed to create a Room object. + * if roomId is empty if roomFactory() failed to create a Room object. */ Room* provideRoom(const QString& roomId, JoinState joinState); @@ -340,7 +340,7 @@ namespace QMatrixClient const QString& initialDeviceName, const QString& deviceId = {}); - static room_factory_t createRoom; - static user_factory_t createUser; + static room_factory_t roomFactory; + static user_factory_t userFactory; }; } // namespace QMatrixClient -- cgit v1.2.3 From 096fbd4ed4033bbf770769b50ed709862c369281 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 26 Jan 2018 20:54:13 +0900 Subject: Connection::createRoom and Connection::createDirectChat --- connection.cpp | 21 +++++++++++++++++++++ connection.h | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/connection.cpp b/connection.cpp index 51a73e8d..00116c5f 100644 --- a/connection.cpp +++ b/connection.cpp @@ -386,6 +386,27 @@ DownloadFileJob* Connection::downloadFile(const QUrl& url, return job; } +CreateRoomJob* Connection::createRoom(RoomVisibility visibility, + const QString& alias, const QString& name, const QString& topic, + const QVector& invites, const QString& presetName, + bool isDirect, bool guestsCanJoin, + const QVector& initialState, + const QVector& invite3pids, + const QJsonObject creationContent) +{ + return callApi( + visibility == PublishRoom ? "public" : "private", alias, name, + topic, invites, invite3pids, creationContent, initialState, + presetName, isDirect, guestsCanJoin); +} + +CreateRoomJob* Connection::createDirectChat(const QString& userId, + const QString& topic, const QString& name) +{ + return createRoom(UnpublishRoom, "", name, topic, {userId}, + "trusted_private_chat", true); +} + ForgetRoomJob* Connection::forgetRoom(const QString& id) { // To forget is hard :) First we should ensure the local user is not diff --git a/connection.h b/connection.h index b9aa328b..47f8e4de 100644 --- a/connection.h +++ b/connection.h @@ -18,6 +18,7 @@ #pragma once +#include "jobs/generated/create_room.h" #include "joinstate.h" #include @@ -58,6 +59,8 @@ namespace QMatrixClient using user_factory_t = std::function; + enum RoomVisibility { PublishRoom, UnpublishRoom }; // FIXME: Should go inside CreateRoomJob + explicit Connection(QObject* parent = nullptr); explicit Connection(const QUrl& server, QObject* parent = nullptr); virtual ~Connection(); @@ -197,6 +200,23 @@ namespace QMatrixClient DownloadFileJob* downloadFile(const QUrl& url, const QString& localFilename = {}) const; + /** + * \brief Create a room (generic method) + * This method allows to customize room entirely to your liking, + * providing all the attributes the original CS API provides. + */ + CreateRoomJob* createRoom(RoomVisibility visibility, + const QString& alias, const QString& name, const QString& topic, + const QVector& invites, const QString& presetName = {}, bool isDirect = false, + bool guestsCanJoin = false, + const QVector& initialState = {}, + const QVector& invite3pids = {}, + const QJsonObject creationContent = {}); + + /** Create a direct chat with a single user, optional name and topic */ + CreateRoomJob* createDirectChat(const QString& userId, + const QString& topic = {}, const QString& name = {}); + virtual JoinRoomJob* joinRoom(const QString& roomAlias); // Old API that will be abolished any time soon. DO NOT USE. -- cgit v1.2.3 From fcb0342410beaacc84c59813a1a7b6195c6abf7f Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 30 Jan 2018 15:13:35 +0900 Subject: Connection: more Q_PROPERTYs, newUser signal --- connection.cpp | 1 + connection.h | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/connection.cpp b/connection.cpp index 00116c5f..01d7461d 100644 --- a/connection.cpp +++ b/connection.cpp @@ -461,6 +461,7 @@ User* Connection::user(const QString& userId) return d->userMap.value(userId); auto* user = userFactory(this, userId); d->userMap.insert(userId, user); + emit newUser(user); return user; } diff --git a/connection.h b/connection.h index 47f8e4de..792ed126 100644 --- a/connection.h +++ b/connection.h @@ -52,6 +52,11 @@ namespace QMatrixClient /** Whether or not the rooms state should be cached locally * \sa loadState(), saveState() */ + Q_PROPERTY(User* localUser READ user CONSTANT) + Q_PROPERTY(QString localUserId READ userId CONSTANT) + Q_PROPERTY(QString deviceId READ deviceId CONSTANT) + Q_PROPERTY(QByteArray accessToken READ accessToken CONSTANT) + Q_PROPERTY(QUrl homeserver READ homeserver WRITE setHomeserver NOTIFY homeserverChanged) Q_PROPERTY(bool cacheState READ cacheState WRITE setCacheState NOTIFY cacheStateChanged) public: using room_factory_t = @@ -83,14 +88,14 @@ namespace QMatrixClient // FIXME: Convert Q_INVOKABLEs to Q_PROPERTIES // (breaks back-compatibility) - Q_INVOKABLE QUrl homeserver() const; + QUrl homeserver() const; Q_INVOKABLE User* user(const QString& userId); - Q_INVOKABLE User* user(); - Q_INVOKABLE QString userId() const; - Q_INVOKABLE QString deviceId() const; + User* user(); + QString userId() const; + QString deviceId() const; /** @deprecated Use accessToken() instead. */ Q_INVOKABLE QString token() const; - Q_INVOKABLE QByteArray accessToken() const; + QByteArray accessToken() const; Q_INVOKABLE SyncJob* syncJob() const; Q_INVOKABLE int millisToReconnect() const; @@ -257,6 +262,8 @@ namespace QMatrixClient void syncDone(); void syncError(QString error); + void newUser(User* user); + /** * \group Signals emitted on room transitions * @@ -364,3 +371,4 @@ namespace QMatrixClient static user_factory_t userFactory; }; } // namespace QMatrixClient +Q_DECLARE_METATYPE(QMatrixClient::Connection*) -- cgit v1.2.3 From 038471e340c51f36f612fbb19d8a2b60a9923973 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 30 Jan 2018 15:35:06 +0900 Subject: Connection: expose the list of users; use an ordered map It's still an open question whether it's better to store a separate sorted index of users, next to an unsorted one; but a sorted list of users is of much more use in GUI than an unsorted one. --- connection.cpp | 7 ++++++- connection.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/connection.cpp b/connection.cpp index 01d7461d..e06baef7 100644 --- a/connection.cpp +++ b/connection.cpp @@ -62,7 +62,7 @@ class Connection::Private // Leave state of the same room. QHash, Room*> roomMap; QVector roomIdsToForget; - QHash userMap; + QMap userMap; QString userId; SyncJob* syncJob = nullptr; @@ -516,6 +516,11 @@ QHash< QPair, Room* > Connection::roomMap() const return roomMap; } +QMap Connection::users() const +{ + return d->userMap; +} + const ConnectionData* Connection::connectionData() const { return d->data.get(); diff --git a/connection.h b/connection.h index 792ed126..2f7c38b3 100644 --- a/connection.h +++ b/connection.h @@ -71,6 +71,7 @@ namespace QMatrixClient virtual ~Connection(); QHash, Room*> roomMap() const; + QMap users() const; /** Sends /forget to the server and also deletes room locally. * This method is in Connection, not in Room, since it's a -- cgit v1.2.3 From db5d99c8b3f68b116fc55a4563bb66db4bf82cf8 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 30 Jan 2018 16:17:03 +0900 Subject: Fix compatibility with Qt before 5.10 --- user.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user.cpp b/user.cpp index 6cc2e0a5..7217413b 100644 --- a/user.cpp +++ b/user.cpp @@ -70,7 +70,7 @@ QString User::id() const bool User::isGuest() const { - Q_ASSERT(!d->userId.isEmpty() && d->userId.front() == '@'); + Q_ASSERT(!d->userId.isEmpty() && d->userId.startsWith('@')); auto it = std::find_if_not(d->userId.begin() + 1, d->userId.end(), std::mem_fn(&QChar::isDigit)); Q_ASSERT(it == d->userId.end()); -- cgit v1.2.3 From db398e7134f3a7b6cd7f4281add1decfeb961a55 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 30 Jan 2018 16:47:14 +0900 Subject: Room: setName(), setCanonicalAlias() --- room.cpp | 11 +++++++++++ room.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/room.cpp b/room.cpp index d5079711..4270875c 100644 --- a/room.cpp +++ b/room.cpp @@ -862,6 +862,17 @@ void Room::postMessage(const RoomMessageEvent& event) connection()->callApi(id(), event); } +void Room::setName(const QString& newName) +{ + connection()->callApi(id(), RoomNameEvent(newName)); +} + +void Room::setCanonicalAlias(const QString& newAlias) +{ + connection()->callApi(id(), + RoomCanonicalAliasEvent(newAlias)); +} + void Room::setTopic(const QString& newTopic) { RoomTopicEvent evt(newTopic); diff --git a/room.h b/room.h index b908a763..0a9bc2b8 100644 --- a/room.h +++ b/room.h @@ -235,6 +235,8 @@ namespace QMatrixClient /** @deprecated If you have a custom event type, construct the event * and pass it as a whole to postMessage() */ void postMessage(const QString& type, const QString& plainText); + void setName(const QString& newName); + void setCanonicalAlias(const QString& newAlias); void setTopic(const QString& newTopic); void getPreviousContent(int limit = 10); -- cgit v1.2.3 From 0a80e38c1b425322d96dc662c6d47e3ca5fc2c86 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 30 Jan 2018 16:49:05 +0900 Subject: Fix compilation with Clang Did two QChar::isDigit() overloads, one static and one member, confuse it? --- user.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user.cpp b/user.cpp index 7217413b..b07cf688 100644 --- a/user.cpp +++ b/user.cpp @@ -72,7 +72,7 @@ bool User::isGuest() const { Q_ASSERT(!d->userId.isEmpty() && d->userId.startsWith('@')); auto it = std::find_if_not(d->userId.begin() + 1, d->userId.end(), - std::mem_fn(&QChar::isDigit)); + [] (QChar c) { return c.isDigit(); }); Q_ASSERT(it == d->userId.end()); return *it == ':'; } -- cgit v1.2.3 From 86c41b9d233918ebc3312d19fc8f702a0f5da789 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 30 Jan 2018 20:36:52 +0900 Subject: User: Fixes in newly introduced methods --- user.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user.cpp b/user.cpp index b07cf688..c80ec883 100644 --- a/user.cpp +++ b/user.cpp @@ -73,7 +73,7 @@ bool User::isGuest() const Q_ASSERT(!d->userId.isEmpty() && d->userId.startsWith('@')); auto it = std::find_if_not(d->userId.begin() + 1, d->userId.end(), [] (QChar c) { return c.isDigit(); }); - Q_ASSERT(it == d->userId.end()); + Q_ASSERT(it != d->userId.end()); return *it == ':'; } @@ -139,7 +139,7 @@ QString User::displayname() const QString User::fullName() const { return d->name.isEmpty() ? d->userId : - d->name % '(' % d->userId % ')'; + d->name % " (" % d->userId % ')'; } QString User::bridged() const -- cgit v1.2.3