diff options
-rw-r--r-- | lib/connection.cpp | 5 | ||||
-rw-r--r-- | lib/events/event.cpp | 16 | ||||
-rw-r--r-- | lib/events/event.h | 30 | ||||
-rw-r--r-- | lib/room.cpp | 47 | ||||
-rw-r--r-- | lib/room.h | 16 |
5 files changed, 68 insertions, 46 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/events/event.cpp b/lib/events/event.cpp index 31520fc9..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) { } @@ -118,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 4e2b1071..396406f1 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -26,8 +26,32 @@ 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); } @@ -94,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; } @@ -174,9 +198,9 @@ namespace QMatrixClient 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; } diff --git a/lib/room.cpp b/lib/room.cpp index 670c7d7c..a4cfadb4 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -205,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() { @@ -712,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; } @@ -1287,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()) @@ -1360,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 @@ -1456,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; @@ -1482,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(); @@ -1490,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:" @@ -1500,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 @@ -1541,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; @@ -1555,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() ) { @@ -1576,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() ) { { @@ -1630,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; @@ -1647,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; |