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/events/accountdataevents.h | 35 ++++++++++++++++++----------------- lib/events/eventloader.h | 10 +++++++--- lib/events/roommemberevent.cpp | 12 +++++------- 3 files changed, 30 insertions(+), 27 deletions(-) (limited to 'lib/events') 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()) -- 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