From b7c1ff183384738f170d53128c684681cb34f3b7 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 7 Feb 2018 15:10:19 +0900 Subject: RoomEvent/RoomMemberEvent: do not store what can be calculated on the fly Basically, segments of originalJsonObject() are used as-you-go instead of parsing them upon event creation. --- events/event.cpp | 27 ++++++++++++++++++++++----- events/event.h | 14 +++++++------- events/roommemberevent.h | 7 ++++--- 3 files changed, 33 insertions(+), 15 deletions(-) (limited to 'events') diff --git a/events/event.cpp b/events/event.cpp index c7345a13..7bc25a07 100644 --- a/events/event.cpp +++ b/events/event.cpp @@ -88,11 +88,12 @@ EventPtr _impl::doMakeEvent(const QJsonObject& obj) RoomEvent::RoomEvent(Event::Type type) : Event(type) { } RoomEvent::RoomEvent(Type type, const QJsonObject& rep) - : Event(type, rep), _id(rep["event_id"].toString()) - , _roomId(rep["room_id"].toString()) - , _senderId(rep["sender"].toString()) - , _serverTimestamp( - QMatrixClient::fromJson(rep["origin_server_ts"])) + : Event(type, rep) + , _id(rep["event_id"].toString()) +// , _roomId(rep["room_id"].toString()) +// , _senderId(rep["sender"].toString()) +// , _serverTimestamp( +// QMatrixClient::fromJson(rep["origin_server_ts"])) { // if (_id.isEmpty()) // { @@ -124,6 +125,22 @@ RoomEvent::RoomEvent(Type type, const QJsonObject& rep) RoomEvent::~RoomEvent() = default; // Let the smart pointer do its job +QDateTime RoomEvent::timestamp() const +{ + return QMatrixClient::fromJson( + originalJsonObject().value("origin_server_ts")); +} + +QString RoomEvent::roomId() const +{ + return originalJsonObject().value("room_id").toString(); +} + +QString RoomEvent::senderId() const +{ + return originalJsonObject().value("sender_id").toString(); +} + QString RoomEvent::redactionReason() const { return isRedacted() ? _redactedBecause->reason() : QString{}; diff --git a/events/event.h b/events/event.h index b5a4d94e..968bc1ad 100644 --- a/events/event.h +++ b/events/event.h @@ -167,10 +167,10 @@ namespace QMatrixClient RoomEvent(Type type, const QJsonObject& rep); ~RoomEvent(); - const QString& id() const { return _id; } - const QDateTime& timestamp() const { return _serverTimestamp; } - const QString& roomId() const { return _roomId; } - const QString& senderId() const { return _senderId; } + QString id() const { return _id; } + QDateTime timestamp() const; + QString roomId() const; + QString senderId() const; bool isRedacted() const { return bool(_redactedBecause); } const RedactionEvent* redactedBecause() const { @@ -202,9 +202,9 @@ namespace QMatrixClient private: QString _id; - QString _roomId; - QString _senderId; - QDateTime _serverTimestamp; +// QString _roomId; +// QString _senderId; +// QDateTime _serverTimestamp; event_ptr_tt _redactedBecause; QString _txnId; }; diff --git a/events/roommemberevent.h b/events/roommemberevent.h index d0c63f15..224f29c2 100644 --- a/events/roommemberevent.h +++ b/events/roommemberevent.h @@ -53,16 +53,17 @@ namespace QMatrixClient explicit RoomMemberEvent(const QJsonObject& obj) : StateEvent(Type::RoomMember, obj) - , _userId(obj["state_key"].toString()) +// , _userId(obj["state_key"].toString()) { } MembershipType membership() const { return content().membership; } - QString userId() const { return _userId; } + QString userId() const + { return originalJsonObject().value("state_key").toString(); } QString displayName() const { return content().displayName; } QUrl avatarUrl() const { return content().avatarUrl; } private: - QString _userId; +// QString _userId; REGISTER_ENUM(MembershipType) }; } // namespace QMatrixClient -- cgit v1.2.3 From 3bf51eea5e6152cd39daa971ac6f88d0571ce198 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 19 Feb 2018 18:51:08 +0900 Subject: Fix a typo in the previous commit A symptom that you suffered from it is you don't see any usernames whatsoever, and after restarting room names are also gone (to fix that, delete cache files). --- events/event.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'events') diff --git a/events/event.cpp b/events/event.cpp index 7bc25a07..366aa858 100644 --- a/events/event.cpp +++ b/events/event.cpp @@ -138,7 +138,7 @@ QString RoomEvent::roomId() const QString RoomEvent::senderId() const { - return originalJsonObject().value("sender_id").toString(); + return originalJsonObject().value("sender").toString(); } QString RoomEvent::redactionReason() const -- cgit v1.2.3 From 76b1d775edae36dd2f36fdd4886c6c956bf6b49b Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 23 Feb 2018 10:50:03 +0900 Subject: RoomMemberEvent: make it sendable To do that, both RoomMemberEvent and MemberEventContent got respective constructors. Also: the fallback value for unknown _received_ membership types is now Undefined; it's not allowed in member events for sending (will fail on assertion now) because the server requires membership to be explicitly set. --- events/roommemberevent.cpp | 10 +++++++--- events/roommemberevent.h | 11 +++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'events') diff --git a/events/roommemberevent.cpp b/events/roommemberevent.cpp index 76df5f2e..a9e301a4 100644 --- a/events/roommemberevent.cpp +++ b/events/roommemberevent.cpp @@ -44,7 +44,7 @@ namespace QMatrixClient return MembershipType(it - membershipStrings.begin()); qCWarning(EVENTS) << "Unknown MembershipType: " << membershipString; - return MembershipType::Join; + return MembershipType::Undefined; } }; } @@ -58,7 +58,11 @@ MemberEventContent::MemberEventContent(const QJsonObject& json) void MemberEventContent::fillJson(QJsonObject* o) const { Q_ASSERT(o); - o->insert("membership", membershipStrings[membership]); + Q_ASSERT_X(membership != MembershipType::Undefined, __FUNCTION__, + "The key 'membership' must be explicit in MemberEventContent"); + if (membership != MembershipType::Undefined) + o->insert("membership", membershipStrings[membership]); o->insert("displayname", displayName); - o->insert("avatar_url", avatarUrl.toString()); + if (avatarUrl.isValid()) + o->insert("avatar_url", avatarUrl.toString()); } diff --git a/events/roommemberevent.h b/events/roommemberevent.h index 224f29c2..b9ff0d70 100644 --- a/events/roommemberevent.h +++ b/events/roommemberevent.h @@ -29,9 +29,13 @@ namespace QMatrixClient class MemberEventContent: public EventContent::Base { public: - enum MembershipType : size_t {Invite = 0, Join, Knock, Leave, Ban}; + enum MembershipType : size_t { Invite = 0, Join, Knock, Leave, Ban, + Undefined }; - MemberEventContent(const QJsonObject& json); + explicit MemberEventContent(MembershipType mt = MembershipType::Join) + : membership(mt) + { } + explicit MemberEventContent(const QJsonObject& json); MembershipType membership; QString displayName; @@ -51,6 +55,9 @@ namespace QMatrixClient using MembershipType = MemberEventContent::MembershipType; + RoomMemberEvent(MemberEventContent&& c) + : StateEvent(Type::RoomMember, c) + { } explicit RoomMemberEvent(const QJsonObject& obj) : StateEvent(Type::RoomMember, obj) // , _userId(obj["state_key"].toString()) -- cgit v1.2.3 From 2c095d29b96393dcfa3121c8cb9f4c4fd4f88d6a Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 24 Feb 2018 19:18:22 +0900 Subject: Don't copy event content in accessors --- events/event.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'events') diff --git a/events/event.h b/events/event.h index 968bc1ad..1a1b994d 100644 --- a/events/event.h +++ b/events/event.h @@ -296,10 +296,10 @@ namespace QMatrixClient QJsonObject toJson() const { return _content.toJson(); } - ContentT content() const { return _content; } + const ContentT& content() const { return _content; } /** @deprecated Use prevContent instead */ - ContentT* prev_content() const { return prevContent(); } - ContentT* prevContent() const + const ContentT* prev_content() const { return prevContent(); } + const ContentT* prevContent() const { return _prev ? &_prev->content : nullptr; } QString prevSenderId() const { return _prev ? _prev->senderId : ""; } -- cgit v1.2.3 From fea4f3b5c8d313b429777a8c73ee520af24eecfe Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 25 Feb 2018 14:37:49 +0900 Subject: ReceiptEvent: code cleanup --- events/receiptevent.cpp | 4 ++-- events/receiptevent.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'events') diff --git a/events/receiptevent.cpp b/events/receiptevent.cpp index e30fe4e4..3c4d34ee 100644 --- a/events/receiptevent.cpp +++ b/events/receiptevent.cpp @@ -43,10 +43,10 @@ using namespace QMatrixClient; ReceiptEvent::ReceiptEvent(const QJsonObject& obj) : Event(Type::Receipt, obj) { - Q_ASSERT(obj["type"].toString() == jsonType); + Q_ASSERT(obj["type"].toString() == TypeId); const QJsonObject contents = contentJson(); - _eventsWithReceipts.reserve(static_cast(contents.size())); + _eventsWithReceipts.reserve(contents.size()); for( auto eventIt = contents.begin(); eventIt != contents.end(); ++eventIt ) { if (eventIt.key().isEmpty()) diff --git a/events/receiptevent.h b/events/receiptevent.h index 9494c7c6..92dace82 100644 --- a/events/receiptevent.h +++ b/events/receiptevent.h @@ -48,7 +48,5 @@ namespace QMatrixClient private: EventsWithReceipts _eventsWithReceipts; bool _unreadMessages; // Spec extension for caching purposes - - static constexpr const char * jsonType = "m.receipt"; }; } // namespace QMatrixClient -- cgit v1.2.3 From 7c10807549b2a73527bd594789d0e5b9ab58c874 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 25 Feb 2018 17:24:59 +0900 Subject: TagEvent: m.tag events parsing Using them in rooms and connection comes in the next commit. --- CMakeLists.txt | 1 + events/event.cpp | 8 +++++++- events/event.h | 4 ++-- events/tagevent.cpp | 42 +++++++++++++++++++++++++++++++++++++++++ events/tagevent.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ libqmatrixclient.pri | 3 ++- 6 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 events/tagevent.cpp create mode 100644 events/tagevent.h (limited to 'events') diff --git a/CMakeLists.txt b/CMakeLists.txt index da5bac9b..709860e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ set(libqmatrixclient_SRCS events/roomavatarevent.cpp events/typingevent.cpp events/receiptevent.cpp + events/tagevent.cpp jobs/requestdata.cpp jobs/basejob.cpp jobs/checkauthmethods.cpp diff --git a/events/event.cpp b/events/event.cpp index 366aa858..b55c44c4 100644 --- a/events/event.cpp +++ b/events/event.cpp @@ -24,6 +24,7 @@ #include "roomavatarevent.h" #include "typingevent.h" #include "receiptevent.h" +#include "tagevent.h" #include "redactionevent.h" #include "logging.h" @@ -44,6 +45,11 @@ Event::Event(Type type, const QJsonObject& rep) Event::~Event() = default; +QString Event::jsonType() const +{ + return originalJsonObject().value("type").toString(); +} + QByteArray Event::originalJson() const { return QJsonDocument(_originalJson).toJson(); @@ -82,7 +88,7 @@ EventPtr _impl::doMakeEvent(const QJsonObject& obj) return EventPtr(move(e)); return EventPtr { makeIfMatches(obj, obj["type"].toString()) }; + TypingEvent, ReceiptEvent, TagEvent>(obj, obj["type"].toString()) }; } RoomEvent::RoomEvent(Event::Type type) : Event(type) { } diff --git a/events/event.h b/events/event.h index 1a1b994d..4bd08b55 100644 --- a/events/event.h +++ b/events/event.h @@ -45,7 +45,7 @@ namespace QMatrixClient enum class Type : quint16 { Unknown = 0, - Typing, Receipt, + Typing, Receipt, Tag, DirectChat, RoomEventBase = 0x1000, RoomMessage = RoomEventBase + 1, RoomEncryptedMessage, Redaction, @@ -63,6 +63,7 @@ namespace QMatrixClient virtual ~Event(); Type type() const { return _type; } + QString jsonType() const; bool isStateEvent() const { return (quint16(_type) & 0x1800) == 0x1800; @@ -76,7 +77,6 @@ namespace QMatrixClient // (and in most cases it will be a combination of other fields // instead of "content" field). - protected: const QJsonObject contentJson() const; private: diff --git a/events/tagevent.cpp b/events/tagevent.cpp new file mode 100644 index 00000000..9f381c76 --- /dev/null +++ b/events/tagevent.cpp @@ -0,0 +1,42 @@ +#include "tagevent.h" + +using namespace QMatrixClient; + +TagRecord::TagRecord(const QJsonObject& json) + : order(json.value("order").toString()) +{ } + +TagEvent::TagEvent(const QJsonObject& obj) + : Event(Type::Tag, obj) +{ + Q_ASSERT(obj["type"].toString() == TypeId); +} + +QStringList TagEvent::tagNames() const +{ + return tagsObject().keys(); +} + +QHash TagEvent::tags() const +{ + QHash result; + auto allTags { tagsObject() }; + for (auto it = allTags.begin(); it != allTags.end(); ++ it) + result.insert(it.key(), TagRecord(it.value().toObject())); + return result; +} + +bool TagEvent::isFavourite() const +{ + return tagsObject().contains("m.favourite"); +} + +bool TagEvent::isLowPriority() const +{ + return tagsObject().contains("m.lowpriority"); +} + +QJsonObject TagEvent::tagsObject() const +{ + return contentJson().value("tags").toObject(); +} diff --git a/events/tagevent.h b/events/tagevent.h new file mode 100644 index 00000000..23b0b703 --- /dev/null +++ b/events/tagevent.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Copyright (C) 2018 Kitsune Ral + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "event.h" + +namespace QMatrixClient +{ + struct TagRecord + { + explicit TagRecord(const QJsonObject& json = {}); + + QString order; + }; + + class TagEvent : public Event + { + public: + explicit TagEvent(const QJsonObject& obj); + + /** Get the list of tag names */ + QStringList tagNames() const; + + /** Get the list of tags along with information on each */ + QHash tags() const; + + /** Check whether the list of tags has m.favourite */ + bool isFavourite() const; + /** Check whether the list of tags has m.lowpriority */ + bool isLowPriority() const; + + static constexpr const char * TypeId = "m.tag"; + + protected: + QJsonObject tagsObject() const; + }; +} diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri index 72637caf..7cfa94a1 100644 --- a/libqmatrixclient.pri +++ b/libqmatrixclient.pri @@ -24,6 +24,7 @@ HEADERS += \ $$PWD/events/roomavatarevent.h \ $$PWD/events/typingevent.h \ $$PWD/events/receiptevent.h \ + $$PWD/events/tagevent.h \ $$PWD/events/redactionevent.h \ $$PWD/jobs/requestdata.h \ $$PWD/jobs/basejob.h \ @@ -55,7 +56,7 @@ SOURCES += \ $$PWD/events/roommemberevent.cpp \ $$PWD/events/typingevent.cpp \ $$PWD/events/receiptevent.cpp \ - $$PWD/events/redactionevent.cpp \ + $$PWD/events/tagevent.cpp \ $$PWD/jobs/requestdata.cpp \ $$PWD/jobs/basejob.cpp \ $$PWD/jobs/checkauthmethods.cpp \ -- cgit v1.2.3 From 979756e26af57e715efe64f8de8068243fa27e9f Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 26 Feb 2018 11:09:34 +0900 Subject: Deal with memory more carefully Plugs some memory leaks reported by Valgrind. --- connection.cpp | 2 +- events/event.cpp | 3 ++- events/event.h | 2 +- networkaccessmanager.cpp | 7 ++++--- networkaccessmanager.h | 2 +- user.cpp | 5 +++++ 6 files changed, 14 insertions(+), 7 deletions(-) (limited to 'events') diff --git a/connection.cpp b/connection.cpp index 52fcc40b..7b72c592 100644 --- a/connection.cpp +++ b/connection.cpp @@ -599,7 +599,7 @@ Room* Connection::provideRoom(const QString& id, JoinState joinState) { qCDebug(MAIN) << "Deleting Invite state for room" << prevInvite->id(); emit aboutToDeleteRoom(prevInvite); - delete prevInvite; + prevInvite->deleteLater(); } } diff --git a/events/event.cpp b/events/event.cpp index b55c44c4..74a2c3d7 100644 --- a/events/event.cpp +++ b/events/event.cpp @@ -120,7 +120,8 @@ RoomEvent::RoomEvent(Type type, const QJsonObject& rep) auto redaction = unsignedData.value("redacted_because"); if (redaction.isObject()) { - _redactedBecause.reset(new RedactionEvent(redaction.toObject())); + _redactedBecause = + std::make_unique(redaction.toObject()); return; } diff --git a/events/event.h b/events/event.h index 4bd08b55..f0ca2d15 100644 --- a/events/event.h +++ b/events/event.h @@ -100,7 +100,7 @@ namespace QMatrixClient { auto e = _impl::doMakeEvent(obj); if (!e) - e.reset(new EventT(EventType::Unknown, obj)); + e = std::make_unique(EventType::Unknown, obj); return e; } diff --git a/networkaccessmanager.cpp b/networkaccessmanager.cpp index 7fb2f602..89967a8a 100644 --- a/networkaccessmanager.cpp +++ b/networkaccessmanager.cpp @@ -19,6 +19,7 @@ #include "networkaccessmanager.h" #include +#include using namespace QMatrixClient; @@ -28,7 +29,7 @@ class NetworkAccessManager::Private QList ignoredSslErrors; }; -NetworkAccessManager::NetworkAccessManager() : d(std::make_unique()) +NetworkAccessManager::NetworkAccessManager(QObject* parent) : d(std::make_unique()) { } QList NetworkAccessManager::ignoredSslErrors() const @@ -48,7 +49,7 @@ void NetworkAccessManager::clearIgnoredSslErrors() static NetworkAccessManager* createNam() { - auto nam = new NetworkAccessManager; + auto nam = new NetworkAccessManager(QCoreApplication::instance()); // See #109. Once Qt bearer management gets better, this workaround // should become unnecessary. nam->connect(nam, &QNetworkAccessManager::networkAccessibleChanged, @@ -56,7 +57,7 @@ static NetworkAccessManager* createNam() return nam; } -NetworkAccessManager*NetworkAccessManager::instance() +NetworkAccessManager* NetworkAccessManager::instance() { static auto* nam = createNam(); return nam; diff --git a/networkaccessmanager.h b/networkaccessmanager.h index ea08c591..ae847582 100644 --- a/networkaccessmanager.h +++ b/networkaccessmanager.h @@ -28,7 +28,7 @@ namespace QMatrixClient { Q_OBJECT public: - NetworkAccessManager(); + NetworkAccessManager(QObject* parent = nullptr); ~NetworkAccessManager() override; QList ignoredSslErrors() const; diff --git a/user.cpp b/user.cpp index 9cdbb420..308b217c 100644 --- a/user.cpp +++ b/user.cpp @@ -48,6 +48,11 @@ class User::Private Private(QString userId, Connection* connection) : userId(move(userId)), connection(connection) { } + ~Private() + { + for (auto a: otherAvatars) + delete a; + } QString userId; Connection* connection; -- cgit v1.2.3 From 967b18197aa262751f357c25d812e63b9bcce8b2 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 26 Feb 2018 17:27:44 +0900 Subject: TagEvent: drop unneeded methods; add a license block to the .cpp file Those methods are more appropriate for Room. --- events/tagevent.cpp | 28 ++++++++++++++++++---------- events/tagevent.h | 8 +++----- 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'events') diff --git a/events/tagevent.cpp b/events/tagevent.cpp index 9f381c76..c6297003 100644 --- a/events/tagevent.cpp +++ b/events/tagevent.cpp @@ -1,3 +1,21 @@ +/****************************************************************************** + * Copyright (C) 2018 Kitsune Ral + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include "tagevent.h" using namespace QMatrixClient; @@ -26,16 +44,6 @@ QHash TagEvent::tags() const return result; } -bool TagEvent::isFavourite() const -{ - return tagsObject().contains("m.favourite"); -} - -bool TagEvent::isLowPriority() const -{ - return tagsObject().contains("m.lowpriority"); -} - QJsonObject TagEvent::tagsObject() const { return contentJson().value("tags").toObject(); diff --git a/events/tagevent.h b/events/tagevent.h index 23b0b703..44a7e49a 100644 --- a/events/tagevent.h +++ b/events/tagevent.h @@ -22,6 +22,9 @@ namespace QMatrixClient { + static constexpr const char* FavouriteTag = "m.favourite"; + static constexpr const char* LowPriorityTag = "m.lowpriority"; + struct TagRecord { explicit TagRecord(const QJsonObject& json = {}); @@ -40,11 +43,6 @@ namespace QMatrixClient /** Get the list of tags along with information on each */ QHash tags() const; - /** Check whether the list of tags has m.favourite */ - bool isFavourite() const; - /** Check whether the list of tags has m.lowpriority */ - bool isLowPriority() const; - static constexpr const char * TypeId = "m.tag"; protected: -- cgit v1.2.3