From 04435ef1d621b18ad837cdcb4b06155952f51f0c Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 4 Nov 2018 15:38:05 +0900 Subject: DEFINE_SIMPLE_STATE_EVENT: fix value_type mistakenly dubbed as content_type --- lib/events/simplestateevents.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/events') diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h index 56be947c..9a212612 100644 --- a/lib/events/simplestateevents.h +++ b/lib/events/simplestateevents.h @@ -59,11 +59,11 @@ namespace QMatrixClient }; } // namespace EventContent -#define DEFINE_SIMPLE_STATE_EVENT(_Name, _TypeId, _ContentType, _ContentKey) \ - class _Name : public StateEvent> \ +#define DEFINE_SIMPLE_STATE_EVENT(_Name, _TypeId, _ValueType, _ContentKey) \ + class _Name : public StateEvent> \ { \ public: \ - using content_type = _ContentType; \ + using value_type = content_type::value_type; \ DEFINE_EVENT_TYPEID(_TypeId, _Name) \ explicit _Name(const QJsonObject& obj) \ : StateEvent(typeId(), obj, QStringLiteral(#_ContentKey)) \ -- cgit v1.2.3 From f3221451ce29c3b571e08fe3ce51a49f252029e5 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 4 Nov 2018 16:06:29 +0900 Subject: DEFINE_SIMPLE_STATE_EVENT: fix construction from an rvalue QJsonObject --- lib/events/simplestateevents.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/events') diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h index 9a212612..3a59ad6d 100644 --- a/lib/events/simplestateevents.h +++ b/lib/events/simplestateevents.h @@ -65,8 +65,9 @@ namespace QMatrixClient public: \ using value_type = content_type::value_type; \ DEFINE_EVENT_TYPEID(_TypeId, _Name) \ - explicit _Name(const QJsonObject& obj) \ - : StateEvent(typeId(), obj, QStringLiteral(#_ContentKey)) \ + explicit _Name(QJsonObject obj) \ + : StateEvent(typeId(), std::move(obj), \ + QStringLiteral(#_ContentKey)) \ { } \ template \ explicit _Name(T&& value) \ -- cgit v1.2.3 From 9993a0ea50165fd70f75b68c329ea045fb51d7f4 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 4 Nov 2018 16:07:53 +0900 Subject: Support dumping Events to QDebug --- lib/events/event.cpp | 5 +++++ lib/events/event.h | 10 ++++++++++ lib/events/stateevent.cpp | 8 ++++++++ lib/events/stateevent.h | 2 ++ 4 files changed, 25 insertions(+) (limited to 'lib/events') diff --git a/lib/events/event.cpp b/lib/events/event.cpp index fd6e3939..c98dfbb6 100644 --- a/lib/events/event.cpp +++ b/lib/events/event.cpp @@ -77,3 +77,8 @@ const QJsonObject Event::unsignedJson() const { return fullJson()[UnsignedKeyL].toObject(); } + +void Event::dumpTo(QDebug dbg) const +{ + dbg << QJsonDocument(contentJson()).toJson(QJsonDocument::Compact); +} diff --git a/lib/events/event.h b/lib/events/event.h index 5b33628f..76e77cf6 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -257,8 +257,18 @@ namespace QMatrixClient return fromJson(contentJson()[key]); } + friend QDebug operator<<(QDebug dbg, const Event& e) + { + QDebugStateSaver _dss { dbg }; + dbg.noquote().nospace() + << e.matrixType() << '(' << e.type() << "): "; + e.dumpTo(dbg); + return dbg; + } + virtual bool isStateEvent() const { return false; } virtual bool isCallEvent() const { return false; } + virtual void dumpTo(QDebug dbg) const; protected: QJsonObject& editJson() { return _json; } diff --git a/lib/events/stateevent.cpp b/lib/events/stateevent.cpp index fd5d2642..ea7533c5 100644 --- a/lib/events/stateevent.cpp +++ b/lib/events/stateevent.cpp @@ -28,3 +28,11 @@ bool StateEventBase::repeatsState() const const auto prevContentJson = unsignedJson().value(PrevContentKeyL); return fullJson().value(ContentKeyL) == prevContentJson; } + +void StateEventBase::dumpTo(QDebug dbg) const +{ + if (unsignedJson().contains(PrevContentKeyL)) + dbg << QJsonDocument(unsignedJson()[PrevContentKeyL].toObject()) + .toJson(QJsonDocument::Compact) << " -> "; + RoomEvent::dumpTo(dbg); +} diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index 6032132e..e499bdff 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -30,6 +30,8 @@ namespace QMatrixClient { ~StateEventBase() override = default; bool isStateEvent() const override { return true; } + void dumpTo(QDebug dbg) const override; + virtual bool repeatsState() const; }; using StateEventPtr = event_ptr_tt; -- cgit v1.2.3 From 2fe086f4e8f15cf366fc2cf1c9942c7b7541cec7 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 4 Nov 2018 17:53:53 +0900 Subject: StateEvent::dumpTo: add state_key to the logline --- lib/events/stateevent.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/events') diff --git a/lib/events/stateevent.cpp b/lib/events/stateevent.cpp index ea7533c5..280c334c 100644 --- a/lib/events/stateevent.cpp +++ b/lib/events/stateevent.cpp @@ -31,6 +31,8 @@ bool StateEventBase::repeatsState() const void StateEventBase::dumpTo(QDebug dbg) const { + if (!stateKey().isEmpty()) + dbg << '<' << stateKey() << "> "; if (unsignedJson().contains(PrevContentKeyL)) dbg << QJsonDocument(unsignedJson()[PrevContentKeyL].toObject()) .toJson(QJsonDocument::Compact) << " -> "; -- cgit v1.2.3 From d4edc5eb4eec92a96fcaf4eefc59943dfb59e02e Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 4 Nov 2018 17:55:22 +0900 Subject: StateEventKey and std::hash to arrange state events in hashmaps --- lib/events/stateevent.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'lib/events') diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index e499bdff..76c749f5 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -37,6 +37,13 @@ namespace QMatrixClient { using StateEventPtr = event_ptr_tt; using StateEvents = EventsArray; + /** + * A combination of event type and state key uniquely identifies a piece + * of state in Matrix. + * \sa https://matrix.org/docs/spec/client_server/unstable.html#types-of-room-events + */ + using StateEventKey = std::pair; + template struct Prev { @@ -92,3 +99,13 @@ namespace QMatrixClient { std::unique_ptr> _prev; }; } // namespace QMatrixClient + +namespace std { + template <> struct hash + { + size_t operator()(const QMatrixClient::StateEventKey& k) const Q_DECL_NOEXCEPT + { + return qHash(k); + } + }; +} -- cgit v1.2.3 From 6ca6dde46b9c72fc8833bc6fb81614fb705424f2 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 11 Nov 2018 15:24:13 +0900 Subject: Improvements in comments - registerEventType(): comment the cryptic _ variable - Room::postEvent: document the return value - Room::Private: upgrade comments to doc-comments - even though in Private, they still are helpful to show hints in IDEs. - General cleanup --- lib/converters.h | 2 +- lib/events/event.h | 2 +- lib/room.cpp | 10 ++++++---- lib/room.h | 1 + 4 files changed, 9 insertions(+), 6 deletions(-) (limited to 'lib/events') diff --git a/lib/converters.h b/lib/converters.h index 70938ab9..53855a1f 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -61,7 +61,7 @@ namespace QMatrixClient inline auto toJson(const QJsonValue& val) { return val; } inline auto toJson(const QJsonObject& o) { return o; } inline auto toJson(const QJsonArray& arr) { return arr; } - // Special-case QStrings and bools to avoid ambiguity between QJsonValue + // Special-case QString to avoid ambiguity between QJsonValue // and QVariant (also, QString.isEmpty() is used in _impl::AddNode<> below) inline auto toJson(const QString& s) { return s; } diff --git a/lib/events/event.h b/lib/events/event.h index 76e77cf6..c51afcc4 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -209,7 +209,7 @@ namespace QMatrixClient inline auto registerEventType() { static const auto _ = setupFactory(); - return _; + return _; // Only to facilitate usage in static initialisation } // === Event === diff --git a/lib/room.cpp b/lib/room.cpp index 5dd244f2..088d1d8e 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -94,9 +94,11 @@ class Room::Private Connection* connection; QString id; JoinState joinState; - // The state of the room at timeline position before-0 + /// The state of the room at timeline position before-0 + /// \sa timelineBase std::unordered_map baseState; - // The state of the room at timeline position after-maxTimelineIndex() + /// The state of the room at timeline position after-maxTimelineIndex() + /// \sa Room::syncEdge QHash currentState; Timeline timeline; PendingEvents unsyncedEvents; @@ -156,8 +158,8 @@ class Room::Private fileTransfers[tid].status = FileTransferInfo::Failed; emit q->fileTransferFailed(tid, errorMessage); } - // A map from event/txn ids to information about the long operation; - // used for both download and upload operations + /// A map from event/txn ids to information about the long operation; + /// used for both download and upload operations QHash fileTransfers; const RoomMessageEvent* getEventWithFile(const QString& eventId) const; diff --git a/lib/room.h b/lib/room.h index f1566ac5..a9ed9647 100644 --- a/lib/room.h +++ b/lib/room.h @@ -323,6 +323,7 @@ namespace QMatrixClient * * Takes ownership of the event, deleting it once the matching one * arrives with the sync + * \return transaction id associated with the event. */ QString postEvent(RoomEvent* event); QString postJson(const QString& matrixType, -- cgit v1.2.3 From 7ce14ccedc7a5239396e7662da1b2ba45195c271 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 14 Nov 2018 07:14:45 +0900 Subject: DEFINE_SIMPLE_STATE_EVENT: Add default constructor ...that creates an "empty" event, i.e. an event with content initialised by a default constructor (not all content types support this but those for simple events do). --- lib/events/simplestateevents.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/events') diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h index 3a59ad6d..5aa24c15 100644 --- a/lib/events/simplestateevents.h +++ b/lib/events/simplestateevents.h @@ -65,16 +65,17 @@ namespace QMatrixClient public: \ using value_type = content_type::value_type; \ DEFINE_EVENT_TYPEID(_TypeId, _Name) \ - explicit _Name(QJsonObject obj) \ - : StateEvent(typeId(), std::move(obj), \ - QStringLiteral(#_ContentKey)) \ - { } \ + explicit _Name() : _Name(value_type()) { } \ template \ explicit _Name(T&& value) \ : StateEvent(typeId(), matrixTypeId(), \ QStringLiteral(#_ContentKey), \ std::forward(value)) \ { } \ + explicit _Name(QJsonObject obj) \ + : StateEvent(typeId(), std::move(obj), \ + QStringLiteral(#_ContentKey)) \ + { } \ auto _ContentKey() const { return content().value; } \ }; \ REGISTER_EVENT_TYPE(_Name) \ -- cgit v1.2.3 From 3478e691df49b9c0938220db57b03a9c6fcbec8d Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 14 Nov 2018 07:26:31 +0900 Subject: Room: fix incorrect handling of state event redactions Also: use Matrix type instead of internal type id in StateEventKey (Because internal type id maps to the library type system which will not discern between Unknown events and therefore will mix together events of different types in Room::Private::baseState/currentState. The Room code is updated accordingly (bonus: more asserts there).) Closes #255. --- lib/events/stateevent.h | 2 +- lib/room.cpp | 39 ++++++++++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 10 deletions(-) (limited to 'lib/events') diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index 76c749f5..d50500f2 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -42,7 +42,7 @@ namespace QMatrixClient { * of state in Matrix. * \sa https://matrix.org/docs/spec/client_server/unstable.html#types-of-room-events */ - using StateEventKey = std::pair; + using StateEventKey = std::pair; template struct Prev diff --git a/lib/room.cpp b/lib/room.cpp index fd4add3b..38a4157e 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -178,10 +178,12 @@ class Room::Private template const EventT* getCurrentState(QString stateKey = {}) const { - static const EventT emptyEvent { QJsonObject{} }; - return static_cast( - currentState.value({EventT::typeId(), stateKey}, - &emptyEvent)); + static const EventT empty; + const auto* evt = + currentState.value({EventT::matrixTypeId(), stateKey}, &empty); + Q_ASSERT(evt->type() == EventT::typeId() && + evt->matrixType() == EventT::matrixTypeId()); + return static_cast(evt); } bool isEventNotable(const TimelineItem& ti) const @@ -1117,7 +1119,8 @@ void Room::updateData(SyncRoomData&& data) for (auto&& eptr: data.state) { const auto& evt = *eptr; - d->baseState[{evt.type(),evt.stateKey()}] = move(eptr); + Q_ASSERT(evt.isStateEvent()); + d->baseState[{evt.matrixType(),evt.stateKey()}] = move(eptr); emitNamesChanged |= processStateEvent(evt); } @@ -1628,11 +1631,26 @@ bool Room::Private::processRedaction(const RedactionEvent& redaction) return true; } - // Make a new event from the redacted JSON, exchange events, - // notify everyone and delete the old event + // Make a new event from the redacted JSON and put it in the timeline + // instead of the redacted one. oldEvent will be deleted on return. auto oldEvent = ti.replaceEvent(makeRedacted(*ti, redaction)); - q->onRedaction(*oldEvent, *ti.event()); qCDebug(MAIN) << "Redacted" << oldEvent->id() << "with" << redaction.id(); + if (oldEvent->isStateEvent()) + { + const StateEventKey evtKey { oldEvent->matrixType(), oldEvent->stateKey() }; + Q_ASSERT(currentState.contains(evtKey)); + if (currentState[evtKey] == oldEvent.get()) + { + Q_ASSERT(ti.index() >= 0); // Historical states can't be in currentState + qCDebug(MAIN).nospace() << "Reverting state " + << oldEvent->matrixType() << "/" << oldEvent->stateKey(); + // Retarget the current state to the newly made event. + if (q->processStateEvent(*ti)) + emit q->namesChanged(q); + updateDisplayname(); + } + } + q->onRedaction(*oldEvent, *ti); emit q->replacedEvent(ti.event(), rawPtr(oldEvent)); return true; } @@ -1791,7 +1809,7 @@ bool Room::processStateEvent(const RoomEvent& e) if (!e.isStateEvent()) return false; - d->currentState[{e.type(),e.stateKey()}] = + d->currentState[{e.matrixType(),e.stateKey()}] = static_cast(&e); if (!is(e)) qCDebug(EVENTS) << "Room state event:" << e; @@ -2060,7 +2078,10 @@ QJsonObject Room::Private::toJson() const QJsonArray stateEvents; for (const auto& evt: currentState) + { + Q_ASSERT(evt->isStateEvent()); stateEvents.append(evt->fullJson()); + } const auto stateObjName = joinState == JoinState::Invite ? QStringLiteral("invite_state") : QStringLiteral("state"); -- cgit v1.2.3 From 760c42bbb6027bfc6ebeb70a3a77608378d7c510 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 17 Nov 2018 19:52:27 +0900 Subject: StateEventBase::replacedState() Brings event id of the state event that was in effect before this one arrived. This key is not specced but it's used in the wild since forever. --- lib/events/stateevent.cpp | 5 +++++ lib/events/stateevent.h | 1 + 2 files changed, 6 insertions(+) (limited to 'lib/events') diff --git a/lib/events/stateevent.cpp b/lib/events/stateevent.cpp index 280c334c..fd8079be 100644 --- a/lib/events/stateevent.cpp +++ b/lib/events/stateevent.cpp @@ -29,6 +29,11 @@ bool StateEventBase::repeatsState() const return fullJson().value(ContentKeyL) == prevContentJson; } +QString StateEventBase::replacedState() const +{ + return unsignedJson().value("replaces_state"_ls).toString(); +} + void StateEventBase::dumpTo(QDebug dbg) const { if (!stateKey().isEmpty()) diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index d50500f2..d4a7e8b3 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -30,6 +30,7 @@ namespace QMatrixClient { ~StateEventBase() override = default; bool isStateEvent() const override { return true; } + QString replacedState() const; void dumpTo(QDebug dbg) const override; virtual bool repeatsState() const; -- cgit v1.2.3 From 8e9e89846f75cae907bb9c2c6868dcb0f37896ae Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 20 Nov 2018 13:25:07 +0900 Subject: eventloader.h: drop unneeded #include --- lib/events/eventloader.h | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/events') diff --git a/lib/events/eventloader.h b/lib/events/eventloader.h index 3ee9a181..cd2f9149 100644 --- a/lib/events/eventloader.h +++ b/lib/events/eventloader.h @@ -19,7 +19,6 @@ #pragma once #include "stateevent.h" -#include "converters.h" namespace QMatrixClient { namespace _impl { -- cgit v1.2.3 From 1414f3b5cc2bca3a3871bfe569510c1a422629fe Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 8 Dec 2018 15:24:45 +0900 Subject: RoomMemberEvent: cleanup Don't make JSON for event content only to parse it again; drop extraneous constructs. --- lib/events/roommemberevent.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'lib/events') diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h index db25d026..149d74f8 100644 --- a/lib/events/roommemberevent.h +++ b/lib/events/roommemberevent.h @@ -29,13 +29,10 @@ namespace QMatrixClient enum MembershipType : size_t { Invite = 0, Join, Knock, Leave, Ban, Undefined }; - explicit MemberEventContent(MembershipType mt = MembershipType::Join) + explicit MemberEventContent(MembershipType mt = Join) : membership(mt) { } explicit MemberEventContent(const QJsonObject& json); - explicit MemberEventContent(const QJsonValue& jv) - : MemberEventContent(jv.toObject()) - { } MembershipType membership; bool isDirect = false; @@ -60,7 +57,7 @@ namespace QMatrixClient : StateEvent(typeId(), obj) { } RoomMemberEvent(MemberEventContent&& c) - : StateEvent(typeId(), matrixTypeId(), c.toJson()) + : StateEvent(typeId(), matrixTypeId(), c) { } // This is a special constructor enabling RoomMemberEvent to be -- cgit v1.2.3 From ced7179117fd67cb1632f943f4ba1fde96423c0c Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 8 Dec 2018 15:26:35 +0900 Subject: StateEvent<>: make data members private Keeping them protected extends API surface with no reasonable use from it (and for now derived classes don't access StateEvent<> data members directly, anyway). --- lib/events/stateevent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/events') diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index d4a7e8b3..d82de7e1 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -95,7 +95,7 @@ namespace QMatrixClient { QString prevSenderId() const { return _prev ? _prev->senderId : QString(); } - protected: + private: ContentT _content; std::unique_ptr> _prev; }; -- cgit v1.2.3 From 3392e66fd015e191b01f6e3fc6839edc3948e31f Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 8 Dec 2018 15:36:04 +0900 Subject: Refactor toJson/fillJson Both now use through a common JsonConverter<> template class with its base definition tuned for structs/QJsonObjects and specialisations for non-object types. This new implementation doesn't work with virtual fillJson functions yet (so EventContent classes still use toJson as a member function) and does not cope quite well with non-constructible objects (you have to specialise JsonConverter<> rather than, more intuitively, JsonObjectConverter<>), but overall is more streamlined compared to the previous implementation. It also fixes one important issue that pushed for a rewrite: the previous implementation was not working with structure hierarchies at all so (in particular) the Filter part of CS API was totally disfunctional. --- lib/application-service/definitions/location.cpp | 20 +- lib/application-service/definitions/location.h | 8 +- lib/application-service/definitions/protocol.cpp | 66 ++--- lib/application-service/definitions/protocol.h | 24 +- lib/application-service/definitions/user.cpp | 20 +- lib/application-service/definitions/user.h | 8 +- lib/converters.cpp | 38 ++- lib/converters.h | 288 ++++++++++----------- lib/csapi/admin.cpp | 40 +-- lib/csapi/administrative_contact.cpp | 40 ++- lib/csapi/content-repo.cpp | 8 +- lib/csapi/create_room.cpp | 32 +-- lib/csapi/definitions/auth_data.cpp | 19 +- lib/csapi/definitions/auth_data.h | 8 +- lib/csapi/definitions/client_device.cpp | 23 +- lib/csapi/definitions/client_device.h | 8 +- lib/csapi/definitions/device_keys.cpp | 26 +- lib/csapi/definitions/device_keys.h | 8 +- lib/csapi/definitions/event_filter.cpp | 26 +- lib/csapi/definitions/event_filter.h | 8 +- lib/csapi/definitions/public_rooms_response.cpp | 61 ++--- lib/csapi/definitions/public_rooms_response.h | 16 +- lib/csapi/definitions/push_condition.cpp | 23 +- lib/csapi/definitions/push_condition.h | 8 +- lib/csapi/definitions/push_rule.cpp | 29 +-- lib/csapi/definitions/push_rule.h | 8 +- lib/csapi/definitions/push_ruleset.cpp | 26 +- lib/csapi/definitions/push_ruleset.h | 8 +- lib/csapi/definitions/room_event_filter.cpp | 28 +- lib/csapi/definitions/room_event_filter.h | 12 +- lib/csapi/definitions/sync_filter.cpp | 74 +++--- lib/csapi/definitions/sync_filter.h | 49 +++- lib/csapi/definitions/user_identifier.cpp | 16 +- lib/csapi/definitions/user_identifier.h | 8 +- lib/csapi/definitions/wellknown/homeserver.cpp | 14 +- lib/csapi/definitions/wellknown/homeserver.h | 8 +- .../definitions/wellknown/identity_server.cpp | 14 +- lib/csapi/definitions/wellknown/identity_server.h | 8 +- lib/csapi/device_management.cpp | 4 +- lib/csapi/directory.cpp | 4 +- lib/csapi/event_context.cpp | 12 +- lib/csapi/filter.cpp | 4 +- lib/csapi/joining.cpp | 51 ++-- lib/csapi/keys.cpp | 35 +-- lib/csapi/list_joined_rooms.cpp | 2 +- lib/csapi/list_public_rooms.cpp | 17 +- lib/csapi/login.cpp | 20 +- lib/csapi/message_pagination.cpp | 6 +- lib/csapi/notifications.cpp | 29 +-- lib/csapi/openid.cpp | 8 +- lib/csapi/peeking_events.cpp | 6 +- lib/csapi/presence.cpp | 10 +- lib/csapi/profile.cpp | 8 +- lib/csapi/pusher.cpp | 59 ++--- lib/csapi/pushrules.cpp | 8 +- lib/csapi/redaction.cpp | 2 +- lib/csapi/registration.cpp | 18 +- lib/csapi/room_send.cpp | 2 +- lib/csapi/room_state.cpp | 4 +- lib/csapi/rooms.cpp | 40 +-- lib/csapi/rooms.h | 13 +- lib/csapi/search.cpp | 179 ++++++------- lib/csapi/tags.cpp | 14 +- lib/csapi/third_party_lookup.cpp | 12 +- lib/csapi/users.cpp | 20 +- lib/csapi/versions.cpp | 2 +- lib/csapi/voip.cpp | 2 +- lib/csapi/wellknown.cpp | 4 +- lib/csapi/whoami.cpp | 2 +- lib/csapi/{{base}}.cpp.mustache | 69 ++--- lib/csapi/{{base}}.h.mustache | 13 +- lib/events/accountdataevents.h | 35 +-- lib/events/eventloader.h | 10 +- lib/events/roommemberevent.cpp | 12 +- .../definitions/request_email_validation.cpp | 23 +- .../definitions/request_email_validation.h | 8 +- .../definitions/request_msisdn_validation.cpp | 26 +- .../definitions/request_msisdn_validation.h | 8 +- lib/identity/definitions/sid.cpp | 14 +- lib/identity/definitions/sid.h | 8 +- 80 files changed, 851 insertions(+), 1100 deletions(-) (limited to 'lib/events') diff --git a/lib/application-service/definitions/location.cpp b/lib/application-service/definitions/location.cpp index 958a55bf..a53db8d7 100644 --- a/lib/application-service/definitions/location.cpp +++ b/lib/application-service/definitions/location.cpp @@ -6,25 +6,19 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const ThirdPartyLocation& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const ThirdPartyLocation& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("alias"), pod.alias); addParam<>(jo, QStringLiteral("protocol"), pod.protocol); addParam<>(jo, QStringLiteral("fields"), pod.fields); - return jo; } -ThirdPartyLocation FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, ThirdPartyLocation& result) { - ThirdPartyLocation result; - result.alias = - fromJson(jo.value("alias"_ls)); - result.protocol = - fromJson(jo.value("protocol"_ls)); - result.fields = - fromJson(jo.value("fields"_ls)); - - return result; + fromJson(jo.value("alias"_ls), result.alias); + fromJson(jo.value("protocol"_ls), result.protocol); + fromJson(jo.value("fields"_ls), result.fields); } diff --git a/lib/application-service/definitions/location.h b/lib/application-service/definitions/location.h index 89b48a43..5586cfc6 100644 --- a/lib/application-service/definitions/location.h +++ b/lib/application-service/definitions/location.h @@ -21,12 +21,10 @@ namespace QMatrixClient /// Information used to identify this third party location. QJsonObject fields; }; - - QJsonObject toJson(const ThirdPartyLocation& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - ThirdPartyLocation operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const ThirdPartyLocation& pod); + static void fillFrom(const QJsonObject& jo, ThirdPartyLocation& pod); }; } // namespace QMatrixClient diff --git a/lib/application-service/definitions/protocol.cpp b/lib/application-service/definitions/protocol.cpp index 04bb7dfc..2a62b15d 100644 --- a/lib/application-service/definitions/protocol.cpp +++ b/lib/application-service/definitions/protocol.cpp @@ -6,75 +6,55 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const FieldType& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const FieldType& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("regexp"), pod.regexp); addParam<>(jo, QStringLiteral("placeholder"), pod.placeholder); - return jo; } -FieldType FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, FieldType& result) { - FieldType result; - result.regexp = - fromJson(jo.value("regexp"_ls)); - result.placeholder = - fromJson(jo.value("placeholder"_ls)); - - return result; + fromJson(jo.value("regexp"_ls), result.regexp); + fromJson(jo.value("placeholder"_ls), result.placeholder); } -QJsonObject QMatrixClient::toJson(const ProtocolInstance& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const ProtocolInstance& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("desc"), pod.desc); addParam(jo, QStringLiteral("icon"), pod.icon); addParam<>(jo, QStringLiteral("fields"), pod.fields); addParam<>(jo, QStringLiteral("network_id"), pod.networkId); - return jo; } -ProtocolInstance FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, ProtocolInstance& result) { - ProtocolInstance result; - result.desc = - fromJson(jo.value("desc"_ls)); - result.icon = - fromJson(jo.value("icon"_ls)); - result.fields = - fromJson(jo.value("fields"_ls)); - result.networkId = - fromJson(jo.value("network_id"_ls)); - - return result; + fromJson(jo.value("desc"_ls), result.desc); + fromJson(jo.value("icon"_ls), result.icon); + fromJson(jo.value("fields"_ls), result.fields); + fromJson(jo.value("network_id"_ls), result.networkId); } -QJsonObject QMatrixClient::toJson(const ThirdPartyProtocol& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const ThirdPartyProtocol& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("user_fields"), pod.userFields); addParam<>(jo, QStringLiteral("location_fields"), pod.locationFields); addParam<>(jo, QStringLiteral("icon"), pod.icon); addParam<>(jo, QStringLiteral("field_types"), pod.fieldTypes); addParam<>(jo, QStringLiteral("instances"), pod.instances); - return jo; } -ThirdPartyProtocol FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, ThirdPartyProtocol& result) { - ThirdPartyProtocol result; - result.userFields = - fromJson(jo.value("user_fields"_ls)); - result.locationFields = - fromJson(jo.value("location_fields"_ls)); - result.icon = - fromJson(jo.value("icon"_ls)); - result.fieldTypes = - fromJson>(jo.value("field_types"_ls)); - result.instances = - fromJson>(jo.value("instances"_ls)); - - return result; + fromJson(jo.value("user_fields"_ls), result.userFields); + fromJson(jo.value("location_fields"_ls), result.locationFields); + fromJson(jo.value("icon"_ls), result.icon); + fromJson(jo.value("field_types"_ls), result.fieldTypes); + fromJson(jo.value("instances"_ls), result.instances); } diff --git a/lib/application-service/definitions/protocol.h b/lib/application-service/definitions/protocol.h index 2aca7d66..0a1f9a21 100644 --- a/lib/application-service/definitions/protocol.h +++ b/lib/application-service/definitions/protocol.h @@ -25,12 +25,10 @@ namespace QMatrixClient /// An placeholder serving as a valid example of the field value. QString placeholder; }; - - QJsonObject toJson(const FieldType& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - FieldType operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const FieldType& pod); + static void fillFrom(const QJsonObject& jo, FieldType& pod); }; struct ProtocolInstance @@ -45,12 +43,10 @@ namespace QMatrixClient /// A unique identifier across all instances. QString networkId; }; - - QJsonObject toJson(const ProtocolInstance& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - ProtocolInstance operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const ProtocolInstance& pod); + static void fillFrom(const QJsonObject& jo, ProtocolInstance& pod); }; struct ThirdPartyProtocol @@ -78,12 +74,10 @@ namespace QMatrixClient /// same application service. QVector instances; }; - - QJsonObject toJson(const ThirdPartyProtocol& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - ThirdPartyProtocol operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const ThirdPartyProtocol& pod); + static void fillFrom(const QJsonObject& jo, ThirdPartyProtocol& pod); }; } // namespace QMatrixClient diff --git a/lib/application-service/definitions/user.cpp b/lib/application-service/definitions/user.cpp index ca334236..8ba92321 100644 --- a/lib/application-service/definitions/user.cpp +++ b/lib/application-service/definitions/user.cpp @@ -6,25 +6,19 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const ThirdPartyUser& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const ThirdPartyUser& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("userid"), pod.userid); addParam<>(jo, QStringLiteral("protocol"), pod.protocol); addParam<>(jo, QStringLiteral("fields"), pod.fields); - return jo; } -ThirdPartyUser FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, ThirdPartyUser& result) { - ThirdPartyUser result; - result.userid = - fromJson(jo.value("userid"_ls)); - result.protocol = - fromJson(jo.value("protocol"_ls)); - result.fields = - fromJson(jo.value("fields"_ls)); - - return result; + fromJson(jo.value("userid"_ls), result.userid); + fromJson(jo.value("protocol"_ls), result.protocol); + fromJson(jo.value("fields"_ls), result.fields); } diff --git a/lib/application-service/definitions/user.h b/lib/application-service/definitions/user.h index 79ca7789..062d2cac 100644 --- a/lib/application-service/definitions/user.h +++ b/lib/application-service/definitions/user.h @@ -21,12 +21,10 @@ namespace QMatrixClient /// Information used to identify this third party location. QJsonObject fields; }; - - QJsonObject toJson(const ThirdPartyUser& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - ThirdPartyUser operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const ThirdPartyUser& pod); + static void fillFrom(const QJsonObject& jo, ThirdPartyUser& pod); }; } // namespace QMatrixClient diff --git a/lib/converters.cpp b/lib/converters.cpp index 41a9a65e..88f5267e 100644 --- a/lib/converters.cpp +++ b/lib/converters.cpp @@ -22,38 +22,34 @@ using namespace QMatrixClient; -QJsonValue QMatrixClient::variantToJson(const QVariant& v) +QJsonValue JsonConverter::dump(const QVariant& v) { return QJsonValue::fromVariant(v); } -QJsonObject QMatrixClient::toJson(const QVariantMap& map) +QVariant JsonConverter::load(const QJsonValue& jv) { - return QJsonObject::fromVariantMap(map); + return jv.toVariant(); } -#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) -QJsonObject QMatrixClient::toJson(const QVariantHash& hMap) +QJsonObject JsonConverter::dump(const variant_map_t& map) { - return QJsonObject::fromVariantHash(hMap); -} + return +#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) + QJsonObject::fromVariantHash +#else + QJsonObject::fromVariantMap #endif - -QVariant FromJson::operator()(const QJsonValue& jv) const -{ - return jv.toVariant(); + (map); } -QMap -FromJson>::operator()(const QJsonValue& jv) const +variant_map_t JsonConverter::load(const QJsonValue& jv) { - return jv.toObject().toVariantMap(); -} - + return jv.toObject(). #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) -QHash -FromJson>::operator()(const QJsonValue& jv) const -{ - return jv.toObject().toVariantHash(); -} + toVariantHash +#else + toVariantMap #endif + (); +} diff --git a/lib/converters.h b/lib/converters.h index 53855a1f..6227902d 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -57,238 +57,221 @@ class QVariant; namespace QMatrixClient { - // This catches anything implicitly convertible to QJsonValue/Object/Array - inline auto toJson(const QJsonValue& val) { return val; } - inline auto toJson(const QJsonObject& o) { return o; } - inline auto toJson(const QJsonArray& arr) { return arr; } - // Special-case QString to avoid ambiguity between QJsonValue - // and QVariant (also, QString.isEmpty() is used in _impl::AddNode<> below) - inline auto toJson(const QString& s) { return s; } - - inline QJsonArray toJson(const QStringList& strings) - { - return QJsonArray::fromStringList(strings); - } - - inline QString toJson(const QByteArray& bytes) + template + struct JsonObjectConverter { - return bytes.constData(); - } + static void dumpTo(QJsonObject& jo, const T& pod) { jo = pod; } + static void fillFrom(const QJsonObject& jo, T& pod) { pod = jo; } + }; - // QVariant is outrageously omnivorous - it consumes whatever is not - // exactly matching the signature of other toJson overloads. The trick - // below disables implicit conversion to QVariant through its numerous - // non-explicit constructors. - QJsonValue variantToJson(const QVariant& v); template - inline auto toJson(T&& /* const QVariant& or QVariant&& */ var) - -> std::enable_if_t, QVariant>::value, - QJsonValue> + struct JsonConverter { - return variantToJson(var); - } - QJsonObject toJson(const QMap& map); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) - QJsonObject toJson(const QHash& hMap); -#endif + static QJsonObject dump(const T& pod) + { + QJsonObject jo; + JsonObjectConverter::dumpTo(jo, pod); + return jo; + } + static T doLoad(const QJsonObject& jo) + { + T pod; + JsonObjectConverter::fillFrom(jo, pod); + return pod; + } + static T load(const QJsonValue& jv) { return doLoad(jv.toObject()); } + static T load(const QJsonDocument& jd) { return doLoad(jd.object()); } + }; template - inline QJsonArray toJson(const std::vector& vals) + inline auto toJson(const T& pod) { - QJsonArray ar; - for (const auto& v: vals) - ar.push_back(toJson(v)); - return ar; + return JsonConverter::dump(pod); } template - inline QJsonArray toJson(const QVector& vals) + inline auto fillJson(QJsonObject& json, const T& data) { - QJsonArray ar; - for (const auto& v: vals) - ar.push_back(toJson(v)); - return ar; + JsonObjectConverter::dumpTo(json, data); } template - inline QJsonObject toJson(const QSet& set) + inline auto fromJson(const QJsonValue& jv) { - QJsonObject json; - for (auto e: set) - json.insert(toJson(e), QJsonObject{}); - return json; + return JsonConverter::load(jv); } template - inline QJsonObject toJson(const QHash& hashMap) + inline T fromJson(const QJsonDocument& jd) { - QJsonObject json; - for (auto it = hashMap.begin(); it != hashMap.end(); ++it) - json.insert(it.key(), toJson(it.value())); - return json; + return JsonConverter::load(jd); } template - inline QJsonObject toJson(const std::unordered_map& hashMap) + inline void fromJson(const QJsonValue& jv, T& pod) { - QJsonObject json; - for (auto it = hashMap.begin(); it != hashMap.end(); ++it) - json.insert(it.key(), toJson(it.value())); - return json; + pod = fromJson(jv); } template - struct FromJsonObject + inline void fromJson(const QJsonDocument& jd, T& pod) { - T operator()(const QJsonObject& jo) const { return T(jo); } - }; + pod = fromJson(jd); + } + // Unfolds Omittable<> template - struct FromJson + inline void fromJson(const QJsonValue& jv, Omittable& pod) { - T operator()(const QJsonValue& jv) const - { - return FromJsonObject()(jv.toObject()); - } - T operator()(const QJsonDocument& jd) const - { - return FromJsonObject()(jd.object()); - } - }; + pod = fromJson(jv); + } template - inline auto fromJson(const QJsonValue& jv) + inline void fillFromJson(const QJsonValue& jv, T& pod) { - return FromJson()(jv); + JsonObjectConverter::fillFrom(jv.toObject(), pod); } + // JsonConverter<> specialisations + template - inline auto fromJson(const QJsonDocument& jd) + struct TrivialJsonDumper { - return FromJson()(jd); - } + // Works for: QJsonValue (and all things it can consume), + // QJsonObject, QJsonArray + static auto dump(const T& val) { return val; } + }; - template <> struct FromJson + template <> struct JsonConverter : public TrivialJsonDumper { - auto operator()(const QJsonValue& jv) const { return jv.toBool(); } + static auto load(const QJsonValue& jv) { return jv.toBool(); } }; - template <> struct FromJson + template <> struct JsonConverter : public TrivialJsonDumper { - auto operator()(const QJsonValue& jv) const { return jv.toInt(); } + static auto load(const QJsonValue& jv) { return jv.toInt(); } }; - template <> struct FromJson + template <> struct JsonConverter + : public TrivialJsonDumper { - auto operator()(const QJsonValue& jv) const { return jv.toDouble(); } + static auto load(const QJsonValue& jv) { return jv.toDouble(); } }; - template <> struct FromJson + template <> struct JsonConverter : public TrivialJsonDumper { - auto operator()(const QJsonValue& jv) const { return float(jv.toDouble()); } + static auto load(const QJsonValue& jv) { return float(jv.toDouble()); } }; - template <> struct FromJson + template <> struct JsonConverter + : public TrivialJsonDumper { - auto operator()(const QJsonValue& jv) const { return qint64(jv.toDouble()); } + static auto load(const QJsonValue& jv) { return qint64(jv.toDouble()); } }; - template <> struct FromJson + template <> struct JsonConverter + : public TrivialJsonDumper { - auto operator()(const QJsonValue& jv) const { return jv.toString(); } + static auto load(const QJsonValue& jv) { return jv.toString(); } }; - template <> struct FromJson + template <> struct JsonConverter { - auto operator()(const QJsonValue& jv) const + static auto dump(const QDateTime& val) = delete; // not provided yet + static auto load(const QJsonValue& jv) { - return QDateTime::fromMSecsSinceEpoch(fromJson(jv), Qt::UTC); + return QDateTime::fromMSecsSinceEpoch( + fromJson(jv), Qt::UTC); } }; - template <> struct FromJson + template <> struct JsonConverter { - auto operator()(const QJsonValue& jv) const + static auto dump(const QDate& val) = delete; // not provided yet + static auto load(const QJsonValue& jv) { return fromJson(jv).date(); } }; - template <> struct FromJson + template <> struct JsonConverter + : public TrivialJsonDumper { - auto operator()(const QJsonValue& jv) const - { - return jv.toArray(); - } + static auto load(const QJsonValue& jv) { return jv.toArray(); } }; - template <> struct FromJson + template <> struct JsonConverter { - auto operator()(const QJsonValue& jv) const + static QString dump(const QByteArray& ba) { return ba.constData(); } + static auto load(const QJsonValue& jv) { return fromJson(jv).toLatin1(); } }; - template <> struct FromJson + template <> struct JsonConverter { - QVariant operator()(const QJsonValue& jv) const; + static QJsonValue dump(const QVariant& v); + static QVariant load(const QJsonValue& jv); }; - template - struct ArrayFromJson + template + struct JsonArrayConverter { - auto operator()(const QJsonArray& ja) const + static void dumpTo(QJsonArray& ar, const VectorT& vals) { - using size_type = typename VectorT::size_type; - VectorT vect; vect.resize(size_type(ja.size())); - std::transform(ja.begin(), ja.end(), - vect.begin(), FromJson()); - return vect; + for (const auto& v: vals) + ar.push_back(toJson(v)); } - auto operator()(const QJsonValue& jv) const + static auto dump(const VectorT& vals) { - return operator()(jv.toArray()); + QJsonArray ja; + dumpTo(ja, vals); + return ja; } - auto operator()(const QJsonDocument& jd) const + static auto load(const QJsonArray& ja) { - return operator()(jd.array()); + VectorT vect; vect.reserve(typename VectorT::size_type(ja.size())); + for (const auto& i: ja) + vect.push_back(fromJson(i)); + return vect; } + static auto load(const QJsonValue& jv) { return load(jv.toArray()); } + static auto load(const QJsonDocument& jd) { return load(jd.array()); } }; - template - struct FromJson> : ArrayFromJson> + template struct JsonConverter> + : public JsonArrayConverter> { }; - template - struct FromJson> : ArrayFromJson> + template struct JsonConverter> + : public JsonArrayConverter> + { }; + + template struct JsonConverter> + : public JsonArrayConverter> { }; - template struct FromJson> + template <> struct JsonConverter + : public JsonConverter> { - auto operator()(const QJsonValue& jv) const + static auto dump(const QStringList& sl) { - const auto jsonArray = jv.toArray(); - QList sl; sl.reserve(jsonArray.size()); - std::transform(jsonArray.begin(), jsonArray.end(), - std::back_inserter(sl), FromJson()); - return sl; + return QJsonArray::fromStringList(sl); } }; - template <> struct FromJson : FromJson> { }; - - template <> struct FromJson> + template <> struct JsonObjectConverter> { - QMap operator()(const QJsonValue& jv) const; - }; - - template struct FromJson> - { - auto operator()(const QJsonValue& jv) const + static void dumpTo(QJsonObject& json, const QSet& s) + { + for (const auto& e: s) + json.insert(toJson(e), QJsonObject{}); + } + static auto fillFrom(const QJsonObject& json, QSet& s) { - const auto json = jv.toObject(); - QSet s; s.reserve(json.size()); + s.reserve(s.size() + json.size()); for (auto it = json.begin(); it != json.end(); ++it) s.insert(it.key()); return s; @@ -298,39 +281,44 @@ namespace QMatrixClient template struct HashMapFromJson { - auto operator()(const QJsonObject& jo) const + static void dumpTo(QJsonObject& json, const HashMapT& hashMap) + { + for (auto it = hashMap.begin(); it != hashMap.end(); ++it) + json.insert(it.key(), toJson(it.value())); + } + static void fillFrom(const QJsonObject& jo, HashMapT& h) { - HashMapT h; h.reserve(jo.size()); + h.reserve(jo.size()); for (auto it = jo.begin(); it != jo.end(); ++it) h[it.key()] = fromJson(it.value()); - return h; - } - auto operator()(const QJsonValue& jv) const - { - return operator()(jv.toObject()); - } - auto operator()(const QJsonDocument& jd) const - { - return operator()(jd.object()); } }; template - struct FromJson> - : HashMapFromJson> + struct JsonObjectConverter> + : public HashMapFromJson> { }; template - struct FromJson> : HashMapFromJson> + struct JsonObjectConverter> + : public HashMapFromJson> { }; + // We could use std::conditional<> below but QT_VERSION* macros in C++ code + // cause (kinda valid but useless and noisy) compiler warnings about + // bitwise operations on signed integers; so use the preprocessor for now. + using variant_map_t = #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) - template <> struct FromJson> + QVariantHash; +#else + QVariantMap; +#endif + template <> struct JsonConverter { - QHash operator()(const QJsonValue& jv) const; + static QJsonObject dump(const variant_map_t& vh); + static QVariantHash load(const QJsonValue& jv); }; -#endif // Conditional insertion into a QJsonObject diff --git a/lib/csapi/admin.cpp b/lib/csapi/admin.cpp index 6066d4d9..ce06a56d 100644 --- a/lib/csapi/admin.cpp +++ b/lib/csapi/admin.cpp @@ -16,43 +16,29 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - GetWhoIsJob::ConnectionInfo operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetWhoIsJob::ConnectionInfo& result) { - GetWhoIsJob::ConnectionInfo result; - result.ip = - fromJson(jo.value("ip"_ls)); - result.lastSeen = - fromJson(jo.value("last_seen"_ls)); - result.userAgent = - fromJson(jo.value("user_agent"_ls)); - - return result; + fromJson(jo.value("ip"_ls), result.ip); + fromJson(jo.value("last_seen"_ls), result.lastSeen); + fromJson(jo.value("user_agent"_ls), result.userAgent); } }; - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - GetWhoIsJob::SessionInfo operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetWhoIsJob::SessionInfo& result) { - GetWhoIsJob::SessionInfo result; - result.connections = - fromJson>(jo.value("connections"_ls)); - - return result; + fromJson(jo.value("connections"_ls), result.connections); } }; - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - GetWhoIsJob::DeviceInfo operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetWhoIsJob::DeviceInfo& result) { - GetWhoIsJob::DeviceInfo result; - result.sessions = - fromJson>(jo.value("sessions"_ls)); - - return result; + fromJson(jo.value("sessions"_ls), result.sessions); } }; } // namespace QMatrixClient @@ -94,8 +80,8 @@ const QHash& GetWhoIsJob::devices() const BaseJob::Status GetWhoIsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->userId = fromJson(json.value("user_id"_ls)); - d->devices = fromJson>(json.value("devices"_ls)); + fromJson(json.value("user_id"_ls), d->userId); + fromJson(json.value("devices"_ls), d->devices); return Success; } diff --git a/lib/csapi/administrative_contact.cpp b/lib/csapi/administrative_contact.cpp index f62002a6..9b021e17 100644 --- a/lib/csapi/administrative_contact.cpp +++ b/lib/csapi/administrative_contact.cpp @@ -16,21 +16,14 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - GetAccount3PIDsJob::ThirdPartyIdentifier operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetAccount3PIDsJob::ThirdPartyIdentifier& result) { - GetAccount3PIDsJob::ThirdPartyIdentifier result; - result.medium = - fromJson(jo.value("medium"_ls)); - result.address = - fromJson(jo.value("address"_ls)); - result.validatedAt = - fromJson(jo.value("validated_at"_ls)); - result.addedAt = - fromJson(jo.value("added_at"_ls)); - - return result; + fromJson(jo.value("medium"_ls), result.medium); + fromJson(jo.value("address"_ls), result.address); + fromJson(jo.value("validated_at"_ls), result.validatedAt); + fromJson(jo.value("added_at"_ls), result.addedAt); } }; } // namespace QMatrixClient @@ -66,7 +59,7 @@ const QVector& GetAccount3PIDsJob::thr BaseJob::Status GetAccount3PIDsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->threepids = fromJson>(json.value("threepids"_ls)); + fromJson(json.value("threepids"_ls), d->threepids); return Success; } @@ -74,14 +67,15 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const Post3PIDsJob::ThreePidCredentials& pod) + template <> struct JsonObjectConverter { - QJsonObject jo; - addParam<>(jo, QStringLiteral("client_secret"), pod.clientSecret); - addParam<>(jo, QStringLiteral("id_server"), pod.idServer); - addParam<>(jo, QStringLiteral("sid"), pod.sid); - return jo; - } + static void dumpTo(QJsonObject& jo, const Post3PIDsJob::ThreePidCredentials& pod) + { + addParam<>(jo, QStringLiteral("client_secret"), pod.clientSecret); + addParam<>(jo, QStringLiteral("id_server"), pod.idServer); + addParam<>(jo, QStringLiteral("sid"), pod.sid); + } + }; } // namespace QMatrixClient static const auto Post3PIDsJobName = QStringLiteral("Post3PIDsJob"); @@ -139,7 +133,7 @@ const Sid& RequestTokenTo3PIDEmailJob::data() const BaseJob::Status RequestTokenTo3PIDEmailJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } @@ -175,7 +169,7 @@ const Sid& RequestTokenTo3PIDMSISDNJob::data() const BaseJob::Status RequestTokenTo3PIDMSISDNJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/content-repo.cpp b/lib/csapi/content-repo.cpp index 9b590e42..22223985 100644 --- a/lib/csapi/content-repo.cpp +++ b/lib/csapi/content-repo.cpp @@ -52,7 +52,7 @@ BaseJob::Status UploadContentJob::parseJson(const QJsonDocument& data) if (!json.contains("content_uri"_ls)) return { JsonParseError, "The key 'content_uri' not found in the response" }; - d->contentUri = fromJson(json.value("content_uri"_ls)); + fromJson(json.value("content_uri"_ls), d->contentUri); return Success; } @@ -276,8 +276,8 @@ const QString& GetUrlPreviewJob::ogImage() const BaseJob::Status GetUrlPreviewJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->matrixImageSize = fromJson(json.value("matrix:image:size"_ls)); - d->ogImage = fromJson(json.value("og:image"_ls)); + fromJson(json.value("matrix:image:size"_ls), d->matrixImageSize); + fromJson(json.value("og:image"_ls), d->ogImage); return Success; } @@ -312,7 +312,7 @@ Omittable GetConfigJob::uploadSize() const BaseJob::Status GetConfigJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->uploadSize = fromJson(json.value("m.upload.size"_ls)); + fromJson(json.value("m.upload.size"_ls), d->uploadSize); return Success; } diff --git a/lib/csapi/create_room.cpp b/lib/csapi/create_room.cpp index 36f83727..c44b73ac 100644 --- a/lib/csapi/create_room.cpp +++ b/lib/csapi/create_room.cpp @@ -16,23 +16,25 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const CreateRoomJob::Invite3pid& pod) + template <> struct JsonObjectConverter { - QJsonObject jo; - addParam<>(jo, QStringLiteral("id_server"), pod.idServer); - addParam<>(jo, QStringLiteral("medium"), pod.medium); - addParam<>(jo, QStringLiteral("address"), pod.address); - return jo; - } + static void dumpTo(QJsonObject& jo, const CreateRoomJob::Invite3pid& pod) + { + addParam<>(jo, QStringLiteral("id_server"), pod.idServer); + addParam<>(jo, QStringLiteral("medium"), pod.medium); + addParam<>(jo, QStringLiteral("address"), pod.address); + } + }; - QJsonObject toJson(const CreateRoomJob::StateEvent& pod) + template <> struct JsonObjectConverter { - QJsonObject jo; - addParam<>(jo, QStringLiteral("type"), pod.type); - addParam(jo, QStringLiteral("state_key"), pod.stateKey); - addParam<>(jo, QStringLiteral("content"), pod.content); - return jo; - } + static void dumpTo(QJsonObject& jo, const CreateRoomJob::StateEvent& pod) + { + addParam<>(jo, QStringLiteral("type"), pod.type); + addParam(jo, QStringLiteral("state_key"), pod.stateKey); + addParam<>(jo, QStringLiteral("content"), pod.content); + } + }; } // namespace QMatrixClient class CreateRoomJob::Private @@ -77,7 +79,7 @@ BaseJob::Status CreateRoomJob::parseJson(const QJsonDocument& data) if (!json.contains("room_id"_ls)) return { JsonParseError, "The key 'room_id' not found in the response" }; - d->roomId = fromJson(json.value("room_id"_ls)); + fromJson(json.value("room_id"_ls), d->roomId); return Success; } diff --git a/lib/csapi/definitions/auth_data.cpp b/lib/csapi/definitions/auth_data.cpp index f8639432..006b8c7e 100644 --- a/lib/csapi/definitions/auth_data.cpp +++ b/lib/csapi/definitions/auth_data.cpp @@ -6,23 +6,20 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const AuthenticationData& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const AuthenticationData& pod) { - QJsonObject jo = toJson(pod.authInfo); + fillJson(jo, pod.authInfo); addParam<>(jo, QStringLiteral("type"), pod.type); addParam(jo, QStringLiteral("session"), pod.session); - return jo; } -AuthenticationData FromJsonObject::operator()(QJsonObject jo) const +void JsonObjectConverter::fillFrom( + QJsonObject jo, AuthenticationData& result) { - AuthenticationData result; - result.type = - fromJson(jo.take("type"_ls)); - result.session = - fromJson(jo.take("session"_ls)); + fromJson(jo.take("type"_ls), result.type); + fromJson(jo.take("session"_ls), result.session); - result.authInfo = fromJson>(jo); - return result; + fromJson(jo, result.authInfo); } diff --git a/lib/csapi/definitions/auth_data.h b/lib/csapi/definitions/auth_data.h index 661d3e5f..26eb205c 100644 --- a/lib/csapi/definitions/auth_data.h +++ b/lib/csapi/definitions/auth_data.h @@ -23,12 +23,10 @@ namespace QMatrixClient /// Keys dependent on the login type QHash authInfo; }; - - QJsonObject toJson(const AuthenticationData& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - AuthenticationData operator()(QJsonObject jo) const; + static void dumpTo(QJsonObject& jo, const AuthenticationData& pod); + static void fillFrom(QJsonObject jo, AuthenticationData& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/client_device.cpp b/lib/csapi/definitions/client_device.cpp index 4a192f85..752b806a 100644 --- a/lib/csapi/definitions/client_device.cpp +++ b/lib/csapi/definitions/client_device.cpp @@ -6,28 +6,21 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const Device& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const Device& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("device_id"), pod.deviceId); addParam(jo, QStringLiteral("display_name"), pod.displayName); addParam(jo, QStringLiteral("last_seen_ip"), pod.lastSeenIp); addParam(jo, QStringLiteral("last_seen_ts"), pod.lastSeenTs); - return jo; } -Device FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, Device& result) { - Device result; - result.deviceId = - fromJson(jo.value("device_id"_ls)); - result.displayName = - fromJson(jo.value("display_name"_ls)); - result.lastSeenIp = - fromJson(jo.value("last_seen_ip"_ls)); - result.lastSeenTs = - fromJson(jo.value("last_seen_ts"_ls)); - - return result; + fromJson(jo.value("device_id"_ls), result.deviceId); + fromJson(jo.value("display_name"_ls), result.displayName); + fromJson(jo.value("last_seen_ip"_ls), result.lastSeenIp); + fromJson(jo.value("last_seen_ts"_ls), result.lastSeenTs); } diff --git a/lib/csapi/definitions/client_device.h b/lib/csapi/definitions/client_device.h index 9f10888a..a6224f71 100644 --- a/lib/csapi/definitions/client_device.h +++ b/lib/csapi/definitions/client_device.h @@ -28,12 +28,10 @@ namespace QMatrixClient /// reasons). Omittable lastSeenTs; }; - - QJsonObject toJson(const Device& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - Device operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const Device& pod); + static void fillFrom(const QJsonObject& jo, Device& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/device_keys.cpp b/lib/csapi/definitions/device_keys.cpp index a0e0ca42..1e79499f 100644 --- a/lib/csapi/definitions/device_keys.cpp +++ b/lib/csapi/definitions/device_keys.cpp @@ -6,31 +6,23 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const DeviceKeys& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const DeviceKeys& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("user_id"), pod.userId); addParam<>(jo, QStringLiteral("device_id"), pod.deviceId); addParam<>(jo, QStringLiteral("algorithms"), pod.algorithms); addParam<>(jo, QStringLiteral("keys"), pod.keys); addParam<>(jo, QStringLiteral("signatures"), pod.signatures); - return jo; } -DeviceKeys FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, DeviceKeys& result) { - DeviceKeys result; - result.userId = - fromJson(jo.value("user_id"_ls)); - result.deviceId = - fromJson(jo.value("device_id"_ls)); - result.algorithms = - fromJson(jo.value("algorithms"_ls)); - result.keys = - fromJson>(jo.value("keys"_ls)); - result.signatures = - fromJson>>(jo.value("signatures"_ls)); - - return result; + fromJson(jo.value("user_id"_ls), result.userId); + fromJson(jo.value("device_id"_ls), result.deviceId); + fromJson(jo.value("algorithms"_ls), result.algorithms); + fromJson(jo.value("keys"_ls), result.keys); + fromJson(jo.value("signatures"_ls), result.signatures); } diff --git a/lib/csapi/definitions/device_keys.h b/lib/csapi/definitions/device_keys.h index 6023e7e8..8ebe1125 100644 --- a/lib/csapi/definitions/device_keys.h +++ b/lib/csapi/definitions/device_keys.h @@ -34,12 +34,10 @@ namespace QMatrixClient /// JSON`_. QHash> signatures; }; - - QJsonObject toJson(const DeviceKeys& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - DeviceKeys operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const DeviceKeys& pod); + static void fillFrom(const QJsonObject& jo, DeviceKeys& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/event_filter.cpp b/lib/csapi/definitions/event_filter.cpp index cc444db0..b20d7807 100644 --- a/lib/csapi/definitions/event_filter.cpp +++ b/lib/csapi/definitions/event_filter.cpp @@ -6,31 +6,23 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const EventFilter& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const EventFilter& pod) { - QJsonObject jo; addParam(jo, QStringLiteral("limit"), pod.limit); addParam(jo, QStringLiteral("not_senders"), pod.notSenders); addParam(jo, QStringLiteral("not_types"), pod.notTypes); addParam(jo, QStringLiteral("senders"), pod.senders); addParam(jo, QStringLiteral("types"), pod.types); - return jo; } -EventFilter FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, EventFilter& result) { - EventFilter result; - result.limit = - fromJson(jo.value("limit"_ls)); - result.notSenders = - fromJson(jo.value("not_senders"_ls)); - result.notTypes = - fromJson(jo.value("not_types"_ls)); - result.senders = - fromJson(jo.value("senders"_ls)); - result.types = - fromJson(jo.value("types"_ls)); - - return result; + fromJson(jo.value("limit"_ls), result.limit); + fromJson(jo.value("not_senders"_ls), result.notSenders); + fromJson(jo.value("not_types"_ls), result.notTypes); + fromJson(jo.value("senders"_ls), result.senders); + fromJson(jo.value("types"_ls), result.types); } diff --git a/lib/csapi/definitions/event_filter.h b/lib/csapi/definitions/event_filter.h index 5c6a5b27..6de1fe79 100644 --- a/lib/csapi/definitions/event_filter.h +++ b/lib/csapi/definitions/event_filter.h @@ -25,12 +25,10 @@ namespace QMatrixClient /// A list of event types to include. If this list is absent then all event types are included. A ``'*'`` can be used as a wildcard to match any sequence of characters. QStringList types; }; - - QJsonObject toJson(const EventFilter& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - EventFilter operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const EventFilter& pod); + static void fillFrom(const QJsonObject& jo, EventFilter& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/public_rooms_response.cpp b/lib/csapi/definitions/public_rooms_response.cpp index 2f52501d..0d26662c 100644 --- a/lib/csapi/definitions/public_rooms_response.cpp +++ b/lib/csapi/definitions/public_rooms_response.cpp @@ -6,9 +6,9 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const PublicRoomsChunk& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const PublicRoomsChunk& pod) { - QJsonObject jo; addParam(jo, QStringLiteral("aliases"), pod.aliases); addParam(jo, QStringLiteral("canonical_alias"), pod.canonicalAlias); addParam(jo, QStringLiteral("name"), pod.name); @@ -18,56 +18,37 @@ QJsonObject QMatrixClient::toJson(const PublicRoomsChunk& pod) addParam<>(jo, QStringLiteral("world_readable"), pod.worldReadable); addParam<>(jo, QStringLiteral("guest_can_join"), pod.guestCanJoin); addParam(jo, QStringLiteral("avatar_url"), pod.avatarUrl); - return jo; } -PublicRoomsChunk FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, PublicRoomsChunk& result) { - PublicRoomsChunk result; - result.aliases = - fromJson(jo.value("aliases"_ls)); - result.canonicalAlias = - fromJson(jo.value("canonical_alias"_ls)); - result.name = - fromJson(jo.value("name"_ls)); - result.numJoinedMembers = - fromJson(jo.value("num_joined_members"_ls)); - result.roomId = - fromJson(jo.value("room_id"_ls)); - result.topic = - fromJson(jo.value("topic"_ls)); - result.worldReadable = - fromJson(jo.value("world_readable"_ls)); - result.guestCanJoin = - fromJson(jo.value("guest_can_join"_ls)); - result.avatarUrl = - fromJson(jo.value("avatar_url"_ls)); - - return result; + fromJson(jo.value("aliases"_ls), result.aliases); + fromJson(jo.value("canonical_alias"_ls), result.canonicalAlias); + fromJson(jo.value("name"_ls), result.name); + fromJson(jo.value("num_joined_members"_ls), result.numJoinedMembers); + fromJson(jo.value("room_id"_ls), result.roomId); + fromJson(jo.value("topic"_ls), result.topic); + fromJson(jo.value("world_readable"_ls), result.worldReadable); + fromJson(jo.value("guest_can_join"_ls), result.guestCanJoin); + fromJson(jo.value("avatar_url"_ls), result.avatarUrl); } -QJsonObject QMatrixClient::toJson(const PublicRoomsResponse& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const PublicRoomsResponse& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("chunk"), pod.chunk); addParam(jo, QStringLiteral("next_batch"), pod.nextBatch); addParam(jo, QStringLiteral("prev_batch"), pod.prevBatch); addParam(jo, QStringLiteral("total_room_count_estimate"), pod.totalRoomCountEstimate); - return jo; } -PublicRoomsResponse FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, PublicRoomsResponse& result) { - PublicRoomsResponse result; - result.chunk = - fromJson>(jo.value("chunk"_ls)); - result.nextBatch = - fromJson(jo.value("next_batch"_ls)); - result.prevBatch = - fromJson(jo.value("prev_batch"_ls)); - result.totalRoomCountEstimate = - fromJson(jo.value("total_room_count_estimate"_ls)); - - return result; + fromJson(jo.value("chunk"_ls), result.chunk); + fromJson(jo.value("next_batch"_ls), result.nextBatch); + fromJson(jo.value("prev_batch"_ls), result.prevBatch); + fromJson(jo.value("total_room_count_estimate"_ls), result.totalRoomCountEstimate); } diff --git a/lib/csapi/definitions/public_rooms_response.h b/lib/csapi/definitions/public_rooms_response.h index 88c805ba..4c54ac25 100644 --- a/lib/csapi/definitions/public_rooms_response.h +++ b/lib/csapi/definitions/public_rooms_response.h @@ -36,12 +36,10 @@ namespace QMatrixClient /// The URL for the room's avatar, if one is set. QString avatarUrl; }; - - QJsonObject toJson(const PublicRoomsChunk& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - PublicRoomsChunk operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const PublicRoomsChunk& pod); + static void fillFrom(const QJsonObject& jo, PublicRoomsChunk& pod); }; /// A list of the rooms on the server. @@ -61,12 +59,10 @@ namespace QMatrixClient /// server has an estimate. Omittable totalRoomCountEstimate; }; - - QJsonObject toJson(const PublicRoomsResponse& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - PublicRoomsResponse operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const PublicRoomsResponse& pod); + static void fillFrom(const QJsonObject& jo, PublicRoomsResponse& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/push_condition.cpp b/lib/csapi/definitions/push_condition.cpp index 045094bc..ace02755 100644 --- a/lib/csapi/definitions/push_condition.cpp +++ b/lib/csapi/definitions/push_condition.cpp @@ -6,28 +6,21 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const PushCondition& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const PushCondition& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("kind"), pod.kind); addParam(jo, QStringLiteral("key"), pod.key); addParam(jo, QStringLiteral("pattern"), pod.pattern); addParam(jo, QStringLiteral("is"), pod.is); - return jo; } -PushCondition FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, PushCondition& result) { - PushCondition result; - result.kind = - fromJson(jo.value("kind"_ls)); - result.key = - fromJson(jo.value("key"_ls)); - result.pattern = - fromJson(jo.value("pattern"_ls)); - result.is = - fromJson(jo.value("is"_ls)); - - return result; + fromJson(jo.value("kind"_ls), result.kind); + fromJson(jo.value("key"_ls), result.key); + fromJson(jo.value("pattern"_ls), result.pattern); + fromJson(jo.value("is"_ls), result.is); } diff --git a/lib/csapi/definitions/push_condition.h b/lib/csapi/definitions/push_condition.h index defcebb3..e45526d2 100644 --- a/lib/csapi/definitions/push_condition.h +++ b/lib/csapi/definitions/push_condition.h @@ -28,12 +28,10 @@ namespace QMatrixClient /// so forth. If no prefix is present, this parameter defaults to ==. QString is; }; - - QJsonObject toJson(const PushCondition& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - PushCondition operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const PushCondition& pod); + static void fillFrom(const QJsonObject& jo, PushCondition& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/push_rule.cpp b/lib/csapi/definitions/push_rule.cpp index baddd187..abbb04b5 100644 --- a/lib/csapi/definitions/push_rule.cpp +++ b/lib/csapi/definitions/push_rule.cpp @@ -6,34 +6,25 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const PushRule& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const PushRule& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("actions"), pod.actions); addParam<>(jo, QStringLiteral("default"), pod.isDefault); addParam<>(jo, QStringLiteral("enabled"), pod.enabled); addParam<>(jo, QStringLiteral("rule_id"), pod.ruleId); addParam(jo, QStringLiteral("conditions"), pod.conditions); addParam(jo, QStringLiteral("pattern"), pod.pattern); - return jo; } -PushRule FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, PushRule& result) { - PushRule result; - result.actions = - fromJson>(jo.value("actions"_ls)); - result.isDefault = - fromJson(jo.value("default"_ls)); - result.enabled = - fromJson(jo.value("enabled"_ls)); - result.ruleId = - fromJson(jo.value("rule_id"_ls)); - result.conditions = - fromJson>(jo.value("conditions"_ls)); - result.pattern = - fromJson(jo.value("pattern"_ls)); - - return result; + fromJson(jo.value("actions"_ls), result.actions); + fromJson(jo.value("default"_ls), result.isDefault); + fromJson(jo.value("enabled"_ls), result.enabled); + fromJson(jo.value("rule_id"_ls), result.ruleId); + fromJson(jo.value("conditions"_ls), result.conditions); + fromJson(jo.value("pattern"_ls), result.pattern); } diff --git a/lib/csapi/definitions/push_rule.h b/lib/csapi/definitions/push_rule.h index 5f52876d..05328b8b 100644 --- a/lib/csapi/definitions/push_rule.h +++ b/lib/csapi/definitions/push_rule.h @@ -34,12 +34,10 @@ namespace QMatrixClient /// rules. QString pattern; }; - - QJsonObject toJson(const PushRule& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - PushRule operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const PushRule& pod); + static void fillFrom(const QJsonObject& jo, PushRule& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/push_ruleset.cpp b/lib/csapi/definitions/push_ruleset.cpp index 14b7a4b6..f1bad882 100644 --- a/lib/csapi/definitions/push_ruleset.cpp +++ b/lib/csapi/definitions/push_ruleset.cpp @@ -6,31 +6,23 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const PushRuleset& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const PushRuleset& pod) { - QJsonObject jo; addParam(jo, QStringLiteral("content"), pod.content); addParam(jo, QStringLiteral("override"), pod.override); addParam(jo, QStringLiteral("room"), pod.room); addParam(jo, QStringLiteral("sender"), pod.sender); addParam(jo, QStringLiteral("underride"), pod.underride); - return jo; } -PushRuleset FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, PushRuleset& result) { - PushRuleset result; - result.content = - fromJson>(jo.value("content"_ls)); - result.override = - fromJson>(jo.value("override"_ls)); - result.room = - fromJson>(jo.value("room"_ls)); - result.sender = - fromJson>(jo.value("sender"_ls)); - result.underride = - fromJson>(jo.value("underride"_ls)); - - return result; + fromJson(jo.value("content"_ls), result.content); + fromJson(jo.value("override"_ls), result.override); + fromJson(jo.value("room"_ls), result.room); + fromJson(jo.value("sender"_ls), result.sender); + fromJson(jo.value("underride"_ls), result.underride); } diff --git a/lib/csapi/definitions/push_ruleset.h b/lib/csapi/definitions/push_ruleset.h index a274b72a..f2d937c0 100644 --- a/lib/csapi/definitions/push_ruleset.h +++ b/lib/csapi/definitions/push_ruleset.h @@ -22,12 +22,10 @@ namespace QMatrixClient QVector sender; QVector underride; }; - - QJsonObject toJson(const PushRuleset& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - PushRuleset operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const PushRuleset& pod); + static void fillFrom(const QJsonObject& jo, PushRuleset& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/room_event_filter.cpp b/lib/csapi/definitions/room_event_filter.cpp index 8cd2ded7..df92e684 100644 --- a/lib/csapi/definitions/room_event_filter.cpp +++ b/lib/csapi/definitions/room_event_filter.cpp @@ -6,31 +6,21 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const RoomEventFilter& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const RoomEventFilter& pod) { - QJsonObject jo; + fillJson(jo, pod); addParam(jo, QStringLiteral("not_rooms"), pod.notRooms); addParam(jo, QStringLiteral("rooms"), pod.rooms); addParam(jo, QStringLiteral("contains_url"), pod.containsUrl); - addParam(jo, QStringLiteral("lazy_load_members"), pod.lazyLoadMembers); - addParam(jo, QStringLiteral("include_redundant_members"), pod.includeRedundantMembers); - return jo; } -RoomEventFilter FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, RoomEventFilter& result) { - RoomEventFilter result; - result.notRooms = - fromJson(jo.value("not_rooms"_ls)); - result.rooms = - fromJson(jo.value("rooms"_ls)); - result.containsUrl = - fromJson(jo.value("contains_url"_ls)); - result.lazyLoadMembers = - fromJson(jo.value("lazy_load_members"_ls)); - result.includeRedundantMembers = - fromJson(jo.value("include_redundant_members"_ls)); - - return result; + fillFromJson(jo, result); + fromJson(jo.value("not_rooms"_ls), result.notRooms); + fromJson(jo.value("rooms"_ls), result.rooms); + fromJson(jo.value("contains_url"_ls), result.containsUrl); } diff --git a/lib/csapi/definitions/room_event_filter.h b/lib/csapi/definitions/room_event_filter.h index 87f01189..3908b8ec 100644 --- a/lib/csapi/definitions/room_event_filter.h +++ b/lib/csapi/definitions/room_event_filter.h @@ -21,17 +21,11 @@ namespace QMatrixClient QStringList rooms; /// If ``true``, includes only events with a ``url`` key in their content. If ``false``, excludes those events. Defaults to ``false``. bool containsUrl; - /// If ``true``, the only ``m.room.member`` events returned in the ``state`` section of the ``/sync`` response are those which are definitely necessary for a client to display the ``sender`` of the timeline events in that response. If ``false``, ``m.room.member`` events are not filtered. By default, servers should suppress duplicate redundant lazy-loaded ``m.room.member`` events from being sent to a given client across multiple calls to ``/sync``, given that most clients cache membership events (see include_redundant_members to change this behaviour). - bool lazyLoadMembers; - /// If ``true``, the ``state`` section of the ``/sync`` response will always contain the ``m.room.member`` events required to display the ``sender`` of the timeline events in that response, assuming ``lazy_load_members`` is enabled. This means that redundant duplicate member events may be returned across multiple calls to ``/sync``. This is useful for naive clients who never track membership data. If ``false``, duplicate ``m.room.member`` events may be suppressed by the server across multiple calls to ``/sync``. If ``lazy_load_members`` is ``false`` this field is ignored. - bool includeRedundantMembers; }; - - QJsonObject toJson(const RoomEventFilter& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - RoomEventFilter operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const RoomEventFilter& pod); + static void fillFrom(const QJsonObject& jo, RoomEventFilter& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/sync_filter.cpp b/lib/csapi/definitions/sync_filter.cpp index bd87804c..32752d1f 100644 --- a/lib/csapi/definitions/sync_filter.cpp +++ b/lib/csapi/definitions/sync_filter.cpp @@ -6,9 +6,25 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const RoomFilter& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const StateFilter& pod) +{ + fillJson(jo, pod); + addParam(jo, QStringLiteral("lazy_load_members"), pod.lazyLoadMembers); + addParam(jo, QStringLiteral("include_redundant_members"), pod.includeRedundantMembers); +} + +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, StateFilter& result) +{ + fillFromJson(jo, result); + fromJson(jo.value("lazy_load_members"_ls), result.lazyLoadMembers); + fromJson(jo.value("include_redundant_members"_ls), result.includeRedundantMembers); +} + +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const RoomFilter& pod) { - QJsonObject jo; addParam(jo, QStringLiteral("not_rooms"), pod.notRooms); addParam(jo, QStringLiteral("rooms"), pod.rooms); addParam(jo, QStringLiteral("ephemeral"), pod.ephemeral); @@ -16,55 +32,37 @@ QJsonObject QMatrixClient::toJson(const RoomFilter& pod) addParam(jo, QStringLiteral("state"), pod.state); addParam(jo, QStringLiteral("timeline"), pod.timeline); addParam(jo, QStringLiteral("account_data"), pod.accountData); - return jo; } -RoomFilter FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, RoomFilter& result) { - RoomFilter result; - result.notRooms = - fromJson(jo.value("not_rooms"_ls)); - result.rooms = - fromJson(jo.value("rooms"_ls)); - result.ephemeral = - fromJson(jo.value("ephemeral"_ls)); - result.includeLeave = - fromJson(jo.value("include_leave"_ls)); - result.state = - fromJson(jo.value("state"_ls)); - result.timeline = - fromJson(jo.value("timeline"_ls)); - result.accountData = - fromJson(jo.value("account_data"_ls)); - - return result; + fromJson(jo.value("not_rooms"_ls), result.notRooms); + fromJson(jo.value("rooms"_ls), result.rooms); + fromJson(jo.value("ephemeral"_ls), result.ephemeral); + fromJson(jo.value("include_leave"_ls), result.includeLeave); + fromJson(jo.value("state"_ls), result.state); + fromJson(jo.value("timeline"_ls), result.timeline); + fromJson(jo.value("account_data"_ls), result.accountData); } -QJsonObject QMatrixClient::toJson(const Filter& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const Filter& pod) { - QJsonObject jo; addParam(jo, QStringLiteral("event_fields"), pod.eventFields); addParam(jo, QStringLiteral("event_format"), pod.eventFormat); addParam(jo, QStringLiteral("presence"), pod.presence); addParam(jo, QStringLiteral("account_data"), pod.accountData); addParam(jo, QStringLiteral("room"), pod.room); - return jo; } -Filter FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, Filter& result) { - Filter result; - result.eventFields = - fromJson(jo.value("event_fields"_ls)); - result.eventFormat = - fromJson(jo.value("event_format"_ls)); - result.presence = - fromJson(jo.value("presence"_ls)); - result.accountData = - fromJson(jo.value("account_data"_ls)); - result.room = - fromJson(jo.value("room"_ls)); - - return result; + fromJson(jo.value("event_fields"_ls), result.eventFields); + fromJson(jo.value("event_format"_ls), result.eventFormat); + fromJson(jo.value("presence"_ls), result.presence); + fromJson(jo.value("account_data"_ls), result.accountData); + fromJson(jo.value("room"_ls), result.room); } diff --git a/lib/csapi/definitions/sync_filter.h b/lib/csapi/definitions/sync_filter.h index ca275a9a..ccc3061b 100644 --- a/lib/csapi/definitions/sync_filter.h +++ b/lib/csapi/definitions/sync_filter.h @@ -14,6 +14,37 @@ namespace QMatrixClient { // Data structures + /// The state events to include for rooms. + struct StateFilter : RoomEventFilter + { + /// If ``true``, the only ``m.room.member`` events returned in + /// the ``state`` section of the ``/sync`` response are those + /// which are definitely necessary for a client to display + /// the ``sender`` of the timeline events in that response. + /// If ``false``, ``m.room.member`` events are not filtered. + /// By default, servers should suppress duplicate redundant + /// lazy-loaded ``m.room.member`` events from being sent to a given + /// client across multiple calls to ``/sync``, given that most clients + /// cache membership events (see ``include_redundant_members`` + /// to change this behaviour). + bool lazyLoadMembers; + /// If ``true``, the ``state`` section of the ``/sync`` response will + /// always contain the ``m.room.member`` events required to display + /// the ``sender`` of the timeline events in that response, assuming + /// ``lazy_load_members`` is enabled. This means that redundant + /// duplicate member events may be returned across multiple calls to + /// ``/sync``. This is useful for naive clients who never track + /// membership data. If ``false``, duplicate ``m.room.member`` events + /// may be suppressed by the server across multiple calls to ``/sync``. + /// If ``lazy_load_members`` is ``false`` this field is ignored. + bool includeRedundantMembers; + }; + template <> struct JsonObjectConverter + { + static void dumpTo(QJsonObject& jo, const StateFilter& pod); + static void fillFrom(const QJsonObject& jo, StateFilter& pod); + }; + /// Filters to be applied to room data. struct RoomFilter { @@ -26,18 +57,16 @@ namespace QMatrixClient /// Include rooms that the user has left in the sync, default false bool includeLeave; /// The state events to include for rooms. - Omittable state; + Omittable state; /// The message and state update events to include for rooms. Omittable timeline; /// The per user account data to include for rooms. Omittable accountData; }; - - QJsonObject toJson(const RoomFilter& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - RoomFilter operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const RoomFilter& pod); + static void fillFrom(const QJsonObject& jo, RoomFilter& pod); }; struct Filter @@ -53,12 +82,10 @@ namespace QMatrixClient /// Filters to be applied to room data. Omittable room; }; - - QJsonObject toJson(const Filter& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - Filter operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const Filter& pod); + static void fillFrom(const QJsonObject& jo, Filter& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/user_identifier.cpp b/lib/csapi/definitions/user_identifier.cpp index 80a6d450..05a27c1c 100644 --- a/lib/csapi/definitions/user_identifier.cpp +++ b/lib/csapi/definitions/user_identifier.cpp @@ -6,20 +6,18 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const UserIdentifier& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const UserIdentifier& pod) { - QJsonObject jo = toJson(pod.additionalProperties); + fillJson(jo, pod.additionalProperties); addParam<>(jo, QStringLiteral("type"), pod.type); - return jo; } -UserIdentifier FromJsonObject::operator()(QJsonObject jo) const +void JsonObjectConverter::fillFrom( + QJsonObject jo, UserIdentifier& result) { - UserIdentifier result; - result.type = - fromJson(jo.take("type"_ls)); + fromJson(jo.take("type"_ls), result.type); - result.additionalProperties = fromJson(jo); - return result; + fromJson(jo, result.additionalProperties); } diff --git a/lib/csapi/definitions/user_identifier.h b/lib/csapi/definitions/user_identifier.h index 42614436..cbb1550f 100644 --- a/lib/csapi/definitions/user_identifier.h +++ b/lib/csapi/definitions/user_identifier.h @@ -20,12 +20,10 @@ namespace QMatrixClient /// Identification information for a user QVariantHash additionalProperties; }; - - QJsonObject toJson(const UserIdentifier& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - UserIdentifier operator()(QJsonObject jo) const; + static void dumpTo(QJsonObject& jo, const UserIdentifier& pod); + static void fillFrom(QJsonObject jo, UserIdentifier& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/wellknown/homeserver.cpp b/lib/csapi/definitions/wellknown/homeserver.cpp index f1482ee4..0783f11b 100644 --- a/lib/csapi/definitions/wellknown/homeserver.cpp +++ b/lib/csapi/definitions/wellknown/homeserver.cpp @@ -6,19 +6,15 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const HomeserverInformation& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const HomeserverInformation& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("base_url"), pod.baseUrl); - return jo; } -HomeserverInformation FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, HomeserverInformation& result) { - HomeserverInformation result; - result.baseUrl = - fromJson(jo.value("base_url"_ls)); - - return result; + fromJson(jo.value("base_url"_ls), result.baseUrl); } diff --git a/lib/csapi/definitions/wellknown/homeserver.h b/lib/csapi/definitions/wellknown/homeserver.h index 09d6ba63..f6761c30 100644 --- a/lib/csapi/definitions/wellknown/homeserver.h +++ b/lib/csapi/definitions/wellknown/homeserver.h @@ -17,12 +17,10 @@ namespace QMatrixClient /// The base URL for the homeserver for client-server connections. QString baseUrl; }; - - QJsonObject toJson(const HomeserverInformation& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - HomeserverInformation operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const HomeserverInformation& pod); + static void fillFrom(const QJsonObject& jo, HomeserverInformation& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/wellknown/identity_server.cpp b/lib/csapi/definitions/wellknown/identity_server.cpp index f9d7bc37..99f36641 100644 --- a/lib/csapi/definitions/wellknown/identity_server.cpp +++ b/lib/csapi/definitions/wellknown/identity_server.cpp @@ -6,19 +6,15 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const IdentityServerInformation& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const IdentityServerInformation& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("base_url"), pod.baseUrl); - return jo; } -IdentityServerInformation FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, IdentityServerInformation& result) { - IdentityServerInformation result; - result.baseUrl = - fromJson(jo.value("base_url"_ls)); - - return result; + fromJson(jo.value("base_url"_ls), result.baseUrl); } diff --git a/lib/csapi/definitions/wellknown/identity_server.h b/lib/csapi/definitions/wellknown/identity_server.h index cb8ffcee..67d8b08d 100644 --- a/lib/csapi/definitions/wellknown/identity_server.h +++ b/lib/csapi/definitions/wellknown/identity_server.h @@ -17,12 +17,10 @@ namespace QMatrixClient /// The base URL for the identity server for client-server connections. QString baseUrl; }; - - QJsonObject toJson(const IdentityServerInformation& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - IdentityServerInformation operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const IdentityServerInformation& pod); + static void fillFrom(const QJsonObject& jo, IdentityServerInformation& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/device_management.cpp b/lib/csapi/device_management.cpp index 861e1994..9c31db5d 100644 --- a/lib/csapi/device_management.cpp +++ b/lib/csapi/device_management.cpp @@ -43,7 +43,7 @@ const QVector& GetDevicesJob::devices() const BaseJob::Status GetDevicesJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->devices = fromJson>(json.value("devices"_ls)); + fromJson(json.value("devices"_ls), d->devices); return Success; } @@ -77,7 +77,7 @@ const Device& GetDeviceJob::data() const BaseJob::Status GetDeviceJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/directory.cpp b/lib/csapi/directory.cpp index 5353f3bc..4af86f7b 100644 --- a/lib/csapi/directory.cpp +++ b/lib/csapi/directory.cpp @@ -60,8 +60,8 @@ const QStringList& GetRoomIdByAliasJob::servers() const BaseJob::Status GetRoomIdByAliasJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->roomId = fromJson(json.value("room_id"_ls)); - d->servers = fromJson(json.value("servers"_ls)); + fromJson(json.value("room_id"_ls), d->roomId); + fromJson(json.value("servers"_ls), d->servers); return Success; } diff --git a/lib/csapi/event_context.cpp b/lib/csapi/event_context.cpp index 806c1613..bb1f5301 100644 --- a/lib/csapi/event_context.cpp +++ b/lib/csapi/event_context.cpp @@ -82,12 +82,12 @@ StateEvents&& GetEventContextJob::state() BaseJob::Status GetEventContextJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->begin = fromJson(json.value("start"_ls)); - d->end = fromJson(json.value("end"_ls)); - d->eventsBefore = fromJson(json.value("events_before"_ls)); - d->event = fromJson(json.value("event"_ls)); - d->eventsAfter = fromJson(json.value("events_after"_ls)); - d->state = fromJson(json.value("state"_ls)); + fromJson(json.value("start"_ls), d->begin); + fromJson(json.value("end"_ls), d->end); + fromJson(json.value("events_before"_ls), d->eventsBefore); + fromJson(json.value("event"_ls), d->event); + fromJson(json.value("events_after"_ls), d->eventsAfter); + fromJson(json.value("state"_ls), d->state); return Success; } diff --git a/lib/csapi/filter.cpp b/lib/csapi/filter.cpp index 77dc9b92..982e60b5 100644 --- a/lib/csapi/filter.cpp +++ b/lib/csapi/filter.cpp @@ -41,7 +41,7 @@ BaseJob::Status DefineFilterJob::parseJson(const QJsonDocument& data) if (!json.contains("filter_id"_ls)) return { JsonParseError, "The key 'filter_id' not found in the response" }; - d->filterId = fromJson(json.value("filter_id"_ls)); + fromJson(json.value("filter_id"_ls), d->filterId); return Success; } @@ -75,7 +75,7 @@ const Filter& GetFilterJob::data() const BaseJob::Status GetFilterJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/joining.cpp b/lib/csapi/joining.cpp index 71781154..00d930fa 100644 --- a/lib/csapi/joining.cpp +++ b/lib/csapi/joining.cpp @@ -16,15 +16,16 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const JoinRoomByIdJob::ThirdPartySigned& pod) + template <> struct JsonObjectConverter { - QJsonObject jo; - addParam<>(jo, QStringLiteral("sender"), pod.sender); - addParam<>(jo, QStringLiteral("mxid"), pod.mxid); - addParam<>(jo, QStringLiteral("token"), pod.token); - addParam<>(jo, QStringLiteral("signatures"), pod.signatures); - return jo; - } + static void dumpTo(QJsonObject& jo, const JoinRoomByIdJob::ThirdPartySigned& pod) + { + addParam<>(jo, QStringLiteral("sender"), pod.sender); + addParam<>(jo, QStringLiteral("mxid"), pod.mxid); + addParam<>(jo, QStringLiteral("token"), pod.token); + addParam<>(jo, QStringLiteral("signatures"), pod.signatures); + } + }; } // namespace QMatrixClient class JoinRoomByIdJob::Private @@ -58,7 +59,7 @@ BaseJob::Status JoinRoomByIdJob::parseJson(const QJsonDocument& data) if (!json.contains("room_id"_ls)) return { JsonParseError, "The key 'room_id' not found in the response" }; - d->roomId = fromJson(json.value("room_id"_ls)); + fromJson(json.value("room_id"_ls), d->roomId); return Success; } @@ -66,22 +67,24 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const JoinRoomJob::Signed& pod) + template <> struct JsonObjectConverter { - QJsonObject jo; - addParam<>(jo, QStringLiteral("sender"), pod.sender); - addParam<>(jo, QStringLiteral("mxid"), pod.mxid); - addParam<>(jo, QStringLiteral("token"), pod.token); - addParam<>(jo, QStringLiteral("signatures"), pod.signatures); - return jo; - } - - QJsonObject toJson(const JoinRoomJob::ThirdPartySigned& pod) + static void dumpTo(QJsonObject& jo, const JoinRoomJob::Signed& pod) + { + addParam<>(jo, QStringLiteral("sender"), pod.sender); + addParam<>(jo, QStringLiteral("mxid"), pod.mxid); + addParam<>(jo, QStringLiteral("token"), pod.token); + addParam<>(jo, QStringLiteral("signatures"), pod.signatures); + } + }; + + template <> struct JsonObjectConverter { - QJsonObject jo; - addParam<>(jo, QStringLiteral("signed"), pod.signedData); - return jo; - } + static void dumpTo(QJsonObject& jo, const JoinRoomJob::ThirdPartySigned& pod) + { + addParam<>(jo, QStringLiteral("signed"), pod.signedData); + } + }; } // namespace QMatrixClient class JoinRoomJob::Private @@ -123,7 +126,7 @@ BaseJob::Status JoinRoomJob::parseJson(const QJsonDocument& data) if (!json.contains("room_id"_ls)) return { JsonParseError, "The key 'room_id' not found in the response" }; - d->roomId = fromJson(json.value("room_id"_ls)); + fromJson(json.value("room_id"_ls), d->roomId); return Success; } diff --git a/lib/csapi/keys.cpp b/lib/csapi/keys.cpp index c7492411..6c16a8a3 100644 --- a/lib/csapi/keys.cpp +++ b/lib/csapi/keys.cpp @@ -44,7 +44,7 @@ BaseJob::Status UploadKeysJob::parseJson(const QJsonDocument& data) if (!json.contains("one_time_key_counts"_ls)) return { JsonParseError, "The key 'one_time_key_counts' not found in the response" }; - d->oneTimeKeyCounts = fromJson>(json.value("one_time_key_counts"_ls)); + fromJson(json.value("one_time_key_counts"_ls), d->oneTimeKeyCounts); return Success; } @@ -52,27 +52,20 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - QueryKeysJob::UnsignedDeviceInfo operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, QueryKeysJob::UnsignedDeviceInfo& result) { - QueryKeysJob::UnsignedDeviceInfo result; - result.deviceDisplayName = - fromJson(jo.value("device_display_name"_ls)); - - return result; + fromJson(jo.value("device_display_name"_ls), result.deviceDisplayName); } }; - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - QueryKeysJob::DeviceInformation operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, QueryKeysJob::DeviceInformation& result) { - QueryKeysJob::DeviceInformation result; - result.unsignedData = - fromJson(jo.value("unsigned"_ls)); - - return result; + fillFromJson(jo, result); + fromJson(jo.value("unsigned"_ls), result.unsignedData); } }; } // namespace QMatrixClient @@ -113,8 +106,8 @@ const QHash>& QueryKeys BaseJob::Status QueryKeysJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->failures = fromJson>(json.value("failures"_ls)); - d->deviceKeys = fromJson>>(json.value("device_keys"_ls)); + fromJson(json.value("failures"_ls), d->failures); + fromJson(json.value("device_keys"_ls), d->deviceKeys); return Success; } @@ -153,8 +146,8 @@ const QHash>& ClaimKeysJob::oneTimeKeys() cons BaseJob::Status ClaimKeysJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->failures = fromJson>(json.value("failures"_ls)); - d->oneTimeKeys = fromJson>>(json.value("one_time_keys"_ls)); + fromJson(json.value("failures"_ls), d->failures); + fromJson(json.value("one_time_keys"_ls), d->oneTimeKeys); return Success; } @@ -205,8 +198,8 @@ const QStringList& GetKeysChangesJob::left() const BaseJob::Status GetKeysChangesJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->changed = fromJson(json.value("changed"_ls)); - d->left = fromJson(json.value("left"_ls)); + fromJson(json.value("changed"_ls), d->changed); + fromJson(json.value("left"_ls), d->left); return Success; } diff --git a/lib/csapi/list_joined_rooms.cpp b/lib/csapi/list_joined_rooms.cpp index a745dba1..85a9cae4 100644 --- a/lib/csapi/list_joined_rooms.cpp +++ b/lib/csapi/list_joined_rooms.cpp @@ -46,7 +46,7 @@ BaseJob::Status GetJoinedRoomsJob::parseJson(const QJsonDocument& data) if (!json.contains("joined_rooms"_ls)) return { JsonParseError, "The key 'joined_rooms' not found in the response" }; - d->joinedRooms = fromJson(json.value("joined_rooms"_ls)); + fromJson(json.value("joined_rooms"_ls), d->joinedRooms); return Success; } diff --git a/lib/csapi/list_public_rooms.cpp b/lib/csapi/list_public_rooms.cpp index 2fdb2005..2a0cb0ff 100644 --- a/lib/csapi/list_public_rooms.cpp +++ b/lib/csapi/list_public_rooms.cpp @@ -43,7 +43,7 @@ const QString& GetRoomVisibilityOnDirectoryJob::visibility() const BaseJob::Status GetRoomVisibilityOnDirectoryJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->visibility = fromJson(json.value("visibility"_ls)); + fromJson(json.value("visibility"_ls), d->visibility); return Success; } @@ -100,7 +100,7 @@ const PublicRoomsResponse& GetPublicRoomsJob::data() const BaseJob::Status GetPublicRoomsJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } @@ -108,12 +108,13 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const QueryPublicRoomsJob::Filter& pod) + template <> struct JsonObjectConverter { - QJsonObject jo; - addParam(jo, QStringLiteral("generic_search_term"), pod.genericSearchTerm); - return jo; - } + static void dumpTo(QJsonObject& jo, const QueryPublicRoomsJob::Filter& pod) + { + addParam(jo, QStringLiteral("generic_search_term"), pod.genericSearchTerm); + } + }; } // namespace QMatrixClient class QueryPublicRoomsJob::Private @@ -155,7 +156,7 @@ const PublicRoomsResponse& QueryPublicRoomsJob::data() const BaseJob::Status QueryPublicRoomsJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/login.cpp b/lib/csapi/login.cpp index 4d15a30b..ee33dac2 100644 --- a/lib/csapi/login.cpp +++ b/lib/csapi/login.cpp @@ -16,15 +16,11 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - GetLoginFlowsJob::LoginFlow operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetLoginFlowsJob::LoginFlow& result) { - GetLoginFlowsJob::LoginFlow result; - result.type = - fromJson(jo.value("type"_ls)); - - return result; + fromJson(jo.value("type"_ls), result.type); } }; } // namespace QMatrixClient @@ -60,7 +56,7 @@ const QVector& GetLoginFlowsJob::flows() const BaseJob::Status GetLoginFlowsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->flows = fromJson>(json.value("flows"_ls)); + fromJson(json.value("flows"_ls), d->flows); return Success; } @@ -118,10 +114,10 @@ const QString& LoginJob::deviceId() const BaseJob::Status LoginJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->userId = fromJson(json.value("user_id"_ls)); - d->accessToken = fromJson(json.value("access_token"_ls)); - d->homeServer = fromJson(json.value("home_server"_ls)); - d->deviceId = fromJson(json.value("device_id"_ls)); + fromJson(json.value("user_id"_ls), d->userId); + fromJson(json.value("access_token"_ls), d->accessToken); + fromJson(json.value("home_server"_ls), d->homeServer); + fromJson(json.value("device_id"_ls), d->deviceId); return Success; } diff --git a/lib/csapi/message_pagination.cpp b/lib/csapi/message_pagination.cpp index c59a51ab..9aca7ec9 100644 --- a/lib/csapi/message_pagination.cpp +++ b/lib/csapi/message_pagination.cpp @@ -68,9 +68,9 @@ RoomEvents&& GetRoomEventsJob::chunk() BaseJob::Status GetRoomEventsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->begin = fromJson(json.value("start"_ls)); - d->end = fromJson(json.value("end"_ls)); - d->chunk = fromJson(json.value("chunk"_ls)); + fromJson(json.value("start"_ls), d->begin); + fromJson(json.value("end"_ls), d->end); + fromJson(json.value("chunk"_ls), d->chunk); return Success; } diff --git a/lib/csapi/notifications.cpp b/lib/csapi/notifications.cpp index 785a0a8a..c00b7cb0 100644 --- a/lib/csapi/notifications.cpp +++ b/lib/csapi/notifications.cpp @@ -16,25 +16,16 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - GetNotificationsJob::Notification operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetNotificationsJob::Notification& result) { - GetNotificationsJob::Notification result; - result.actions = - fromJson>(jo.value("actions"_ls)); - result.event = - fromJson(jo.value("event"_ls)); - result.profileTag = - fromJson(jo.value("profile_tag"_ls)); - result.read = - fromJson(jo.value("read"_ls)); - result.roomId = - fromJson(jo.value("room_id"_ls)); - result.ts = - fromJson(jo.value("ts"_ls)); - - return result; + fromJson(jo.value("actions"_ls), result.actions); + fromJson(jo.value("event"_ls), result.event); + fromJson(jo.value("profile_tag"_ls), result.profileTag); + fromJson(jo.value("read"_ls), result.read); + fromJson(jo.value("room_id"_ls), result.roomId); + fromJson(jo.value("ts"_ls), result.ts); } }; } // namespace QMatrixClient @@ -87,11 +78,11 @@ std::vector&& GetNotificationsJob::notificati BaseJob::Status GetNotificationsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->nextToken = fromJson(json.value("next_token"_ls)); + fromJson(json.value("next_token"_ls), d->nextToken); if (!json.contains("notifications"_ls)) return { JsonParseError, "The key 'notifications' not found in the response" }; - d->notifications = fromJson>(json.value("notifications"_ls)); + fromJson(json.value("notifications"_ls), d->notifications); return Success; } diff --git a/lib/csapi/openid.cpp b/lib/csapi/openid.cpp index 2547f0c8..b27fe0b8 100644 --- a/lib/csapi/openid.cpp +++ b/lib/csapi/openid.cpp @@ -59,19 +59,19 @@ BaseJob::Status RequestOpenIdTokenJob::parseJson(const QJsonDocument& data) if (!json.contains("access_token"_ls)) return { JsonParseError, "The key 'access_token' not found in the response" }; - d->accessToken = fromJson(json.value("access_token"_ls)); + fromJson(json.value("access_token"_ls), d->accessToken); if (!json.contains("token_type"_ls)) return { JsonParseError, "The key 'token_type' not found in the response" }; - d->tokenType = fromJson(json.value("token_type"_ls)); + fromJson(json.value("token_type"_ls), d->tokenType); if (!json.contains("matrix_server_name"_ls)) return { JsonParseError, "The key 'matrix_server_name' not found in the response" }; - d->matrixServerName = fromJson(json.value("matrix_server_name"_ls)); + fromJson(json.value("matrix_server_name"_ls), d->matrixServerName); if (!json.contains("expires_in"_ls)) return { JsonParseError, "The key 'expires_in' not found in the response" }; - d->expiresIn = fromJson(json.value("expires_in"_ls)); + fromJson(json.value("expires_in"_ls), d->expiresIn); return Success; } diff --git a/lib/csapi/peeking_events.cpp b/lib/csapi/peeking_events.cpp index e046a62e..3208d48d 100644 --- a/lib/csapi/peeking_events.cpp +++ b/lib/csapi/peeking_events.cpp @@ -66,9 +66,9 @@ RoomEvents&& PeekEventsJob::chunk() BaseJob::Status PeekEventsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->begin = fromJson(json.value("start"_ls)); - d->end = fromJson(json.value("end"_ls)); - d->chunk = fromJson(json.value("chunk"_ls)); + fromJson(json.value("start"_ls), d->begin); + fromJson(json.value("end"_ls), d->end); + fromJson(json.value("chunk"_ls), d->chunk); return Success; } diff --git a/lib/csapi/presence.cpp b/lib/csapi/presence.cpp index 7aba8b61..94a3e6c5 100644 --- a/lib/csapi/presence.cpp +++ b/lib/csapi/presence.cpp @@ -76,10 +76,10 @@ BaseJob::Status GetPresenceJob::parseJson(const QJsonDocument& data) if (!json.contains("presence"_ls)) return { JsonParseError, "The key 'presence' not found in the response" }; - d->presence = fromJson(json.value("presence"_ls)); - d->lastActiveAgo = fromJson(json.value("last_active_ago"_ls)); - d->statusMsg = fromJson(json.value("status_msg"_ls)); - d->currentlyActive = fromJson(json.value("currently_active"_ls)); + fromJson(json.value("presence"_ls), d->presence); + fromJson(json.value("last_active_ago"_ls), d->lastActiveAgo); + fromJson(json.value("status_msg"_ls), d->statusMsg); + fromJson(json.value("currently_active"_ls), d->currentlyActive); return Success; } @@ -125,7 +125,7 @@ Events&& GetPresenceForListJob::data() BaseJob::Status GetPresenceForListJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/profile.cpp b/lib/csapi/profile.cpp index bb053062..4ed3ad9b 100644 --- a/lib/csapi/profile.cpp +++ b/lib/csapi/profile.cpp @@ -54,7 +54,7 @@ const QString& GetDisplayNameJob::displayname() const BaseJob::Status GetDisplayNameJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->displayname = fromJson(json.value("displayname"_ls)); + fromJson(json.value("displayname"_ls), d->displayname); return Success; } @@ -100,7 +100,7 @@ const QString& GetAvatarUrlJob::avatarUrl() const BaseJob::Status GetAvatarUrlJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->avatarUrl = fromJson(json.value("avatar_url"_ls)); + fromJson(json.value("avatar_url"_ls), d->avatarUrl); return Success; } @@ -141,8 +141,8 @@ const QString& GetUserProfileJob::displayname() const BaseJob::Status GetUserProfileJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->avatarUrl = fromJson(json.value("avatar_url"_ls)); - d->displayname = fromJson(json.value("displayname"_ls)); + fromJson(json.value("avatar_url"_ls), d->avatarUrl); + fromJson(json.value("displayname"_ls), d->displayname); return Success; } diff --git a/lib/csapi/pusher.cpp b/lib/csapi/pusher.cpp index d20db88a..3ad0dcbe 100644 --- a/lib/csapi/pusher.cpp +++ b/lib/csapi/pusher.cpp @@ -16,43 +16,27 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - GetPushersJob::PusherData operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetPushersJob::PusherData& result) { - GetPushersJob::PusherData result; - result.url = - fromJson(jo.value("url"_ls)); - result.format = - fromJson(jo.value("format"_ls)); - - return result; + fromJson(jo.value("url"_ls), result.url); + fromJson(jo.value("format"_ls), result.format); } }; - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - GetPushersJob::Pusher operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetPushersJob::Pusher& result) { - GetPushersJob::Pusher result; - result.pushkey = - fromJson(jo.value("pushkey"_ls)); - result.kind = - fromJson(jo.value("kind"_ls)); - result.appId = - fromJson(jo.value("app_id"_ls)); - result.appDisplayName = - fromJson(jo.value("app_display_name"_ls)); - result.deviceDisplayName = - fromJson(jo.value("device_display_name"_ls)); - result.profileTag = - fromJson(jo.value("profile_tag"_ls)); - result.lang = - fromJson(jo.value("lang"_ls)); - result.data = - fromJson(jo.value("data"_ls)); - - return result; + fromJson(jo.value("pushkey"_ls), result.pushkey); + fromJson(jo.value("kind"_ls), result.kind); + fromJson(jo.value("app_id"_ls), result.appId); + fromJson(jo.value("app_display_name"_ls), result.appDisplayName); + fromJson(jo.value("device_display_name"_ls), result.deviceDisplayName); + fromJson(jo.value("profile_tag"_ls), result.profileTag); + fromJson(jo.value("lang"_ls), result.lang); + fromJson(jo.value("data"_ls), result.data); } }; } // namespace QMatrixClient @@ -88,7 +72,7 @@ const QVector& GetPushersJob::pushers() const BaseJob::Status GetPushersJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->pushers = fromJson>(json.value("pushers"_ls)); + fromJson(json.value("pushers"_ls), d->pushers); return Success; } @@ -96,13 +80,14 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const PostPusherJob::PusherData& pod) + template <> struct JsonObjectConverter { - QJsonObject jo; - addParam(jo, QStringLiteral("url"), pod.url); - addParam(jo, QStringLiteral("format"), pod.format); - return jo; - } + static void dumpTo(QJsonObject& jo, const PostPusherJob::PusherData& pod) + { + addParam(jo, QStringLiteral("url"), pod.url); + addParam(jo, QStringLiteral("format"), pod.format); + } + }; } // namespace QMatrixClient static const auto PostPusherJobName = QStringLiteral("PostPusherJob"); diff --git a/lib/csapi/pushrules.cpp b/lib/csapi/pushrules.cpp index ea8ad02a..b91d18f7 100644 --- a/lib/csapi/pushrules.cpp +++ b/lib/csapi/pushrules.cpp @@ -46,7 +46,7 @@ BaseJob::Status GetPushRulesJob::parseJson(const QJsonDocument& data) if (!json.contains("global"_ls)) return { JsonParseError, "The key 'global' not found in the response" }; - d->global = fromJson(json.value("global"_ls)); + fromJson(json.value("global"_ls), d->global); return Success; } @@ -80,7 +80,7 @@ const PushRule& GetPushRuleJob::data() const BaseJob::Status GetPushRuleJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } @@ -154,7 +154,7 @@ BaseJob::Status IsPushRuleEnabledJob::parseJson(const QJsonDocument& data) if (!json.contains("enabled"_ls)) return { JsonParseError, "The key 'enabled' not found in the response" }; - d->enabled = fromJson(json.value("enabled"_ls)); + fromJson(json.value("enabled"_ls), d->enabled); return Success; } @@ -203,7 +203,7 @@ BaseJob::Status GetPushRuleActionsJob::parseJson(const QJsonDocument& data) if (!json.contains("actions"_ls)) return { JsonParseError, "The key 'actions' not found in the response" }; - d->actions = fromJson(json.value("actions"_ls)); + fromJson(json.value("actions"_ls), d->actions); return Success; } diff --git a/lib/csapi/redaction.cpp b/lib/csapi/redaction.cpp index 64098670..1d54e36d 100644 --- a/lib/csapi/redaction.cpp +++ b/lib/csapi/redaction.cpp @@ -40,7 +40,7 @@ const QString& RedactEventJob::eventId() const BaseJob::Status RedactEventJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->eventId = fromJson(json.value("event_id"_ls)); + fromJson(json.value("event_id"_ls), d->eventId); return Success; } diff --git a/lib/csapi/registration.cpp b/lib/csapi/registration.cpp index 320ec796..2772cd57 100644 --- a/lib/csapi/registration.cpp +++ b/lib/csapi/registration.cpp @@ -76,10 +76,10 @@ BaseJob::Status RegisterJob::parseJson(const QJsonDocument& data) if (!json.contains("user_id"_ls)) return { JsonParseError, "The key 'user_id' not found in the response" }; - d->userId = fromJson(json.value("user_id"_ls)); - d->accessToken = fromJson(json.value("access_token"_ls)); - d->homeServer = fromJson(json.value("home_server"_ls)); - d->deviceId = fromJson(json.value("device_id"_ls)); + fromJson(json.value("user_id"_ls), d->userId); + fromJson(json.value("access_token"_ls), d->accessToken); + fromJson(json.value("home_server"_ls), d->homeServer); + fromJson(json.value("device_id"_ls), d->deviceId); return Success; } @@ -114,7 +114,7 @@ const Sid& RequestTokenToRegisterEmailJob::data() const BaseJob::Status RequestTokenToRegisterEmailJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } @@ -150,7 +150,7 @@ const Sid& RequestTokenToRegisterMSISDNJob::data() const BaseJob::Status RequestTokenToRegisterMSISDNJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } @@ -197,7 +197,7 @@ const Sid& RequestTokenToResetPasswordEmailJob::data() const BaseJob::Status RequestTokenToResetPasswordEmailJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } @@ -233,7 +233,7 @@ const Sid& RequestTokenToResetPasswordMSISDNJob::data() const BaseJob::Status RequestTokenToResetPasswordMSISDNJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } @@ -289,7 +289,7 @@ bool CheckUsernameAvailabilityJob::available() const BaseJob::Status CheckUsernameAvailabilityJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->available = fromJson(json.value("available"_ls)); + fromJson(json.value("available"_ls), d->available); return Success; } diff --git a/lib/csapi/room_send.cpp b/lib/csapi/room_send.cpp index 2b39ede2..0d25eb69 100644 --- a/lib/csapi/room_send.cpp +++ b/lib/csapi/room_send.cpp @@ -38,7 +38,7 @@ const QString& SendMessageJob::eventId() const BaseJob::Status SendMessageJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->eventId = fromJson(json.value("event_id"_ls)); + fromJson(json.value("event_id"_ls), d->eventId); return Success; } diff --git a/lib/csapi/room_state.cpp b/lib/csapi/room_state.cpp index 8f87979d..3aa7d736 100644 --- a/lib/csapi/room_state.cpp +++ b/lib/csapi/room_state.cpp @@ -38,7 +38,7 @@ const QString& SetRoomStateWithKeyJob::eventId() const BaseJob::Status SetRoomStateWithKeyJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->eventId = fromJson(json.value("event_id"_ls)); + fromJson(json.value("event_id"_ls), d->eventId); return Success; } @@ -68,7 +68,7 @@ const QString& SetRoomStateJob::eventId() const BaseJob::Status SetRoomStateJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->eventId = fromJson(json.value("event_id"_ls)); + fromJson(json.value("event_id"_ls), d->eventId); return Success; } diff --git a/lib/csapi/rooms.cpp b/lib/csapi/rooms.cpp index cebb295a..0b08ccec 100644 --- a/lib/csapi/rooms.cpp +++ b/lib/csapi/rooms.cpp @@ -42,7 +42,7 @@ EventPtr&& GetOneRoomEventJob::data() BaseJob::Status GetOneRoomEventJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } @@ -104,7 +104,7 @@ StateEvents&& GetRoomStateJob::data() BaseJob::Status GetRoomStateJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } @@ -114,17 +114,28 @@ class GetMembersByRoomJob::Private EventsArray chunk; }; -QUrl GetMembersByRoomJob::makeRequestUrl(QUrl baseUrl, const QString& roomId) +BaseJob::Query queryToGetMembersByRoom(const QString& at, const QString& membership, const QString& notMembership) +{ + BaseJob::Query _q; + addParam(_q, QStringLiteral("at"), at); + addParam(_q, QStringLiteral("membership"), membership); + addParam(_q, QStringLiteral("not_membership"), notMembership); + return _q; +} + +QUrl GetMembersByRoomJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& at, const QString& membership, const QString& notMembership) { return BaseJob::makeRequestUrl(std::move(baseUrl), - basePath % "/rooms/" % roomId % "/members"); + basePath % "/rooms/" % roomId % "/members", + queryToGetMembersByRoom(at, membership, notMembership)); } static const auto GetMembersByRoomJobName = QStringLiteral("GetMembersByRoomJob"); -GetMembersByRoomJob::GetMembersByRoomJob(const QString& roomId) +GetMembersByRoomJob::GetMembersByRoomJob(const QString& roomId, const QString& at, const QString& membership, const QString& notMembership) : BaseJob(HttpVerb::Get, GetMembersByRoomJobName, - basePath % "/rooms/" % roomId % "/members") + basePath % "/rooms/" % roomId % "/members", + queryToGetMembersByRoom(at, membership, notMembership)) , d(new Private) { } @@ -139,7 +150,7 @@ EventsArray&& GetMembersByRoomJob::chunk() BaseJob::Status GetMembersByRoomJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->chunk = fromJson>(json.value("chunk"_ls)); + fromJson(json.value("chunk"_ls), d->chunk); return Success; } @@ -147,17 +158,12 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - GetJoinedMembersByRoomJob::RoomMember operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetJoinedMembersByRoomJob::RoomMember& result) { - GetJoinedMembersByRoomJob::RoomMember result; - result.displayName = - fromJson(jo.value("display_name"_ls)); - result.avatarUrl = - fromJson(jo.value("avatar_url"_ls)); - - return result; + fromJson(jo.value("display_name"_ls), result.displayName); + fromJson(jo.value("avatar_url"_ls), result.avatarUrl); } }; } // namespace QMatrixClient @@ -193,7 +199,7 @@ const QHash& GetJoinedMembersByR BaseJob::Status GetJoinedMembersByRoomJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->joined = fromJson>(json.value("joined"_ls)); + fromJson(json.value("joined"_ls), d->joined); return Success; } diff --git a/lib/csapi/rooms.h b/lib/csapi/rooms.h index 80895b4e..415aa4ed 100644 --- a/lib/csapi/rooms.h +++ b/lib/csapi/rooms.h @@ -158,8 +158,17 @@ namespace QMatrixClient /*! Get the m.room.member events for the room. * \param roomId * The room to get the member events for. + * \param at + * The token defining the timeline position as-of which to return + * the list of members. This token can be obtained from + * a ``prev_batch`` token returned for each room by the sync API, or + * from a ``start`` or ``end`` token returned by a /messages request. + * \param membership + * Only return users with the specified membership + * \param notMembership + * Only return users with membership state other than specified */ - explicit GetMembersByRoomJob(const QString& roomId); + explicit GetMembersByRoomJob(const QString& roomId, const QString& at = {}, const QString& membership = {}, const QString& notMembership = {}); /*! Construct a URL without creating a full-fledged job object * @@ -167,7 +176,7 @@ namespace QMatrixClient * GetMembersByRoomJob is necessary but the job * itself isn't. */ - static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId); + static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& at = {}, const QString& membership = {}, const QString& notMembership = {}); ~GetMembersByRoomJob() override; diff --git a/lib/csapi/search.cpp b/lib/csapi/search.cpp index 9436eb47..a5f83c79 100644 --- a/lib/csapi/search.cpp +++ b/lib/csapi/search.cpp @@ -16,146 +16,113 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const SearchJob::IncludeEventContext& pod) + template <> struct JsonObjectConverter { - QJsonObject jo; - addParam(jo, QStringLiteral("before_limit"), pod.beforeLimit); - addParam(jo, QStringLiteral("after_limit"), pod.afterLimit); - addParam(jo, QStringLiteral("include_profile"), pod.includeProfile); - return jo; - } - - QJsonObject toJson(const SearchJob::Group& pod) - { - QJsonObject jo; - addParam(jo, QStringLiteral("key"), pod.key); - return jo; - } + static void dumpTo(QJsonObject& jo, const SearchJob::IncludeEventContext& pod) + { + addParam(jo, QStringLiteral("before_limit"), pod.beforeLimit); + addParam(jo, QStringLiteral("after_limit"), pod.afterLimit); + addParam(jo, QStringLiteral("include_profile"), pod.includeProfile); + } + }; - QJsonObject toJson(const SearchJob::Groupings& pod) + template <> struct JsonObjectConverter { - QJsonObject jo; - addParam(jo, QStringLiteral("group_by"), pod.groupBy); - return jo; - } + static void dumpTo(QJsonObject& jo, const SearchJob::Group& pod) + { + addParam(jo, QStringLiteral("key"), pod.key); + } + }; - QJsonObject toJson(const SearchJob::RoomEventsCriteria& pod) - { - QJsonObject jo; - addParam<>(jo, QStringLiteral("search_term"), pod.searchTerm); - addParam(jo, QStringLiteral("keys"), pod.keys); - addParam(jo, QStringLiteral("filter"), pod.filter); - addParam(jo, QStringLiteral("order_by"), pod.orderBy); - addParam(jo, QStringLiteral("event_context"), pod.eventContext); - addParam(jo, QStringLiteral("include_state"), pod.includeState); - addParam(jo, QStringLiteral("groupings"), pod.groupings); - return jo; - } - - QJsonObject toJson(const SearchJob::Categories& pod) + template <> struct JsonObjectConverter { - QJsonObject jo; - addParam(jo, QStringLiteral("room_events"), pod.roomEvents); - return jo; - } + static void dumpTo(QJsonObject& jo, const SearchJob::Groupings& pod) + { + addParam(jo, QStringLiteral("group_by"), pod.groupBy); + } + }; - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - SearchJob::UserProfile operator()(const QJsonObject& jo) const + static void dumpTo(QJsonObject& jo, const SearchJob::RoomEventsCriteria& pod) { - SearchJob::UserProfile result; - result.displayname = - fromJson(jo.value("displayname"_ls)); - result.avatarUrl = - fromJson(jo.value("avatar_url"_ls)); + addParam<>(jo, QStringLiteral("search_term"), pod.searchTerm); + addParam(jo, QStringLiteral("keys"), pod.keys); + addParam(jo, QStringLiteral("filter"), pod.filter); + addParam(jo, QStringLiteral("order_by"), pod.orderBy); + addParam(jo, QStringLiteral("event_context"), pod.eventContext); + addParam(jo, QStringLiteral("include_state"), pod.includeState); + addParam(jo, QStringLiteral("groupings"), pod.groupings); + } + }; - return result; + template <> struct JsonObjectConverter + { + static void dumpTo(QJsonObject& jo, const SearchJob::Categories& pod) + { + addParam(jo, QStringLiteral("room_events"), pod.roomEvents); } }; - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - SearchJob::EventContext operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, SearchJob::UserProfile& result) { - SearchJob::EventContext result; - result.begin = - fromJson(jo.value("start"_ls)); - result.end = - fromJson(jo.value("end"_ls)); - result.profileInfo = - fromJson>(jo.value("profile_info"_ls)); - result.eventsBefore = - fromJson(jo.value("events_before"_ls)); - result.eventsAfter = - fromJson(jo.value("events_after"_ls)); - - return result; + fromJson(jo.value("displayname"_ls), result.displayname); + fromJson(jo.value("avatar_url"_ls), result.avatarUrl); } }; - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - SearchJob::Result operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, SearchJob::EventContext& result) { - SearchJob::Result result; - result.rank = - fromJson(jo.value("rank"_ls)); - result.result = - fromJson(jo.value("result"_ls)); - result.context = - fromJson(jo.value("context"_ls)); - - return result; + fromJson(jo.value("start"_ls), result.begin); + fromJson(jo.value("end"_ls), result.end); + fromJson(jo.value("profile_info"_ls), result.profileInfo); + fromJson(jo.value("events_before"_ls), result.eventsBefore); + fromJson(jo.value("events_after"_ls), result.eventsAfter); } }; - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - SearchJob::GroupValue operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, SearchJob::Result& result) { - SearchJob::GroupValue result; - result.nextBatch = - fromJson(jo.value("next_batch"_ls)); - result.order = - fromJson(jo.value("order"_ls)); - result.results = - fromJson(jo.value("results"_ls)); - - return result; + fromJson(jo.value("rank"_ls), result.rank); + fromJson(jo.value("result"_ls), result.result); + fromJson(jo.value("context"_ls), result.context); } }; - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - SearchJob::ResultRoomEvents operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, SearchJob::GroupValue& result) { - SearchJob::ResultRoomEvents result; - result.count = - fromJson(jo.value("count"_ls)); - result.highlights = - fromJson(jo.value("highlights"_ls)); - result.results = - fromJson>(jo.value("results"_ls)); - result.state = - fromJson>(jo.value("state"_ls)); - result.groups = - fromJson>>(jo.value("groups"_ls)); - result.nextBatch = - fromJson(jo.value("next_batch"_ls)); - - return result; + fromJson(jo.value("next_batch"_ls), result.nextBatch); + fromJson(jo.value("order"_ls), result.order); + fromJson(jo.value("results"_ls), result.results); } }; - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - SearchJob::ResultCategories operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, SearchJob::ResultRoomEvents& result) { - SearchJob::ResultCategories result; - result.roomEvents = - fromJson(jo.value("room_events"_ls)); + fromJson(jo.value("count"_ls), result.count); + fromJson(jo.value("highlights"_ls), result.highlights); + fromJson(jo.value("results"_ls), result.results); + fromJson(jo.value("state"_ls), result.state); + fromJson(jo.value("groups"_ls), result.groups); + fromJson(jo.value("next_batch"_ls), result.nextBatch); + } + }; - return result; + template <> struct JsonObjectConverter + { + static void fillFrom(const QJsonObject& jo, SearchJob::ResultCategories& result) + { + fromJson(jo.value("room_events"_ls), result.roomEvents); } }; } // namespace QMatrixClient @@ -199,7 +166,7 @@ BaseJob::Status SearchJob::parseJson(const QJsonDocument& data) if (!json.contains("search_categories"_ls)) return { JsonParseError, "The key 'search_categories' not found in the response" }; - d->searchCategories = fromJson(json.value("search_categories"_ls)); + fromJson(json.value("search_categories"_ls), d->searchCategories); return Success; } diff --git a/lib/csapi/tags.cpp b/lib/csapi/tags.cpp index 808915ac..94026bb9 100644 --- a/lib/csapi/tags.cpp +++ b/lib/csapi/tags.cpp @@ -16,16 +16,12 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - GetRoomTagsJob::Tag operator()(QJsonObject jo) const + static void fillFrom(QJsonObject jo, GetRoomTagsJob::Tag& result) { - GetRoomTagsJob::Tag result; - result.order = - fromJson(jo.take("order"_ls)); - - result.additionalProperties = fromJson(jo); - return result; + fromJson(jo.take("order"_ls), result.order); + fromJson(jo, result.additionalProperties); } }; } // namespace QMatrixClient @@ -61,7 +57,7 @@ const QHash& GetRoomTagsJob::tags() const BaseJob::Status GetRoomTagsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->tags = fromJson>(json.value("tags"_ls)); + fromJson(json.value("tags"_ls), d->tags); return Success; } diff --git a/lib/csapi/third_party_lookup.cpp b/lib/csapi/third_party_lookup.cpp index 3ba1a5ad..12cb7c59 100644 --- a/lib/csapi/third_party_lookup.cpp +++ b/lib/csapi/third_party_lookup.cpp @@ -42,7 +42,7 @@ const QHash& GetProtocolsJob::data() const BaseJob::Status GetProtocolsJob::parseJson(const QJsonDocument& data) { - d->data = fromJson>(data); + fromJson(data, d->data); return Success; } @@ -76,7 +76,7 @@ const ThirdPartyProtocol& GetProtocolMetadataJob::data() const BaseJob::Status GetProtocolMetadataJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } @@ -119,7 +119,7 @@ const QVector& QueryLocationByProtocolJob::data() const BaseJob::Status QueryLocationByProtocolJob::parseJson(const QJsonDocument& data) { - d->data = fromJson>(data); + fromJson(data, d->data); return Success; } @@ -162,7 +162,7 @@ const QVector& QueryUserByProtocolJob::data() const BaseJob::Status QueryUserByProtocolJob::parseJson(const QJsonDocument& data) { - d->data = fromJson>(data); + fromJson(data, d->data); return Success; } @@ -205,7 +205,7 @@ const QVector& QueryLocationByAliasJob::data() const BaseJob::Status QueryLocationByAliasJob::parseJson(const QJsonDocument& data) { - d->data = fromJson>(data); + fromJson(data, d->data); return Success; } @@ -248,7 +248,7 @@ const QVector& QueryUserByIDJob::data() const BaseJob::Status QueryUserByIDJob::parseJson(const QJsonDocument& data) { - d->data = fromJson>(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/users.cpp b/lib/csapi/users.cpp index deb9cb8a..97d8962d 100644 --- a/lib/csapi/users.cpp +++ b/lib/csapi/users.cpp @@ -16,19 +16,13 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - SearchUserDirectoryJob::User operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, SearchUserDirectoryJob::User& result) { - SearchUserDirectoryJob::User result; - result.userId = - fromJson(jo.value("user_id"_ls)); - result.displayName = - fromJson(jo.value("display_name"_ls)); - result.avatarUrl = - fromJson(jo.value("avatar_url"_ls)); - - return result; + fromJson(jo.value("user_id"_ls), result.userId); + fromJson(jo.value("display_name"_ls), result.displayName); + fromJson(jo.value("avatar_url"_ls), result.avatarUrl); } }; } // namespace QMatrixClient @@ -71,11 +65,11 @@ BaseJob::Status SearchUserDirectoryJob::parseJson(const QJsonDocument& data) if (!json.contains("results"_ls)) return { JsonParseError, "The key 'results' not found in the response" }; - d->results = fromJson>(json.value("results"_ls)); + fromJson(json.value("results"_ls), d->results); if (!json.contains("limited"_ls)) return { JsonParseError, "The key 'limited' not found in the response" }; - d->limited = fromJson(json.value("limited"_ls)); + fromJson(json.value("limited"_ls), d->limited); return Success; } diff --git a/lib/csapi/versions.cpp b/lib/csapi/versions.cpp index 128902e2..c853ec06 100644 --- a/lib/csapi/versions.cpp +++ b/lib/csapi/versions.cpp @@ -43,7 +43,7 @@ const QStringList& GetVersionsJob::versions() const BaseJob::Status GetVersionsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->versions = fromJson(json.value("versions"_ls)); + fromJson(json.value("versions"_ls), d->versions); return Success; } diff --git a/lib/csapi/voip.cpp b/lib/csapi/voip.cpp index 0479b645..e8158723 100644 --- a/lib/csapi/voip.cpp +++ b/lib/csapi/voip.cpp @@ -42,7 +42,7 @@ const QJsonObject& GetTurnServerJob::data() const BaseJob::Status GetTurnServerJob::parseJson(const QJsonDocument& data) { - d->data = fromJson(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/wellknown.cpp b/lib/csapi/wellknown.cpp index d42534a0..97505830 100644 --- a/lib/csapi/wellknown.cpp +++ b/lib/csapi/wellknown.cpp @@ -52,8 +52,8 @@ BaseJob::Status GetWellknownJob::parseJson(const QJsonDocument& data) if (!json.contains("m.homeserver"_ls)) return { JsonParseError, "The key 'm.homeserver' not found in the response" }; - d->homeserver = fromJson(json.value("m.homeserver"_ls)); - d->identityServer = fromJson(json.value("m.identity_server"_ls)); + fromJson(json.value("m.homeserver"_ls), d->homeserver); + fromJson(json.value("m.identity_server"_ls), d->identityServer); return Success; } diff --git a/lib/csapi/whoami.cpp b/lib/csapi/whoami.cpp index cb6439ef..aebdf5d3 100644 --- a/lib/csapi/whoami.cpp +++ b/lib/csapi/whoami.cpp @@ -46,7 +46,7 @@ BaseJob::Status GetTokenOwnerJob::parseJson(const QJsonDocument& data) if (!json.contains("user_id"_ls)) return { JsonParseError, "The key 'user_id' not found in the response" }; - d->userId = fromJson(json.value("user_id"_ls)); + fromJson(json.value("user_id"_ls), d->userId); return Success; } diff --git a/lib/csapi/{{base}}.cpp.mustache b/lib/csapi/{{base}}.cpp.mustache index 64fd8bf3..ff888d76 100644 --- a/lib/csapi/{{base}}.cpp.mustache +++ b/lib/csapi/{{base}}.cpp.mustache @@ -8,49 +8,52 @@ {{/operations}} using namespace QMatrixClient; {{#models.model}}{{#in?}} -QJsonObject QMatrixClient::toJson(const {{qualifiedName}}& pod) +void JsonObjectConverter<{{qualifiedName}}>::dumpTo( + QJsonObject& jo, const {{qualifiedName}}& pod) { - QJsonObject jo{{#propertyMap}} = toJson(pod.{{nameCamelCase}}){{/propertyMap}};{{#vars}} - addParam<{{^required?}}IfNotEmpty{{/required?}}>(jo, QStringLiteral("{{baseName}}"), pod.{{nameCamelCase}});{{/vars}} - return jo; -} +{{#propertyMap}} fillJson(jo, pod.{{nameCamelCase}}); +{{/propertyMap}}{{#parents}} fillJson<{{name}}>(jo, pod); +{{/parents}}{{#vars}} addParam<{{^required?}}IfNotEmpty{{/required?}}>(jo, QStringLiteral("{{baseName}}"), pod.{{nameCamelCase}}); +{{/vars}}}{{!<- dumpTo() ends here}} {{/in?}}{{#out?}} -{{qualifiedName}} FromJsonObject<{{qualifiedName}}>::operator()({{^propertyMap}}const QJsonObject&{{/propertyMap}}{{#propertyMap}}QJsonObject{{/propertyMap}} jo) const +void JsonObjectConverter<{{qualifiedName}}>::fillFrom( + {{^propertyMap}}const QJsonObject&{{/propertyMap + }}{{#propertyMap}}QJsonObject{{/propertyMap}} jo, {{qualifiedName}}& result) { - {{qualifiedName}} result; -{{#vars}} result.{{nameCamelCase}} = - fromJson<{{dataType.qualifiedName}}>(jo.{{#propertyMap}}take{{/propertyMap}}{{^propertyMap}}value{{/propertyMap}}("{{baseName}}"_ls)); +{{#parents}} fillFromJson<{{qualifiedName}}>(jo, result); +{{/parents}}{{#vars}} fromJson(jo.{{#propertyMap}}take{{/propertyMap + }}{{^propertyMap}}value{{/propertyMap}}("{{baseName}}"_ls), result.{{nameCamelCase}}); {{/vars}}{{#propertyMap}} - result.{{nameCamelCase}} = fromJson<{{dataType.qualifiedName}}>(jo);{{/propertyMap}} - return result; -} + fromJson(jo, result.{{nameCamelCase}}); +{{/propertyMap}}} {{/out?}}{{/models.model}}{{#operations}} static const auto basePath = QStringLiteral("{{basePathWithoutHost}}"); {{# operation}}{{#models}} namespace QMatrixClient { // Converters -{{#model}}{{#in?}} - QJsonObject toJson(const {{qualifiedName}}& pod) - { - QJsonObject jo{{#propertyMap}} = toJson(pod.{{nameCamelCase}}){{/propertyMap}};{{#vars}} - addParam<{{^required?}}IfNotEmpty{{/required?}}>(jo, QStringLiteral("{{baseName}}"), pod.{{nameCamelCase}});{{/vars}} - return jo; - } -{{/in?}}{{#out?}} - template <> struct FromJsonObject<{{qualifiedName}}> +{{#model}} + template <> struct JsonObjectConverter<{{qualifiedName}}> { - {{qualifiedName}} operator()({{^propertyMap}}const QJsonObject&{{/propertyMap}}{{#propertyMap}}QJsonObject{{/propertyMap}} jo) const +{{#in?}} static void dumpTo(QJsonObject& jo, const {{qualifiedName}}& pod) { - {{qualifiedName}} result; -{{#vars}} result.{{nameCamelCase}} = - fromJson<{{dataType.qualifiedName}}>(jo.{{#propertyMap}}take{{/propertyMap}}{{^propertyMap}}value{{/propertyMap}}("{{baseName}}"_ls)); -{{/vars}}{{#propertyMap}} - result.{{nameCamelCase}} = fromJson<{{dataType.qualifiedName}}>(jo);{{/propertyMap}} - return result; - } - }; -{{/out?}}{{/model}}} // namespace QMatrixClient +{{#propertyMap}} fillJson(jo, pod.{{nameCamelCase}}); + {{/propertyMap}}{{#parents}}fillJson<{{name}}>(jo, pod); + {{/parents}}{{#vars +}} addParam<{{^required?}}IfNotEmpty{{/required?}}>(jo, QStringLiteral("{{baseName}}"), pod.{{nameCamelCase}}); +{{/vars}} } +{{/in?}}{{#out? +}} static void fillFrom({{^propertyMap}}const QJsonObject&{{/propertyMap + }}{{#propertyMap}}QJsonObject{{/propertyMap}} jo, {{qualifiedName}}& result) + { +{{#parents}} fillFromJson<{{qualifiedName}}{{!of the parent!}}>(jo, result); + {{/parents}}{{#vars +}} fromJson(jo.{{#propertyMap}}take{{/propertyMap + }}{{^propertyMap}}value{{/propertyMap}}("{{baseName}}"_ls), result.{{nameCamelCase}}); +{{/vars}}{{#propertyMap}} fromJson(jo, result.{{nameCamelCase}}); +{{/propertyMap}} } +{{/out?}} }; +{{/model}}} // namespace QMatrixClient {{/ models}}{{#responses}}{{#normalResponse?}}{{#allProperties?}} class {{camelCaseOperationId}}Job::Private { @@ -109,12 +112,12 @@ BaseJob::Status {{camelCaseOperationId}}Job::parseReply(QNetworkReply* reply) }{{/ producesNonJson?}}{{^producesNonJson?}} BaseJob::Status {{camelCaseOperationId}}Job::parseJson(const QJsonDocument& data) { -{{#inlineResponse}} d->{{paramName}} = fromJson<{{dataType.name}}>(data); +{{#inlineResponse}} fromJson(data, d->{{paramName}}); {{/inlineResponse}}{{^inlineResponse}} auto json = data.object(); {{#properties}}{{#required?}} if (!json.contains("{{baseName}}"_ls)) return { JsonParseError, "The key '{{baseName}}' not found in the response" }; -{{/required?}} d->{{paramName}} = fromJson<{{dataType.name}}>(json.value("{{baseName}}"_ls)); +{{/required?}} fromJson(json.value("{{baseName}}"_ls), d->{{paramName}}); {{/properties}}{{/inlineResponse}} return Success; }{{/ producesNonJson?}} {{/allProperties?}}{{/normalResponse?}}{{/responses}}{{/operation}}{{/operations}} diff --git a/lib/csapi/{{base}}.h.mustache b/lib/csapi/{{base}}.h.mustache index 147c8607..a9c3a63a 100644 --- a/lib/csapi/{{base}}.h.mustache +++ b/lib/csapi/{{base}}.h.mustache @@ -18,14 +18,13 @@ namespace QMatrixClient {{/vars}}{{#propertyMap}}{{#description}} /// {{_}} {{/description}} {{>maybeOmittableType}} {{nameCamelCase}}; {{/propertyMap}} }; -{{#in?}} - QJsonObject toJson(const {{name}}& pod); -{{/in?}}{{#out?}} - template <> struct FromJsonObject<{{name}}> + template <> struct JsonObjectConverter<{{name}}> { - {{name}} operator()({{^propertyMap}}const QJsonObject&{{/propertyMap}}{{#propertyMap}}QJsonObject{{/propertyMap}} jo) const; - }; -{{/ out?}}{{/model}} + {{#in?}}static void dumpTo(QJsonObject& jo, const {{name}}& pod); + {{/in?}}{{#out?}}static void fillFrom({{^propertyMap}}const QJsonObject&{{/propertyMap + }}{{#propertyMap}}QJsonObject{{/propertyMap}} jo, {{name}}& pod); +{{/out?}} }; +{{/model}} {{/models}}{{#operations}} // Operations {{# operation}}{{#summary}} /// {{summary}}{{#description?}}{{!add a linebreak between summary and description if both exist}} diff --git a/lib/events/accountdataevents.h b/lib/events/accountdataevents.h index d1c1abc8..a99d85ac 100644 --- a/lib/events/accountdataevents.h +++ b/lib/events/accountdataevents.h @@ -36,37 +36,38 @@ namespace QMatrixClient order_type order; TagRecord (order_type order = none) : order(order) { } - explicit TagRecord(const QJsonObject& jo) + + bool operator<(const TagRecord& other) const + { + // Per The Spec, rooms with no order should be after those with order + return !order.omitted() && + (other.order.omitted() || order.value() < other.order.value()); + } + }; + + template <> struct JsonObjectConverter + { + static void fillFrom(const QJsonObject& jo, TagRecord& rec) { // Parse a float both from JSON double and JSON string because // libqmatrixclient previously used to use strings to store order. const auto orderJv = jo.value("order"_ls); if (orderJv.isDouble()) - order = fromJson(orderJv); - else if (orderJv.isString()) + rec.order = fromJson(orderJv); + if (orderJv.isString()) { bool ok; - order = orderJv.toString().toFloat(&ok); + rec.order = orderJv.toString().toFloat(&ok); if (!ok) - order = none; + rec.order = none; } } - - bool operator<(const TagRecord& other) const + static void dumpTo(QJsonObject& jo, const TagRecord& rec) { - // Per The Spec, rooms with no order should be after those with order - return !order.omitted() && - (other.order.omitted() || order.value() < other.order.value()); + addParam(jo, QStringLiteral("order"), rec.order); } }; - inline QJsonValue toJson(const TagRecord& rec) - { - QJsonObject o; - addParam(o, QStringLiteral("order"), rec.order); - return o; - } - using TagsMap = QHash; #define DEFINE_SIMPLE_EVENT(_Name, _TypeId, _ContentType, _ContentKey) \ diff --git a/lib/events/eventloader.h b/lib/events/eventloader.h index cd2f9149..da663392 100644 --- a/lib/events/eventloader.h +++ b/lib/events/eventloader.h @@ -57,11 +57,15 @@ namespace QMatrixClient { matrixType); } - template struct FromJsonObject> + template struct JsonConverter> { - auto operator()(const QJsonObject& jo) const + static auto load(const QJsonValue& jv) { - return loadEvent(jo); + return loadEvent(jv.toObject()); + } + static auto load(const QJsonDocument& jd) + { + return loadEvent(jd.object()); } }; } // namespace QMatrixClient diff --git a/lib/events/roommemberevent.cpp b/lib/events/roommemberevent.cpp index eaa3302c..a5ac3c5f 100644 --- a/lib/events/roommemberevent.cpp +++ b/lib/events/roommemberevent.cpp @@ -23,20 +23,17 @@ #include -using namespace QMatrixClient; - static const std::array membershipStrings = { { QStringLiteral("invite"), QStringLiteral("join"), QStringLiteral("knock"), QStringLiteral("leave"), QStringLiteral("ban") } }; -namespace QMatrixClient -{ +namespace QMatrixClient { template <> - struct FromJson + struct JsonConverter { - MembershipType operator()(const QJsonValue& jv) const + static MembershipType load(const QJsonValue& jv) { const auto& membershipString = jv.toString(); for (auto it = membershipStrings.begin(); @@ -48,9 +45,10 @@ namespace QMatrixClient return MembershipType::Undefined; } }; - } +using namespace QMatrixClient; + MemberEventContent::MemberEventContent(const QJsonObject& json) : membership(fromJson(json["membership"_ls])) , isDirect(json["is_direct"_ls].toBool()) diff --git a/lib/identity/definitions/request_email_validation.cpp b/lib/identity/definitions/request_email_validation.cpp index 95088bcb..47463a8b 100644 --- a/lib/identity/definitions/request_email_validation.cpp +++ b/lib/identity/definitions/request_email_validation.cpp @@ -6,28 +6,21 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const RequestEmailValidation& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const RequestEmailValidation& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("client_secret"), pod.clientSecret); addParam<>(jo, QStringLiteral("email"), pod.email); addParam<>(jo, QStringLiteral("send_attempt"), pod.sendAttempt); addParam(jo, QStringLiteral("next_link"), pod.nextLink); - return jo; } -RequestEmailValidation FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, RequestEmailValidation& result) { - RequestEmailValidation result; - result.clientSecret = - fromJson(jo.value("client_secret"_ls)); - result.email = - fromJson(jo.value("email"_ls)); - result.sendAttempt = - fromJson(jo.value("send_attempt"_ls)); - result.nextLink = - fromJson(jo.value("next_link"_ls)); - - return result; + fromJson(jo.value("client_secret"_ls), result.clientSecret); + fromJson(jo.value("email"_ls), result.email); + fromJson(jo.value("send_attempt"_ls), result.sendAttempt); + fromJson(jo.value("next_link"_ls), result.nextLink); } diff --git a/lib/identity/definitions/request_email_validation.h b/lib/identity/definitions/request_email_validation.h index 3e72275f..eb7d8ed6 100644 --- a/lib/identity/definitions/request_email_validation.h +++ b/lib/identity/definitions/request_email_validation.h @@ -33,12 +33,10 @@ namespace QMatrixClient /// server will redirect the user to this URL. QString nextLink; }; - - QJsonObject toJson(const RequestEmailValidation& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - RequestEmailValidation operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const RequestEmailValidation& pod); + static void fillFrom(const QJsonObject& jo, RequestEmailValidation& pod); }; } // namespace QMatrixClient diff --git a/lib/identity/definitions/request_msisdn_validation.cpp b/lib/identity/definitions/request_msisdn_validation.cpp index 125baa9c..a123d326 100644 --- a/lib/identity/definitions/request_msisdn_validation.cpp +++ b/lib/identity/definitions/request_msisdn_validation.cpp @@ -6,31 +6,23 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const RequestMsisdnValidation& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const RequestMsisdnValidation& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("client_secret"), pod.clientSecret); addParam<>(jo, QStringLiteral("country"), pod.country); addParam<>(jo, QStringLiteral("phone_number"), pod.phoneNumber); addParam<>(jo, QStringLiteral("send_attempt"), pod.sendAttempt); addParam(jo, QStringLiteral("next_link"), pod.nextLink); - return jo; } -RequestMsisdnValidation FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, RequestMsisdnValidation& result) { - RequestMsisdnValidation result; - result.clientSecret = - fromJson(jo.value("client_secret"_ls)); - result.country = - fromJson(jo.value("country"_ls)); - result.phoneNumber = - fromJson(jo.value("phone_number"_ls)); - result.sendAttempt = - fromJson(jo.value("send_attempt"_ls)); - result.nextLink = - fromJson(jo.value("next_link"_ls)); - - return result; + fromJson(jo.value("client_secret"_ls), result.clientSecret); + fromJson(jo.value("country"_ls), result.country); + fromJson(jo.value("phone_number"_ls), result.phoneNumber); + fromJson(jo.value("send_attempt"_ls), result.sendAttempt); + fromJson(jo.value("next_link"_ls), result.nextLink); } diff --git a/lib/identity/definitions/request_msisdn_validation.h b/lib/identity/definitions/request_msisdn_validation.h index 77bea2bc..b48ed6d5 100644 --- a/lib/identity/definitions/request_msisdn_validation.h +++ b/lib/identity/definitions/request_msisdn_validation.h @@ -36,12 +36,10 @@ namespace QMatrixClient /// server will redirect the user to this URL. QString nextLink; }; - - QJsonObject toJson(const RequestMsisdnValidation& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - RequestMsisdnValidation operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const RequestMsisdnValidation& pod); + static void fillFrom(const QJsonObject& jo, RequestMsisdnValidation& pod); }; } // namespace QMatrixClient diff --git a/lib/identity/definitions/sid.cpp b/lib/identity/definitions/sid.cpp index 443dbedf..1ba4b3b5 100644 --- a/lib/identity/definitions/sid.cpp +++ b/lib/identity/definitions/sid.cpp @@ -6,19 +6,15 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const Sid& pod) +void JsonObjectConverter::dumpTo( + QJsonObject& jo, const Sid& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("sid"), pod.sid); - return jo; } -Sid FromJsonObject::operator()(const QJsonObject& jo) const +void JsonObjectConverter::fillFrom( + const QJsonObject& jo, Sid& result) { - Sid result; - result.sid = - fromJson(jo.value("sid"_ls)); - - return result; + fromJson(jo.value("sid"_ls), result.sid); } diff --git a/lib/identity/definitions/sid.h b/lib/identity/definitions/sid.h index eae60c47..ac8c4130 100644 --- a/lib/identity/definitions/sid.h +++ b/lib/identity/definitions/sid.h @@ -19,12 +19,10 @@ namespace QMatrixClient /// must not be empty. QString sid; }; - - QJsonObject toJson(const Sid& pod); - - template <> struct FromJsonObject + template <> struct JsonObjectConverter { - Sid operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const Sid& pod); + static void fillFrom(const QJsonObject& jo, Sid& pod); }; } // namespace QMatrixClient -- cgit v1.2.3 From 9628594881346c8e06594e65d3befafc310e12d5 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 8 Dec 2018 15:36:28 +0900 Subject: EventContent: minor cleanup --- lib/events/eventcontent.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/events') diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index 91d7a8c8..bedf0078 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -43,9 +43,10 @@ namespace QMatrixClient class Base { public: - explicit Base (const QJsonObject& o = {}) : originalJson(o) { } + explicit Base (QJsonObject o = {}) : originalJson(std::move(o)) { } virtual ~Base() = default; + // FIXME: make toJson() from converters.* work on base classes QJsonObject toJson() const; public: -- cgit v1.2.3 From 0e67d1e92285e0c03e4e34ad747490ae4dc5482d Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 11 Dec 2018 12:26:05 +0900 Subject: RoomMemberEvent: properly integrate with GetMembersByRoomJob GetMembersByRoomJob was dysfunctional so far, creating "unknown RoomMemberEvents" instead of proper ones. Now that we need it for lazy- loading, it's fixed! --- lib/events/roommemberevent.h | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'lib/events') diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h index 149d74f8..b8224033 100644 --- a/lib/events/roommemberevent.h +++ b/lib/events/roommemberevent.h @@ -60,8 +60,16 @@ namespace QMatrixClient : StateEvent(typeId(), matrixTypeId(), c) { } - // This is a special constructor enabling RoomMemberEvent to be - // a base class for more specific member events. + /// A special constructor to create unknown RoomMemberEvents + /** + * This is needed in order to use RoomMemberEvent as a "base event + * class" in cases like GetMembersByRoomJob when RoomMemberEvents + * (rather than RoomEvents or StateEvents) are resolved from JSON. + * For such cases loadEvent<> requires an underlying class to be + * constructible with unknownTypeId() instead of its genuine id. + * Don't use it directly. + * \sa GetMembersByRoomJob, loadEvent, unknownTypeId + */ RoomMemberEvent(Type type, const QJsonObject& fullJson) : StateEvent(type, fullJson) { } @@ -81,6 +89,18 @@ namespace QMatrixClient private: REGISTER_ENUM(MembershipType) }; + + template <> + class EventFactory + { + public: + static event_ptr_tt make(const QJsonObject& json, + const QString&) + { + return makeEvent(json); + } + }; + REGISTER_EVENT_TYPE(RoomMemberEvent) DEFINE_EVENTTYPE_ALIAS(RoomMember, RoomMemberEvent) } // namespace QMatrixClient -- cgit v1.2.3 From 5e85dba348676009b2e3b1e41ce9d3e7b8bca1ca Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 26 Dec 2018 10:56:49 +0900 Subject: RoomAvatarEvent: use correct #includes --- lib/events/roomavatarevent.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/events') diff --git a/lib/events/roomavatarevent.h b/lib/events/roomavatarevent.h index 491861b1..a43d3a85 100644 --- a/lib/events/roomavatarevent.h +++ b/lib/events/roomavatarevent.h @@ -18,8 +18,7 @@ #pragma once -#include "event.h" - +#include "stateevent.h" #include "eventcontent.h" namespace QMatrixClient -- cgit v1.2.3 From 241f7165816624da45fca58578885b17589ec1f7 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 26 Dec 2018 10:57:50 +0900 Subject: EventContent: allow empty (default-constructed) thumbnails --- lib/events/eventcontent.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'lib/events') diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index bedf0078..ea321fb6 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -149,10 +149,10 @@ namespace QMatrixClient class Thumbnail : public ImageInfo { public: + Thumbnail() : ImageInfo(QUrl()) { } // To allow empty thumbnails Thumbnail(const QJsonObject& infoJson); - Thumbnail(const ImageInfo& info) - : ImageInfo(info) - { } + Thumbnail(const ImageInfo& info) : ImageInfo(info) { } + using ImageInfo::ImageInfo; /** * Writes thumbnail information to "thumbnail_info" subobject @@ -184,9 +184,7 @@ namespace QMatrixClient class UrlBasedContent : public TypedBase, public InfoT { public: - UrlBasedContent(QUrl url, InfoT&& info, QString filename = {}) - : InfoT(url, std::forward(info), filename) - { } + using InfoT::InfoT; explicit UrlBasedContent(const QJsonObject& json) : TypedBase(json) , InfoT(json["url"].toString(), json["info"].toObject(), @@ -214,7 +212,7 @@ namespace QMatrixClient class UrlWithThumbnailContent : public UrlBasedContent { public: - // TODO: POD constructor + using UrlBasedContent::UrlBasedContent; explicit UrlWithThumbnailContent(const QJsonObject& json) : UrlBasedContent(json) , thumbnail(InfoT::originalInfoJson) -- cgit v1.2.3 From 3ecf762f497a4d4b6ea7583689c0b9b284300201 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 28 Dec 2018 12:47:02 +0900 Subject: EventContent: use qint64 for the payload size --- lib/events/eventcontent.cpp | 8 +++++--- lib/events/eventcontent.h | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'lib/events') diff --git a/lib/events/eventcontent.cpp b/lib/events/eventcontent.cpp index a6b1c763..bac2b72f 100644 --- a/lib/events/eventcontent.cpp +++ b/lib/events/eventcontent.cpp @@ -17,6 +17,8 @@ */ #include "eventcontent.h" + +#include "converters.h" #include "util.h" #include @@ -30,7 +32,7 @@ QJsonObject Base::toJson() const return o; } -FileInfo::FileInfo(const QUrl& u, int payloadSize, const QMimeType& mimeType, +FileInfo::FileInfo(const QUrl& u, qint64 payloadSize, const QMimeType& mimeType, const QString& originalFilename) : mimeType(mimeType), url(u), payloadSize(payloadSize) , originalName(originalFilename) @@ -41,7 +43,7 @@ FileInfo::FileInfo(const QUrl& u, const QJsonObject& infoJson, : originalInfoJson(infoJson) , mimeType(QMimeDatabase().mimeTypeForName(infoJson["mimetype"_ls].toString())) , url(u) - , payloadSize(infoJson["size"_ls].toInt()) + , payloadSize(fromJson(infoJson["size"_ls])) , originalName(originalFilename) { if (!mimeType.isValid()) @@ -55,7 +57,7 @@ void FileInfo::fillInfoJson(QJsonObject* infoJson) const infoJson->insert(QStringLiteral("mimetype"), mimeType.name()); } -ImageInfo::ImageInfo(const QUrl& u, int fileSize, QMimeType mimeType, +ImageInfo::ImageInfo(const QUrl& u, qint64 fileSize, QMimeType mimeType, const QSize& imageSize) : FileInfo(u, fileSize, mimeType), imageSize(imageSize) { } diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index ea321fb6..2a48e910 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -88,7 +88,7 @@ namespace QMatrixClient class FileInfo { public: - explicit FileInfo(const QUrl& u, int payloadSize = -1, + explicit FileInfo(const QUrl& u, qint64 payloadSize = -1, const QMimeType& mimeType = {}, const QString& originalFilename = {}); FileInfo(const QUrl& u, const QJsonObject& infoJson, @@ -109,7 +109,7 @@ namespace QMatrixClient QJsonObject originalInfoJson; QMimeType mimeType; QUrl url; - int payloadSize; + qint64 payloadSize; QString originalName; }; @@ -127,7 +127,7 @@ namespace QMatrixClient class ImageInfo : public FileInfo { public: - explicit ImageInfo(const QUrl& u, int fileSize = -1, + explicit ImageInfo(const QUrl& u, qint64 fileSize = -1, QMimeType mimeType = {}, const QSize& imageSize = {}); ImageInfo(const QUrl& u, const QJsonObject& infoJson, -- cgit v1.2.3 From 4ec3dd92d2cb5af4cf4893770e29db51d23e0e67 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 26 Dec 2018 19:31:11 +0900 Subject: Make content in events editable --- lib/events/eventcontent.h | 2 ++ lib/events/roommessageevent.cpp | 6 +++--- lib/events/roommessageevent.h | 10 ++++++++++ lib/events/stateevent.h | 6 ++++++ 4 files changed, 21 insertions(+), 3 deletions(-) (limited to 'lib/events') diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index 2a48e910..2e61276b 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -167,6 +167,7 @@ namespace QMatrixClient explicit TypedBase(const QJsonObject& o = {}) : Base(o) { } virtual QMimeType type() const = 0; virtual const FileInfo* fileInfo() const { return nullptr; } + virtual FileInfo* fileInfo() { return nullptr; } virtual const Thumbnail* thumbnailInfo() const { return nullptr; } }; @@ -196,6 +197,7 @@ namespace QMatrixClient QMimeType type() const override { return InfoT::mimeType; } const FileInfo* fileInfo() const override { return this; } + FileInfo* fileInfo() override { return this; } protected: void fillJson(QJsonObject* json) const override diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index 1c5cf058..572c7173 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -71,8 +71,8 @@ MsgType jsonToMsgType(const QString& matrixType) return MsgType::Unknown; } -inline QJsonObject toMsgJson(const QString& plainBody, const QString& jsonMsgType, - TypedBase* content) +QJsonObject RoomMessageEvent::assembleContentJson(const QString& plainBody, + const QString& jsonMsgType, TypedBase* content) { auto json = content ? content->toJson() : QJsonObject(); json.insert(QStringLiteral("msgtype"), jsonMsgType); @@ -86,7 +86,7 @@ static const auto BodyKey = "body"_ls; RoomMessageEvent::RoomMessageEvent(const QString& plainBody, const QString& jsonMsgType, TypedBase* content) : RoomEvent(typeId(), matrixTypeId(), - toMsgJson(plainBody, jsonMsgType, content)) + assembleContentJson(plainBody, jsonMsgType, content)) , _content(content) { } diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index 4c29a93e..a4ba6e65 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -56,6 +56,13 @@ namespace QMatrixClient QString plainBody() const; EventContent::TypedBase* content() const { return _content.data(); } + template + void editContent(VisitorT visitor) + { + visitor(*_content); + editJson()[ContentKeyL] = + assembleContentJson(plainBody(), rawMsgtype(), content()); + } QMimeType mimeType() const; bool hasTextContent() const; bool hasFileContent() const; @@ -64,6 +71,9 @@ namespace QMatrixClient private: QScopedPointer _content; + static QJsonObject assembleContentJson(const QString& plainBody, + const QString& jsonMsgType, EventContent::TypedBase* content); + REGISTER_ENUM(MsgType) }; REGISTER_EVENT_TYPE(RoomMessageEvent) diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index d82de7e1..d488c0a0 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -88,6 +88,12 @@ namespace QMatrixClient { } const ContentT& content() const { return _content; } + template + void editContent(VisitorT&& visitor) + { + visitor(_content); + editJson()[ContentKeyL] = _content.toJson(); + } [[deprecated("Use prevContent instead")]] const ContentT* prev_content() const { return prevContent(); } const ContentT* prevContent() const -- cgit v1.2.3 From 77830a97e524a4bd27d8cbcd3830cbe450a5755a Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 28 Dec 2018 12:46:13 +0900 Subject: EventContent: only dump to json non-empty/valid values --- lib/events/eventcontent.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'lib/events') diff --git a/lib/events/eventcontent.cpp b/lib/events/eventcontent.cpp index bac2b72f..03880885 100644 --- a/lib/events/eventcontent.cpp +++ b/lib/events/eventcontent.cpp @@ -53,8 +53,10 @@ FileInfo::FileInfo(const QUrl& u, const QJsonObject& infoJson, void FileInfo::fillInfoJson(QJsonObject* infoJson) const { Q_ASSERT(infoJson); - infoJson->insert(QStringLiteral("size"), payloadSize); - infoJson->insert(QStringLiteral("mimetype"), mimeType.name()); + if (payloadSize != -1) + infoJson->insert(QStringLiteral("size"), payloadSize); + if (mimeType.isValid()) + infoJson->insert(QStringLiteral("mimetype"), mimeType.name()); } ImageInfo::ImageInfo(const QUrl& u, qint64 fileSize, QMimeType mimeType, @@ -71,8 +73,10 @@ ImageInfo::ImageInfo(const QUrl& u, const QJsonObject& infoJson, void ImageInfo::fillInfoJson(QJsonObject* infoJson) const { FileInfo::fillInfoJson(infoJson); - infoJson->insert(QStringLiteral("w"), imageSize.width()); - infoJson->insert(QStringLiteral("h"), imageSize.height()); + if (imageSize.width() != -1) + infoJson->insert(QStringLiteral("w"), imageSize.width()); + if (imageSize.height() != -1) + infoJson->insert(QStringLiteral("h"), imageSize.height()); } Thumbnail::Thumbnail(const QJsonObject& infoJson) @@ -82,7 +86,9 @@ Thumbnail::Thumbnail(const QJsonObject& infoJson) void Thumbnail::fillInfoJson(QJsonObject* infoJson) const { - infoJson->insert(QStringLiteral("thumbnail_url"), url.toString()); - infoJson->insert(QStringLiteral("thumbnail_info"), - toInfoJson(*this)); + if (url.isValid()) + infoJson->insert(QStringLiteral("thumbnail_url"), url.toString()); + if (!imageSize.isEmpty()) + infoJson->insert(QStringLiteral("thumbnail_info"), + toInfoJson(*this)); } -- cgit v1.2.3 From 816377ea3c204f22698e1458b815fdd3c3837adc Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 3 Jan 2019 17:57:42 +0900 Subject: More defaults to construct LocationContent and PlayableContent --- lib/events/roommessageevent.cpp | 3 ++- lib/events/roommessageevent.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/events') diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index 572c7173..69969c0f 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -200,7 +200,8 @@ void TextContent::fillJson(QJsonObject* json) const } } -LocationContent::LocationContent(const QString& geoUri, const ImageInfo& thumbnail) +LocationContent::LocationContent(const QString& geoUri, + const Thumbnail& thumbnail) : geoUri(geoUri), thumbnail(thumbnail) { } diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index a4ba6e65..5657135b 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -122,7 +122,7 @@ namespace QMatrixClient { public: LocationContent(const QString& geoUri, - const ImageInfo& thumbnail); + const Thumbnail& thumbnail = {}); explicit LocationContent(const QJsonObject& json); QMimeType type() const override; @@ -142,6 +142,7 @@ namespace QMatrixClient class PlayableContent : public ContentT { public: + using ContentT::ContentT; PlayableContent(const QJsonObject& json) : ContentT(json) , duration(ContentT::originalInfoJson["duration"_ls].toInt()) -- cgit v1.2.3 From 2a6cbbff8246dd2f682624d1551facb2813394ad Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 3 Jan 2019 21:08:40 +0900 Subject: RoomMessageEvent: easier creation of file-based events --- lib/events/roommessageevent.cpp | 53 +++++++++++++++++++++++++++++++++++++++++ lib/events/roommessageevent.h | 8 +++++++ 2 files changed, 61 insertions(+) (limited to 'lib/events') diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index 69969c0f..d63ae2fe 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -21,6 +21,8 @@ #include "logging.h" #include +#include +#include using namespace QMatrixClient; using namespace EventContent; @@ -95,6 +97,38 @@ RoomMessageEvent::RoomMessageEvent(const QString& plainBody, : RoomMessageEvent(plainBody, msgTypeToJson(msgType), content) { } +TypedBase* contentFromFile(const QFileInfo& file, bool asGenericFile) +{ + auto filePath = file.absoluteFilePath(); + auto localUrl = QUrl::fromLocalFile(filePath); + auto mimeType = QMimeDatabase().mimeTypeForFile(file); + auto payloadSize = file.size(); + if (!asGenericFile) + { + auto mimeTypeName = mimeType.name(); + if (mimeTypeName.startsWith("image/")) + return new ImageContent(localUrl, payloadSize, mimeType, + QImageReader(filePath).size()); + + // duration can only be obtained asynchronously and can only be reliably + // done by starting to play the file. Left for a future implementation. + if (mimeTypeName.startsWith("video/")) + return new VideoContent(localUrl, payloadSize, mimeType); + + if (mimeTypeName.startsWith("audio/")) + return new AudioContent(localUrl, payloadSize, mimeType); + + } + return new FileContent(localUrl, payloadSize, mimeType); +} + +RoomMessageEvent::RoomMessageEvent(const QString& plainBody, + const QFileInfo& file, bool asGenericFile) + : RoomMessageEvent(plainBody, + asGenericFile ? QStringLiteral("m.file") : rawMsgTypeForFile(file), + contentFromFile(file, asGenericFile)) +{ } + RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) : RoomEvent(typeId(), obj), _content(nullptr) { @@ -162,6 +196,25 @@ bool RoomMessageEvent::hasThumbnail() const return content() && content()->thumbnailInfo(); } +QString rawMsgTypeForMimeType(const QMimeType& mimeType) +{ + auto name = mimeType.name(); + return name.startsWith("image/") ? QStringLiteral("m.image") : + name.startsWith("video/") ? QStringLiteral("m.video") : + name.startsWith("audio/") ? QStringLiteral("m.audio") : + QStringLiteral("m.file"); +} + +QString RoomMessageEvent::rawMsgTypeForUrl(const QUrl& url) +{ + return rawMsgTypeForMimeType(QMimeDatabase().mimeTypeForUrl(url)); +} + +QString RoomMessageEvent::rawMsgTypeForFile(const QFileInfo& fi) +{ + return rawMsgTypeForMimeType(QMimeDatabase().mimeTypeForFile(fi)); +} + TextContent::TextContent(const QString& text, const QString& contentType) : mimeType(QMimeDatabase().mimeTypeForName(contentType)), body(text) { diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index 5657135b..d5b570f5 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -21,6 +21,8 @@ #include "roomevent.h" #include "eventcontent.h" +class QFileInfo; + namespace QMatrixClient { namespace MessageEventContent = EventContent; // Back-compatibility @@ -49,6 +51,9 @@ namespace QMatrixClient explicit RoomMessageEvent(const QString& plainBody, MsgType msgType = MsgType::Text, EventContent::TypedBase* content = nullptr); + explicit RoomMessageEvent(const QString& plainBody, + const QFileInfo& file, + bool asGenericFile = false); explicit RoomMessageEvent(const QJsonObject& obj); MsgType msgtype() const; @@ -68,6 +73,9 @@ namespace QMatrixClient bool hasFileContent() const; bool hasThumbnail() const; + static QString rawMsgTypeForUrl(const QUrl& url); + static QString rawMsgTypeForFile(const QFileInfo& fi); + private: QScopedPointer _content; -- cgit v1.2.3 From e3578b3cc6b978db1c04a1f684e1a03676c33f3b Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 5 Jan 2019 19:59:48 +0900 Subject: EventContent::ImageInfo: support originalFilename in POD constructor It's not mandated by the spec for anything except m.file but hey it's convenient. --- lib/events/eventcontent.cpp | 4 ++-- lib/events/eventcontent.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/events') diff --git a/lib/events/eventcontent.cpp b/lib/events/eventcontent.cpp index 03880885..9a5e872c 100644 --- a/lib/events/eventcontent.cpp +++ b/lib/events/eventcontent.cpp @@ -60,8 +60,8 @@ void FileInfo::fillInfoJson(QJsonObject* infoJson) const } ImageInfo::ImageInfo(const QUrl& u, qint64 fileSize, QMimeType mimeType, - const QSize& imageSize) - : FileInfo(u, fileSize, mimeType), imageSize(imageSize) + const QSize& imageSize, const QString& originalFilename) + : FileInfo(u, fileSize, mimeType, originalFilename), imageSize(imageSize) { } ImageInfo::ImageInfo(const QUrl& u, const QJsonObject& infoJson, diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index 2e61276b..0588c0e2 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -129,7 +129,8 @@ namespace QMatrixClient public: explicit ImageInfo(const QUrl& u, qint64 fileSize = -1, QMimeType mimeType = {}, - const QSize& imageSize = {}); + const QSize& imageSize = {}, + const QString& originalFilename = {}); ImageInfo(const QUrl& u, const QJsonObject& infoJson, const QString& originalFilename = {}); -- cgit v1.2.3 From 24c80a57fe1a79289f3028a81d6f8e0ac5f505fe Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 5 Jan 2019 20:06:09 +0900 Subject: API version++; use QMediaResource from QtMultimedia (new dep) to detect m.video resolution The API version number should have been bumped long ago. --- .travis.yml | 1 + CMakeLists.txt | 8 +++++--- lib/events/roommessageevent.cpp | 17 ++++++++++------- libqmatrixclient.pri | 2 +- 4 files changed, 17 insertions(+), 11 deletions(-) (limited to 'lib/events') diff --git a/.travis.yml b/.travis.yml index 0b2967cf..c0e8c097 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ addons: packages: - g++-5 - qt57base + - qt57multimedia - valgrind matrix: diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a3193a4..c48a7ba9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,9 @@ foreach (FLAG all "" pedantic extra error=return-type no-unused-parameter no-gnu endif () endforeach () -find_package(Qt5 5.4.1 REQUIRED Network Gui) +# Qt 5.6+ is the formal requirement but for the sake of supporting UBPorts +# upstream Qt 5.4 is required. +find_package(Qt5 5.4.1 REQUIRED Network Gui Multimedia) get_filename_component(Qt5_Prefix "${Qt5_DIR}/../../../.." ABSOLUTE) if (GTAD_PATH) @@ -140,7 +142,7 @@ add_library(QMatrixClient ${libqmatrixclient_SRCS} ${libqmatrixclient_job_SRCS} ${libqmatrixclient_csdef_SRCS} ${libqmatrixclient_cswellknown_SRCS} ${libqmatrixclient_asdef_SRCS} ${libqmatrixclient_isdef_SRCS}) -set(API_VERSION "0.4") +set(API_VERSION "0.5") set_property(TARGET QMatrixClient PROPERTY VERSION "${API_VERSION}.0") set_property(TARGET QMatrixClient PROPERTY SOVERSION ${API_VERSION} ) set_property(TARGET QMatrixClient PROPERTY @@ -152,7 +154,7 @@ target_include_directories(QMatrixClient PUBLIC $ $ ) -target_link_libraries(QMatrixClient Qt5::Core Qt5::Network Qt5::Gui) +target_link_libraries(QMatrixClient Qt5::Core Qt5::Network Qt5::Gui Qt5::Multimedia) add_executable(qmc-example ${example_SRCS}) target_link_libraries(qmc-example Qt5::Core QMatrixClient) diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index d63ae2fe..c3007fa0 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -23,6 +23,7 @@ #include #include #include +#include using namespace QMatrixClient; using namespace EventContent; @@ -102,24 +103,26 @@ TypedBase* contentFromFile(const QFileInfo& file, bool asGenericFile) auto filePath = file.absoluteFilePath(); auto localUrl = QUrl::fromLocalFile(filePath); auto mimeType = QMimeDatabase().mimeTypeForFile(file); - auto payloadSize = file.size(); if (!asGenericFile) { auto mimeTypeName = mimeType.name(); if (mimeTypeName.startsWith("image/")) - return new ImageContent(localUrl, payloadSize, mimeType, - QImageReader(filePath).size()); + return new ImageContent(localUrl, file.size(), mimeType, + QImageReader(filePath).size(), + file.fileName()); // duration can only be obtained asynchronously and can only be reliably // done by starting to play the file. Left for a future implementation. if (mimeTypeName.startsWith("video/")) - return new VideoContent(localUrl, payloadSize, mimeType); + return new VideoContent(localUrl, file.size(), mimeType, + QMediaResource(localUrl).resolution(), + file.fileName()); if (mimeTypeName.startsWith("audio/")) - return new AudioContent(localUrl, payloadSize, mimeType); - + return new AudioContent(localUrl, file.size(), mimeType, + file.fileName()); } - return new FileContent(localUrl, payloadSize, mimeType); + return new FileContent(localUrl, file.size(), mimeType, file.fileName()); } RoomMessageEvent::RoomMessageEvent(const QString& plainBody, diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri index 8ca43e56..eefaec67 100644 --- a/libqmatrixclient.pri +++ b/libqmatrixclient.pri @@ -1,4 +1,4 @@ -QT += network +QT += network multimedia CONFIG += c++14 warn_on rtti_off create_prl object_parallel_to_source win32-msvc* { -- cgit v1.2.3 From e3a048ed3a8a5060affe6fcba1e1867294351177 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 5 Jan 2019 18:36:46 +0900 Subject: RoomEvent: don't log transactionId anymore It's already logged in Room - actually, several times at different stages. --- lib/events/roomevent.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'lib/events') diff --git a/lib/events/roomevent.cpp b/lib/events/roomevent.cpp index 80d121de..3d03509f 100644 --- a/lib/events/roomevent.cpp +++ b/lib/events/roomevent.cpp @@ -42,10 +42,6 @@ RoomEvent::RoomEvent(Type type, const QJsonObject& json) _redactedBecause = makeEvent(redaction.toObject()); return; } - - const auto& txnId = transactionId(); - if (!txnId.isEmpty()) - qCDebug(EVENTS) << "Event transactionId:" << txnId; } RoomEvent::~RoomEvent() = default; // Let the smart pointer do its job @@ -90,7 +86,6 @@ void RoomEvent::setTransactionId(const QString& txnId) auto unsignedData = fullJson()[UnsignedKeyL].toObject(); unsignedData.insert(QStringLiteral("transaction_id"), txnId); editJson().insert(UnsignedKey, unsignedData); - qCDebug(EVENTS) << "New event transactionId:" << txnId; Q_ASSERT(transactionId() == txnId); } -- cgit v1.2.3 From a23fa6df08008f4a3f7437efa8afe839a102dc8e Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 6 Jan 2019 17:43:37 +0900 Subject: visit(): pass decayed event types to is() So that is<> could be specialised for some types. --- lib/events/event.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'lib/events') diff --git a/lib/events/event.h b/lib/events/event.h index c51afcc4..d7ac4292 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -208,6 +208,9 @@ namespace QMatrixClient template inline auto registerEventType() { + // Initialise exactly once, even if this function is called twice for + // the same type (for whatever reason - you never know the ways of + // static initialisation is done). static const auto _ = setupFactory(); return _; // Only to facilitate usage in static initialisation } @@ -337,7 +340,8 @@ namespace QMatrixClient -> decltype(static_cast(&*eptr)) { Q_ASSERT(eptr); - return is(*eptr) ? static_cast(&*eptr) : nullptr; + return is>(*eptr) + ? static_cast(&*eptr) : nullptr; } // A single generic catch-all visitor @@ -369,7 +373,7 @@ namespace QMatrixClient visit(const BaseEventT& event, FnT&& visitor) { using event_type = fn_arg_t; - if (is(event)) + if (is>(event)) visitor(static_cast(event)); } @@ -383,7 +387,7 @@ namespace QMatrixClient fn_return_t&& defaultValue = {}) { using event_type = fn_arg_t; - if (is(event)) + if (is>(event)) return visitor(static_cast(event)); return std::forward>(defaultValue); } @@ -396,7 +400,7 @@ namespace QMatrixClient FnTs&&... visitors) { using event_type1 = fn_arg_t; - if (is(event)) + if (is>(event)) return visitor1(static_cast(event)); return visit(event, std::forward(visitor2), std::forward(visitors)...); -- cgit v1.2.3 From c83a73b17eaef465150458282e63a478ba238f26 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 6 Jan 2019 17:45:34 +0900 Subject: Create StateEventBase events if state_key is there This makes unknown state events to still be treated as state events. --- lib/events/stateevent.cpp | 13 ++++++++++++- lib/events/stateevent.h | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'lib/events') diff --git a/lib/events/stateevent.cpp b/lib/events/stateevent.cpp index fd8079be..c4151676 100644 --- a/lib/events/stateevent.cpp +++ b/lib/events/stateevent.cpp @@ -20,8 +20,19 @@ using namespace QMatrixClient; +// Aside from the normal factory to instantiate StateEventBase inheritors +// StateEventBase itself can be instantiated if there's a state_key JSON key +// but the event type is unknown. [[gnu::unused]] static auto stateEventTypeInitialised = - RoomEvent::factory_t::chainFactory(); + RoomEvent::factory_t::addMethod( + [] (const QJsonObject& json, const QString& matrixType) + { + if (auto e = StateEventBase::factory_t::make(json, matrixType)) + return e; + return json.contains("state_key") + ? makeEvent(unknownEventTypeId(), json) + : nullptr; + }); bool StateEventBase::repeatsState() const { diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index d488c0a0..dc017b11 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -38,6 +38,9 @@ namespace QMatrixClient { using StateEventPtr = event_ptr_tt; using StateEvents = EventsArray; + template <> + inline bool is(const Event& e) { return e.isStateEvent(); } + /** * A combination of event type and state key uniquely identifies a piece * of state in Matrix. -- cgit v1.2.3 From 4c30996f28bfb6507eb5fb6f730a8769f8d964e3 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 10 Jan 2019 16:46:57 +0900 Subject: Security fix: require that state events have state_key This has been fixed in the past but got undone after the great remaking of the event types system. Further commits will introduce tests to make sure this does not get undone again. --- lib/events/stateevent.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'lib/events') diff --git a/lib/events/stateevent.cpp b/lib/events/stateevent.cpp index c4151676..e96614d2 100644 --- a/lib/events/stateevent.cpp +++ b/lib/events/stateevent.cpp @@ -25,13 +25,15 @@ using namespace QMatrixClient; // but the event type is unknown. [[gnu::unused]] static auto stateEventTypeInitialised = RoomEvent::factory_t::addMethod( - [] (const QJsonObject& json, const QString& matrixType) + [] (const QJsonObject& json, const QString& matrixType) -> StateEventPtr { + if (!json.contains("state_key")) + return nullptr; + if (auto e = StateEventBase::factory_t::make(json, matrixType)) return e; - return json.contains("state_key") - ? makeEvent(unknownEventTypeId(), json) - : nullptr; + + return makeEvent(unknownEventTypeId(), json); }); bool StateEventBase::repeatsState() const -- cgit v1.2.3 From 1e273212eca1dfa294d1a4bb9271261bf5671aa3 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 11 Feb 2019 08:05:31 +0900 Subject: SimpleContent: don't derive from Base as it gives zero added value Originally there was an idea to make a common base class for all event content. Aside from really trivial unification of toJson() this doesn't span across various types of events, and since state events use static, rather than dynamic, polymorphism (StateEvent<> is a template with the aggregated content vs. RoomMessageEvent with the aggregated pointer-to-content-base), there's no considerable value in using the base class. If state events start using the same approach as message events, this may be brought back but not until then. --- lib/events/simplestateevents.h | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'lib/events') diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h index 5aa24c15..2c23d9ca 100644 --- a/lib/events/simplestateevents.h +++ b/lib/events/simplestateevents.h @@ -19,7 +19,6 @@ #pragma once #include "stateevent.h" -#include "eventcontent.h" #include "converters.h" @@ -28,7 +27,7 @@ namespace QMatrixClient namespace EventContent { template - class SimpleContent: public Base + class SimpleContent { public: using value_type = T; @@ -39,23 +38,19 @@ namespace QMatrixClient : value(std::forward(value)), key(std::move(keyName)) { } SimpleContent(const QJsonObject& json, QString keyName) - : Base(json) - , value(QMatrixClient::fromJson(json[keyName])) + : value(fromJson(json[keyName])) , key(std::move(keyName)) { } + QJsonObject toJson() const + { + return { { key, QMatrixClient::toJson(value) } }; + } public: T value; protected: QString key; - - private: - void fillJson(QJsonObject* json) const override - { - Q_ASSERT(json); - json->insert(key, QMatrixClient::toJson(value)); - } }; } // namespace EventContent -- cgit v1.2.3 From 01230c16ef8b529ec07d429617247ee383e5c2bb Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 8 Feb 2019 07:18:36 +0900 Subject: RoomCreateEvent Closes #234. --- CMakeLists.txt | 1 + lib/events/roomcreateevent.cpp | 38 +++++++++++++++++++++++++++++++ lib/events/roomcreateevent.h | 51 ++++++++++++++++++++++++++++++++++++++++++ libqmatrixclient.pri | 2 ++ 4 files changed, 92 insertions(+) create mode 100644 lib/events/roomcreateevent.cpp create mode 100644 lib/events/roomcreateevent.h (limited to 'lib/events') diff --git a/CMakeLists.txt b/CMakeLists.txt index 9729811b..c7f1012a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,7 @@ set(libqmatrixclient_SRCS lib/events/roomevent.cpp lib/events/stateevent.cpp lib/events/eventcontent.cpp + lib/events/roomcreateevent.cpp lib/events/roommessageevent.cpp lib/events/roommemberevent.cpp lib/events/typingevent.cpp diff --git a/lib/events/roomcreateevent.cpp b/lib/events/roomcreateevent.cpp new file mode 100644 index 00000000..635efb92 --- /dev/null +++ b/lib/events/roomcreateevent.cpp @@ -0,0 +1,38 @@ +/****************************************************************************** +* Copyright (C) 2019 QMatrixClient project +* +* 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 "roomcreateevent.h" + +using namespace QMatrixClient; + +RoomCreateDetails::RoomCreateDetails(const QJsonObject& json) + : federated(fromJson(json["m.federate"_ls])) + , version(fromJson(json["room_version"_ls])) +{ + const auto predecessorJson = json["predecessor"_ls].toObject(); + if (!predecessorJson.isEmpty()) + { + fromJson(predecessorJson["room_id"_ls], predRoomId); + fromJson(predecessorJson["event_id"_ls], predEventId); + } +} + +std::pair RoomCreateEvent::predecessor() const +{ + return { content().predRoomId, content().predEventId }; +} diff --git a/lib/events/roomcreateevent.h b/lib/events/roomcreateevent.h new file mode 100644 index 00000000..d93668f9 --- /dev/null +++ b/lib/events/roomcreateevent.h @@ -0,0 +1,51 @@ +/****************************************************************************** +* Copyright (C) 2019 QMatrixClient project +* +* 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 "stateevent.h" + +namespace QMatrixClient +{ + class RoomCreateDetails + { + public: + explicit RoomCreateDetails(const QJsonObject& json); + + bool federated; + QString version; + QString predRoomId; + QString predEventId; + }; + + class RoomCreateEvent : public StateEvent + { + public: + DEFINE_EVENT_TYPEID("m.room.create", RoomCreateEvent) + + explicit RoomCreateEvent(const QJsonObject& obj) + : StateEvent(typeId(), obj) + { } + + bool isFederated() const { return content().federated; } + QString version() const { return content().version; } + std::pair predecessor() const; + bool isUpgrade() const { return !content().predRoomId.isEmpty(); } + }; + REGISTER_EVENT_TYPE(RoomCreateEvent) +} diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri index f523f3a2..598a86d6 100644 --- a/libqmatrixclient.pri +++ b/libqmatrixclient.pri @@ -26,6 +26,7 @@ HEADERS += \ $$SRCPATH/events/eventcontent.h \ $$SRCPATH/events/roommessageevent.h \ $$SRCPATH/events/simplestateevents.h \ + $$SRCPATH/events/roomcreateevent.h \ $$SRCPATH/events/roommemberevent.h \ $$SRCPATH/events/roomavatarevent.h \ $$SRCPATH/events/typingevent.h \ @@ -68,6 +69,7 @@ SOURCES += \ $$SRCPATH/events/roomevent.cpp \ $$SRCPATH/events/stateevent.cpp \ $$SRCPATH/events/eventcontent.cpp \ + $$SRCPATH/events/roomcreateevent.cpp \ $$SRCPATH/events/roommessageevent.cpp \ $$SRCPATH/events/roommemberevent.cpp \ $$SRCPATH/events/typingevent.cpp \ -- cgit v1.2.3 From a8adbc1d3c8ba787321ebd558062a9c12b12324a Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 15 Feb 2019 11:10:39 +0900 Subject: RoomTombstoneEvent --- CMakeLists.txt | 1 + lib/events/roomtombstoneevent.cpp | 31 +++++++++++++++++++++++++++++ lib/events/roomtombstoneevent.h | 41 +++++++++++++++++++++++++++++++++++++++ libqmatrixclient.pri | 2 ++ 4 files changed, 75 insertions(+) create mode 100644 lib/events/roomtombstoneevent.cpp create mode 100644 lib/events/roomtombstoneevent.h (limited to 'lib/events') diff --git a/CMakeLists.txt b/CMakeLists.txt index c7f1012a..d2d8c218 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,6 +91,7 @@ set(libqmatrixclient_SRCS lib/events/stateevent.cpp lib/events/eventcontent.cpp lib/events/roomcreateevent.cpp + lib/events/roomtombstoneevent.cpp lib/events/roommessageevent.cpp lib/events/roommemberevent.cpp lib/events/typingevent.cpp diff --git a/lib/events/roomtombstoneevent.cpp b/lib/events/roomtombstoneevent.cpp new file mode 100644 index 00000000..9c3bafd4 --- /dev/null +++ b/lib/events/roomtombstoneevent.cpp @@ -0,0 +1,31 @@ +/****************************************************************************** +* Copyright (C) 2019 QMatrixClient project +* +* 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 "roomtombstoneevent.h" + +using namespace QMatrixClient; + +QString RoomTombstoneEvent::serverMessage() const +{ + return fromJson(contentJson()["body"_ls]); +} + +QString RoomTombstoneEvent::successorRoomId() const +{ + return fromJson(contentJson()["replacement_room"_ls]); +} diff --git a/lib/events/roomtombstoneevent.h b/lib/events/roomtombstoneevent.h new file mode 100644 index 00000000..c7008ec4 --- /dev/null +++ b/lib/events/roomtombstoneevent.h @@ -0,0 +1,41 @@ +/****************************************************************************** +* Copyright (C) 2019 QMatrixClient project +* +* 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 "stateevent.h" + +namespace QMatrixClient +{ + class RoomTombstoneEvent : public StateEventBase + { + public: + DEFINE_EVENT_TYPEID("m.room.tombstone", RoomTombstoneEvent) + + explicit RoomTombstoneEvent() + : StateEventBase(typeId(), matrixTypeId()) + { } + explicit RoomTombstoneEvent(const QJsonObject& obj) + : StateEventBase(typeId(), obj) + { } + + QString serverMessage() const; + QString successorRoomId() const; + }; + REGISTER_EVENT_TYPE(RoomTombstoneEvent) +} diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri index 598a86d6..be568bd2 100644 --- a/libqmatrixclient.pri +++ b/libqmatrixclient.pri @@ -27,6 +27,7 @@ HEADERS += \ $$SRCPATH/events/roommessageevent.h \ $$SRCPATH/events/simplestateevents.h \ $$SRCPATH/events/roomcreateevent.h \ + $$SRCPATH/events/roomtombstoneevent.h \ $$SRCPATH/events/roommemberevent.h \ $$SRCPATH/events/roomavatarevent.h \ $$SRCPATH/events/typingevent.h \ @@ -70,6 +71,7 @@ SOURCES += \ $$SRCPATH/events/stateevent.cpp \ $$SRCPATH/events/eventcontent.cpp \ $$SRCPATH/events/roomcreateevent.cpp \ + $$SRCPATH/events/roomtombstoneevent.cpp \ $$SRCPATH/events/roommessageevent.cpp \ $$SRCPATH/events/roommemberevent.cpp \ $$SRCPATH/events/typingevent.cpp \ -- cgit v1.2.3 From 6af5e93134065cd97644d2eee43b2852df549553 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 15 Feb 2019 11:11:47 +0900 Subject: Simplify RoomCreateEvent --- lib/events/roomcreateevent.cpp | 29 ++++++++++++++++++----------- lib/events/roomcreateevent.h | 32 +++++++++++++++----------------- 2 files changed, 33 insertions(+), 28 deletions(-) (limited to 'lib/events') diff --git a/lib/events/roomcreateevent.cpp b/lib/events/roomcreateevent.cpp index 635efb92..8fd0f1de 100644 --- a/lib/events/roomcreateevent.cpp +++ b/lib/events/roomcreateevent.cpp @@ -20,19 +20,26 @@ using namespace QMatrixClient; -RoomCreateDetails::RoomCreateDetails(const QJsonObject& json) - : federated(fromJson(json["m.federate"_ls])) - , version(fromJson(json["room_version"_ls])) +bool RoomCreateEvent::isFederated() const { - const auto predecessorJson = json["predecessor"_ls].toObject(); - if (!predecessorJson.isEmpty()) - { - fromJson(predecessorJson["room_id"_ls], predRoomId); - fromJson(predecessorJson["event_id"_ls], predEventId); - } + return fromJson(contentJson()["m.federate"_ls]); } -std::pair RoomCreateEvent::predecessor() const +QString RoomCreateEvent::version() const { - return { content().predRoomId, content().predEventId }; + return fromJson(contentJson()["room_version"_ls]); +} + +RoomCreateEvent::Predecessor RoomCreateEvent::predecessor() const +{ + const auto predJson = contentJson()["predecessor"_ls].toObject(); + return { + fromJson(predJson["room_id"_ls]), + fromJson(predJson["event_id"_ls]) + }; +} + +bool RoomCreateEvent::isUpgrade() const +{ + return contentJson().contains("predecessor"_ls); } diff --git a/lib/events/roomcreateevent.h b/lib/events/roomcreateevent.h index d93668f9..0a8f27cc 100644 --- a/lib/events/roomcreateevent.h +++ b/lib/events/roomcreateevent.h @@ -22,30 +22,28 @@ namespace QMatrixClient { - class RoomCreateDetails - { - public: - explicit RoomCreateDetails(const QJsonObject& json); - - bool federated; - QString version; - QString predRoomId; - QString predEventId; - }; - - class RoomCreateEvent : public StateEvent + class RoomCreateEvent : public StateEventBase { public: DEFINE_EVENT_TYPEID("m.room.create", RoomCreateEvent) + explicit RoomCreateEvent() + : StateEventBase(typeId(), matrixTypeId()) + { } explicit RoomCreateEvent(const QJsonObject& obj) - : StateEvent(typeId(), obj) + : StateEventBase(typeId(), obj) { } - bool isFederated() const { return content().federated; } - QString version() const { return content().version; } - std::pair predecessor() const; - bool isUpgrade() const { return !content().predRoomId.isEmpty(); } + struct Predecessor + { + QString roomId; + QString eventId; + }; + + bool isFederated() const; + QString version() const; + Predecessor predecessor() const; + bool isUpgrade() const; }; REGISTER_EVENT_TYPE(RoomCreateEvent) } -- cgit v1.2.3 From 1a9fd422581cf14c384d2467950ab3f2e1039565 Mon Sep 17 00:00:00 2001 From: Alexey Andreyev Date: Sun, 24 Feb 2019 12:45:16 +0300 Subject: Fix Qt<5.7 build for std::hash --- lib/events/stateevent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/events') diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index dc017b11..3f54f7bf 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -46,7 +46,7 @@ namespace QMatrixClient { * of state in Matrix. * \sa https://matrix.org/docs/spec/client_server/unstable.html#types-of-room-events */ - using StateEventKey = std::pair; + using StateEventKey = QPair; template struct Prev -- cgit v1.2.3 From 2213080a13a4eb472c8ac2267efcebc6f0936eb1 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 25 Feb 2019 13:32:27 +0900 Subject: RoomMessageEvent: support m.in_reply_to (not spec-compliant yet); optimise away TextContent when not needed 1. The spec says "if you support rich replies you MUST support fallbacks" - this commit only adds dealing with event JSON but not with textual fallbacks. 2. TextContent is only created if there's something on top of plain body (an HTML body or a reply). --- lib/events/roommessageevent.cpp | 64 ++++++++++++++++++++++++++++++----------- lib/events/roommessageevent.h | 15 +++++++++- 2 files changed, 62 insertions(+), 17 deletions(-) (limited to 'lib/events') diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index c3007fa0..8f4e0ebc 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -30,12 +30,29 @@ using namespace EventContent; using MsgType = RoomMessageEvent::MsgType; +static const auto RelatesToKey = "m.relates_to"_ls; +static const auto MsgTypeKey = "msgtype"_ls; +static const auto BodyKey = "body"_ls; +static const auto FormattedBodyKey = "formatted_body"_ls; + +static const auto TextTypeKey = "m.text"; +static const auto NoticeTypeKey = "m.notice"; + +static const auto HtmlContentTypeId = QStringLiteral("org.matrix.custom.html"); + template TypedBase* make(const QJsonObject& json) { return new ContentT(json); } +template <> +TypedBase* make(const QJsonObject& json) +{ + return json.contains(FormattedBodyKey) || json.contains(RelatesToKey) + ? new TextContent(json) : nullptr; +} + struct MsgTypeDesc { QString matrixType; @@ -44,9 +61,9 @@ struct MsgTypeDesc }; const std::vector msgTypes = - { { QStringLiteral("m.text"), MsgType::Text, make } + { { TextTypeKey, MsgType::Text, make } , { QStringLiteral("m.emote"), MsgType::Emote, make } - , { QStringLiteral("m.notice"), MsgType::Notice, make } + , { NoticeTypeKey, MsgType::Notice, make } , { QStringLiteral("m.image"), MsgType::Image, make } , { QStringLiteral("m.file"), MsgType::File, make } , { QStringLiteral("m.location"), MsgType::Location, make } @@ -78,14 +95,18 @@ QJsonObject RoomMessageEvent::assembleContentJson(const QString& plainBody, const QString& jsonMsgType, TypedBase* content) { auto json = content ? content->toJson() : QJsonObject(); + if (jsonMsgType != TextTypeKey && jsonMsgType != NoticeTypeKey && + json.contains(RelatesToKey)) + { + json.remove(RelatesToKey); + qCWarning(EVENTS) << RelatesToKey << "cannot be used in" << jsonMsgType + << "messages; the relation has been stripped off"; + } json.insert(QStringLiteral("msgtype"), jsonMsgType); json.insert(QStringLiteral("body"), plainBody); return json; } -static const auto MsgTypeKey = "msgtype"_ls; -static const auto BodyKey = "body"_ls; - RoomMessageEvent::RoomMessageEvent(const QString& plainBody, const QString& jsonMsgType, TypedBase* content) : RoomEvent(typeId(), matrixTypeId(), @@ -141,13 +162,17 @@ RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) if ( content.contains(MsgTypeKey) && content.contains(BodyKey) ) { auto msgtype = content[MsgTypeKey].toString(); + bool msgTypeFound = false; for (const auto& mt: msgTypes) if (mt.matrixType == msgtype) + { _content.reset(mt.maker(content)); + msgTypeFound = true; + } - if (!_content) + if (!msgTypeFound) { - qCWarning(EVENTS) << "RoomMessageEvent: couldn't load content," + qCWarning(EVENTS) << "RoomMessageEvent: unknown msg_type," << " full content dump follows"; qCWarning(EVENTS) << formatJson << content; } @@ -179,14 +204,13 @@ QMimeType RoomMessageEvent::mimeType() const static const auto PlainTextMimeType = QMimeDatabase().mimeTypeForName("text/plain"); return _content ? _content->type() : PlainTextMimeType; - ; } bool RoomMessageEvent::hasTextContent() const { - return content() && + return !content() || (msgtype() == MsgType::Text || msgtype() == MsgType::Emote || - msgtype() == MsgType::Notice); // FIXME: Unbind from specific msgtypes + msgtype() == MsgType::Notice); } bool RoomMessageEvent::hasFileContent() const @@ -218,10 +242,12 @@ QString RoomMessageEvent::rawMsgTypeForFile(const QFileInfo& fi) return rawMsgTypeForMimeType(QMimeDatabase().mimeTypeForFile(fi)); } -TextContent::TextContent(const QString& text, const QString& contentType) +TextContent::TextContent(const QString& text, const QString& contentType, + Omittable relatesTo) : mimeType(QMimeDatabase().mimeTypeForName(contentType)), body(text) + , relatesTo(std::move(relatesTo)) { - if (contentType == "org.matrix.custom.html") + if (contentType == HtmlContentTypeId) mimeType = QMimeDatabase().mimeTypeForName("text/html"); } @@ -233,16 +259,20 @@ TextContent::TextContent(const QJsonObject& json) // Special-casing the custom matrix.org's (actually, Riot's) way // of sending HTML messages. - if (json["format"_ls].toString() == "org.matrix.custom.html") + if (json["format"_ls].toString() == HtmlContentTypeId) { mimeType = HtmlMimeType; - body = json["formatted_body"_ls].toString(); + body = json[FormattedBodyKey].toString(); } else { // Falling back to plain text, as there's no standard way to describe // rich text in messages. mimeType = PlainTextMimeType; body = json[BodyKey].toString(); } + const auto replyJson = json[RelatesToKey].toObject() + .value(RelatesTo::ReplyTypeId()).toObject(); + if (!replyJson.isEmpty()) + relatesTo = replyTo(fromJson(replyJson[EventIdKeyL])); } void TextContent::fillJson(QJsonObject* json) const @@ -250,10 +280,12 @@ void TextContent::fillJson(QJsonObject* json) const Q_ASSERT(json); if (mimeType.inherits("text/html")) { - json->insert(QStringLiteral("format"), - QStringLiteral("org.matrix.custom.html")); + json->insert(QStringLiteral("format"), HtmlContentTypeId); json->insert(QStringLiteral("formatted_body"), body); } + if (!relatesTo.omitted()) + json->insert(QStringLiteral("m.relates_to"), + QJsonObject { { relatesTo->type, relatesTo->eventId } }); } LocationContent::LocationContent(const QString& geoUri, diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index d5b570f5..c2e075eb 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -92,6 +92,17 @@ namespace QMatrixClient { // Additional event content types + struct RelatesTo + { + static constexpr const char* ReplyTypeId() { return "m.in_reply_to"; } + QString type; // The only supported relation so far + QString eventId; + }; + inline RelatesTo replyTo(QString eventId) + { + return { RelatesTo::ReplyTypeId(), std::move(eventId) }; + } + /** * Rich text content for m.text, m.emote, m.notice * @@ -101,13 +112,15 @@ namespace QMatrixClient class TextContent: public TypedBase { public: - TextContent(const QString& text, const QString& contentType); + TextContent(const QString& text, const QString& contentType, + Omittable relatesTo = none); explicit TextContent(const QJsonObject& json); QMimeType type() const override { return mimeType; } QMimeType mimeType; QString body; + Omittable relatesTo; protected: void fillJson(QJsonObject* json) const override; -- cgit v1.2.3 From 6577320f8653fbd99a100a844d7b42a46da5f45a Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 17 Mar 2019 09:03:34 +0900 Subject: RoomMemberEvent: sanitize user display names MemberEventContent::displayName() will strip away Unicode text direction override characters. Direct access to JSON can still provide "raw" data. --- lib/events/roommemberevent.cpp | 2 +- lib/util.cpp | 10 +++++++++- lib/util.h | 7 ++++++- 3 files changed, 16 insertions(+), 3 deletions(-) (limited to 'lib/events') diff --git a/lib/events/roommemberevent.cpp b/lib/events/roommemberevent.cpp index a5ac3c5f..6da76526 100644 --- a/lib/events/roommemberevent.cpp +++ b/lib/events/roommemberevent.cpp @@ -52,7 +52,7 @@ using namespace QMatrixClient; MemberEventContent::MemberEventContent(const QJsonObject& json) : membership(fromJson(json["membership"_ls])) , isDirect(json["is_direct"_ls].toBool()) - , displayName(json["displayname"_ls].toString()) + , displayName(sanitized(json["displayname"_ls].toString())) , avatarUrl(json["avatar_url"_ls].toString()) { } diff --git a/lib/util.cpp b/lib/util.cpp index d042aa34..2744d45f 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -63,10 +63,18 @@ static void linkifyUrls(QString& htmlEscapedText) QStringLiteral(R"(\1\2)")); } +QString QMatrixClient::sanitized(const QString& plainText) +{ + auto text = plainText; + text.remove(QChar(0x202e)); + text.remove(QChar(0x202d)); + return text.toHtmlEscaped(); +} + QString QMatrixClient::prettyPrint(const QString& plainText) { auto pt = QStringLiteral("") + - plainText.toHtmlEscaped() + QStringLiteral(""); + sanitized(plainText).toHtmlEscaped() + QStringLiteral(""); pt.replace('\n', QStringLiteral("
")); linkifyUrls(pt); diff --git a/lib/util.h b/lib/util.h index f7f646da..beb3c697 100644 --- a/lib/util.h +++ b/lib/util.h @@ -296,7 +296,12 @@ namespace QMatrixClient return std::make_pair(last, sLast); } - /** Pretty-prints plain text into HTML + /** Sanitize the text before showing in HTML + * This does toHtmlEscaped() and removes Unicode BiDi marks. + */ + QString sanitized(const QString& plainText); + + /** Pretty-print plain text into HTML * This includes HTML escaping of <,>,",& and URLs linkification. */ QString prettyPrint(const QString& plainText); -- cgit v1.2.3 From 23352250c9b9f9fa7d1d46294f8c1a7de1e19f61 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 23 Mar 2019 20:43:02 +0900 Subject: Room::downloadFile(): Tighten URL validations Check the URL before passing over to Connection::downloadFile(), not only the file name. --- lib/events/eventcontent.cpp | 6 ++++++ lib/events/eventcontent.h | 2 ++ lib/room.cpp | 9 ++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'lib/events') diff --git a/lib/events/eventcontent.cpp b/lib/events/eventcontent.cpp index 9a5e872c..77f756cd 100644 --- a/lib/events/eventcontent.cpp +++ b/lib/events/eventcontent.cpp @@ -50,6 +50,12 @@ FileInfo::FileInfo(const QUrl& u, const QJsonObject& infoJson, mimeType = QMimeDatabase().mimeTypeForData(QByteArray()); } +bool FileInfo::isValid() const +{ + return url.scheme() == "mxc" + && (url.authority() + url.path()).count('/') == 1; +} + void FileInfo::fillInfoJson(QJsonObject* infoJson) const { Q_ASSERT(infoJson); diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index 0588c0e2..ab31a75d 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -94,6 +94,8 @@ namespace QMatrixClient FileInfo(const QUrl& u, const QJsonObject& infoJson, const QString& originalFilename = {}); + bool isValid() const; + void fillInfoJson(QJsonObject* infoJson) const; /** diff --git a/lib/room.cpp b/lib/room.cpp index dbddad05..411a17d6 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1785,7 +1785,14 @@ void Room::downloadFile(const QString& eventId, const QUrl& localFilename) Q_ASSERT(false); return; } - const auto fileUrl = event->content()->fileInfo()->url; + const auto* const fileInfo = event->content()->fileInfo(); + if (!fileInfo->isValid()) + { + qCWarning(MAIN) << "Event" << eventId + << "has an empty or malformed mxc URL; won't download"; + return; + } + const auto fileUrl = fileInfo->url; auto filePath = localFilename.toLocalFile(); if (filePath.isEmpty()) { -- cgit v1.2.3 From 1c5696e8f5a9ef87a065e2496eecf178e41e75a7 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 4 Apr 2019 21:27:38 +0900 Subject: Clean up on clang-tidy/clazy analysis --- lib/avatar.cpp | 2 +- lib/connection.cpp | 25 +++++++++++++++---------- lib/connectiondata.cpp | 6 +++--- lib/events/event.cpp | 3 ++- lib/events/stateevent.cpp | 2 +- lib/jobs/basejob.cpp | 2 +- lib/jobs/downloadfilejob.cpp | 5 +++-- lib/jobs/mediathumbnailjob.cpp | 2 +- lib/networkaccessmanager.cpp | 3 ++- lib/networksettings.cpp | 2 +- lib/room.cpp | 32 ++++++++++++++++---------------- lib/settings.cpp | 21 ++++++++++++--------- lib/settings.h | 2 +- lib/syncdata.cpp | 8 ++++---- lib/user.cpp | 14 ++++++++------ lib/util.cpp | 2 +- 16 files changed, 72 insertions(+), 59 deletions(-) (limited to 'lib/events') diff --git a/lib/avatar.cpp b/lib/avatar.cpp index c0ef3cba..9279ef9d 100644 --- a/lib/avatar.cpp +++ b/lib/avatar.cpp @@ -191,7 +191,7 @@ bool Avatar::Private::checkUrl(const QUrl& url) const } QString Avatar::Private::localFile() const { - static const auto cachePath = cacheLocation("avatars"); + static const auto cachePath = cacheLocation(QStringLiteral("avatars")); return cachePath % _url.authority() % '_' % _url.fileName() % ".png"; } diff --git a/lib/connection.cpp b/lib/connection.cpp index c09de979..5ed72616 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -717,8 +717,8 @@ void Connection::doInDirectChat(User* u, CreateRoomJob* Connection::createDirectChat(const QString& userId, const QString& topic, const QString& name) { - return createRoom(UnpublishRoom, "", name, topic, {userId}, - "trusted_private_chat", {}, true); + return createRoom(UnpublishRoom, {}, name, topic, {userId}, + QStringLiteral("trusted_private_chat"), {}, true); } ForgetRoomJob* Connection::forgetRoom(const QString& id) @@ -964,7 +964,8 @@ QHash> Connection::tagsToRooms() const QHash> result; for (auto* r: qAsConst(d->roomMap)) { - for (const auto& tagName: r->tagNames()) + const auto& tagNames = r->tagNames(); + for (const auto& tagName: tagNames) result[tagName].push_back(r); } for (auto it = result.begin(); it != result.end(); ++it) @@ -979,9 +980,12 @@ QStringList Connection::tagNames() const { QStringList tags ({FavouriteTag}); for (auto* r: qAsConst(d->roomMap)) - for (const auto& tag: r->tagNames()) + { + const auto& tagNames = r->tagNames(); + for (const auto& tag: tagNames) if (tag != LowPriorityTag && !tags.contains(tag)) tags.push_back(tag); + } tags.push_back(LowPriorityTag); return tags; } @@ -1264,18 +1268,19 @@ void Connection::saveState() const { QJsonObject rooms; QJsonObject inviteRooms; - for (const auto* i : roomMap()) // Pass on rooms in Leave state + const auto& rs = roomMap(); // Pass on rooms in Leave state + for (const auto* i : rs) (i->joinState() == JoinState::Invite ? inviteRooms : rooms) .insert(i->id(), QJsonValue::Null); QJsonObject roomObj; if (!rooms.isEmpty()) - roomObj.insert("join", rooms); + roomObj.insert(QStringLiteral("join"), rooms); if (!inviteRooms.isEmpty()) - roomObj.insert("invite", inviteRooms); + roomObj.insert(QStringLiteral("invite"), inviteRooms); - rootObj.insert("next_batch", d->data->lastEvent()); - rootObj.insert("rooms", roomObj); + rootObj.insert(QStringLiteral("next_batch"), d->data->lastEvent()); + rootObj.insert(QStringLiteral("rooms"), roomObj); } { QJsonArray accountDataEvents { @@ -1285,7 +1290,7 @@ void Connection::saveState() const accountDataEvents.append( basicEventJson(e.first, e.second->contentJson())); - rootObj.insert("account_data", + rootObj.insert(QStringLiteral("account_data"), QJsonObject {{ QStringLiteral("events"), accountDataEvents }}); } diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index eb516ef7..91cda09f 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -25,7 +25,7 @@ using namespace QMatrixClient; struct ConnectionData::Private { - explicit Private(const QUrl& url) : baseUrl(url) { } + explicit Private(QUrl url) : baseUrl(std::move(url)) { } QUrl baseUrl; QByteArray accessToken; @@ -37,7 +37,7 @@ struct ConnectionData::Private }; ConnectionData::ConnectionData(QUrl baseUrl) - : d(std::make_unique(baseUrl)) + : d(std::make_unique(std::move(baseUrl))) { } ConnectionData::~ConnectionData() = default; @@ -98,7 +98,7 @@ QString ConnectionData::lastEvent() const void ConnectionData::setLastEvent(QString identifier) { - d->lastEvent = identifier; + d->lastEvent = std::move(identifier); } QByteArray ConnectionData::generateTxnId() const diff --git a/lib/events/event.cpp b/lib/events/event.cpp index c98dfbb6..6505d89a 100644 --- a/lib/events/event.cpp +++ b/lib/events/event.cpp @@ -38,7 +38,8 @@ event_type_t EventTypeRegistry::initializeTypeId(event_mtype_t matrixTypeId) QString EventTypeRegistry::getMatrixType(event_type_t typeId) { - return typeId < get().eventTypes.size() ? get().eventTypes[typeId] : ""; + return typeId < get().eventTypes.size() + ? get().eventTypes[typeId] : QString(); } Event::Event(Type type, const QJsonObject& json) diff --git a/lib/events/stateevent.cpp b/lib/events/stateevent.cpp index e96614d2..a84f302b 100644 --- a/lib/events/stateevent.cpp +++ b/lib/events/stateevent.cpp @@ -27,7 +27,7 @@ using namespace QMatrixClient; RoomEvent::factory_t::addMethod( [] (const QJsonObject& json, const QString& matrixType) -> StateEventPtr { - if (!json.contains("state_key")) + if (!json.contains("state_key"_ls)) return nullptr; if (auto e = StateEventBase::factory_t::make(json, matrixType)) diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index f738ce7a..f521cc4b 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -430,7 +430,7 @@ BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const BaseJob::Status BaseJob::parseReply(QNetworkReply* reply) { d->rawResponse = reply->readAll(); - QJsonParseError error; + QJsonParseError error { 0, QJsonParseError::MissingObject }; const auto& json = QJsonDocument::fromJson(d->rawResponse, &error); if( error.error == QJsonParseError::NoError ) return parseJson(json); diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp index 2bf9dd8f..672a7b2d 100644 --- a/lib/jobs/downloadfilejob.cpp +++ b/lib/jobs/downloadfilejob.cpp @@ -22,7 +22,8 @@ class DownloadFileJob::Private QUrl DownloadFileJob::makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri) { - return makeRequestUrl(baseUrl, mxcUri.authority(), mxcUri.path().mid(1)); + return makeRequestUrl( + std::move(baseUrl), mxcUri.authority(), mxcUri.path().mid(1)); } DownloadFileJob::DownloadFileJob(const QString& serverName, @@ -31,7 +32,7 @@ DownloadFileJob::DownloadFileJob(const QString& serverName, : GetContentJob(serverName, mediaId) , d(localFilename.isEmpty() ? new Private : new Private(localFilename)) { - setObjectName("DownloadFileJob"); + setObjectName(QStringLiteral("DownloadFileJob")); } QString DownloadFileJob::targetFileName() const diff --git a/lib/jobs/mediathumbnailjob.cpp b/lib/jobs/mediathumbnailjob.cpp index aeb49839..edb9b156 100644 --- a/lib/jobs/mediathumbnailjob.cpp +++ b/lib/jobs/mediathumbnailjob.cpp @@ -59,5 +59,5 @@ BaseJob::Status MediaThumbnailJob::parseReply(QNetworkReply* reply) if( _thumbnail.loadFromData(data()->readAll()) ) return Success; - return { IncorrectResponseError, "Could not read image data" }; + return { IncorrectResponseError, QStringLiteral("Could not read image data") }; } diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index 89967a8a..7d9cb360 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -29,7 +29,8 @@ class NetworkAccessManager::Private QList ignoredSslErrors; }; -NetworkAccessManager::NetworkAccessManager(QObject* parent) : d(std::make_unique()) +NetworkAccessManager::NetworkAccessManager(QObject* parent) + : QNetworkAccessManager(parent), d(std::make_unique()) { } QList NetworkAccessManager::ignoredSslErrors() const diff --git a/lib/networksettings.cpp b/lib/networksettings.cpp index 48bd09f3..6ff2bc1f 100644 --- a/lib/networksettings.cpp +++ b/lib/networksettings.cpp @@ -27,5 +27,5 @@ void NetworkSettings::setupApplicationProxy() const } QMC_DEFINE_SETTING(NetworkSettings, QNetworkProxy::ProxyType, proxyType, "proxy_type", QNetworkProxy::DefaultProxy, setProxyType) -QMC_DEFINE_SETTING(NetworkSettings, QString, proxyHostName, "proxy_hostname", "", setProxyHostName) +QMC_DEFINE_SETTING(NetworkSettings, QString, proxyHostName, "proxy_hostname", {}, setProxyHostName) QMC_DEFINE_SETTING(NetworkSettings, quint16, proxyPort, "proxy_port", -1, setProxyPort) diff --git a/lib/room.cpp b/lib/room.cpp index 1a63866f..caeeb499 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -168,7 +168,7 @@ class Room::Private //void inviteUser(User* u); // We might get it at some point in time. void insertMemberIntoMap(User* u); - void renameMember(User* u, QString oldName); + void renameMember(User* u, const QString& oldName); void removeMemberFromMap(const QString& username, User* u); // This updates the room displayname field (which is the way a room @@ -185,7 +185,7 @@ class Room::Private void getPreviousContent(int limit = 10); template - const EventT* getCurrentState(QString stateKey = {}) const + const EventT* getCurrentState(const QString& stateKey = {}) const { static const EventT empty; const auto* evt = @@ -236,8 +236,8 @@ class Room::Private * @param placement - position and direction of insertion: Older for * historical messages, Newer for new ones */ - Timeline::difference_type moveEventsToTimeline(RoomEventsRange events, - EventsPlacement placement); + Timeline::size_type moveEventsToTimeline(RoomEventsRange events, + EventsPlacement placement); /** * Remove events from the passed container that are already in the timeline @@ -341,7 +341,7 @@ const QString& Room::id() const QString Room::version() const { const auto v = d->getCurrentState()->version(); - return v.isEmpty() ? "1" : v; + return v.isEmpty() ? QStringLiteral("1") : v; } bool Room::isUnstable() const @@ -546,8 +546,8 @@ Room::Changes Room::Private::promoteReadMarker(User* u, rev_iter_t newMarker, { const auto oldUnreadCount = unreadMessages; QElapsedTimer et; et.start(); - unreadMessages = count_if(eagerMarker, timeline.cend(), - std::bind(&Room::Private::isEventNotable, this, _1)); + unreadMessages = int(count_if(eagerMarker, timeline.cend(), + std::bind(&Room::Private::isEventNotable, this, _1))); if (et.nsecsElapsed() > profilerMinNsecs() / 10) qCDebug(PROFILER) << "Recounting unread messages took" << et; @@ -611,7 +611,7 @@ bool Room::canSwitchVersions() const // TODO, #276: m.room.power_levels const auto* plEvt = - d->currentState.value({"m.room.power_levels", ""}); + d->currentState.value({QStringLiteral("m.room.power_levels"), {}}); if (!plEvt) return true; @@ -621,7 +621,7 @@ bool Room::canSwitchVersions() const .value(localUser()->id()).toInt( plJson.value("users_default"_ls).toInt()); const auto tombstonePowerLevel = - plJson.value("events").toObject() + plJson.value("events"_ls).toObject() .value("m.room.tombstone"_ls).toInt( plJson.value("state_default"_ls).toInt()); return currentUserLevel >= tombstonePowerLevel; @@ -947,7 +947,7 @@ void Room::Private::setTags(TagsMap newTags) } tags = move(newTags); qCDebug(MAIN) << "Room" << q->objectName() << "is tagged with" - << q->tagNames().join(", "); + << q->tagNames().join(QStringLiteral(", ")); emit q->tagsChanged(); } @@ -1196,7 +1196,7 @@ void Room::Private::insertMemberIntoMap(User *u) emit q->memberRenamed(namesakes.front()); } -void Room::Private::renameMember(User* u, QString oldName) +void Room::Private::renameMember(User* u, const QString& oldName) { if (u->name(q) == oldName) { @@ -1234,7 +1234,7 @@ inline auto makeErrorStr(const Event& e, QByteArray msg) return msg.append("; event dump follows:\n").append(e.originalJson()); } -Room::Timeline::difference_type Room::Private::moveEventsToTimeline( +Room::Timeline::size_type Room::Private::moveEventsToTimeline( RoomEventsRange events, EventsPlacement placement) { Q_ASSERT(!events.empty()); @@ -1407,7 +1407,7 @@ QString Room::Private::doSendEvent(const RoomEvent* pEvent) return; } it->setDeparted(); - emit q->pendingEventChanged(it - unsyncedEvents.begin()); + emit q->pendingEventChanged(int(it - unsyncedEvents.begin())); }); Room::connect(call, &BaseJob::failure, q, std::bind(&Room::Private::onEventSendingFailure, this, txnId, call)); @@ -1423,7 +1423,7 @@ QString Room::Private::doSendEvent(const RoomEvent* pEvent) } it->setReachedServer(call->eventId()); - emit q->pendingEventChanged(it - unsyncedEvents.begin()); + emit q->pendingEventChanged(int(it - unsyncedEvents.begin())); }); } else onEventSendingFailure(txnId); @@ -1442,7 +1442,7 @@ void Room::Private::onEventSendingFailure(const QString& txnId, BaseJob* call) it->setSendingFailed(call ? call->statusCaption() % ": " % call->errorString() : tr("The call could not be started")); - emit q->pendingEventChanged(it - unsyncedEvents.begin()); + emit q->pendingEventChanged(int(it - unsyncedEvents.begin())); } QString Room::retryMessage(const QString& txnId) @@ -2045,7 +2045,7 @@ Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events) roomChanges |= q->processStateEvent(*eptr); auto timelineSize = timeline.size(); - auto totalInserted = 0; + size_t totalInserted = 0; for (auto it = events.begin(); it != events.end();) { auto nextPendingPair = findFirstOf(it, events.end(), diff --git a/lib/settings.cpp b/lib/settings.cpp index 852e19cb..124d7042 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -84,18 +84,21 @@ void SettingsGroup::remove(const QString& key) Settings::remove(fullKey); } -QMC_DEFINE_SETTING(AccountSettings, QString, deviceId, "device_id", "", setDeviceId) -QMC_DEFINE_SETTING(AccountSettings, QString, deviceName, "device_name", "", setDeviceName) +QMC_DEFINE_SETTING(AccountSettings, QString, deviceId, "device_id", {}, setDeviceId) +QMC_DEFINE_SETTING(AccountSettings, QString, deviceName, "device_name", {}, setDeviceName) QMC_DEFINE_SETTING(AccountSettings, bool, keepLoggedIn, "keep_logged_in", false, setKeepLoggedIn) +static const auto HomeserverKey = QStringLiteral("homeserver"); +static const auto AccessTokenKey = QStringLiteral("access_token"); + QUrl AccountSettings::homeserver() const { - return QUrl::fromUserInput(value("homeserver").toString()); + return QUrl::fromUserInput(value(HomeserverKey).toString()); } void AccountSettings::setHomeserver(const QUrl& url) { - setValue("homeserver", url.toString()); + setValue(HomeserverKey, url.toString()); } QString AccountSettings::userId() const @@ -105,19 +108,19 @@ QString AccountSettings::userId() const QString AccountSettings::accessToken() const { - return value("access_token").toString(); + return value(AccessTokenKey).toString(); } void AccountSettings::setAccessToken(const QString& accessToken) { qCWarning(MAIN) << "Saving access_token to QSettings is insecure." " Developers, please save access_token separately."; - setValue("access_token", accessToken); + setValue(AccessTokenKey, accessToken); } void AccountSettings::clearAccessToken() { - legacySettings.remove("access_token"); - legacySettings.remove("device_id"); // Force the server to re-issue it - remove("access_token"); + legacySettings.remove(AccessTokenKey); + legacySettings.remove(QStringLiteral("device_id")); // Force the server to re-issue it + remove(AccessTokenKey); } diff --git a/lib/settings.h b/lib/settings.h index 0b3ecaff..759bda35 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -119,7 +119,7 @@ type classname::propname() const \ \ void classname::setter(type newValue) \ { \ - setValue(QStringLiteral(qsettingname), newValue); \ + setValue(QStringLiteral(qsettingname), std::move(newValue)); \ } \ class AccountSettings: public SettingsGroup diff --git a/lib/syncdata.cpp b/lib/syncdata.cpp index f55d4396..21517884 100644 --- a/lib/syncdata.cpp +++ b/lib/syncdata.cpp @@ -72,7 +72,7 @@ void JsonObjectConverter::fillFrom(const QJsonObject& jo, { fromJson(jo["m.joined_member_count"_ls], rs.joinedMemberCount); fromJson(jo["m.invited_member_count"_ls], rs.invitedMemberCount); - fromJson(jo["m.heroes"], rs.heroes); + fromJson(jo["m.heroes"_ls], rs.heroes); } template @@ -85,7 +85,7 @@ SyncRoomData::SyncRoomData(const QString& roomId_, JoinState joinState_, const QJsonObject& room_) : roomId(roomId_) , joinState(joinState_) - , summary(fromJson(room_["summary"])) + , summary(fromJson(room_["summary"_ls])) , state(load(room_, joinState == JoinState::Invite ? "invite_state"_ls : "state"_ls)) { @@ -121,8 +121,8 @@ SyncData::SyncData(const QString& cacheFileName) QFileInfo cacheFileInfo { cacheFileName }; auto json = loadJson(cacheFileName); auto requiredVersion = std::get<0>(cacheVersion()); - auto actualVersion = json.value("cache_version").toObject() - .value("major").toInt(); + auto actualVersion = json.value("cache_version"_ls).toObject() + .value("major"_ls).toInt(); if (actualVersion == requiredVersion) parseJson(json, cacheFileInfo.absolutePath() + '/'); else diff --git a/lib/user.cpp b/lib/user.cpp index 951ad87d..17db5760 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -59,7 +59,7 @@ class User::Private QMultiHash otherNames; Avatar mostUsedAvatar { makeAvatar({}) }; std::vector otherAvatars; - auto otherAvatar(QUrl url) + auto otherAvatar(const QUrl& url) { return std::find_if(otherAvatars.begin(), otherAvatars.end(), [&url] (const auto& av) { return av.url() == url; }); @@ -69,7 +69,7 @@ class User::Private mutable int totalRooms = 0; QString nameForRoom(const Room* r, const QString& hint = {}) const; - void setNameForRoom(const Room* r, QString newName, QString oldName); + void setNameForRoom(const Room* r, QString newName, const QString& oldName); QUrl avatarUrlForRoom(const Room* r, const QUrl& hint = {}) const; void setAvatarForRoom(const Room* r, const QUrl& newUrl, const QUrl& oldUrl); @@ -91,7 +91,7 @@ QString User::Private::nameForRoom(const Room* r, const QString& hint) const static constexpr int MIN_JOINED_ROOMS_TO_LOG = 20; void User::Private::setNameForRoom(const Room* r, QString newName, - QString oldName) + const QString& oldName) { Q_ASSERT(oldName != newName); Q_ASSERT(oldName == mostUsedName || otherNames.contains(oldName, r)); @@ -118,7 +118,8 @@ void User::Private::setNameForRoom(const Room* r, QString newName, et.start(); } - for (auto* r1: connection->roomMap()) + const auto& roomMap = connection->roomMap(); + for (auto* r1: roomMap) if (nameForRoom(r1) == mostUsedName) otherNames.insert(mostUsedName, r1); @@ -178,7 +179,8 @@ void User::Private::setAvatarForRoom(const Room* r, const QUrl& newUrl, auto nextMostUsedIt = otherAvatar(newUrl); Q_ASSERT(nextMostUsedIt != otherAvatars.end()); std::swap(mostUsedAvatar, *nextMostUsedIt); - for (const auto* r1: connection->roomMap()) + const auto& roomMap = connection->roomMap(); + for (const auto* r1: roomMap) if (avatarUrlForRoom(r1) == nextMostUsedIt->url()) avatarsToRooms.insert(nextMostUsedIt->url(), r1); @@ -399,7 +401,7 @@ void User::processEvent(const RoomMemberEvent& event, const Room* room, // exceptionally rare (the only reasonable case being that the bridge // changes the naming convention). For the same reason room-specific // bridge tags are not supported at all. - QRegularExpression reSuffix(" \\((IRC|Gitter|Telegram)\\)$"); + QRegularExpression reSuffix(QStringLiteral(" \\((IRC|Gitter|Telegram)\\)$")); auto match = reSuffix.match(newName); if (match.hasMatch()) { diff --git a/lib/util.cpp b/lib/util.cpp index 8d16cfc8..17674b84 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -156,7 +156,7 @@ static_assert(!is_callable_v>, "Test non-function object"); // "Test returns<> with static member function"); template -QString ft(T&&); +QString ft(T&&) { return {}; } static_assert(std::is_same)>, QString&&>(), "Test function templates"); -- cgit v1.2.3 From e3d2edbea279da8c3ed19b9faa77a287b6a65faf Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 18 May 2019 21:48:04 +0900 Subject: event.h: add doc-comments; deprecate ptrCast() --- lib/events/event.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/events') diff --git a/lib/events/event.h b/lib/events/event.h index d7ac4292..b7bbd83e 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -32,19 +32,23 @@ namespace QMatrixClient template using event_ptr_tt = std::unique_ptr; + /// Unwrap a plain pointer from a smart pointer template - inline EventT* rawPtr(const event_ptr_tt& ptr) // unwrap + inline EventT* rawPtr(const event_ptr_tt& ptr) { return ptr.get(); } + /// Unwrap a plain pointer and downcast it to the specified type template inline TargetEventT* weakPtrCast(const event_ptr_tt& ptr) { return static_cast(rawPtr(ptr)); } + /// Re-wrap a smart pointer to base into a smart pointer to derived template + [[deprecated("Consider using eventCast() or visit() instead")]] inline event_ptr_tt ptrCast(event_ptr_tt&& ptr) { return unique_ptr_cast(ptr); -- cgit v1.2.3