From bb26ca86ad350f2562b51284e7c631b1e4f77106 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 18 May 2017 03:37:06 +0900 Subject: util.h: lookup() uses forwarding refs; added Dispatch/dispatch and REGISTER_ENUM The Dispatch<> template and dispatch(), a facility function for it, simplify dispatching to functions that have different signatures that still can be converted to the same std::function<> type. The case in point is in event.cpp; Event::fromJson calls make() that always returns the type we need; however, once we have several possible base types (Event, RoomEvent, StateEvent), we'd have to either write a specific make() incarnation for each of them, or mess with function return type conversions. Dispatch<> helps to keep the code clean. REGISTER_ENUM is a cross-Qt versions approach to dumping enumeration values to qDebug() and the likes. --- events/event.cpp | 27 +++++++++++++-------------- events/roommessageevent.cpp | 20 ++++++++++---------- 2 files changed, 23 insertions(+), 24 deletions(-) (limited to 'events') diff --git a/events/event.cpp b/events/event.cpp index 07649b02..5df816fe 100644 --- a/events/event.cpp +++ b/events/event.cpp @@ -87,27 +87,26 @@ QString Event::originalJson() const return d->originalJson; } -template -Event* make(const QJsonObject& obj) +template +EventT* make(const QJsonObject& obj) { - return T::fromJson(obj); + return EventT::fromJson(obj); } Event* Event::fromJson(const QJsonObject& obj) { - auto delegate = lookup(obj.value("type").toString(), - "m.room.message", make, - "m.room.name", make, - "m.room.aliases", make, - "m.room.canonical_alias", make, - "m.room.member", make, - "m.room.topic", make, - "m.typing", make, - "m.receipt", make, + return dispatch(obj).to(obj["type"].toString(), + "m.room.message", &make, + "m.room.name", &make, + "m.room.aliases", &make, + "m.room.canonical_alias", &make, + "m.room.member", &make, + "m.room.topic", &make, + "m.typing", &make, + "m.receipt", &make, /* Insert new event types BEFORE this line */ - make + &make ); - return delegate(obj); } bool Event::parseJson(const QJsonObject& obj) diff --git a/events/roommessageevent.cpp b/events/roommessageevent.cpp index 677bb79f..d5e960a1 100644 --- a/events/roommessageevent.cpp +++ b/events/roommessageevent.cpp @@ -120,17 +120,17 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) { e->d->plainBody = content["body"].toString(); - auto delegate = lookup(content.value("msgtype").toString(), - "m.text", make, - "m.emote", make, - "m.notice", make, - "m.image", make, - "m.file", make, - "m.location", make, - "m.video", makeVideo, - "m.audio", make, + auto delegate = lookup(content["msgtype"].toString(), + "m.text", &make, + "m.emote", &make, + "m.notice", &make, + "m.image", &make, + "m.file", &make, + "m.location", &make, + "m.video", &makeVideo, + "m.audio", &make, // Insert new message types before this line - makeUnknown + &makeUnknown ); std::tie(e->d->msgtype, e->d->content) = delegate(content); } -- cgit v1.2.3 From be838b2f4f294a7e1b3f8a771f91d9d1eac14431 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 22 May 2017 10:22:28 +0900 Subject: Refactored Events The biggest change is we have no pimpls in Event objects anymore - because it's two new's instead of one per Event, and we have thousands and even more of Events created during initial sync. The other big change is introduction of RoomEvent, so that now the structure of events almost precisely reflects the CS API spec. The refactoring made UnknownEvent unnecessary as a separate class; a respective base class (either RoomEvent or Event) is used for this purpose now. All the other changes are consequences of these (mostly of RoomEvent introduction). --- events/event.cpp | 148 ++++++++++++++++--------------------- events/event.h | 103 +++++++++++++++++++------- events/receiptevent.cpp | 40 +++------- events/receiptevent.h | 35 ++++----- events/roomaliasesevent.cpp | 42 +---------- events/roomaliasesevent.h | 14 ++-- events/roomcanonicalaliasevent.cpp | 32 -------- events/roomcanonicalaliasevent.h | 17 ++--- events/roommemberevent.cpp | 77 ++++--------------- events/roommemberevent.h | 29 ++++---- events/roommessageevent.cpp | 121 +++++++++--------------------- events/roommessageevent.h | 67 ++++++++--------- events/roomnameevent.cpp | 30 -------- events/roomnameevent.h | 17 ++--- events/roomtopicevent.cpp | 29 -------- events/roomtopicevent.h | 17 ++--- events/typingevent.cpp | 42 ++--------- events/typingevent.h | 12 +-- 18 files changed, 306 insertions(+), 566 deletions(-) (limited to 'events') diff --git a/events/event.cpp b/events/event.cpp index 5df816fe..bd7e1b03 100644 --- a/events/event.cpp +++ b/events/event.cpp @@ -18,9 +18,6 @@ #include "event.h" -#include -#include - #include "roommessageevent.h" #include "roomnameevent.h" #include "roomaliasesevent.h" @@ -31,120 +28,101 @@ #include "receiptevent.h" #include "unknownevent.h" #include "logging.h" -#include "util.h" - -using namespace QMatrixClient; - -class Event::Private -{ - public: - EventType type; - QString id; - QDateTime timestamp; - QString roomId; - QString senderId; - QString originalJson; -}; -Event::Event(EventType type) - : d(new Private) -{ - d->type = type; -} +#include -Event::~Event() -{ - delete d; -} +using namespace QMatrixClient; -EventType Event::type() const +Event::Event(Type type, const QJsonObject& rep) + : _type(type), _originalJson(rep) { - return d->type; + if (!rep.contains("content")) + { + qCWarning(EVENTS) << "Event without 'content' node"; + qCWarning(EVENTS) << formatJson << rep; + } } -QString Event::id() const +QByteArray Event::originalJson() const { - return d->id; + return QJsonDocument(_originalJson).toJson(); } -QDateTime Event::timestamp() const +QDateTime Event::toTimestamp(const QJsonValue& v) { - return d->timestamp; + Q_ASSERT(v.isDouble()); + return QDateTime::fromMSecsSinceEpoch( + static_cast(v.toDouble()), Qt::UTC); } -QString Event::roomId() const +QStringList Event::toStringList(const QJsonValue& v) { - return d->roomId; -} + Q_ASSERT(v.isArray()); -QString Event::senderId() const -{ - return d->senderId; + QStringList l; + for( const QJsonValue& e : v.toArray() ) + l.push_back(e.toString()); + return l; } -QString Event::originalJson() const +const QJsonObject Event::contentJson() const { - return d->originalJson; + return _originalJson["content"].toObject(); } template -EventT* make(const QJsonObject& obj) +EventT* make(const QJsonObject& o) { - return EventT::fromJson(obj); + return new EventT(o); } Event* Event::fromJson(const QJsonObject& obj) { + // Check more specific event types first + if (auto e = RoomEvent::fromJson(obj)) + return e; + return dispatch(obj).to(obj["type"].toString(), - "m.room.message", &make, - "m.room.name", &make, - "m.room.aliases", &make, - "m.room.canonical_alias", &make, - "m.room.member", &make, - "m.room.topic", &make, - "m.typing", &make, - "m.receipt", &make, - /* Insert new event types BEFORE this line */ - &make - ); + "m.typing", make, + "m.receipt", make, + /* Insert new event types (except room events) BEFORE this line */ + nullptr + ); } -bool Event::parseJson(const QJsonObject& obj) +RoomEvent::RoomEvent(Type type, const QJsonObject& rep) + : Event(type, rep), _id(rep["event_id"].toString()) + , _serverTimestamp(toTimestamp(rep["origin_server_ts"])) + , _roomId(rep["room_id"].toString()) + , _senderId(rep["sender"].toString()) { - d->originalJson = QString::fromUtf8(QJsonDocument(obj).toJson()); - d->id = obj.value("event_id").toString(); - d->roomId = obj.value("room_id").toString(); - d->senderId = obj.value("sender").toString(); - bool correct = (d->type != EventType::Unknown); - if ( d->type != EventType::Typing && - d->type != EventType::Receipt ) + if (_id.isEmpty()) { - if (d->id.isEmpty()) - { - correct = false; - qCDebug(EVENTS) << "Event: can't find event_id; event dump follows"; - qCDebug(EVENTS) << formatJson << obj; - } - if( obj.contains("origin_server_ts") ) - { - d->timestamp = QDateTime::fromMSecsSinceEpoch( - static_cast(obj.value("origin_server_ts").toDouble()), Qt::UTC ); - } - else if (d->type != EventType::Unknown) - { - correct = false; - qCDebug(EVENTS) << "Event: can't find ts; event dump follows"; - qCDebug(EVENTS) << formatJson << obj; - } + qCWarning(EVENTS) << "Can't find event_id in a room event"; + qCWarning(EVENTS) << formatJson << rep; + } + if (!rep.contains("origin_server_ts")) + { + qCWarning(EVENTS) << "Event: can't find server timestamp in a room event"; + qCWarning(EVENTS) << formatJson << rep; + } + if (_senderId.isEmpty()) + { + qCWarning(EVENTS) << "user_id not found in a room event"; + qCWarning(EVENTS) << formatJson << rep; } - return correct; } -Events QMatrixClient::eventsFromJson(const QJsonArray& json) +RoomEvent* RoomEvent::fromJson(const QJsonObject& obj) { - Events evs; - evs.reserve(json.size()); - for (auto event: json) - evs.push_back(Event::fromJson(event.toObject())); - return evs; + return dispatch(obj).to(obj["type"].toString(), + "m.room.message", make, + "m.room.name", make, + "m.room.aliases", make, + "m.room.canonical_alias", make, + "m.room.member", make, + "m.room.topic", make, + /* Insert new ROOM event types BEFORE this line */ + nullptr + ); } diff --git a/events/event.h b/events/event.h index f60dfb64..fd2f6feb 100644 --- a/events/event.h +++ b/events/event.h @@ -21,43 +21,92 @@ #include #include #include -#include +#include -class QJsonArray; +#include "util.h" namespace QMatrixClient { - enum class EventType - { - RoomMessage, RoomName, RoomAliases, RoomCanonicalAlias, - RoomMember, RoomTopic, Typing, Receipt, Unknown - }; - class Event { + Q_GADGET public: - explicit Event(EventType type); - Event(Event&) = delete; - virtual ~Event(); - - EventType type() const; - QString id() const; - QDateTime timestamp() const; - QString roomId() const; - QString senderId() const; - // only for debug purposes! - QString originalJson() const; + enum class Type + { + RoomMessage, RoomName, RoomAliases, RoomCanonicalAlias, + RoomMember, RoomTopic, Typing, Receipt, Unknown + }; + + explicit Event(Type type, const QJsonObject& rep); + Event(const Event&) = delete; + + Type type() const { return _type; } + QByteArray originalJson() const; + + // Every event also has a "content" object but since its structure is + // different for different types, we're implementing it per-event type + // (and in most cases it will be a combination of other fields + // instead of "content" field). static Event* fromJson(const QJsonObject& obj); - + protected: - bool parseJson(const QJsonObject& obj); - + static QDateTime toTimestamp(const QJsonValue& v); + static QStringList toStringList(const QJsonValue& v); + + const QJsonObject contentJson() const; + private: - class Private; - Private* d; + Type _type; + QJsonObject _originalJson; + + REGISTER_ENUM(Type) }; - using Events = QVector; + using EventType = Event::Type; + template + using EventsBatch = std::vector; + using Events = EventsBatch; + + template + BaseEventT* makeEvent(const QJsonObject& obj) + { + if (auto e = BaseEventT::fromJson(obj)) + return e; + + return new BaseEventT(EventType::Unknown, obj); + } + + template > + BatchT makeEvents(const QJsonArray& objs) + { + BatchT evs; + // The below line accommodates the difference in size types of + // STL and Qt containers. + evs.reserve(static_cast(objs.size())); + for (auto obj: objs) + evs.push_back(makeEvent(obj.toObject())); + return evs; + } - Events eventsFromJson(const QJsonArray& json); -} + class RoomEvent : public Event + { + public: + RoomEvent(Type type, const QJsonObject& rep); + + const QString& id() const { return _id; } + const QDateTime& timestamp() const { return _serverTimestamp; } + const QString& roomId() const { return _roomId; } + const QString& senderId() const { return _senderId; } + + // "Static override" of the one in Event + static RoomEvent* fromJson(const QJsonObject& obj); + + private: + QString _id; + QDateTime _serverTimestamp; + QString _roomId; + QString _senderId; + }; + using RoomEvents = EventsBatch; +} // namespace QMatrixClient diff --git a/events/receiptevent.cpp b/events/receiptevent.cpp index c163424f..e3478cf1 100644 --- a/events/receiptevent.cpp +++ b/events/receiptevent.cpp @@ -41,34 +41,13 @@ Example of a Receipt Event: using namespace QMatrixClient; -class ReceiptEvent::Private +ReceiptEvent::ReceiptEvent(const QJsonObject& obj) + : Event(Type::Receipt, obj) { - public: - EventsToReceipts eventsToReceipts; -}; + Q_ASSERT(obj["type"].toString() == jsonType); -ReceiptEvent::ReceiptEvent() - : Event(EventType::Receipt) - , d(new Private) -{ -} - -ReceiptEvent::~ReceiptEvent() -{ - delete d; -} - -EventsToReceipts ReceiptEvent::events() const -{ - return d->eventsToReceipts; -} - -ReceiptEvent* ReceiptEvent::fromJson(const QJsonObject& obj) -{ - ReceiptEvent* e = new ReceiptEvent(); - e->parseJson(obj); const QJsonObject contents = obj["content"].toObject(); - e->d->eventsToReceipts.reserve(contents.size()); + _eventsWithReceipts.reserve(static_cast(contents.size())); for( auto eventIt = contents.begin(); eventIt != contents.end(); ++eventIt ) { if (eventIt.key().isEmpty()) @@ -78,15 +57,14 @@ ReceiptEvent* ReceiptEvent::fromJson(const QJsonObject& obj) continue; } const QJsonObject reads = eventIt.value().toObject().value("m.read").toObject(); - Receipts receipts; receipts.reserve(reads.size()); + std::vector receipts; + receipts.reserve(static_cast(reads.size())); for( auto userIt = reads.begin(); userIt != reads.end(); ++userIt ) { const QJsonObject user = userIt.value().toObject(); - const auto time = QDateTime::fromMSecsSinceEpoch( - static_cast(user["ts"].toDouble()), Qt::UTC ); - receipts.push_back({ userIt.key(), time }); + receipts.push_back({userIt.key(), toTimestamp(user["ts"])}); } - e->d->eventsToReceipts.push_back({ eventIt.key(), receipts }); + _eventsWithReceipts.push_back({eventIt.key(), receipts}); } - return e; } + diff --git a/events/receiptevent.h b/events/receiptevent.h index 40c0384f..1d280822 100644 --- a/events/receiptevent.h +++ b/events/receiptevent.h @@ -22,32 +22,29 @@ namespace QMatrixClient { - class Receipt + struct Receipt { - public: - QString userId; - QDateTime timestamp; + QString userId; + QDateTime timestamp; }; -} -Q_DECLARE_TYPEINFO(QMatrixClient::Receipt, Q_MOVABLE_TYPE); - -namespace QMatrixClient -{ - using Receipts = QVector; - using EventsToReceipts = QVector< QPair >; + struct ReceiptsForEvent + { + QString evtId; + std::vector receipts; + }; + using EventsWithReceipts = std::vector; class ReceiptEvent: public Event { public: - ReceiptEvent(); - virtual ~ReceiptEvent(); + explicit ReceiptEvent(const QJsonObject& obj); - EventsToReceipts events() const; - - static ReceiptEvent* fromJson(const QJsonObject& obj); + EventsWithReceipts eventsWithReceipts() const + { return _eventsWithReceipts; } private: - class Private; - Private* d; + EventsWithReceipts _eventsWithReceipts; + + static constexpr const char * jsonType = "m.receipt"; }; -} +} // namespace QMatrixClient diff --git a/events/roomaliasesevent.cpp b/events/roomaliasesevent.cpp index ab414498..344b4367 100644 --- a/events/roomaliasesevent.cpp +++ b/events/roomaliasesevent.cpp @@ -34,44 +34,10 @@ #include "roomaliasesevent.h" -#include "logging.h" - -#include - using namespace QMatrixClient; -class RoomAliasesEvent::Private -{ - public: - QStringList aliases; -}; - -RoomAliasesEvent::RoomAliasesEvent() - : Event(EventType::RoomAliases) - , d(new Private) -{ -} - -RoomAliasesEvent::~RoomAliasesEvent() -{ - delete d; -} - -QStringList RoomAliasesEvent::aliases() const -{ - return d->aliases; -} +RoomAliasesEvent::RoomAliasesEvent(const QJsonObject& obj) + : RoomEvent(Type::RoomAliases, obj) + , _aliases(toStringList(contentJson()["aliases"])) +{ } -RoomAliasesEvent* RoomAliasesEvent::fromJson(const QJsonObject& obj) -{ - RoomAliasesEvent* e = new RoomAliasesEvent(); - e->parseJson(obj); - const QJsonObject contents = obj.value("content").toObject(); - const QJsonArray aliases = contents.value("aliases").toArray(); - for( const QJsonValue& alias : aliases ) - { - e->d->aliases << alias.toString(); - } - qCDebug(EVENTS) << "RoomAliasesEvent:" << e->d->aliases; - return e; -} diff --git a/events/roomaliasesevent.h b/events/roomaliasesevent.h index 8f638be2..efafcb30 100644 --- a/events/roomaliasesevent.h +++ b/events/roomaliasesevent.h @@ -24,18 +24,14 @@ namespace QMatrixClient { - class RoomAliasesEvent: public Event + class RoomAliasesEvent: public RoomEvent { public: - RoomAliasesEvent(); - virtual ~RoomAliasesEvent(); + explicit RoomAliasesEvent(const QJsonObject& obj); - QStringList aliases() const; - - static RoomAliasesEvent* fromJson(const QJsonObject& obj); + QStringList aliases() const { return _aliases; } private: - class Private; - Private* d; + QStringList _aliases; }; -} +} // namespace QMatrixClient diff --git a/events/roomcanonicalaliasevent.cpp b/events/roomcanonicalaliasevent.cpp index d84c07fc..6884bc15 100644 --- a/events/roomcanonicalaliasevent.cpp +++ b/events/roomcanonicalaliasevent.cpp @@ -19,35 +19,3 @@ #include "roomcanonicalaliasevent.h" using namespace QMatrixClient; - -class RoomCanonicalAliasEvent::Private -{ - public: - QString alias; -}; - -RoomCanonicalAliasEvent::RoomCanonicalAliasEvent() - : Event(EventType::RoomCanonicalAlias) - , d(new Private) -{ -} - -RoomCanonicalAliasEvent::~RoomCanonicalAliasEvent() -{ - delete d; -} - -QString RoomCanonicalAliasEvent::alias() -{ - return d->alias; -} - -RoomCanonicalAliasEvent* RoomCanonicalAliasEvent::fromJson(const QJsonObject& obj) -{ - RoomCanonicalAliasEvent* e = new RoomCanonicalAliasEvent(); - e->parseJson(obj); - const QJsonObject contents = obj.value("content").toObject(); - e->d->alias = contents.value("alias").toString(); - return e; -} - diff --git a/events/roomcanonicalaliasevent.h b/events/roomcanonicalaliasevent.h index 87219be6..72620d74 100644 --- a/events/roomcanonicalaliasevent.h +++ b/events/roomcanonicalaliasevent.h @@ -22,18 +22,17 @@ namespace QMatrixClient { - class RoomCanonicalAliasEvent: public Event + class RoomCanonicalAliasEvent : public RoomEvent { public: - RoomCanonicalAliasEvent(); - virtual ~RoomCanonicalAliasEvent(); + explicit RoomCanonicalAliasEvent(const QJsonObject& obj) + : RoomEvent(Type::RoomCanonicalAlias, obj) + , _canonicalAlias(contentJson()["alias"].toString()) + { } - QString alias(); - - static RoomCanonicalAliasEvent* fromJson(const QJsonObject& obj); + QString alias() const { return _canonicalAlias; } private: - class Private; - Private* d; + QString _canonicalAlias; }; -} +} // namespace QMatrixClient diff --git a/events/roommemberevent.cpp b/events/roommemberevent.cpp index 51dbbbab..5973acc7 100644 --- a/events/roommemberevent.cpp +++ b/events/roommemberevent.cpp @@ -22,66 +22,19 @@ using namespace QMatrixClient; -class RoomMemberEvent::Private -{ - public: - MembershipType membership; - QString userId; - QString displayname; - QUrl avatarUrl; -}; - -RoomMemberEvent::RoomMemberEvent() - : Event(EventType::RoomMember) - , d(new Private) -{ -} - -RoomMemberEvent::~RoomMemberEvent() -{ - delete d; -} - -MembershipType RoomMemberEvent::membership() const -{ - return d->membership; -} - -QString RoomMemberEvent::userId() const -{ - return d->userId; -} - -QString RoomMemberEvent::displayName() const -{ - return d->displayname; -} - -QUrl RoomMemberEvent::avatarUrl() const -{ - return d->avatarUrl; -} - -RoomMemberEvent* RoomMemberEvent::fromJson(const QJsonObject& obj) -{ - RoomMemberEvent* e = new RoomMemberEvent(); - e->parseJson(obj); - e->d->userId = obj.value("state_key").toString(); - QJsonObject content = obj.value("content").toObject(); - e->d->displayname = content.value("displayname").toString(); - QString membershipString = content.value("membership").toString(); - if( membershipString == "invite" ) - e->d->membership = MembershipType::Invite; - else if( membershipString == "join" ) - e->d->membership = MembershipType::Join; - else if( membershipString == "knock" ) - e->d->membership = MembershipType::Knock; - else if( membershipString == "leave" ) - e->d->membership = MembershipType::Leave; - else if( membershipString == "ban" ) - e->d->membership = MembershipType::Ban; - else - qCDebug(EVENTS) << "Unknown MembershipType: " << membershipString; - e->d->avatarUrl = QUrl(content.value("avatar_url").toString()); - return e; +RoomMemberEvent::RoomMemberEvent(const QJsonObject& obj) + : RoomEvent(Type::RoomMember, obj), _userId(obj["state_key"].toString()) +{ + const auto contentObj = contentJson(); + _displayName = contentObj["displayname"].toString(); + _avatarUrl = contentObj["avatar_url"].toString(); + QString membershipString = contentObj["membership"].toString(); + const auto supportedStrings = { "invite", "join", "knock", "leave", "ban" }; + for (auto it = supportedStrings.begin(); it != supportedStrings.end(); ++it) + if (membershipString == *it) + { + _membership = MembershipType(it - supportedStrings.begin()); + return; + } + qCWarning(EVENTS) << "Unknown MembershipType: " << membershipString; } diff --git a/events/roommemberevent.h b/events/roommemberevent.h index a33c2982..9ebb75ee 100644 --- a/events/roommemberevent.h +++ b/events/roommemberevent.h @@ -24,23 +24,26 @@ namespace QMatrixClient { - enum class MembershipType {Invite, Join, Knock, Leave, Ban}; - - class RoomMemberEvent: public Event + class RoomMemberEvent: public RoomEvent { + Q_GADGET public: - RoomMemberEvent(); - virtual ~RoomMemberEvent(); + enum MembershipType : int {Invite = 0, Join, Knock, Leave, Ban}; - MembershipType membership() const; - QString userId() const; - QString displayName() const; - QUrl avatarUrl() const; + explicit RoomMemberEvent(const QJsonObject& obj); - static RoomMemberEvent* fromJson(const QJsonObject& obj); + MembershipType membership() const { return _membership; } + const QString& userId() const { return _userId; } + const QString& displayName() const { return _displayName; } + const QUrl& avatarUrl() const { return _avatarUrl; } private: - class Private; - Private* d; + MembershipType _membership; + QString _userId; + QString _displayName; + QUrl _avatarUrl; + + REGISTER_ENUM(MembershipType) }; -} + using MembershipType = RoomMemberEvent::MembershipType; +} // namespace QMatrixClient diff --git a/events/roommessageevent.cpp b/events/roommessageevent.cpp index d5e960a1..49bb4053 100644 --- a/events/roommessageevent.cpp +++ b/events/roommessageevent.cpp @@ -19,64 +19,15 @@ #include "roommessageevent.h" #include "logging.h" -#include "util.h" #include using namespace QMatrixClient; - -class RoomMessageEvent::Private -{ - public: - Private() : msgtype(MessageEventType::Unknown), content(nullptr) {} - ~Private() { if (content) delete content; } - - QString userId; - MessageEventType msgtype; - QString plainBody; - MessageEventContent::Base* content; -}; - -RoomMessageEvent::RoomMessageEvent() - : Event(EventType::RoomMessage) - , d(new Private) -{ } - -RoomMessageEvent::~RoomMessageEvent() -{ - delete d; -} - -QString RoomMessageEvent::userId() const -{ - return d->userId; -} - -MessageEventType RoomMessageEvent::msgtype() const -{ - return d->msgtype; -} - -QString RoomMessageEvent::plainBody() const -{ - return d->plainBody; -} - -QString RoomMessageEvent::body() const -{ - return plainBody(); -} - using namespace MessageEventContent; -Base* RoomMessageEvent::content() const -{ - return d->content; -} - -using ContentPair = std::pair; +using ContentPair = std::pair; -template +template ContentPair make(const QJsonObject& json) { return { EnumType, new ContentT(json) }; @@ -91,59 +42,53 @@ ContentPair makeVideo(const QJsonObject& json) if (infoJson.contains("thumbnail_url")) { c->thumbnail = ImageInfo(infoJson["thumbnail_url"].toString(), - infoJson["thumbnail_info"].toObject()); + infoJson["thumbnail_info"].toObject()); } - return { MessageEventType::Video, c }; + return { CType::Video, c }; }; ContentPair makeUnknown(const QJsonObject& json) { qCDebug(EVENTS) << "RoomMessageEvent: couldn't resolve msgtype, JSON follows:"; qCDebug(EVENTS) << json; - return { MessageEventType::Unknown, new Base }; + return { CType::Unknown, new Base() }; } -RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) +RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) + : RoomEvent(Type::RoomMessage, obj), _msgtype(CType::Unknown) + , _content(nullptr) { - RoomMessageEvent* e = new RoomMessageEvent(); - e->parseJson(obj); - if( obj.contains("sender") ) + const QJsonObject content = contentJson(); + if ( content.contains("msgtype") && content.contains("body") ) { - e->d->userId = obj.value("sender").toString(); - } else { - qCDebug(EVENTS) << "RoomMessageEvent: user_id not found"; + _plainBody = content["body"].toString(); + + auto factory = lookup(content["msgtype"].toString(), + "m.text", make, + "m.emote", make, + "m.notice", make, + "m.image", make, + "m.file", make, + "m.location", make, + "m.video", makeVideo, + "m.audio", make, + // Insert new message types before this line + makeUnknown + ); + std::tie(_msgtype, _content) = factory(content); } - if( obj.contains("content") ) + else { - const QJsonObject content = obj["content"].toObject(); - if ( content.contains("msgtype") && content.contains("body") ) - { - e->d->plainBody = content["body"].toString(); - - auto delegate = lookup(content["msgtype"].toString(), - "m.text", &make, - "m.emote", &make, - "m.notice", &make, - "m.image", &make, - "m.file", &make, - "m.location", &make, - "m.video", &makeVideo, - "m.audio", &make, - // Insert new message types before this line - &makeUnknown - ); - std::tie(e->d->msgtype, e->d->content) = delegate(content); - } - else - { - qCWarning(EVENTS) << "RoomMessageEvent(" << e->id() << "): no body or msgtype"; - qCDebug(EVENTS) << obj; - } + qCWarning(EVENTS) << "No body or msgtype in room message event"; + qCWarning(EVENTS) << formatJson << obj; } - return e; } -using namespace MessageEventContent; +RoomMessageEvent::~RoomMessageEvent() +{ + if (_content) + delete _content; +} TextContent::TextContent(const QJsonObject& json) { diff --git a/events/roommessageevent.h b/events/roommessageevent.h index 5d5336aa..6acaad6f 100644 --- a/events/roommessageevent.h +++ b/events/roommessageevent.h @@ -24,44 +24,45 @@ #include #include +#include + namespace QMatrixClient { - enum class MessageEventType - { - Text, Emote, Notice, Image, File, Location, Video, Audio, Unknown - }; - namespace MessageEventContent { - class Base { }; - } - - class RoomMessageEvent: public Event - { - public: - RoomMessageEvent(); - virtual ~RoomMessageEvent(); - - QString userId() const; - MessageEventType msgtype() const; + class Base + { + Q_GADGET + public: + enum class Type + { + Text, Emote, Notice, Image, File, Location, Video, Audio, Unknown + }; - QString plainBody() const; + virtual ~Base() = default; - /** - * Same as plainBody() for now; might change for "best-looking body" - * in the future. For richer contents, use content-specific data. - * - * @deprecated - */ - QString body() const; + REGISTER_ENUM(Type) + }; + using CType = Base::Type; + } // namespace MessageEventContent + using MessageEventType = MessageEventContent::CType; - MessageEventContent::Base* content() const; + class RoomMessageEvent: public RoomEvent + { + public: + explicit RoomMessageEvent(const QJsonObject& obj); + ~RoomMessageEvent(); - static RoomMessageEvent* fromJson( const QJsonObject& obj ); + const QString& userId() const { return _userId; } + MessageEventType msgtype() const { return _msgtype; } + const QString& plainBody() const { return _plainBody; } + const MessageEventContent::Base* content() const { return _content; } private: - class Private; - Private* d; + QString _userId; + MessageEventType _msgtype; + QString _plainBody; + MessageEventContent::Base* _content; }; namespace MessageEventContent @@ -73,7 +74,7 @@ namespace QMatrixClient class TextContent: public Base { public: - TextContent(const QJsonObject& json); + explicit TextContent(const QJsonObject& json); QMimeType mimeType; QString body; @@ -103,7 +104,7 @@ namespace QMatrixClient class ThumbnailedContent: public ContentInfoT { public: - ThumbnailedContent(const QJsonObject& json) + explicit ThumbnailedContent(const QJsonObject& json) : ContentInfoT(json["url"].toString(), json["info"].toObject()) , thumbnail(json["thumbnail_url"].toString(), json["thumbnail_info"].toObject()) @@ -118,7 +119,7 @@ namespace QMatrixClient class LocationContent: public Base { public: - LocationContent(const QJsonObject& json); + explicit LocationContent(const QJsonObject& json); QString geoUri; ImageInfo thumbnail; @@ -142,5 +143,5 @@ namespace QMatrixClient int duration; }; using AudioContent = ThumbnailedContent; - } -} + } // namespace MessageEventContent +} // namespace QMatrixClient diff --git a/events/roomnameevent.cpp b/events/roomnameevent.cpp index c94cb2c3..c202d17a 100644 --- a/events/roomnameevent.cpp +++ b/events/roomnameevent.cpp @@ -20,33 +20,3 @@ using namespace QMatrixClient; -class RoomNameEvent::Private -{ - public: - QString name; -}; - -RoomNameEvent::RoomNameEvent() : - Event(EventType::RoomName), - d(new Private) -{ -} - -RoomNameEvent::~RoomNameEvent() -{ - delete d; -} - -QString RoomNameEvent::name() const -{ - return d->name; -} - -RoomNameEvent* RoomNameEvent::fromJson(const QJsonObject& obj) -{ - RoomNameEvent* e = new RoomNameEvent(); - e->parseJson(obj); - const QJsonObject contents = obj.value("content").toObject(); - e->d->name = contents.value("name").toString(); - return e; -} diff --git a/events/roomnameevent.h b/events/roomnameevent.h index 8748c4be..bb823933 100644 --- a/events/roomnameevent.h +++ b/events/roomnameevent.h @@ -22,18 +22,17 @@ namespace QMatrixClient { - class RoomNameEvent : public Event + class RoomNameEvent : public RoomEvent { public: - RoomNameEvent(); - virtual ~RoomNameEvent(); + explicit RoomNameEvent(const QJsonObject& obj) + : RoomEvent(Type::RoomName, obj) + , _name(contentJson()["name"].toString()) + { } - QString name() const; - - static RoomNameEvent* fromJson(const QJsonObject& obj); + QString name() const { return _name; } private: - class Private; - Private *d; + QString _name{}; }; -} +} // namespace QMatrixClient diff --git a/events/roomtopicevent.cpp b/events/roomtopicevent.cpp index 2e186c4b..26677e78 100644 --- a/events/roomtopicevent.cpp +++ b/events/roomtopicevent.cpp @@ -20,32 +20,3 @@ using namespace QMatrixClient; -class RoomTopicEvent::Private -{ - public: - QString topic; -}; - -RoomTopicEvent::RoomTopicEvent() - : Event(EventType::RoomTopic) - , d(new Private) -{ -} - -RoomTopicEvent::~RoomTopicEvent() -{ - delete d; -} - -QString RoomTopicEvent::topic() const -{ - return d->topic; -} - -RoomTopicEvent* RoomTopicEvent::fromJson(const QJsonObject& obj) -{ - auto e = new RoomTopicEvent(); - e->parseJson(obj); - e->d->topic = obj.value("content").toObject().value("topic").toString(); - return e; -} diff --git a/events/roomtopicevent.h b/events/roomtopicevent.h index 4b0a24b0..fb849afe 100644 --- a/events/roomtopicevent.h +++ b/events/roomtopicevent.h @@ -22,18 +22,17 @@ namespace QMatrixClient { - class RoomTopicEvent: public Event + class RoomTopicEvent: public RoomEvent { public: - RoomTopicEvent(); - virtual ~RoomTopicEvent(); + explicit RoomTopicEvent(const QJsonObject& obj) + : RoomEvent(Type::RoomTopic, obj) + , _topic(contentJson()["topic"].toString()) + { } - QString topic() const; - - static RoomTopicEvent* fromJson(const QJsonObject& obj); + QString topic() const { return _topic; } private: - class Private; - Private* d; + QString _topic; }; -} +} // namespace QMatrixClient diff --git a/events/typingevent.cpp b/events/typingevent.cpp index 009059af..a4d3bae4 100644 --- a/events/typingevent.cpp +++ b/events/typingevent.cpp @@ -18,43 +18,15 @@ #include "typingevent.h" -#include "logging.h" - -#include - using namespace QMatrixClient; -class TypingEvent::Private -{ - public: - QStringList users; -}; - -TypingEvent::TypingEvent() - : Event(EventType::Typing) - , d( new Private ) -{ -} - -TypingEvent::~TypingEvent() +TypingEvent::TypingEvent(const QJsonObject& obj) + : Event(Type::Typing, obj) { - delete d; -} - -QStringList TypingEvent::users() -{ - return d->users; -} - -TypingEvent* TypingEvent::fromJson(const QJsonObject& obj) -{ - TypingEvent* e = new TypingEvent(); - e->parseJson(obj); - QJsonArray array = obj.value("content").toObject().value("user_ids").toArray(); + QJsonValue result; + result= contentJson()["user_ids"]; + QJsonArray array = result.toArray(); for( const QJsonValue& user: array ) - { - e->d->users << user.toString(); - } - qCDebug(EPHEMERAL) << "Typing:" << e->d->users; - return e; + _users.push_back(user.toString()); } + diff --git a/events/typingevent.h b/events/typingevent.h index da57a389..b12d224e 100644 --- a/events/typingevent.h +++ b/events/typingevent.h @@ -27,15 +27,11 @@ namespace QMatrixClient class TypingEvent: public Event { public: - TypingEvent(); - virtual ~TypingEvent(); + TypingEvent(const QJsonObject& obj); - QStringList users(); - - static TypingEvent* fromJson(const QJsonObject& obj); + QStringList users() const { return _users; } private: - class Private; - Private* d; + QStringList _users; }; -} +} // namespace QMatrixClient -- cgit v1.2.3 From a5e14da86c3299ca8d36eb4a4eb58ce2a245dc4e Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 22 May 2017 16:55:41 +0900 Subject: Fixed building with CLang 3.5 --- events/roommessageevent.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'events') diff --git a/events/roommessageevent.cpp b/events/roommessageevent.cpp index 49bb4053..19da8827 100644 --- a/events/roommessageevent.cpp +++ b/events/roommessageevent.cpp @@ -64,16 +64,16 @@ RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) _plainBody = content["body"].toString(); auto factory = lookup(content["msgtype"].toString(), - "m.text", make, - "m.emote", make, - "m.notice", make, - "m.image", make, - "m.file", make, - "m.location", make, - "m.video", makeVideo, - "m.audio", make, + "m.text", &make, + "m.emote", &make, + "m.notice", &make, + "m.image", &make, + "m.file", &make, + "m.location", &make, + "m.video", &makeVideo, + "m.audio", &make, // Insert new message types before this line - makeUnknown + &makeUnknown ); std::tie(_msgtype, _content) = factory(content); } -- cgit v1.2.3