diff options
author | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2018-11-22 13:00:33 +0900 |
---|---|---|
committer | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2018-11-22 16:53:57 +0900 |
commit | 0c3a45356a803baa0eb5e553262a85cac897ac4f (patch) | |
tree | fea3f4964ff8de340b63e5c289cc64bc7c5d7a3b | |
parent | 7f6dec0676123629d2cdf9da7640c1e17566ed3d (diff) | |
download | libquotient-0c3a45356a803baa0eb5e553262a85cac897ac4f.tar.gz libquotient-0c3a45356a803baa0eb5e553262a85cac897ac4f.zip |
Room: Change enum, Changes flag set, and changed() signal
This allows to batch updates into signals being emitted only once per
sync. Also supercedes emitNamesChanged flag used in a few places.
-rw-r--r-- | lib/room.cpp | 49 | ||||
-rw-r--r-- | lib/room.h | 28 |
2 files changed, 54 insertions, 23 deletions
diff --git a/lib/room.cpp b/lib/room.cpp index e5653258..55923ed8 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -192,7 +192,7 @@ class Room::Private is<RoomMessageEvent>(*ti); } - bool addNewMessageEvents(RoomEvents&& events); + Changes addNewMessageEvents(RoomEvents&& events); void addHistoricalMessageEvents(RoomEvents&& events); /** Move events into the timeline @@ -1116,7 +1116,7 @@ void Room::updateData(SyncRoomData&& data) for (auto&& event: data.accountData) processAccountDataEvent(move(event)); - bool emitNamesChanged = false; + Changes roomChanges = Change::NoChange; if (!data.state.empty()) { et.restart(); @@ -1125,7 +1125,7 @@ void Room::updateData(SyncRoomData&& data) const auto& evt = *eptr; Q_ASSERT(evt.isStateEvent()); d->baseState[{evt.matrixType(),evt.stateKey()}] = move(eptr); - emitNamesChanged |= processStateEvent(evt); + roomChanges |= processStateEvent(evt); } if (data.state.size() > 9 || et.nsecsElapsed() >= profilerMinNsecs()) @@ -1135,13 +1135,17 @@ void Room::updateData(SyncRoomData&& data) if (!data.timeline.empty()) { et.restart(); - emitNamesChanged |= d->addNewMessageEvents(move(data.timeline)); + roomChanges |= d->addNewMessageEvents(move(data.timeline)); if (data.timeline.size() > 9 || et.nsecsElapsed() >= profilerMinNsecs()) qCDebug(PROFILER) << "*** Room::addNewMessageEvents():" << data.timeline.size() << "event(s)," << et; } - if (emitNamesChanged) + if (roomChanges&TopicChange) + emit topicChanged(); + + if (roomChanges&NameChange) emit namesChanged(this); + d->updateDisplayname(); for( auto&& ephemeralEvent: data.ephemeral ) @@ -1165,6 +1169,8 @@ void Room::updateData(SyncRoomData&& data) d->notificationCount = data.notificationCount; emit notificationCountChanged(this); } + if (roomChanges != Change::NoChange) + emit changed(roomChanges); } QString Room::Private::sendEvent(RoomEventPtr&& event) @@ -1670,11 +1676,11 @@ inline bool isRedaction(const RoomEventPtr& ep) return is<RedactionEvent>(*ep); } -bool Room::Private::addNewMessageEvents(RoomEvents&& events) +Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events) { dropDuplicateEvents(events); if (events.empty()) - return false; + return Change::NoChange; // Pre-process redactions so that events that get redacted in the same // batch landed in the timeline already redacted. @@ -1704,9 +1710,9 @@ bool Room::Private::addNewMessageEvents(RoomEvents&& events) // clients historically expect. This may eventually change though if we // postulate that the current state is only current between syncs but not // within a sync. - bool emitNamesChanged = false; + Changes stateChanges = Change::NoChange; for (const auto& eptr: events) - emitNamesChanged |= q->processStateEvent(*eptr); + stateChanges |= q->processStateEvent(*eptr); auto timelineSize = timeline.size(); auto totalInserted = 0; @@ -1775,7 +1781,7 @@ bool Room::Private::addNewMessageEvents(RoomEvents&& events) } Q_ASSERT(timeline.size() == timelineSize + totalInserted); - return emitNamesChanged; + return stateChanges; } void Room::Private::addHistoricalMessageEvents(RoomEvents&& events) @@ -1819,10 +1825,10 @@ void Room::Private::addHistoricalMessageEvents(RoomEvents&& events) << insertedSize << "event(s)," << et; } -bool Room::processStateEvent(const RoomEvent& e) +Room::Changes Room::processStateEvent(const RoomEvent& e) { if (!e.isStateEvent()) - return false; + return Change::NoChange; d->currentState[{e.matrixType(),e.stateKey()}] = static_cast<const StateEventBase*>(&e); @@ -1831,23 +1837,22 @@ bool Room::processStateEvent(const RoomEvent& e) return visit(e , [] (const RoomNameEvent&) { - return true; + return NameChange; } , [] (const RoomAliasesEvent&) { - return true; + return OtherChange; } , [this] (const RoomCanonicalAliasEvent& evt) { setObjectName(evt.alias().isEmpty() ? d->id : evt.alias()); - return true; + return CanonicalAliasChange; } - , [this] (const RoomTopicEvent&) { - emit topicChanged(); - return false; + , [] (const RoomTopicEvent&) { + return TopicChange; } , [this] (const RoomAvatarEvent& evt) { if (d->avatar.updateUrl(evt.url())) emit avatarChanged(); - return false; + return AvatarChange; } , [this] (const RoomMemberEvent& evt) { auto* u = user(evt.userId()); @@ -1886,11 +1891,11 @@ bool Room::processStateEvent(const RoomEvent& e) emit userRemoved(u); } } - return false; + return MembersChange; } , [this] (const EncryptionEvent&) { - emit encryption(); - return false; + emit encryption(); // It can only be done once, so emit it here. + return EncryptionOn; } ); } @@ -104,6 +104,24 @@ namespace QMatrixClient using rev_iter_t = Timeline::const_reverse_iterator; using timeline_iter_t = Timeline::const_iterator; + enum Change : uint { + NoChange = 0x0, + NameChange = 0x1, + CanonicalAliasChange = 0x2, + TopicChange = 0x4, + UnreadNotifsChange = 0x8, + AvatarChange = 0x10, + JoinStateChange = 0x20, + TagsChange = 0x40, + MembersChange = 0x80, + EncryptionOn = 0x100, + AccountDataChange = 0x200, + OtherChange = 0x1000, + AnyChange = 0x1FFF + }; + Q_DECLARE_FLAGS(Changes, Change) + Q_FLAG(Changes) + Room(Connection* connection, QString id, JoinState initialJoinState); ~Room() override; @@ -382,6 +400,13 @@ namespace QMatrixClient void pendingEventDiscarded(); void pendingEventChanged(int pendingEventIndex); + /** A common signal for various kinds of changes in the room + * Aside from all changes in the room state + * @param changes a set of flags describing what changes occured + * upon the last sync + * \sa StateChange + */ + void changed(Changes changes); /** * \brief The room name, the canonical alias or other aliases changed * @@ -441,7 +466,7 @@ namespace QMatrixClient protected: /// Returns true if any of room names/aliases has changed - virtual bool processStateEvent(const RoomEvent& e); + virtual Changes processStateEvent(const RoomEvent& e); virtual void processEphemeralEvent(EventPtr&& event); virtual void processAccountDataEvent(EventPtr&& event); virtual void onAddNewTimelineEvents(timeline_iter_t /*from*/) { } @@ -474,3 +499,4 @@ namespace QMatrixClient }; } // namespace QMatrixClient Q_DECLARE_METATYPE(QMatrixClient::FileTransferInfo) +Q_DECLARE_OPERATORS_FOR_FLAGS(QMatrixClient::Room::Changes) |