diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/connection.cpp | 5 | ||||
-rw-r--r-- | lib/converters.h | 21 | ||||
-rw-r--r-- | lib/events/event.cpp | 20 | ||||
-rw-r--r-- | lib/events/event.h | 51 | ||||
-rw-r--r-- | lib/events/redactionevent.h | 2 | ||||
-rw-r--r-- | lib/jobs/generated/notifications.cpp | 2 | ||||
-rw-r--r-- | lib/jobs/generated/notifications.h | 4 | ||||
-rw-r--r-- | lib/room.cpp | 56 | ||||
-rw-r--r-- | lib/room.h | 16 | ||||
-rw-r--r-- | lib/user.cpp | 2 | ||||
-rw-r--r-- | lib/user.h | 3 |
11 files changed, 110 insertions, 72 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp index 5f930d57..adeb7929 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -306,9 +306,8 @@ void Connection::onSyncSuccess(SyncData &&data) { { if (accountEvent->type() == EventType::DirectChat) { - const auto usersToDCs = - unique_ptr_cast<DirectChatEvent>(accountEvent) - ->usersToDirectChats(); + const auto usersToDCs = ptrCast<DirectChatEvent>(move(accountEvent)) + ->usersToDirectChats(); DirectChatsMap removals = erase_if(d->directChats, [&usersToDCs] (auto it) { return !usersToDCs.contains(it.key()->id(), it.value()); diff --git a/lib/converters.h b/lib/converters.h index 22b22f25..cfe9c01c 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -34,6 +34,15 @@ namespace QMatrixClient #endif template <typename T> + inline QJsonArray toJson(const std::vector<T>& vals) + { + QJsonArray ar; + for (const auto& v: vals) + ar.push_back(toJson(v)); + return ar; + } + + template <typename T> inline QJsonArray toJson(const QVector<T>& vals) { QJsonArray ar; @@ -142,6 +151,18 @@ namespace QMatrixClient } }; + template <typename T> struct FromJson<std::vector<T>> + { + std::vector<T> operator()(const QJsonValue& jv) const + { + const auto jsonArray = jv.toArray(); + std::vector<T> vect; vect.resize(size_t(jsonArray.size())); + std::transform(jsonArray.begin(), jsonArray.end(), + vect.begin(), FromJson<T>()); + return vect; + } + }; + template <typename T> struct FromJson<QVector<T>> { QVector<T> operator()(const QJsonValue& jv) const diff --git a/lib/events/event.cpp b/lib/events/event.cpp index 8ddf3945..193250de 100644 --- a/lib/events/event.cpp +++ b/lib/events/event.cpp @@ -67,16 +67,17 @@ const QJsonObject Event::contentJson() const } template <typename BaseEventT> -inline BaseEventT* makeIfMatches(const QJsonObject&, const QString&) +inline event_ptr_tt<BaseEventT> makeIfMatches(const QJsonObject&, const QString&) { return nullptr; } template <typename BaseEventT, typename EventT, typename... EventTs> -inline BaseEventT* makeIfMatches(const QJsonObject& o, const QString& selector) +inline event_ptr_tt<BaseEventT> makeIfMatches(const QJsonObject& o, + const QString& selector) { if (selector == EventT::TypeId) - return new EventT(o); + return _impl::create<EventT>(o); return makeIfMatches<BaseEventT, EventTs...>(o, selector); } @@ -86,11 +87,11 @@ EventPtr _impl::doMakeEvent<Event>(const QJsonObject& obj) { // Check more specific event types first if (auto e = doMakeEvent<RoomEvent>(obj)) - return EventPtr(move(e)); + return e; - return EventPtr { makeIfMatches<Event, + return makeIfMatches<Event, TypingEvent, ReceiptEvent, TagEvent, ReadMarkerEvent, DirectChatEvent>( - obj, obj["type"].toString()) }; + obj, obj["type"].toString()); } RoomEvent::RoomEvent(Event::Type type) : Event(type) { } @@ -98,10 +99,6 @@ 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<QDateTime>(rep["origin_server_ts"])) { // if (_id.isEmpty()) // { @@ -122,8 +119,7 @@ RoomEvent::RoomEvent(Type type, const QJsonObject& rep) auto redaction = unsignedData.value("redacted_because"); if (redaction.isObject()) { - _redactedBecause = - std::make_unique<RedactionEvent>(redaction.toObject()); + _redactedBecause = _impl::create<RedactionEvent>(redaction.toObject()); return; } diff --git a/lib/events/event.h b/lib/events/event.h index d614115a..396406f1 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -18,22 +18,40 @@ #pragma once -#include <QtCore/QString> -#include <QtCore/QDateTime> -#include <QtCore/QJsonObject> -#include <QtCore/QJsonArray> - +#include "converters.h" #include "util.h" -#include <memory> - namespace QMatrixClient { template <typename EventT> using event_ptr_tt = std::unique_ptr<EventT>; + template <typename EventT> + inline EventT* rawPtr(const event_ptr_tt<EventT>& ptr) + { + return ptr.get(); + } + + template <typename TargetEventT, typename EventT> + inline TargetEventT* weakPtr(const event_ptr_tt<EventT>& ptr) + { + return static_cast<TargetEventT*>(rawPtr(ptr)); + } + + template <typename TargetT, typename SourceT> + inline event_ptr_tt<TargetT> ptrCast(event_ptr_tt<SourceT>&& ptr) + { + return unique_ptr_cast<TargetT>(ptr); + } + namespace _impl { + template <typename EventT, typename... ArgTs> + inline event_ptr_tt<EventT> create(ArgTs&&... args) + { + return std::make_unique<EventT>(std::forward<ArgTs>(args)...); + } + template <typename EventT> event_ptr_tt<EventT> doMakeEvent(const QJsonObject& obj); } @@ -100,7 +118,7 @@ namespace QMatrixClient { auto e = _impl::doMakeEvent<EventT>(obj); if (!e) - e = std::make_unique<EventT>(EventType::Unknown, obj); + e = _impl::create<EventT>(EventType::Unknown, obj); return e; } @@ -110,6 +128,14 @@ namespace QMatrixClient EventPtr doMakeEvent<Event>(const QJsonObject& obj); } + template <> struct FromJson<EventPtr> + { + EventPtr operator()(const QJsonValue& jv) const + { + return makeEvent<Event>(jv.toObject()); + } + }; + /** * \brief A vector of pointers to events with deserialisation capabilities * @@ -165,16 +191,16 @@ namespace QMatrixClient // constructors and destructors explicit RoomEvent(Type type); RoomEvent(Type type, const QJsonObject& rep); - ~RoomEvent(); + ~RoomEvent() override; QString id() const { return _id; } QDateTime timestamp() const; QString roomId() const; QString senderId() const; bool isRedacted() const { return bool(_redactedBecause); } - const RedactionEvent* redactedBecause() const + const event_ptr_tt<RedactionEvent>& redactedBecause() const { - return _redactedBecause.get(); + return _redactedBecause; } QString redactionReason() const; const QString& transactionId() const { return _txnId; } @@ -202,9 +228,6 @@ namespace QMatrixClient private: QString _id; -// QString _roomId; -// QString _senderId; -// QDateTime _serverTimestamp; event_ptr_tt<RedactionEvent> _redactedBecause; QString _txnId; }; diff --git a/lib/events/redactionevent.h b/lib/events/redactionevent.h index fa6902ab..829b9085 100644 --- a/lib/events/redactionevent.h +++ b/lib/events/redactionevent.h @@ -27,7 +27,7 @@ namespace QMatrixClient public: static constexpr const char* const TypeId = "m.room.redaction"; - RedactionEvent(const QJsonObject& obj) + explicit RedactionEvent(const QJsonObject& obj) : RoomEvent(Type::Redaction, obj) , _redactedEvent(obj.value("redacts").toString()) , _reason(contentJson().value("reason").toString()) diff --git a/lib/jobs/generated/notifications.cpp b/lib/jobs/generated/notifications.cpp index ffd17b8a..df6b10ba 100644 --- a/lib/jobs/generated/notifications.cpp +++ b/lib/jobs/generated/notifications.cpp @@ -21,7 +21,7 @@ namespace QMatrixClient result.actions = fromJson<QVector<QJsonObject>>(o.value("actions")); result.event = - fromJson<GetNotificationsJob::Event>(o.value("event")); + fromJson<EventPtr>(o.value("event")); result.profileTag = fromJson<QString>(o.value("profile_tag")); result.read = diff --git a/lib/jobs/generated/notifications.h b/lib/jobs/generated/notifications.h index 72318f69..798b9576 100644 --- a/lib/jobs/generated/notifications.h +++ b/lib/jobs/generated/notifications.h @@ -22,12 +22,10 @@ namespace QMatrixClient public: // Inner data structures - using Event = EventPtr; - struct Notification { QVector<QJsonObject> actions; - Event event; + EventPtr event; QString profileTag; bool read; QString roomId; diff --git a/lib/room.cpp b/lib/room.cpp index 1fa9212e..a4cfadb4 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -55,6 +55,7 @@ using namespace QMatrixClient; using namespace std::placeholders; +using std::move; #if !(defined __GLIBCXX__ && __GLIBCXX__ <= 20150123) using std::llround; #endif @@ -74,7 +75,7 @@ class Room::Private typedef QMultiHash<QString, User*> members_map_t; Private(Connection* c, QString id_, JoinState initialJoinState) - : q(nullptr), connection(c), id(std::move(id_)) + : q(nullptr), connection(c), id(move(id_)) , joinState(initialJoinState) { } @@ -204,7 +205,7 @@ class Room::Private * Tries to find an event in the timeline and redact it; deletes the * redaction event whether the redacted event was found or not. */ - void processRedaction(RoomEventPtr redactionEvent); + void processRedaction(RoomEventPtr&& redactionEvent); void broadcastTagUpdates() { @@ -228,7 +229,7 @@ class Room::Private RoomEventPtr TimelineItem::replaceEvent(RoomEventPtr&& other) { - return std::exchange(evt, std::move(other)); + return std::exchange(evt, move(other)); } Room::Room(Connection* connection, QString id, JoinState initialJoinState) @@ -711,7 +712,7 @@ Room::Private::getEventWithFile(const QString& eventId) const if (evtIt != timeline.rend() && evtIt->event()->type() == EventType::RoomMessage) { - auto* event = static_cast<const RoomMessageEvent*>(evtIt->event()); + auto* event = evtIt->viewAs<RoomMessageEvent>(); if (event->hasFileContent()) return event; } @@ -1286,11 +1287,10 @@ inline bool isRedaction(const RoomEventPtr& e) return e->type() == EventType::Redaction; } -void Room::Private::processRedaction(RoomEventPtr redactionEvent) +void Room::Private::processRedaction(RoomEventPtr&& redactionEvent) { Q_ASSERT(redactionEvent && isRedaction(redactionEvent)); - const auto& redaction = - static_cast<const RedactionEvent*>(redactionEvent.get()); + const auto& redaction = ptrCast<RedactionEvent>(move(redactionEvent)); const auto pIdx = eventsIndex.find(redaction->redactedEvent()); if (pIdx == eventsIndex.end()) @@ -1359,9 +1359,9 @@ void Room::Private::processRedaction(RoomEventPtr redactionEvent) // notify everyone and delete the old event RoomEventPtr oldEvent { ti.replaceEvent(makeEvent<RoomEvent>(originalJson)) }; - q->onRedaction(oldEvent.get(), ti.event()); + q->onRedaction(*oldEvent, *ti.event()); qCDebug(MAIN) << "Redacted" << oldEvent->id() << "with" << redaction->id(); - emit q->replacedEvent(ti.event(), oldEvent.get()); + emit q->replacedEvent(ti.event(), rawPtr(oldEvent)); } Connection* Room::connection() const @@ -1389,7 +1389,7 @@ void Room::Private::addNewMessageEvents(RoomEvents&& events) if (!normalEvents.empty()) emit q->aboutToAddNewMessages(normalEvents); - const auto insertedSize = insertEvents(std::move(normalEvents), Newer); + const auto insertedSize = insertEvents(move(normalEvents), Newer); const auto from = timeline.cend() - insertedSize; if (insertedSize > 0) { @@ -1436,7 +1436,7 @@ void Room::Private::addHistoricalMessageEvents(RoomEvents&& events) return; emit q->aboutToAddHistoricalMessages(normalEvents); - const auto insertedSize = insertEvents(std::move(normalEvents), Older); + const auto insertedSize = insertEvents(move(normalEvents), Older); const auto from = timeline.crend() - insertedSize; qCDebug(MAIN) << "Room" << displayname << "received" << insertedSize @@ -1455,25 +1455,24 @@ void Room::processStateEvents(const RoomEvents& events) bool emitNamesChanged = false; for (const auto& e: events) { - auto* event = e.get(); - switch (event->type()) + switch (e->type()) { case EventType::RoomName: { - auto nameEvent = static_cast<RoomNameEvent*>(event); + auto* nameEvent = weakPtr<const RoomNameEvent>(e); d->name = nameEvent->name(); qCDebug(MAIN) << "Room name updated:" << d->name; emitNamesChanged = true; break; } case EventType::RoomAliases: { - auto aliasesEvent = static_cast<RoomAliasesEvent*>(event); + auto* aliasesEvent = weakPtr<const RoomAliasesEvent>(e); d->aliases = aliasesEvent->aliases(); qCDebug(MAIN) << "Room aliases updated:" << d->aliases; emitNamesChanged = true; break; } case EventType::RoomCanonicalAlias: { - auto aliasEvent = static_cast<RoomCanonicalAliasEvent*>(event); + auto* aliasEvent = weakPtr<const RoomCanonicalAliasEvent>(e); d->canonicalAlias = aliasEvent->alias(); setObjectName(d->canonicalAlias); qCDebug(MAIN) << "Room canonical alias updated:" << d->canonicalAlias; @@ -1481,7 +1480,7 @@ void Room::processStateEvents(const RoomEvents& events) break; } case EventType::RoomTopic: { - auto topicEvent = static_cast<RoomTopicEvent*>(event); + auto* topicEvent = weakPtr<const RoomTopicEvent>(e); d->topic = topicEvent->topic(); qCDebug(MAIN) << "Room topic updated:" << d->topic; emit topicChanged(); @@ -1489,7 +1488,7 @@ void Room::processStateEvents(const RoomEvents& events) } case EventType::RoomAvatar: { const auto& avatarEventContent = - static_cast<RoomAvatarEvent*>(event)->content(); + weakPtr<const RoomAvatarEvent>(e)->content(); if (d->avatar.updateUrl(avatarEventContent.url)) { qCDebug(MAIN) << "Room avatar URL updated:" @@ -1499,7 +1498,7 @@ void Room::processStateEvents(const RoomEvents& events) break; } case EventType::RoomMember: { - auto memberEvent = static_cast<RoomMemberEvent*>(event); + auto* memberEvent = weakPtr<const RoomMemberEvent>(e); auto u = user(memberEvent->userId()); u->processEvent(memberEvent, this); if (u == localUser() && memberJoinState(u) == JoinState::Invite @@ -1540,7 +1539,7 @@ void Room::processStateEvents(const RoomEvents& events) case EventType::RoomEncryption: { d->encryptionAlgorithm = - static_cast<EncryptionEvent*>(event)->algorithm(); + weakPtr<const EncryptionEvent>(e)->algorithm(); qCDebug(MAIN) << "Encryption switched on in" << displayName(); emit encryption(); break; @@ -1554,13 +1553,13 @@ void Room::processStateEvents(const RoomEvents& events) d->updateDisplayname(); } -void Room::processEphemeralEvent(EventPtr event) +void Room::processEphemeralEvent(EventPtr&& event) { QElapsedTimer et; et.start(); switch (event->type()) { case EventType::Typing: { - auto typingEvent = static_cast<TypingEvent*>(event.get()); + auto typingEvent = ptrCast<TypingEvent>(move(event)); d->usersTyping.clear(); for( const QString& userId: typingEvent->users() ) { @@ -1575,7 +1574,7 @@ void Room::processEphemeralEvent(EventPtr event) break; } case EventType::Receipt: { - auto receiptEvent = static_cast<ReceiptEvent*>(event.get()); + auto receiptEvent = ptrCast<ReceiptEvent>(move(event)); for( const auto &p: receiptEvent->eventsWithReceipts() ) { { @@ -1629,13 +1628,13 @@ void Room::processEphemeralEvent(EventPtr event) } } -void Room::processAccountDataEvent(EventPtr event) +void Room::processAccountDataEvent(EventPtr&& event) { switch (event->type()) { case EventType::Tag: { - auto newTags = static_cast<TagEvent*>(event.get())->tags(); + auto newTags = ptrCast<const TagEvent>(move(event))->tags(); if (newTags == d->tags) break; d->tags = newTags; @@ -1646,16 +1645,15 @@ void Room::processAccountDataEvent(EventPtr event) } case EventType::ReadMarker: { - const auto* rmEvent = static_cast<ReadMarkerEvent*>(event.get()); - const auto& readEventId = rmEvent->event_id(); + auto readEventId = + ptrCast<const ReadMarkerEvent>(move(event))->event_id(); qCDebug(MAIN) << "Server-side read marker at" << readEventId; d->serverReadMarker = readEventId; const auto newMarker = findInTimeline(readEventId); if (newMarker != timelineEdge()) d->markMessagesAsRead(newMarker); - else { + else d->setLastReadEvent(localUser(), readEventId); - } break; } default: @@ -46,10 +46,12 @@ namespace QMatrixClient using index_t = int; TimelineItem(RoomEventPtr&& e, index_t number) - : evt(move(e)), idx(number) { } + : evt(std::move(e)), idx(number) { } - RoomEvent* event() const { return evt.get(); } - RoomEvent* operator->() const { return evt.operator->(); } + const RoomEvent* event() const { return rawPtr(evt); } + template <typename EventT> + const EventT* viewAs() const { return weakPtr<const EventT>(evt); } + const RoomEventPtr& operator->() const { return evt; } index_t index() const { return idx; } // Used for event redaction @@ -407,12 +409,12 @@ namespace QMatrixClient protected: virtual void processStateEvents(const RoomEvents& events); - virtual void processEphemeralEvent(EventPtr event); - virtual void processAccountDataEvent(EventPtr event); + virtual void processEphemeralEvent(EventPtr&& event); + virtual void processAccountDataEvent(EventPtr&& event); virtual void onAddNewTimelineEvents(timeline_iter_t from) { } virtual void onAddHistoricalTimelineEvents(rev_iter_t from) { } - virtual void onRedaction(const RoomEvent* prevEvent, - const RoomEvent* after) { } + virtual void onRedaction(const RoomEvent& prevEvent, + const RoomEvent& after) { } private: class Private; diff --git a/lib/user.cpp b/lib/user.cpp index c4fbfe35..91b340d5 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -358,7 +358,7 @@ QUrl User::avatarUrl(const Room* room) const return avatarObject(room).url(); } -void User::processEvent(RoomMemberEvent* event, const Room* room) +void User::processEvent(const RoomMemberEvent* event, const Room* room) { if (event->membership() != MembershipType::Invite && event->membership() != MembershipType::Join) @@ -103,7 +103,8 @@ namespace QMatrixClient QString avatarMediaId(const Room* room = nullptr) const; QUrl avatarUrl(const Room* room = nullptr) const; - void processEvent(RoomMemberEvent* event, const Room* r = nullptr); + void processEvent(const RoomMemberEvent* event, + const Room* r = nullptr); public slots: void rename(const QString& newName); |