From 853fda2e7942ffb3bc8051e6411faa23cff6f3c2 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 3 May 2018 12:14:10 +0900 Subject: Cleanup --- lib/events/roommemberevent.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/events') diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h index 89b970c9..5f1e578d 100644 --- a/lib/events/roommemberevent.h +++ b/lib/events/roommemberevent.h @@ -56,12 +56,14 @@ namespace QMatrixClient using MembershipType = MemberEventContent::MembershipType; + explicit RoomMemberEvent(Type type, const QJsonObject& obj) + : StateEvent(type, obj) + { } RoomMemberEvent(MemberEventContent&& c) : StateEvent(Type::RoomMember, c) { } explicit RoomMemberEvent(const QJsonObject& obj) - : StateEvent(Type::RoomMember, obj) -// , _userId(obj["state_key"].toString()) + : RoomMemberEvent(Type::RoomMember, obj) { } MembershipType membership() const { return content().membership; } @@ -72,7 +74,6 @@ namespace QMatrixClient QUrl avatarUrl() const { return content().avatarUrl; } private: -// QString _userId; REGISTER_ENUM(MembershipType) }; } // namespace QMatrixClient -- cgit v1.2.3 From 564d518c086f2aeab0f0466b7cd1915e20edc7da Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 3 May 2018 21:23:28 +0900 Subject: GetRoomEventsJob (replaces RoomMessagesJob) + refactoring 1. Updates in this commit (see further) allow to generate and build GetRoomEventsJob from message_pagination.yaml; this job completely preempts RoomMessagesJob. 2. EventsBatch<> is no more a thing; there's EventsArray<> to replace it but it's loaded from a JSON array rather than an event batch (a JSON array inside another JSON object). SyncJob that used it extensively has been moved to "conventional" containers (Events, RoomEvents and the newly introduced StateEvents). RoomMessagesJob that also used EventsBatch<> is decommissioned (see above). 3. RoomEventsRange is now an alias for Range, defined in util.h (otherwise almost the same). 4. Connection::getMessages() is no more. Use Room::getPreviousContent() and Connection::callApi() instead. 5. Moving things around in Room, since SyncJob now supplies state events in more specific StateEvents, rather than RoomEvents. --- CMakeLists.txt | 1 - lib/connection.cpp | 6 - lib/connection.h | 4 +- lib/events/event.cpp | 23 ++-- lib/events/event.h | 86 ++++--------- lib/jobs/generated/message_pagination.cpp | 76 ++++++++++++ lib/jobs/generated/message_pagination.h | 40 ++++++ lib/jobs/roommessagesjob.cpp | 65 ---------- lib/jobs/roommessagesjob.h | 47 ------- lib/jobs/syncjob.cpp | 43 ++++--- lib/jobs/syncjob.h | 27 +--- lib/room.cpp | 200 +++++++++++++++--------------- lib/room.h | 11 +- lib/user.cpp | 23 ++-- lib/user.h | 3 +- lib/util.h | 31 +++++ libqmatrixclient.pri | 2 - 17 files changed, 330 insertions(+), 358 deletions(-) create mode 100644 lib/jobs/generated/message_pagination.cpp create mode 100644 lib/jobs/generated/message_pagination.h delete mode 100644 lib/jobs/roommessagesjob.cpp delete mode 100644 lib/jobs/roommessagesjob.h (limited to 'lib/events') diff --git a/CMakeLists.txt b/CMakeLists.txt index 49608f95..c69d0cfa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,6 @@ set(libqmatrixclient_SRCS lib/jobs/sendeventjob.cpp lib/jobs/setroomstatejob.cpp lib/jobs/joinroomjob.cpp - lib/jobs/roommessagesjob.cpp lib/jobs/syncjob.cpp lib/jobs/mediathumbnailjob.cpp lib/jobs/downloadfilejob.cpp diff --git a/lib/connection.cpp b/lib/connection.cpp index adeb7929..b433ccbc 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -30,7 +30,6 @@ #include "jobs/generated/account-data.h" #include "jobs/sendeventjob.h" #include "jobs/joinroomjob.h" -#include "jobs/roommessagesjob.h" #include "jobs/syncjob.h" #include "jobs/mediathumbnailjob.h" #include "jobs/downloadfilejob.h" @@ -372,11 +371,6 @@ void Connection::leaveRoom(Room* room) callApi(room->id()); } -RoomMessagesJob* Connection::getMessages(Room* room, const QString& from) const -{ - return callApi(room->id(), from); -} - inline auto splitMediaId(const QString& mediaId) { auto idParts = mediaId.split('/'); diff --git a/lib/connection.h b/lib/connection.h index 839371ef..22f71eac 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -331,9 +331,7 @@ namespace QMatrixClient RoomEvent* event) const; /** @deprecated Use callApi() or Room::leaveRoom() instead */ virtual void leaveRoom( Room* room ); - /** @deprecated User callApi() or Room::getPreviousContent() instead */ - virtual RoomMessagesJob* getMessages(Room* room, - const QString& from) const; + signals: /** * @deprecated diff --git a/lib/events/event.cpp b/lib/events/event.cpp index 193250de..57049671 100644 --- a/lib/events/event.cpp +++ b/lib/events/event.cpp @@ -160,14 +160,13 @@ void RoomEvent::addId(const QString& id) template <> RoomEventPtr _impl::doMakeEvent(const QJsonObject& obj) { - return RoomEventPtr { makeIfMatches - (obj, obj["type"].toString()) }; -} + // Check more specific event types first + if (auto e = doMakeEvent(obj)) + return e; -StateEventBase::~StateEventBase() = default; + return makeIfMatches(obj, obj["type"].toString()); +} bool StateEventBase::repeatsState() const { @@ -176,3 +175,13 @@ bool StateEventBase::repeatsState() const .toObject().value("prev_content"); return contentJson == prevContentJson; } + +template<> +StateEventPtr _impl::doMakeEvent(const QJsonObject& obj) +{ + return makeIfMatches(obj, obj["type"].toString()); + +} diff --git a/lib/events/event.h b/lib/events/event.h index 396406f1..8449c2ec 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -53,7 +53,10 @@ namespace QMatrixClient } template - event_ptr_tt doMakeEvent(const QJsonObject& obj); + inline event_ptr_tt doMakeEvent(const QJsonObject& obj) + { + return create(obj); + } } class Event @@ -114,7 +117,7 @@ namespace QMatrixClient * parameter type) and create an event object of that type. */ template - event_ptr_tt makeEvent(const QJsonObject& obj) + inline event_ptr_tt makeEvent(const QJsonObject& obj) { auto e = _impl::doMakeEvent(obj); if (!e) @@ -128,50 +131,17 @@ namespace QMatrixClient EventPtr doMakeEvent(const QJsonObject& obj); } - template <> struct FromJson + template struct FromJson> { - EventPtr operator()(const QJsonValue& jv) const + auto operator()(const QJsonValue& jv) const { - return makeEvent(jv.toObject()); + return makeEvent(jv.toObject()); } }; - /** - * \brief A vector of pointers to events with deserialisation capabilities - * - * This is a simple wrapper over a generic vector type that adds - * a convenience method to deserialise events from QJsonArray. - * \tparam EventT base type of all events in the vector - */ template - class EventsBatch : public std::vector> - { - public: - /** - * \brief Deserialise events from an array - * - * Given the following JSON construct, creates events from - * the array stored at key "node": - * \code - * "container": { - * "node": [ { "event_id": "!evt1:srv.org", ... }, ... ] - * } - * \endcode - * \param container - the wrapping JSON object - * \param node - the key in container that holds the array of events - */ - void fromJson(const QJsonObject& container, const QString& node) - { - const auto objs = container.value(node).toArray(); - using size_type = typename std::vector>::size_type; - // The below line accommodates the difference in size types of - // STL and Qt containers. - this->reserve(static_cast(objs.size())); - for (const auto& objValue: objs) - this->emplace_back(makeEvent(objValue.toObject())); - } - }; - using Events = EventsBatch; + using EventsArray = std::vector>; + using Events = EventsArray; class RedactionEvent; @@ -231,8 +201,9 @@ namespace QMatrixClient event_ptr_tt _redactedBecause; QString _txnId; }; - using RoomEvents = EventsBatch; using RoomEventPtr = event_ptr_tt; + using RoomEvents = EventsArray; + using RoomEventsRange = Range; namespace _impl { @@ -240,29 +211,6 @@ namespace QMatrixClient RoomEventPtr doMakeEvent(const QJsonObject& obj); } - /** - * Conceptually similar to QStringView (but much more primitive), it's a - * simple abstraction over a pair of RoomEvents::const_iterator values - * referring to the beginning and the end of a range in a RoomEvents - * container. - */ - struct RoomEventsRange - { - RoomEvents::iterator from; - RoomEvents::iterator to; - - RoomEvents::size_type size() const - { - Q_ASSERT(std::distance(from, to) >= 0); - return RoomEvents::size_type(std::distance(from, to)); - } - bool empty() const { return from == to; } - RoomEvents::const_iterator begin() const { return from; } - RoomEvents::const_iterator end() const { return to; } - RoomEvents::iterator begin() { return from; } - RoomEvents::iterator end() { return to; } - }; - class StateEventBase: public RoomEvent { public: @@ -273,10 +221,18 @@ namespace QMatrixClient explicit StateEventBase(Type type) : RoomEvent(type) { } - ~StateEventBase() override = 0; + ~StateEventBase() override = default; virtual bool repeatsState() const; }; + using StateEventPtr = event_ptr_tt; + using StateEvents = EventsArray; + + namespace _impl + { + template <> + StateEventPtr doMakeEvent(const QJsonObject& obj); + } template struct Prev diff --git a/lib/jobs/generated/message_pagination.cpp b/lib/jobs/generated/message_pagination.cpp new file mode 100644 index 00000000..f89ccd03 --- /dev/null +++ b/lib/jobs/generated/message_pagination.cpp @@ -0,0 +1,76 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "message_pagination.h" + +#include "converters.h" + +#include + +using namespace QMatrixClient; + +static const auto basePath = QStringLiteral("/_matrix/client/r0"); + +class GetRoomEventsJob::Private +{ + public: + QString begin; + QString end; + RoomEvents chunk; +}; + +BaseJob::Query queryToGetRoomEvents(const QString& from, const QString& to, const QString& dir, int limit, const QString& filter) +{ + BaseJob::Query _q; + _q.addQueryItem("from", from); + if (!to.isEmpty()) + _q.addQueryItem("to", to); + _q.addQueryItem("dir", dir); + _q.addQueryItem("limit", QString("%1").arg(limit)); + if (!filter.isEmpty()) + _q.addQueryItem("filter", filter); + return _q; +} + +QUrl GetRoomEventsJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& from, const QString& dir, const QString& to, int limit, const QString& filter) +{ + return BaseJob::makeRequestUrl(std::move(baseUrl), + basePath % "/rooms/" % roomId % "/messages", + queryToGetRoomEvents(from, to, dir, limit, filter)); +} + +GetRoomEventsJob::GetRoomEventsJob(const QString& roomId, const QString& from, const QString& dir, const QString& to, int limit, const QString& filter) + : BaseJob(HttpVerb::Get, "GetRoomEventsJob", + basePath % "/rooms/" % roomId % "/messages", + queryToGetRoomEvents(from, to, dir, limit, filter)) + , d(new Private) +{ +} + +GetRoomEventsJob::~GetRoomEventsJob() = default; + +const QString& GetRoomEventsJob::begin() const +{ + return d->begin; +} + +const QString& GetRoomEventsJob::end() const +{ + return d->end; +} + +RoomEvents&& GetRoomEventsJob::chunk() +{ + return std::move(d->chunk); +} + +BaseJob::Status GetRoomEventsJob::parseJson(const QJsonDocument& data) +{ + auto json = data.object(); + d->begin = fromJson(json.value("start")); + d->end = fromJson(json.value("end")); + d->chunk = fromJson(json.value("chunk")); + return Success; +} + diff --git a/lib/jobs/generated/message_pagination.h b/lib/jobs/generated/message_pagination.h new file mode 100644 index 00000000..b8588ad1 --- /dev/null +++ b/lib/jobs/generated/message_pagination.h @@ -0,0 +1,40 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "../basejob.h" + +#include "events/event.h" + + +namespace QMatrixClient +{ + // Operations + + class GetRoomEventsJob : public BaseJob + { + public: + /** Construct a URL out of baseUrl and usual parameters passed to + * GetRoomEventsJob. This function can be used when + * a URL for GetRoomEventsJob is necessary but the job + * itself isn't. + */ + static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& from, const QString& dir, const QString& to = {}, int limit = {}, const QString& filter = {}); + + explicit GetRoomEventsJob(const QString& roomId, const QString& from, const QString& dir, const QString& to = {}, int limit = {}, const QString& filter = {}); + ~GetRoomEventsJob() override; + + const QString& begin() const; + const QString& end() const; + RoomEvents&& chunk(); + + protected: + Status parseJson(const QJsonDocument& data) override; + + private: + class Private; + QScopedPointer d; + }; +} // namespace QMatrixClient diff --git a/lib/jobs/roommessagesjob.cpp b/lib/jobs/roommessagesjob.cpp deleted file mode 100644 index e5568f17..00000000 --- a/lib/jobs/roommessagesjob.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2016 Felix Rohrbach - * - * 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 "roommessagesjob.h" - -using namespace QMatrixClient; - -class RoomMessagesJob::Private -{ - public: - RoomEvents events; - QString end; -}; - -RoomMessagesJob::RoomMessagesJob(const QString& roomId, const QString& from, - int limit, FetchDirection dir) - : BaseJob(HttpVerb::Get, "RoomMessagesJob", - QStringLiteral("/_matrix/client/r0/rooms/%1/messages").arg(roomId), - Query( - { { "from", from } - , { "dir", dir == FetchDirection::Backward ? "b" : "f" } - , { "limit", QString::number(limit) } - })) - , d(new Private) -{ - qCDebug(JOBS) << "Room messages query:" << query().toString(QUrl::PrettyDecoded); -} - -RoomMessagesJob::~RoomMessagesJob() -{ - delete d; -} - -RoomEvents&& RoomMessagesJob::releaseEvents() -{ - return move(d->events); -} - -QString RoomMessagesJob::end() const -{ - return d->end; -} - -BaseJob::Status RoomMessagesJob::parseJson(const QJsonDocument& data) -{ - const auto obj = data.object(); - d->events.fromJson(obj, "chunk"); - d->end = obj.value("end").toString(); - return Success; -} diff --git a/lib/jobs/roommessagesjob.h b/lib/jobs/roommessagesjob.h deleted file mode 100644 index 7b3fd9c9..00000000 --- a/lib/jobs/roommessagesjob.h +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2016 Felix Rohrbach - * - * 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 "basejob.h" - -#include "../events/event.h" - -namespace QMatrixClient -{ - enum class FetchDirection { Backward, Forward }; - - class RoomMessagesJob: public BaseJob - { - public: - RoomMessagesJob(const QString& roomId, const QString& from, - int limit = 10, - FetchDirection dir = FetchDirection::Backward); - virtual ~RoomMessagesJob(); - - RoomEvents&& releaseEvents(); - QString end() const; - - protected: - Status parseJson(const QJsonDocument& data) override; - - private: - class Private; - Private* d; - }; -} // namespace QMatrixClient diff --git a/lib/jobs/syncjob.cpp b/lib/jobs/syncjob.cpp index 435dfd0e..a739ea0d 100644 --- a/lib/jobs/syncjob.cpp +++ b/lib/jobs/syncjob.cpp @@ -54,11 +54,17 @@ SyncDataList&& SyncData::takeRoomData() return std::move(roomData); } -SyncBatch&& SyncData::takeAccountData() +Events&& SyncData::takeAccountData() { return std::move(accountData); } +template +inline EventsArrayT load(const QJsonObject& batches, StrT keyName) +{ + return fromJson(batches[keyName].toObject().value("events")); +} + BaseJob::Status SyncJob::parseJson(const QJsonDocument& data) { return d.parseJson(data); @@ -71,7 +77,7 @@ BaseJob::Status SyncData::parseJson(const QJsonDocument &data) auto json = data.object(); nextBatch_ = json.value("next_batch").toString(); // TODO: presence - accountData.fromJson(json); + accountData = load(json, "account_data"); QJsonObject rooms = json.value("rooms").toObject(); JoinStates::Int ii = 1; // ii is used to make a JoinState value @@ -96,33 +102,26 @@ SyncRoomData::SyncRoomData(const QString& roomId_, JoinState joinState_, const QJsonObject& room_) : roomId(roomId_) , joinState(joinState_) - , state(joinState == JoinState::Invite ? "invite_state" : "state") - , timeline("timeline") - , ephemeral("ephemeral") - , accountData("account_data") + , state(load(room_, + joinState == JoinState::Invite ? "invite_state" : "state")) { switch (joinState) { - case JoinState::Invite: - state.fromJson(room_); - break; case JoinState::Join: - state.fromJson(room_); - timeline.fromJson(room_); - ephemeral.fromJson(room_); - accountData.fromJson(room_); - break; + ephemeral = load(room_, "ephemeral"); + accountData = load(room_, "account_data"); + // [[fallthrough]] case JoinState::Leave: - state.fromJson(room_); - timeline.fromJson(room_); + { + timeline = load(room_, "timeline"); + auto timelineJson = room_.value("timeline").toObject(); + timelineLimited = timelineJson.value("limited").toBool(); + timelinePrevBatch = timelineJson.value("prev_batch").toString(); + break; - default: - qCWarning(SYNCJOB) << "SyncRoomData: Unknown JoinState value, ignoring:" << int(joinState); + } + default: /* nothing on top of state */; } - auto timelineJson = room_.value("timeline").toObject(); - timelineLimited = timelineJson.value("limited").toBool(); - timelinePrevBatch = timelineJson.value("prev_batch").toString(); - auto unreadJson = room_.value("unread_notifications").toObject(); unreadCount = unreadJson.value(UnreadCountKey).toInt(-2); highlightCount = unreadJson.value("highlight_count").toInt(); diff --git a/lib/jobs/syncjob.h b/lib/jobs/syncjob.h index 919060be..b12f9fff 100644 --- a/lib/jobs/syncjob.h +++ b/lib/jobs/syncjob.h @@ -26,30 +26,15 @@ namespace QMatrixClient { - template - class SyncBatch : public EventsBatch - { - public: - explicit SyncBatch(QString k) : jsonKey(std::move(k)) { } - void fromJson(const QJsonObject& roomContents) - { - EventsBatch::fromJson( - roomContents[jsonKey].toObject(), "events"); - } - - private: - QString jsonKey; - }; - class SyncRoomData { public: QString roomId; JoinState joinState; - SyncBatch state; - SyncBatch timeline; - SyncBatch ephemeral; - SyncBatch accountData; + StateEvents state; + RoomEvents timeline; + Events ephemeral; + Events accountData; bool timelineLimited; QString timelinePrevBatch; @@ -71,13 +56,13 @@ namespace QMatrixClient { public: BaseJob::Status parseJson(const QJsonDocument &data); - SyncBatch&& takeAccountData(); + Events&& takeAccountData(); SyncDataList&& takeRoomData(); QString nextBatch() const; private: QString nextBatch_; - SyncBatch accountData { "account_data" }; + Events accountData; SyncDataList roomData; }; diff --git a/lib/room.cpp b/lib/room.cpp index 5771c51d..6c708a42 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -25,6 +25,7 @@ #include "jobs/generated/receipts.h" #include "jobs/generated/redaction.h" #include "jobs/generated/account-data.h" +#include "jobs/generated/message_pagination.h" #include "jobs/setroomstatejob.h" #include "events/simplestateevents.h" #include "events/roomavatarevent.h" @@ -33,7 +34,6 @@ #include "events/receiptevent.h" #include "events/redactionevent.h" #include "jobs/sendeventjob.h" -#include "jobs/roommessagesjob.h" #include "jobs/mediathumbnailjob.h" #include "jobs/downloadfilejob.h" #include "jobs/postreadmarkersjob.h" @@ -112,7 +112,7 @@ class Room::Private TagsMap tags; QHash accountData; QString prevBatch; - QPointer roomMessagesJob; + QPointer eventsHistoryJob; struct FileTransferPrivateInfo { @@ -1036,21 +1036,31 @@ void Room::updateData(SyncRoomData&& data) for (auto&& event: data.accountData) processAccountDataEvent(move(event)); + bool emitNamesChanged = false; if (!data.state.empty()) { et.restart(); - processStateEvents(data.state); - qCDebug(PROFILER) << "*** Room::processStateEvents(state):" + for (const auto& e: data.state) + emitNamesChanged |= processStateEvent(*e); + + qCDebug(PROFILER) << "*** Room::processStateEvents():" << data.state.size() << "event(s)," << et; } if (!data.timeline.empty()) { et.restart(); // State changes can arrive in a timeline event; so check those. - processStateEvents(data.timeline); + for (const auto& e: data.timeline) + emitNamesChanged |= processStateEvent(*e); qCDebug(PROFILER) << "*** Room::processStateEvents(timeline):" << data.timeline.size() << "event(s)," << et; + } + if (emitNamesChanged) + emit namesChanged(this); + d->updateDisplayname(); + if (!data.timeline.empty()) + { et.restart(); d->addNewMessageEvents(move(data.timeline)); qCDebug(PROFILER) << "*** Room::addNewMessageEvents():" << et; @@ -1122,13 +1132,13 @@ void Room::getPreviousContent(int limit) void Room::Private::getPreviousContent(int limit) { - if( !isJobRunning(roomMessagesJob) ) + if( !isJobRunning(eventsHistoryJob) ) { - roomMessagesJob = - connection->callApi(id, prevBatch, limit); - connect( roomMessagesJob, &RoomMessagesJob::success, [=] { - prevBatch = roomMessagesJob->end(); - addHistoricalMessageEvents(roomMessagesJob->releaseEvents()); + eventsHistoryJob = + connection->callApi(id, prevBatch, "b", "", limit); + connect( eventsHistoryJob, &BaseJob::success, q, [=] { + prevBatch = eventsHistoryJob->end(); + addHistoricalMessageEvents(eventsHistoryJob->chunk()); }); } } @@ -1450,107 +1460,95 @@ void Room::Private::addHistoricalMessageEvents(RoomEvents&& events) Q_ASSERT(timeline.size() == timelineSize + insertedSize); } -void Room::processStateEvents(const RoomEvents& events) +bool Room::processStateEvent(const RoomEvent& e) { - bool emitNamesChanged = false; - for (const auto& e: events) + switch (e.type()) { - switch (e->type()) - { - case EventType::RoomName: { - auto* nameEvent = weakPtr(e); - d->name = nameEvent->name(); - qCDebug(MAIN) << "Room name updated:" << d->name; - emitNamesChanged = true; - break; - } - case EventType::RoomAliases: { - auto* aliasesEvent = weakPtr(e); - d->aliases = aliasesEvent->aliases(); - qCDebug(MAIN) << "Room aliases updated:" << d->aliases; - emitNamesChanged = true; - break; - } - case EventType::RoomCanonicalAlias: { - auto* aliasEvent = weakPtr(e); - d->canonicalAlias = aliasEvent->alias(); - setObjectName(d->canonicalAlias); - qCDebug(MAIN) << "Room canonical alias updated:" << d->canonicalAlias; - emitNamesChanged = true; - break; - } - case EventType::RoomTopic: { - auto* topicEvent = weakPtr(e); - d->topic = topicEvent->topic(); - qCDebug(MAIN) << "Room topic updated:" << d->topic; - emit topicChanged(); - break; + case EventType::RoomName: { + d->name = static_cast(e).name(); + qCDebug(MAIN) << "Room name updated:" << d->name; + return true; + } + case EventType::RoomAliases: { + d->aliases = static_cast(e).aliases(); + qCDebug(MAIN) << "Room aliases updated:" << d->aliases; + return true; + } + case EventType::RoomCanonicalAlias: { + d->canonicalAlias = + static_cast(e).alias(); + setObjectName(d->canonicalAlias); + qCDebug(MAIN) << "Room canonical alias updated:" << d->canonicalAlias; + return true; + } + case EventType::RoomTopic: { + d->topic = static_cast(e).topic(); + qCDebug(MAIN) << "Room topic updated:" << d->topic; + emit topicChanged(); + return false; + } + case EventType::RoomAvatar: { + const auto& avatarEventContent = + static_cast(e).content(); + if (d->avatar.updateUrl(avatarEventContent.url)) + { + qCDebug(MAIN) << "Room avatar URL updated:" + << avatarEventContent.url.toString(); + emit avatarChanged(); } - case EventType::RoomAvatar: { - const auto& avatarEventContent = - weakPtr(e)->content(); - if (d->avatar.updateUrl(avatarEventContent.url)) + return false; + } + case EventType::RoomMember: { + const auto& memberEvent = static_cast(e); + auto* u = user(memberEvent.userId()); + u->processEvent(memberEvent, this); + if (u == localUser() && memberJoinState(u) == JoinState::Invite + && memberEvent.isDirect()) + connection()->addToDirectChats(this, + user(memberEvent.senderId())); + + if( memberEvent.membership() == MembershipType::Join ) + { + if (memberJoinState(u) != JoinState::Join) { - qCDebug(MAIN) << "Room avatar URL updated:" - << avatarEventContent.url.toString(); - emit avatarChanged(); + d->insertMemberIntoMap(u); + connect(u, &User::nameAboutToChange, this, + [=] (QString newName, QString, const Room* context) { + if (context == this) + emit memberAboutToRename(u, newName); + }); + connect(u, &User::nameChanged, this, + [=] (QString, QString oldName, const Room* context) { + if (context == this) + d->renameMember(u, oldName); + }); + emit userAdded(u); } - break; } - case EventType::RoomMember: { - auto* memberEvent = weakPtr(e); - auto u = user(memberEvent->userId()); - u->processEvent(memberEvent, this); - if (u == localUser() && memberJoinState(u) == JoinState::Invite - && memberEvent->isDirect()) - connection()->addToDirectChats(this, - user(memberEvent->senderId())); - - if( memberEvent->membership() == MembershipType::Join ) - { - if (memberJoinState(u) != JoinState::Join) - { - d->insertMemberIntoMap(u); - connect(u, &User::nameAboutToChange, this, - [=] (QString newName, QString, const Room* context) { - if (context == this) - emit memberAboutToRename(u, newName); - }); - connect(u, &User::nameChanged, this, - [=] (QString, QString oldName, const Room* context) { - if (context == this) - d->renameMember(u, oldName); - }); - emit userAdded(u); - } - } - else if( memberEvent->membership() == MembershipType::Leave ) + else if( memberEvent.membership() == MembershipType::Leave ) + { + if (memberJoinState(u) == JoinState::Join) { - if (memberJoinState(u) == JoinState::Join) - { - if (!d->membersLeft.contains(u)) - d->membersLeft.append(u); - d->removeMemberFromMap(u->name(this), u); - emit userRemoved(u); - } + if (!d->membersLeft.contains(u)) + d->membersLeft.append(u); + d->removeMemberFromMap(u->name(this), u); + emit userRemoved(u); } - break; } - case EventType::RoomEncryption: - { - d->encryptionAlgorithm = - weakPtr(e)->algorithm(); - qCDebug(MAIN) << "Encryption switched on in" << displayName(); - emit encryption(); - break; - } - default: /* Ignore events of other types */; + return false; } + case EventType::RoomEncryption: + { + d->encryptionAlgorithm = + static_cast(e).algorithm(); + qCDebug(MAIN) << "Encryption switched on in" << displayName(); + emit encryption(); + return false; + } + default: + /* Ignore events of other types */ + return false; } - if (emitNamesChanged) { - emit namesChanged(this); - } - d->updateDisplayname(); } void Room::processEphemeralEvent(EventPtr&& event) diff --git a/lib/room.h b/lib/room.h index 288db5fb..7b4b3578 100644 --- a/lib/room.h +++ b/lib/room.h @@ -408,13 +408,14 @@ namespace QMatrixClient void fileTransferCancelled(QString id); protected: - virtual void processStateEvents(const RoomEvents& events); + /// Returns true if any of room names/aliases has changed + virtual bool processStateEvent(const RoomEvent& e); 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 onAddNewTimelineEvents(timeline_iter_t /*from*/) { } + virtual void onAddHistoricalTimelineEvents(rev_iter_t /*from*/) { } + virtual void onRedaction(const RoomEvent& /*prevEvent*/, + const RoomEvent& /*after*/) { } private: class Private; diff --git a/lib/user.cpp b/lib/user.cpp index 91b340d5..89e324f9 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -358,19 +358,20 @@ QUrl User::avatarUrl(const Room* room) const return avatarObject(room).url(); } -void User::processEvent(const RoomMemberEvent* event, const Room* room) +void User::processEvent(const RoomMemberEvent& event, const Room* room) { - if (event->membership() != MembershipType::Invite && - event->membership() != MembershipType::Join) + Q_ASSERT(room); + if (event.membership() != MembershipType::Invite && + event.membership() != MembershipType::Join) return; auto aboutToEnter = room->memberJoinState(this) == JoinState::Leave && - (event->membership() == MembershipType::Join || - event->membership() == MembershipType::Invite); + (event.membership() == MembershipType::Join || + event.membership() == MembershipType::Invite); if (aboutToEnter) ++d->totalRooms; - auto newName = event->displayName(); + auto newName = event.displayName(); // `bridged` value uses the same notification signal as the name; // it is assumed that first setting of the bridge occurs together with // the first setting of the name, and further bridge updates are @@ -390,17 +391,17 @@ void User::processEvent(const RoomMemberEvent* event, const Room* room) } newName.truncate(match.capturedStart(0)); } - if (event->prevContent()) + if (event.prevContent()) { // FIXME: the hint doesn't work for bridged users auto oldNameHint = - d->nameForRoom(room, event->prevContent()->displayName); + d->nameForRoom(room, event.prevContent()->displayName); updateName(newName, oldNameHint, room); - updateAvatarUrl(event->avatarUrl(), - d->avatarUrlForRoom(room, event->prevContent()->avatarUrl), + updateAvatarUrl(event.avatarUrl(), + d->avatarUrlForRoom(room, event.prevContent()->avatarUrl), room); } else { updateName(newName, room); - updateAvatarUrl(event->avatarUrl(), d->avatarUrlForRoom(room), room); + updateAvatarUrl(event.avatarUrl(), d->avatarUrlForRoom(room), room); } } diff --git a/lib/user.h b/lib/user.h index 8ac96539..76aa672f 100644 --- a/lib/user.h +++ b/lib/user.h @@ -103,8 +103,7 @@ namespace QMatrixClient QString avatarMediaId(const Room* room = nullptr) const; QUrl avatarUrl(const Room* room = nullptr) const; - void processEvent(const RoomMemberEvent* event, - const Room* r = nullptr); + void processEvent(const RoomMemberEvent& event, const Room* r); public slots: void rename(const QString& newName); diff --git a/lib/util.h b/lib/util.h index 55f3af6a..f65b05a3 100644 --- a/lib/util.h +++ b/lib/util.h @@ -58,6 +58,37 @@ namespace QMatrixClient static void qAsConst(const T &&) Q_DECL_EQ_DELETE; #endif + /** An abstraction over a pair of iterators + * This is a very basic range type over a container with iterators that + * are at least ForwardIterators. Inspired by Ranges TS. + */ + template + class Range + { + // Looking forward for Ranges TS to produce something (in C++23?..) + using iterator = typename ArrayT::iterator; + using const_iterator = typename ArrayT::const_iterator; + using size_type = typename ArrayT::size_type; + public: + Range(ArrayT& arr) : from(std::begin(arr)), to(std::end(arr)) { } + Range(iterator from, iterator to) : from(from), to(to) { } + + size_type size() const + { + Q_ASSERT(std::distance(from, to) >= 0); + return size_type(std::distance(from, to)); + } + bool empty() const { return from == to; } + const_iterator begin() const { return from; } + const_iterator end() const { return to; } + iterator begin() { return from; } + iterator end() { return to; } + + private: + iterator from; + iterator to; + }; + /** A guard pointer that disconnects an interested object upon destruction * It's almost QPointer<> except that you have to initialise it with one * more additional parameter - a pointer to a QObject that will be diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri index 4a0928b0..52a12be0 100644 --- a/libqmatrixclient.pri +++ b/libqmatrixclient.pri @@ -35,7 +35,6 @@ HEADERS += \ $$SRCPATH/jobs/sendeventjob.h \ $$SRCPATH/jobs/postreceiptjob.h \ $$SRCPATH/jobs/joinroomjob.h \ - $$SRCPATH/jobs/roommessagesjob.h \ $$SRCPATH/jobs/syncjob.h \ $$SRCPATH/jobs/mediathumbnailjob.h \ $$SRCPATH/jobs/setroomstatejob.h \ @@ -68,7 +67,6 @@ SOURCES += \ $$SRCPATH/jobs/sendeventjob.cpp \ $$SRCPATH/jobs/postreceiptjob.cpp \ $$SRCPATH/jobs/joinroomjob.cpp \ - $$SRCPATH/jobs/roommessagesjob.cpp \ $$SRCPATH/jobs/syncjob.cpp \ $$SRCPATH/jobs/mediathumbnailjob.cpp \ $$SRCPATH/jobs/setroomstatejob.cpp \ -- cgit v1.2.3 From 28a0d70164e2596d306521cd18d25c0e8c0b5336 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 4 May 2018 12:13:43 +0900 Subject: EvT::TypeId: Use a member function instead of a variable The latter one causes linkage errors when used from a template method (but not from a template class, puzzlingly). --- lib/events/accountdataevents.h | 3 +-- lib/events/directchatevent.h | 2 +- lib/events/event.cpp | 2 +- lib/events/receiptevent.cpp | 2 +- lib/events/receiptevent.h | 2 +- lib/events/redactionevent.h | 2 +- lib/events/roomavatarevent.h | 2 +- lib/events/roommemberevent.h | 2 +- lib/events/roommessageevent.h | 2 +- lib/events/simplestateevents.h | 2 +- lib/events/typingevent.h | 2 +- lib/jobs/sendeventjob.h | 2 +- lib/jobs/setroomstatejob.h | 4 ++-- lib/room.cpp | 2 +- 14 files changed, 15 insertions(+), 16 deletions(-) (limited to 'lib/events') diff --git a/lib/events/accountdataevents.h b/lib/events/accountdataevents.h index f3ba27bb..11667172 100644 --- a/lib/events/accountdataevents.h +++ b/lib/events/accountdataevents.h @@ -54,8 +54,7 @@ namespace QMatrixClient class _Name : public Event \ { \ public: \ - static constexpr const char* TypeId = _TypeId; \ - static const char* typeId() { return TypeId; } \ + static constexpr const char* typeId() { return _TypeId; } \ explicit _Name(const QJsonObject& obj) \ : Event((_EnumType), obj) \ , _content(contentJson(), QStringLiteral(#_ContentKey)) \ diff --git a/lib/events/directchatevent.h b/lib/events/directchatevent.h index 2b0ad0a0..bd8f2d35 100644 --- a/lib/events/directchatevent.h +++ b/lib/events/directchatevent.h @@ -29,6 +29,6 @@ namespace QMatrixClient QMultiHash usersToDirectChats() const; - static constexpr const char * TypeId = "m.direct"; + static constexpr const char* typeId() { return "m.direct"; } }; } diff --git a/lib/events/event.cpp b/lib/events/event.cpp index 57049671..c2b92a50 100644 --- a/lib/events/event.cpp +++ b/lib/events/event.cpp @@ -76,7 +76,7 @@ template inline event_ptr_tt makeIfMatches(const QJsonObject& o, const QString& selector) { - if (selector == EventT::TypeId) + if (selector == EventT::typeId()) return _impl::create(o); return makeIfMatches(o, selector); diff --git a/lib/events/receiptevent.cpp b/lib/events/receiptevent.cpp index 7555db82..a12f4c05 100644 --- a/lib/events/receiptevent.cpp +++ b/lib/events/receiptevent.cpp @@ -43,7 +43,7 @@ using namespace QMatrixClient; ReceiptEvent::ReceiptEvent(const QJsonObject& obj) : Event(Type::Receipt, obj) { - Q_ASSERT(obj["type"].toString() == TypeId); + Q_ASSERT(obj["type"].toString() == typeId()); const QJsonObject contents = contentJson(); _eventsWithReceipts.reserve(contents.size()); diff --git a/lib/events/receiptevent.h b/lib/events/receiptevent.h index 5b99ae3f..e1d2d1ec 100644 --- a/lib/events/receiptevent.h +++ b/lib/events/receiptevent.h @@ -42,7 +42,7 @@ namespace QMatrixClient EventsWithReceipts eventsWithReceipts() const { return _eventsWithReceipts; } - static constexpr const char* const TypeId = "m.receipt"; + static constexpr const char* typeId() { return "m.receipt"; } private: EventsWithReceipts _eventsWithReceipts; diff --git a/lib/events/redactionevent.h b/lib/events/redactionevent.h index 829b9085..dad54788 100644 --- a/lib/events/redactionevent.h +++ b/lib/events/redactionevent.h @@ -25,7 +25,7 @@ namespace QMatrixClient class RedactionEvent : public RoomEvent { public: - static constexpr const char* const TypeId = "m.room.redaction"; + static constexpr const char* typeId() { return "m.room.redaction"; } explicit RedactionEvent(const QJsonObject& obj) : RoomEvent(Type::Redaction, obj) diff --git a/lib/events/roomavatarevent.h b/lib/events/roomavatarevent.h index ccfe8fbf..0e44ad7c 100644 --- a/lib/events/roomavatarevent.h +++ b/lib/events/roomavatarevent.h @@ -37,7 +37,7 @@ namespace QMatrixClient : StateEvent(Type::RoomAvatar, obj) { } - static constexpr const char* TypeId = "m.room.avatar"; + static constexpr const char* typeId() { return "m.room.avatar"; } }; } // namespace QMatrixClient diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h index 5f1e578d..8e0cc0a4 100644 --- a/lib/events/roommemberevent.h +++ b/lib/events/roommemberevent.h @@ -52,7 +52,7 @@ namespace QMatrixClient { Q_GADGET public: - static constexpr const char* TypeId = "m.room.member"; + static constexpr const char* typeId() { return "m.room.member"; } using MembershipType = MemberEventContent::MembershipType; diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index a55564ed..dc734b6e 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -65,7 +65,7 @@ namespace QMatrixClient QJsonObject toJson() const; - static constexpr const char* TypeId = "m.room.message"; + static constexpr const char* typeId() { return "m.room.message"; } private: QString _msgtype; diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h index 6b0cd51a..d9f403e8 100644 --- a/lib/events/simplestateevents.h +++ b/lib/events/simplestateevents.h @@ -28,7 +28,7 @@ namespace QMatrixClient : public StateEvent> \ { \ public: \ - static constexpr const char* TypeId = _TypeId; \ + static constexpr const char* typeId() { return _TypeId; } \ explicit _Name(const QJsonObject& obj) \ : StateEvent(_EnumType, obj, QStringLiteral(#_ContentKey)) \ { } \ diff --git a/lib/events/typingevent.h b/lib/events/typingevent.h index 8c9551a4..6ccbc1c8 100644 --- a/lib/events/typingevent.h +++ b/lib/events/typingevent.h @@ -27,7 +27,7 @@ namespace QMatrixClient class TypingEvent: public Event { public: - static constexpr const char* const TypeId = "m.typing"; + static constexpr const char* typeId() { return "m.typing"; } TypingEvent(const QJsonObject& obj); diff --git a/lib/jobs/sendeventjob.h b/lib/jobs/sendeventjob.h index 3a11eb6a..a3e9a291 100644 --- a/lib/jobs/sendeventjob.h +++ b/lib/jobs/sendeventjob.h @@ -32,7 +32,7 @@ namespace QMatrixClient SendEventJob(const QString& roomId, const EvT& event) : BaseJob(HttpVerb::Put, QStringLiteral("SendEventJob"), QStringLiteral("_matrix/client/r0/rooms/%1/send/%2/") - .arg(roomId, EvT::TypeId), // See also beforeStart() + .arg(roomId, EvT::typeId()), // See also beforeStart() Query(), Data(event.toJson())) { } diff --git a/lib/jobs/setroomstatejob.h b/lib/jobs/setroomstatejob.h index b7e6d4a1..36047667 100644 --- a/lib/jobs/setroomstatejob.h +++ b/lib/jobs/setroomstatejob.h @@ -36,7 +36,7 @@ namespace QMatrixClient const EvT& event) : BaseJob(HttpVerb::Put, "SetRoomStateJob", QStringLiteral("_matrix/client/r0/rooms/%1/state/%2/%3") - .arg(roomId, EvT::TypeId, stateKey), + .arg(roomId, EvT::typeId(), stateKey), Query(), Data(event.toJson())) { } @@ -48,7 +48,7 @@ namespace QMatrixClient SetRoomStateJob(const QString& roomId, const EvT& event) : BaseJob(HttpVerb::Put, "SetRoomStateJob", QStringLiteral("_matrix/client/r0/rooms/%1/state/%2") - .arg(roomId, EvT::TypeId), + .arg(roomId, EvT::typeId()), Query(), Data(event.toJson())) { } diff --git a/lib/room.cpp b/lib/room.cpp index 6c708a42..f8f195e1 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1774,7 +1774,7 @@ void appendEvent(QJsonArray& events, const QString& type, template void appendEvent(QJsonArray& events, const EvtT& event) { - appendEvent(events, EvtT::TypeId, event.toJson()); + appendEvent(events, EvtT::typeId(), event.toJson()); } QJsonObject Room::Private::toJson() const -- cgit v1.2.3 From f70ec41accd6da9f223bc41b446ad1d2d77de3f4 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 1 May 2018 21:08:06 +0900 Subject: Fix building on OSX --- lib/events/event.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/events') diff --git a/lib/events/event.cpp b/lib/events/event.cpp index c2b92a50..576e9426 100644 --- a/lib/events/event.cpp +++ b/lib/events/event.cpp @@ -87,7 +87,7 @@ EventPtr _impl::doMakeEvent(const QJsonObject& obj) { // Check more specific event types first if (auto e = doMakeEvent(obj)) - return e; + return ptrCast(move(e)); return makeIfMatches( @@ -162,7 +162,7 @@ RoomEventPtr _impl::doMakeEvent(const QJsonObject& obj) { // Check more specific event types first if (auto e = doMakeEvent(obj)) - return e; + return ptrCast(move(e)); return makeIfMatches(obj, obj["type"].toString()); -- cgit v1.2.3