From f2e59227aa325e060319e8ee86b8368bef4f4240 Mon Sep 17 00:00:00 2001 From: Roman Plášil Date: Fri, 20 Oct 2017 16:18:25 +0800 Subject: Try using wildcard for qmake project file --- libqmatrixclient.pri | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'libqmatrixclient.pri') diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri index 36f6429c..dcdf1709 100644 --- a/libqmatrixclient.pri +++ b/libqmatrixclient.pri @@ -24,14 +24,11 @@ HEADERS += \ $$PWD/jobs/sendeventjob.h \ $$PWD/jobs/postreceiptjob.h \ $$PWD/jobs/joinroomjob.h \ - $$PWD/jobs/leaveroomjob.h \ $$PWD/jobs/roommessagesjob.h \ $$PWD/jobs/syncjob.h \ $$PWD/jobs/mediathumbnailjob.h \ - $$PWD/jobs/logoutjob.h \ $$PWD/jobs/setroomstatejob.h \ - $$PWD/jobs/generated/inviting.h \ - $$PWD/jobs/generated/kicking.h \ + $$files($$PWD/jobs/generated/*.h, false) \ $$PWD/logging.h \ $$PWD/settings.h @@ -55,13 +52,10 @@ SOURCES += \ $$PWD/jobs/sendeventjob.cpp \ $$PWD/jobs/postreceiptjob.cpp \ $$PWD/jobs/joinroomjob.cpp \ - $$PWD/jobs/leaveroomjob.cpp \ $$PWD/jobs/roommessagesjob.cpp \ $$PWD/jobs/syncjob.cpp \ $$PWD/jobs/mediathumbnailjob.cpp \ - $$PWD/jobs/logoutjob.cpp \ $$PWD/jobs/setroomstatejob.cpp \ - $$PWD/jobs/generated/inviting.cpp \ - $$PWD/jobs/generated/kicking.cpp \ + $$files($$PWD/jobs/generated/*.cpp, false) \ $$PWD/logging.cpp \ $$PWD/settings.cpp -- cgit v1.2.3 From 34faa56649f04fafd6ace276ba186070f41901be Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 20 Oct 2017 20:16:23 +0900 Subject: Better support of qmake qmc-example.pro added; better CONFIG for libqmatrixclient; refreshed files list. Closes #104 --- .travis.yml | 2 ++ libqmatrixclient.pri | 4 ++-- qmc-example.pro | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 qmc-example.pro (limited to 'libqmatrixclient.pri') diff --git a/.travis.yml b/.travis.yml index 24a182cf..313d1408 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,8 @@ install: - cmake .. script: - cmake --build . --target all + - cd .. + - qmake qmc-example.pro && make all notifications: webhooks: urls: diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri index dcdf1709..e974bda2 100644 --- a/libqmatrixclient.pri +++ b/libqmatrixclient.pri @@ -1,5 +1,5 @@ QT += network -CONFIG += c++11 +CONFIG += c++11 warn_on rtti_off INCLUDEPATH += $$PWD @@ -8,7 +8,7 @@ HEADERS += \ $$PWD/connection.h \ $$PWD/room.h \ $$PWD/user.h \ - $$PWD/state.h \ + $$PWD/util.h \ $$PWD/events/event.h \ $$PWD/events/roommessageevent.h \ $$PWD/events/roomnameevent.h \ diff --git a/qmc-example.pro b/qmc-example.pro new file mode 100644 index 00000000..4dc3fed1 --- /dev/null +++ b/qmc-example.pro @@ -0,0 +1,7 @@ +TEMPLATE = app + +windows { CONFIG += console } + +include(libqmatrixclient.pri) + +SOURCES += examples/qmc-example.cpp -- cgit v1.2.3 From c287d335da0d2ae6609dd090d45a89c6b8974af0 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 27 Oct 2017 14:43:58 +0300 Subject: Fixed building with qmake --- libqmatrixclient.pri | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'libqmatrixclient.pri') diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri index e974bda2..9bcb911f 100644 --- a/libqmatrixclient.pri +++ b/libqmatrixclient.pri @@ -8,8 +8,10 @@ HEADERS += \ $$PWD/connection.h \ $$PWD/room.h \ $$PWD/user.h \ + $$PWD/avatar.h \ $$PWD/util.h \ $$PWD/events/event.h \ + $$PWD/events/eventcontent.h \ $$PWD/events/roommessageevent.h \ $$PWD/events/roomnameevent.h \ $$PWD/events/roomaliasesevent.h \ @@ -37,7 +39,9 @@ SOURCES += \ $$PWD/connection.cpp \ $$PWD/room.cpp \ $$PWD/user.cpp \ + $$PWD/avatar.cpp \ $$PWD/events/event.cpp \ + $$PWD/events/eventcontent.cpp \ $$PWD/events/roommessageevent.cpp \ $$PWD/events/roomnameevent.cpp \ $$PWD/events/roomaliasesevent.cpp \ -- cgit v1.2.3 From 0fb7adfcaa5dffee4efd0a34a2a4fd655fe5c709 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 27 Oct 2017 15:19:07 +0300 Subject: Support m.room.avatar events The events are detected in /sync output, and avatars for rooms are loaded from respective URLs. Clients can use Room::avatar() method to request a pixmap of a certain size, and react to avatarChanged() in order to update the UI when new pixmaps/avatars arrive. avatarChanged() signal is overloaded with two tasks - the first firing merely indicates that a new avatar is available (without actual pixmap yet available) while the second firing means that an actual pixmap has arrived (all this is entirely transparent for clients, they just should update their pixmaps from Room::avatar() every time when Room::avatarChanged() is emitted). --- CMakeLists.txt | 1 + events/event.cpp | 2 ++ events/event.h | 3 ++- events/roomavatarevent.cpp | 23 +++++++++++++++++++ events/roomavatarevent.h | 53 ++++++++++++++++++++++++++++++++++++++++++ libqmatrixclient.pri | 2 ++ room.cpp | 57 ++++++++++++++++++++++++++++++++++++++-------- room.h | 10 +++++++- user.cpp | 5 ++++ user.h | 2 ++ 10 files changed, 146 insertions(+), 12 deletions(-) create mode 100644 events/roomavatarevent.cpp create mode 100644 events/roomavatarevent.h (limited to 'libqmatrixclient.pri') diff --git a/CMakeLists.txt b/CMakeLists.txt index fc3276c9..26c7bf46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,7 @@ set(libqmatrixclient_SRCS events/roomcanonicalaliasevent.cpp events/roommemberevent.cpp events/roomtopicevent.cpp + events/roomavatarevent.cpp events/typingevent.cpp events/receiptevent.cpp events/encryptedevent.cpp diff --git a/events/event.cpp b/events/event.cpp index 304f2af6..9963a0ef 100644 --- a/events/event.cpp +++ b/events/event.cpp @@ -24,6 +24,7 @@ #include "roomcanonicalaliasevent.h" #include "roommemberevent.h" #include "roomtopicevent.h" +#include "roomavatarevent.h" #include "typingevent.h" #include "receiptevent.h" #include "encryptedevent.h" @@ -136,6 +137,7 @@ RoomEvent* RoomEvent::fromJson(const QJsonObject& obj) "m.room.canonical_alias", make, "m.room.member", make, "m.room.topic", make, + "m.room.avatar", make, "m.room.encryption", make, /* Insert new ROOM event types BEFORE this line */ nullptr diff --git a/events/event.h b/events/event.h index ec993522..c151ac0e 100644 --- a/events/event.h +++ b/events/event.h @@ -34,7 +34,8 @@ namespace QMatrixClient enum class Type { RoomMessage, RoomName, RoomAliases, RoomCanonicalAlias, - RoomMember, RoomTopic, RoomEncryption, RoomEncryptedMessage, + RoomMember, RoomTopic, RoomAvatar, + RoomEncryption, RoomEncryptedMessage, Typing, Receipt, Unknown }; diff --git a/events/roomavatarevent.cpp b/events/roomavatarevent.cpp new file mode 100644 index 00000000..7a5f82a1 --- /dev/null +++ b/events/roomavatarevent.cpp @@ -0,0 +1,23 @@ +/****************************************************************************** + * Copyright (C) 2017 Kitsune Ral + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "roomavatarevent.h" + +using namespace QMatrixClient; + + diff --git a/events/roomavatarevent.h b/events/roomavatarevent.h new file mode 100644 index 00000000..411de4e8 --- /dev/null +++ b/events/roomavatarevent.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Copyright (C) 2017 Kitsune Ral + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "event.h" + +#include + +#include "eventcontent.h" + +namespace QMatrixClient +{ + class RoomAvatarEvent: public RoomEvent + { + public: + explicit RoomAvatarEvent(EventContent::ImageContent avatar) + : RoomEvent(Type::RoomAvatar), _avatar(std::move(avatar)) + { } + explicit RoomAvatarEvent(const QJsonObject& obj) + : RoomEvent(Type::RoomAvatar, obj), _avatar(contentJson()) + { } + + const EventContent::ImageContent& content() const { return _avatar; } + + QJsonObject toJson() const { return _avatar.toJson(); } + + static constexpr const char* TypeId = "m.room.avatar"; + + private: + // It's a bit of an overkill to use a full-fledged ImageContent + // because in reality m.room.avatar usually only has a single URL, + // without a thumbnail. But The Spec says there be thumbnails, and + // we follow The Spec. + EventContent::ImageContent _avatar; + }; + +} // namespace QMatrixClient diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri index 9bcb911f..9eb6bd16 100644 --- a/libqmatrixclient.pri +++ b/libqmatrixclient.pri @@ -18,6 +18,7 @@ HEADERS += \ $$PWD/events/roomcanonicalaliasevent.h \ $$PWD/events/roommemberevent.h \ $$PWD/events/roomtopicevent.h \ + $$PWD/events/roomavatarevent.h \ $$PWD/events/typingevent.h \ $$PWD/events/receiptevent.h \ $$PWD/jobs/basejob.h \ @@ -48,6 +49,7 @@ SOURCES += \ $$PWD/events/roomcanonicalaliasevent.cpp \ $$PWD/events/roommemberevent.cpp \ $$PWD/events/roomtopicevent.cpp \ + $$PWD/events/roomavatarevent.cpp \ $$PWD/events/typingevent.cpp \ $$PWD/events/receiptevent.cpp \ $$PWD/jobs/basejob.cpp \ diff --git a/room.cpp b/room.cpp index 65cf2d2a..53a6b160 100644 --- a/room.cpp +++ b/room.cpp @@ -27,12 +27,14 @@ #include "events/roomaliasesevent.h" #include "events/roomcanonicalaliasevent.h" #include "events/roomtopicevent.h" +#include "events/roomavatarevent.h" #include "events/roommemberevent.h" #include "events/typingevent.h" #include "events/receiptevent.h" #include "jobs/sendeventjob.h" #include "jobs/roommessagesjob.h" #include "jobs/postreceiptjob.h" +#include "avatar.h" #include "connection.h" #include "user.h" @@ -53,7 +55,7 @@ class Room::Private Private(Connection* c, QString id_, JoinState initialJoinState) : q(nullptr), connection(c), id(std::move(id_)) - , joinState(initialJoinState), unreadMessages(false) + , avatar(c), joinState(initialJoinState), unreadMessages(false) , highlightCount(0), notificationCount(0), roomMessagesJob(nullptr) { } @@ -73,6 +75,7 @@ class Room::Private QString name; QString displayname; QString topic; + Avatar avatar; JoinState joinState; bool unreadMessages; int highlightCount; @@ -189,6 +192,23 @@ QString Room::topic() const return d->topic; } +QPixmap Room::avatar(int width, int height) +{ + if (!d->avatar.url().isEmpty()) + return d->avatar.get(width, height, [=] { emit avatarChanged(); }); + + // Use the other side's avatar for 1:1's + if (d->membersMap.size() == 2) + { + auto theOtherOneIt = d->membersMap.begin(); + if (theOtherOneIt.value() == localUser()) + ++theOtherOneIt; + return theOtherOneIt.value()->avatarObject() + .get(width, height, [=] { emit avatarChanged(); }); + } + return {}; +} + JoinState Room::joinState() const { return d->joinState; @@ -778,6 +798,17 @@ void Room::processStateEvents(const RoomEvents& events) emit topicChanged(); break; } + case EventType::RoomAvatar: { + const auto& avatarEventContent = + static_cast(event)->content(); + if (d->avatar.updateUrl(avatarEventContent.url)) + { + qCDebug(MAIN) << "Room avatar URL updated:" + << avatarEventContent.url.toString(); + emit avatarChanged(); + } + break; + } case EventType::RoomMember: { auto memberEvent = static_cast(event); // Can't use d->member() below because the user may be not a member (yet) @@ -939,9 +970,13 @@ void Room::Private::updateDisplayname() emit q->displaynameChanged(q); } -QJsonObject stateEventToJson(const QString& type, const QString& name, - const QJsonValue& content) +template +void appendEventJson(QJsonArray& events, const QString& type, + const QString& name, const T& content) { + if (content.isEmpty()) + return; + QJsonObject contentObj; contentObj.insert(name, content); @@ -949,7 +984,7 @@ QJsonObject stateEventToJson(const QString& type, const QString& name, eventObj.insert("type", type); eventObj.insert("content", contentObj); - return eventObj; + events.append(eventObj); } QJsonObject Room::Private::toJson() const @@ -958,12 +993,14 @@ QJsonObject Room::Private::toJson() const { QJsonArray stateEvents; - stateEvents.append(stateEventToJson("m.room.name", "name", name)); - stateEvents.append(stateEventToJson("m.room.topic", "topic", topic)); - stateEvents.append(stateEventToJson("m.room.aliases", "aliases", - QJsonArray::fromStringList(aliases))); - stateEvents.append(stateEventToJson("m.room.canonical_alias", "alias", - canonicalAlias)); + appendEventJson(stateEvents, "m.room.name", "name", name); + appendEventJson(stateEvents, "m.room.topic", "topic", topic); + appendEventJson(stateEvents, "m.room.avatar", "avatar_url", + avatar.url().toString()); + appendEventJson(stateEvents, "m.room.aliases", "aliases", + QJsonArray::fromStringList(aliases)); + appendEventJson(stateEvents, "m.room.canonical_alias", "alias", + canonicalAlias); for (const auto &i : membersMap) { diff --git a/room.h b/room.h index 2d0453bc..2fa7e7d5 100644 --- a/room.h +++ b/room.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "jobs/syncjob.h" #include "events/roommessageevent.h" @@ -79,7 +80,7 @@ namespace QMatrixClient using rev_iter_t = Timeline::const_reverse_iterator; Room(Connection* connection, QString id, JoinState initialJoinState); - virtual ~Room(); + ~Room() override; Connection* connection() const; User* localUser() const; @@ -97,6 +98,12 @@ namespace QMatrixClient Q_INVOKABLE QStringList memberNames() const; Q_INVOKABLE int memberCount() const; + /** + * Returns a room avatar and requests it from the network if needed + * @return a pixmap with the avatar or a placeholder if there's none + * available yet + */ + Q_INVOKABLE QPixmap avatar(int width, int height); /** * @brief Produces a disambiguated name for a given user in * the context of the room @@ -181,6 +188,7 @@ namespace QMatrixClient /** @brief The room displayname changed */ void displaynameChanged(Room* room); void topicChanged(); + void avatarChanged(); void userAdded(User* user); void userRemoved(User* user); void memberRenamed(User* user); diff --git a/user.cpp b/user.cpp index b2c0dc1e..8c8a7fdb 100644 --- a/user.cpp +++ b/user.cpp @@ -90,6 +90,11 @@ QString User::bridged() const { return d->bridged; } +Avatar& User::avatarObject() +{ + return d->avatar; +} + QPixmap User::avatar(int width, int height) { return d->avatar.get(width, height, [=] { emit avatarChanged(this); }); diff --git a/user.h b/user.h index aee6ec3e..148ed64d 100644 --- a/user.h +++ b/user.h @@ -20,6 +20,7 @@ #include #include +#include "avatar.h" namespace QMatrixClient { @@ -52,6 +53,7 @@ namespace QMatrixClient */ Q_INVOKABLE QString bridged() const; + Avatar& avatarObject(); QPixmap avatar(int requestedWidth, int requestedHeight); QUrl avatarUrl() const; -- cgit v1.2.3 From a275ef911b3f4d0334df0628324aee0081dd3a65 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 1 Nov 2017 18:19:56 +0300 Subject: StateEvent; EventContent::SimpleContent; event types refactoring * StateEvent<> is a new class template for all state events. It provides a uniform interface to the state content, as well as a means to serialize the content back to JSON. In addition, StateEvent now parses the "prev_content" JSON object, so one can refer to the previous state now (a notable step to proper reflection of state changes in the displayed timeline in clients). * EventContent::SimpleContent, together with StateEvent<>, forms a generalisation for simple state events, such as room name, topic, aliases etc. that boil down to a single key-value pair. DECLARE_SIMPLE_STATE_EVENT is a macro defined to streamline creation of events based on SimpleContent, providing API back-compatibility for events defined so far. As a result, a very concise simplestateevents.h replaces all those room*event.* files. * Event/RoomEvent::fromJson() code is squeezed down to plain type lists passed to makeIfMatches() "chained factory" function template. TypeId is mandatory for an event type to be included into that factory. * Event::toTimestamp() and Event::toStringList are completely superseded by respective fromJson<>() converters. --- CMakeLists.txt | 5 ---- events/encryptedevent.cpp | 5 ---- events/encryptedevent.h | 39 ------------------------ events/event.cpp | 61 ++++++++++++-------------------------- events/event.h | 53 +++++++++++++++++++++++---------- events/eventcontent.h | 31 +++++++++++++++++++ events/roomaliasesevent.cpp | 43 --------------------------- events/roomaliasesevent.h | 37 ----------------------- events/roomavatarevent.h | 22 ++++---------- events/roomcanonicalaliasevent.cpp | 21 ------------- events/roomcanonicalaliasevent.h | 38 ------------------------ events/roomnameevent.cpp | 22 -------------- events/roomnameevent.h | 38 ------------------------ events/roomtopicevent.cpp | 22 -------------- events/roomtopicevent.h | 50 ------------------------------- events/simplestateevents.h | 54 +++++++++++++++++++++++++++++++++ libqmatrixclient.pri | 10 +------ room.cpp | 5 +--- 18 files changed, 150 insertions(+), 406 deletions(-) delete mode 100644 events/encryptedevent.cpp delete mode 100644 events/encryptedevent.h delete mode 100644 events/roomaliasesevent.cpp delete mode 100644 events/roomaliasesevent.h delete mode 100644 events/roomcanonicalaliasevent.cpp delete mode 100644 events/roomcanonicalaliasevent.h delete mode 100644 events/roomnameevent.cpp delete mode 100644 events/roomnameevent.h delete mode 100644 events/roomtopicevent.cpp delete mode 100644 events/roomtopicevent.h create mode 100644 events/simplestateevents.h (limited to 'libqmatrixclient.pri') diff --git a/CMakeLists.txt b/CMakeLists.txt index 26c7bf46..6163b7be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,15 +65,10 @@ set(libqmatrixclient_SRCS events/event.cpp events/eventcontent.cpp events/roommessageevent.cpp - events/roomnameevent.cpp - events/roomaliasesevent.cpp - events/roomcanonicalaliasevent.cpp events/roommemberevent.cpp - events/roomtopicevent.cpp events/roomavatarevent.cpp events/typingevent.cpp events/receiptevent.cpp - events/encryptedevent.cpp jobs/basejob.cpp jobs/checkauthmethods.cpp jobs/passwordlogin.cpp diff --git a/events/encryptedevent.cpp b/events/encryptedevent.cpp deleted file mode 100644 index 90e77c36..00000000 --- a/events/encryptedevent.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// -// Created by rusakov on 26/09/2017. -// - -#include "encryptedevent.h" diff --git a/events/encryptedevent.h b/events/encryptedevent.h deleted file mode 100644 index 9db462e1..00000000 --- a/events/encryptedevent.h +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2017 Kitsune Ral - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "event.h" - -namespace QMatrixClient -{ - class EncryptionEvent : public RoomEvent - { - public: - explicit EncryptionEvent(const QJsonObject& obj) - : RoomEvent(Type::RoomEncryption, obj) - , _algorithm(contentJson()["algorithm"].toString()) - { } - - QString algorithm() const { return _algorithm; } - - private: - QString _algorithm; - }; -} // namespace QMatrixClient - diff --git a/events/event.cpp b/events/event.cpp index 9963a0ef..44b742c1 100644 --- a/events/event.cpp +++ b/events/event.cpp @@ -19,15 +19,11 @@ #include "event.h" #include "roommessageevent.h" -#include "roomnameevent.h" -#include "roomaliasesevent.h" -#include "roomcanonicalaliasevent.h" +#include "simplestateevents.h" #include "roommemberevent.h" -#include "roomtopicevent.h" #include "roomavatarevent.h" #include "typingevent.h" #include "receiptevent.h" -#include "encryptedevent.h" #include "logging.h" #include @@ -54,32 +50,24 @@ QJsonObject Event::originalJsonObject() const return _originalJson; } -QDateTime Event::toTimestamp(const QJsonValue& v) +const QJsonObject Event::contentJson() const { - Q_ASSERT(v.isDouble() || v.isNull() || v.isUndefined()); - return QDateTime::fromMSecsSinceEpoch( - static_cast(v.toDouble()), Qt::UTC); + return _originalJson["content"].toObject(); } -QStringList Event::toStringList(const QJsonValue& v) +template +inline BaseEventT* makeIfMatches(const QJsonObject&, const QString&) { - Q_ASSERT(v.isArray() || v.isNull() || v.isUndefined()); - - QStringList l; - for( const QJsonValue& e : v.toArray() ) - l.push_back(e.toString()); - return l; + return nullptr; } -const QJsonObject Event::contentJson() const +template +inline BaseEventT* makeIfMatches(const QJsonObject& o, const QString& selector) { - return _originalJson["content"].toObject(); -} + if (selector == EventT::TypeId) + return new EventT(o); -template -EventT* make(const QJsonObject& o) -{ - return new EventT(o); + return makeIfMatches(o, selector); } Event* Event::fromJson(const QJsonObject& obj) @@ -88,17 +76,14 @@ Event* Event::fromJson(const QJsonObject& obj) if (auto e = RoomEvent::fromJson(obj)) return e; - return dispatch(obj).to(obj["type"].toString(), - "m.typing", make, - "m.receipt", make, - /* Insert new event types (except room events) BEFORE this line */ - nullptr - ); + return makeIfMatches(obj, obj["type"].toString()); } RoomEvent::RoomEvent(Type type, const QJsonObject& rep) : Event(type, rep), _id(rep["event_id"].toString()) - , _serverTimestamp(toTimestamp(rep["origin_server_ts"])) + , _serverTimestamp( + QMatrixClient::fromJson(rep["origin_server_ts"])) , _roomId(rep["room_id"].toString()) , _senderId(rep["sender"].toString()) , _txnId(rep["unsigned"].toObject().value("transactionId").toString()) @@ -130,16 +115,8 @@ void RoomEvent::addId(const QString& id) RoomEvent* RoomEvent::fromJson(const QJsonObject& obj) { - return dispatch(obj).to(obj["type"].toString(), - "m.room.message", make, - "m.room.name", make, - "m.room.aliases", make, - "m.room.canonical_alias", make, - "m.room.member", make, - "m.room.topic", make, - "m.room.avatar", make, - "m.room.encryption", make, - /* Insert new ROOM event types BEFORE this line */ - nullptr - ); + return makeIfMatches(obj, obj["type"].toString()); } diff --git a/events/event.h b/events/event.h index c151ac0e..020ef54b 100644 --- a/events/event.h +++ b/events/event.h @@ -56,9 +56,6 @@ namespace QMatrixClient static Event* fromJson(const QJsonObject& obj); protected: - static QDateTime toTimestamp(const QJsonValue& v); - static QStringList toStringList(const QJsonValue& v); - const QJsonObject contentJson() const; private: @@ -74,25 +71,20 @@ namespace QMatrixClient using EventsBatch = std::vector; using Events = EventsBatch; - template - BaseEventT* makeEvent(const QJsonObject& obj) - { - if (auto e = BaseEventT::fromJson(obj)) - return e; - - return new BaseEventT(EventType::Unknown, obj); - } - template > - BatchT makeEvents(const QJsonArray& objs) + inline BatchT makeEvents(const QJsonArray& objs) { BatchT evs; // The below line accommodates the difference in size types of // STL and Qt containers. evs.reserve(static_cast(objs.size())); - for (auto obj: objs) - evs.push_back(makeEvent(obj.toObject())); + for (auto objValue: objs) + { + const auto o = objValue.toObject(); + auto e = BaseEventT::fromJson(o); + evs.push_back(e ? e : new BaseEventT(EventType::Unknown, o)); + } return evs; } @@ -147,6 +139,37 @@ namespace QMatrixClient QString _txnId; }; using RoomEvents = EventsBatch; + + template + class StateEvent: public RoomEvent + { + public: + using content_type = ContentT; + + template + explicit StateEvent(Type type, const QJsonObject& obj, + ContentParamTs&&... contentParams) + : RoomEvent(type, obj) + , _content(contentJson(), + std::forward(contentParams)...) + , _prev(new ContentT(obj["prev_content"].toObject(), + std::forward(contentParams)...)) + { } + template + explicit StateEvent(Type type, ContentParamTs&&... contentParams) + : RoomEvent(type) + , _content(std::forward(contentParams)...) + { } + + QJsonObject toJson() const { return _content.toJson(); } + + ContentT content() const { return _content; } + ContentT* prev_content() const { return _prev.data(); } + + protected: + ContentT _content; + QScopedPointer _prev; + }; } // namespace QMatrixClient Q_DECLARE_OPAQUE_POINTER(QMatrixClient::Event*) Q_DECLARE_METATYPE(QMatrixClient::Event*) diff --git a/events/eventcontent.h b/events/eventcontent.h index f9cdaf11..60437995 100644 --- a/events/eventcontent.h +++ b/events/eventcontent.h @@ -21,6 +21,8 @@ // This file contains generic event content definitions, applicable to room // message events as well as other events (e.g., avatars). +#include "converters.h" + #include #include #include @@ -60,6 +62,35 @@ namespace QMatrixClient virtual QMimeType type() const = 0; }; + template + class SimpleContent: public Base + { + public: + using value_type = T; + + // The constructor is templated to enable perfect forwarding + template + SimpleContent(QString keyName, TT&& value) + : value(std::forward(value)), key(std::move(keyName)) + { } + SimpleContent(const QJsonObject& json, QString keyName) + : value(QMatrixClient::fromJson(json[keyName])) + , key(std::move(keyName)) + { } + + T value; + + protected: + QString key; + + private: + void fillJson(QJsonObject* json) const override + { + Q_ASSERT(json); + json->insert(key, QMatrixClient::toJson(value)); + } + }; + /** * A base class for content types that have an "info" object in their * JSON representation diff --git a/events/roomaliasesevent.cpp b/events/roomaliasesevent.cpp deleted file mode 100644 index 344b4367..00000000 --- a/events/roomaliasesevent.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -// Example of a RoomAliases Event: -// -// { -// "age":3758857346, -// "content":{ -// "aliases":["#freenode_#testest376:matrix.org"] -// }, -// "event_id":"$1439989428122drFjY:matrix.org", -// "origin_server_ts":1439989428910, -// "replaces_state":"$143613875199223YYPrN:matrix.org", -// "room_id":"!UoqtanuuSGTMvNRfDG:matrix.org", -// "state_key":"matrix.org", -// "type":"m.room.aliases", -// "user_id":"@appservice-irc:matrix.org" -// } - -#include "roomaliasesevent.h" - -using namespace QMatrixClient; - -RoomAliasesEvent::RoomAliasesEvent(const QJsonObject& obj) - : RoomEvent(Type::RoomAliases, obj) - , _aliases(toStringList(contentJson()["aliases"])) -{ } - diff --git a/events/roomaliasesevent.h b/events/roomaliasesevent.h deleted file mode 100644 index efafcb30..00000000 --- a/events/roomaliasesevent.h +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "event.h" - -#include - -namespace QMatrixClient -{ - class RoomAliasesEvent: public RoomEvent - { - public: - explicit RoomAliasesEvent(const QJsonObject& obj); - - QStringList aliases() const { return _aliases; } - - private: - QStringList _aliases; - }; -} // namespace QMatrixClient diff --git a/events/roomavatarevent.h b/events/roomavatarevent.h index 411de4e8..ccfe8fbf 100644 --- a/events/roomavatarevent.h +++ b/events/roomavatarevent.h @@ -26,28 +26,18 @@ namespace QMatrixClient { - class RoomAvatarEvent: public RoomEvent + class RoomAvatarEvent: public StateEvent { + // It's a bit of an overkill to use a full-fledged ImageContent + // because in reality m.room.avatar usually only has a single URL, + // without a thumbnail. But The Spec says there be thumbnails, and + // we follow The Spec. public: - explicit RoomAvatarEvent(EventContent::ImageContent avatar) - : RoomEvent(Type::RoomAvatar), _avatar(std::move(avatar)) - { } explicit RoomAvatarEvent(const QJsonObject& obj) - : RoomEvent(Type::RoomAvatar, obj), _avatar(contentJson()) + : StateEvent(Type::RoomAvatar, obj) { } - const EventContent::ImageContent& content() const { return _avatar; } - - QJsonObject toJson() const { return _avatar.toJson(); } - static constexpr const char* TypeId = "m.room.avatar"; - - private: - // It's a bit of an overkill to use a full-fledged ImageContent - // because in reality m.room.avatar usually only has a single URL, - // without a thumbnail. But The Spec says there be thumbnails, and - // we follow The Spec. - EventContent::ImageContent _avatar; }; } // namespace QMatrixClient diff --git a/events/roomcanonicalaliasevent.cpp b/events/roomcanonicalaliasevent.cpp deleted file mode 100644 index 6884bc15..00000000 --- a/events/roomcanonicalaliasevent.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2016 Felix Rohrbach - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "roomcanonicalaliasevent.h" - -using namespace QMatrixClient; diff --git a/events/roomcanonicalaliasevent.h b/events/roomcanonicalaliasevent.h deleted file mode 100644 index 72620d74..00000000 --- a/events/roomcanonicalaliasevent.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2016 Felix Rohrbach - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "event.h" - -namespace QMatrixClient -{ - class RoomCanonicalAliasEvent : public RoomEvent - { - public: - explicit RoomCanonicalAliasEvent(const QJsonObject& obj) - : RoomEvent(Type::RoomCanonicalAlias, obj) - , _canonicalAlias(contentJson()["alias"].toString()) - { } - - QString alias() const { return _canonicalAlias; } - - private: - QString _canonicalAlias; - }; -} // namespace QMatrixClient diff --git a/events/roomnameevent.cpp b/events/roomnameevent.cpp deleted file mode 100644 index c202d17a..00000000 --- a/events/roomnameevent.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2015 Kitsune Ral - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "roomnameevent.h" - -using namespace QMatrixClient; - diff --git a/events/roomnameevent.h b/events/roomnameevent.h deleted file mode 100644 index bb823933..00000000 --- a/events/roomnameevent.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2015 Kitsune Ral - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "event.h" - -namespace QMatrixClient -{ - class RoomNameEvent : public RoomEvent - { - public: - explicit RoomNameEvent(const QJsonObject& obj) - : RoomEvent(Type::RoomName, obj) - , _name(contentJson()["name"].toString()) - { } - - QString name() const { return _name; } - - private: - QString _name{}; - }; -} // namespace QMatrixClient diff --git a/events/roomtopicevent.cpp b/events/roomtopicevent.cpp deleted file mode 100644 index 26677e78..00000000 --- a/events/roomtopicevent.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "roomtopicevent.h" - -using namespace QMatrixClient; - diff --git a/events/roomtopicevent.h b/events/roomtopicevent.h deleted file mode 100644 index 95ad0e04..00000000 --- a/events/roomtopicevent.h +++ /dev/null @@ -1,50 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "event.h" - -namespace QMatrixClient -{ - class RoomTopicEvent: public RoomEvent - { - public: - explicit RoomTopicEvent(const QString& topic) - : RoomEvent(Type::RoomTopic), _topic(topic) - { } - explicit RoomTopicEvent(const QJsonObject& obj) - : RoomEvent(Type::RoomTopic, obj) - , _topic(contentJson()["topic"].toString()) - { } - - QString topic() const { return _topic; } - - QJsonObject toJson() const - { - QJsonObject obj; - obj.insert("topic", _topic); - return obj; - } - - static constexpr const char* TypeId = "m.room.topic"; - - private: - QString _topic; - }; -} // namespace QMatrixClient diff --git a/events/simplestateevents.h b/events/simplestateevents.h new file mode 100644 index 00000000..d5841bdc --- /dev/null +++ b/events/simplestateevents.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * Copyright (C) 2017 Kitsune Ral + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "event.h" + +#include "eventcontent.h" + +namespace QMatrixClient +{ +#define DECLARE_SIMPLE_STATE_EVENT(_Name, _TypeId, _EnumType, _ContentType, _ContentKey) \ + class _Name \ + : public StateEvent> \ + { \ + public: \ + static constexpr const char* TypeId = _TypeId; \ + explicit _Name(const QJsonObject& obj) \ + : StateEvent(_EnumType, obj, #_ContentKey) \ + { } \ + template \ + explicit _Name(T&& value) \ + : StateEvent(_EnumType, #_ContentKey, \ + std::forward(value)) \ + { } \ + _ContentType _ContentKey() const { return content().value; } \ + }; + + DECLARE_SIMPLE_STATE_EVENT(RoomNameEvent, "m.room.name", + Event::Type::RoomName, QString, name) + DECLARE_SIMPLE_STATE_EVENT(RoomAliasesEvent, "m.room.aliases", + Event::Type::RoomAliases, QStringList, aliases) + DECLARE_SIMPLE_STATE_EVENT(RoomCanonicalAliasEvent, "m.room.canonical_alias", + Event::Type::RoomCanonicalAlias, QString, alias) + DECLARE_SIMPLE_STATE_EVENT(RoomTopicEvent, "m.room.topic", + Event::Type::RoomTopic, QString, topic) + DECLARE_SIMPLE_STATE_EVENT(EncryptionEvent, "m.room.encryption", + Event::Type::RoomEncryption, QString, algorithm) +} // namespace QMatrixClient diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri index 9eb6bd16..86648860 100644 --- a/libqmatrixclient.pri +++ b/libqmatrixclient.pri @@ -13,11 +13,8 @@ HEADERS += \ $$PWD/events/event.h \ $$PWD/events/eventcontent.h \ $$PWD/events/roommessageevent.h \ - $$PWD/events/roomnameevent.h \ - $$PWD/events/roomaliasesevent.h \ - $$PWD/events/roomcanonicalaliasevent.h \ + $$PWD/events/simplestateevents.h \ $$PWD/events/roommemberevent.h \ - $$PWD/events/roomtopicevent.h \ $$PWD/events/roomavatarevent.h \ $$PWD/events/typingevent.h \ $$PWD/events/receiptevent.h \ @@ -44,12 +41,7 @@ SOURCES += \ $$PWD/events/event.cpp \ $$PWD/events/eventcontent.cpp \ $$PWD/events/roommessageevent.cpp \ - $$PWD/events/roomnameevent.cpp \ - $$PWD/events/roomaliasesevent.cpp \ - $$PWD/events/roomcanonicalaliasevent.cpp \ $$PWD/events/roommemberevent.cpp \ - $$PWD/events/roomtopicevent.cpp \ - $$PWD/events/roomavatarevent.cpp \ $$PWD/events/typingevent.cpp \ $$PWD/events/receiptevent.cpp \ $$PWD/jobs/basejob.cpp \ diff --git a/room.cpp b/room.cpp index 1b6afac9..c4e4c6cd 100644 --- a/room.cpp +++ b/room.cpp @@ -23,10 +23,7 @@ #include "jobs/generated/banning.h" #include "jobs/generated/leaving.h" #include "jobs/setroomstatejob.h" -#include "events/roomnameevent.h" -#include "events/roomaliasesevent.h" -#include "events/roomcanonicalaliasevent.h" -#include "events/roomtopicevent.h" +#include "events/simplestateevents.h" #include "events/roomavatarevent.h" #include "events/roommemberevent.h" #include "events/typingevent.h" -- cgit v1.2.3