diff options
Diffstat (limited to 'lib/connection.cpp')
-rw-r--r-- | lib/connection.cpp | 826 |
1 files changed, 377 insertions, 449 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp index 26b40c03..2b1cc1b9 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -13,39 +13,39 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "connection.h" #include "connectiondata.h" -#include "user.h" -#include "events/directchatevent.h" -#include "events/eventloader.h" -#include "room.h" -#include "settings.h" -#include "csapi/login.h" +#include "csapi/account-data.h" #include "csapi/capabilities.h" +#include "csapi/joining.h" +#include "csapi/leaving.h" +#include "csapi/login.h" #include "csapi/logout.h" #include "csapi/receipts.h" -#include "csapi/leaving.h" -#include "csapi/account-data.h" -#include "csapi/joining.h" -#include "csapi/to_device.h" #include "csapi/room_send.h" -#include "jobs/syncjob.h" -#include "jobs/mediathumbnailjob.h" -#include "jobs/downloadfilejob.h" +#include "csapi/to_device.h" #include "csapi/voip.h" +#include "events/directchatevent.h" +#include "events/eventloader.h" +#include "jobs/downloadfilejob.h" +#include "jobs/mediathumbnailjob.h" +#include "jobs/syncjob.h" +#include "room.h" +#include "settings.h" +#include "user.h" -#include <QtNetwork/QDnsLookup> -#include <QtCore/QFile> +#include <QtCore/QCoreApplication> #include <QtCore/QDir> -#include <QtCore/QStandardPaths> -#include <QtCore/QStringBuilder> #include <QtCore/QElapsedTimer> -#include <QtCore/QRegularExpression> +#include <QtCore/QFile> #include <QtCore/QMimeDatabase> -#include <QtCore/QCoreApplication> +#include <QtCore/QRegularExpression> +#include <QtCore/QStandardPaths> +#include <QtCore/QStringBuilder> +#include <QtNetwork/QDnsLookup> using namespace QMatrixClient; @@ -54,10 +54,8 @@ template <typename HashT, typename Pred> HashT erase_if(HashT& hashMap, Pred pred) { HashT removals; - for (auto it = hashMap.begin(); it != hashMap.end();) - { - if (pred(it)) - { + for (auto it = hashMap.begin(); it != hashMap.end();) { + if (pred(it)) { removals.insert(it.key(), it.value()); it = hashMap.erase(it); } else @@ -69,82 +67,81 @@ HashT erase_if(HashT& hashMap, Pred pred) class Connection::Private { public: - explicit Private(std::unique_ptr<ConnectionData>&& connection) - : data(move(connection)) - { } - Q_DISABLE_COPY(Private) - Private(Private&&) = delete; - Private operator=(Private&&) = delete; - - Connection* q = nullptr; - std::unique_ptr<ConnectionData> data; - // A complex key below is a pair of room name and whether its - // state is Invited. The spec mandates to keep Invited room state - // separately so we should, e.g., keep objects for Invite and - // Leave state of the same room. - QHash<QPair<QString, bool>, Room*> roomMap; - // Mapping from aliases to room ids, as per the last sync - QHash<QString, QString> roomAliasMap; - QVector<QString> roomIdsToForget; - QVector<Room*> firstTimeRooms; - QVector<QString> pendingStateRoomIds; - QMap<QString, User*> userMap; - DirectChatsMap directChats; - DirectChatUsersMap directChatUsers; - std::unordered_map<QString, EventPtr> accountData; - QString userId; - int syncLoopTimeout = -1; - - GetCapabilitiesJob* capabilitiesJob = nullptr; - GetCapabilitiesJob::Capabilities capabilities; - - SyncJob* syncJob = nullptr; - - bool cacheState = true; - bool cacheToBinary = SettingsGroup("libqmatrixclient") - .value("cache_type").toString() != "json"; - bool lazyLoading = false; - - void connectWithToken(const QString& user, const QString& accessToken, - const QString& deviceId); - void broadcastDirectChatUpdates(const DirectChatsMap& additions, - const DirectChatsMap& removals); - - template <typename EventT> - EventT* unpackAccountData() const - { - const auto& eventIt = accountData.find(EventT::matrixTypeId()); - return eventIt == accountData.end() - ? nullptr : weakPtrCast<EventT>(eventIt->second); - } + explicit Private(std::unique_ptr<ConnectionData>&& connection) + : data(move(connection)) + { + } + Q_DISABLE_COPY(Private) + Private(Private&&) = delete; + Private operator=(Private&&) = delete; + + Connection* q = nullptr; + std::unique_ptr<ConnectionData> data; + // A complex key below is a pair of room name and whether its + // state is Invited. The spec mandates to keep Invited room state + // separately so we should, e.g., keep objects for Invite and + // Leave state of the same room. + QHash<QPair<QString, bool>, Room*> roomMap; + // Mapping from aliases to room ids, as per the last sync + QHash<QString, QString> roomAliasMap; + QVector<QString> roomIdsToForget; + QVector<Room*> firstTimeRooms; + QVector<QString> pendingStateRoomIds; + QMap<QString, User*> userMap; + DirectChatsMap directChats; + DirectChatUsersMap directChatUsers; + std::unordered_map<QString, EventPtr> accountData; + QString userId; + int syncLoopTimeout = -1; + + GetCapabilitiesJob* capabilitiesJob = nullptr; + GetCapabilitiesJob::Capabilities capabilities; + + SyncJob* syncJob = nullptr; + + bool cacheState = true; + bool cacheToBinary = + SettingsGroup("libqmatrixclient").value("cache_type").toString() + != "json"; + bool lazyLoading = false; + + void connectWithToken(const QString& user, const QString& accessToken, + const QString& deviceId); + void broadcastDirectChatUpdates(const DirectChatsMap& additions, + const DirectChatsMap& removals); + + template <typename EventT> EventT* unpackAccountData() const + { + const auto& eventIt = accountData.find(EventT::matrixTypeId()); + return eventIt == accountData.end() + ? nullptr + : weakPtrCast<EventT>(eventIt->second); + } - void packAndSendAccountData(EventPtr&& event) - { - const auto eventType = event->matrixType(); - q->callApi<SetAccountDataJob>(userId, eventType, - event->contentJson()); - accountData[eventType] = std::move(event); - emit q->accountDataChanged(eventType); - } + void packAndSendAccountData(EventPtr&& event) + { + const auto eventType = event->matrixType(); + q->callApi<SetAccountDataJob>(userId, eventType, event->contentJson()); + accountData[eventType] = std::move(event); + emit q->accountDataChanged(eventType); + } - template <typename EventT, typename ContentT> - void packAndSendAccountData(ContentT&& content) - { - packAndSendAccountData( - makeEvent<EventT>(std::forward<ContentT>(content))); - } + template <typename EventT, typename ContentT> + void packAndSendAccountData(ContentT&& content) + { + packAndSendAccountData( + makeEvent<EventT>(std::forward<ContentT>(content))); + } }; Connection::Connection(const QUrl& server, QObject* parent) - : QObject(parent) - , d(std::make_unique<Private>(std::make_unique<ConnectionData>(server))) + : QObject(parent), + d(std::make_unique<Private>(std::make_unique<ConnectionData>(server))) { d->q = this; // All d initialization should occur before this line } -Connection::Connection(QObject* parent) - : Connection({}, parent) -{ } +Connection::Connection(QObject* parent) : Connection({}, parent) {} Connection::~Connection() { @@ -159,19 +156,20 @@ void Connection::resolveServer(const QString& mxidOrDomain) // Try to parse as an FQID; if there's no @ part, assume it's a domain name. QRegularExpression parser( - "^(@.+?:)?" // Optional username (allow everything for compatibility) - "(\\[[^]]+\\]|[^:@]+)" // Either IPv6 address or hostname/IPv4 address - "(:\\d{1,5})?$", // Optional port - QRegularExpression::UseUnicodePropertiesOption); // Because asian digits + "^(@.+?:)?" // Optional username (allow everything for + // compatibility) + "(\\[[^]]+\\]|[^:@]+)" // Either IPv6 address or hostname/IPv4 + // address + "(:\\d{1,5})?$", // Optional port + QRegularExpression::UseUnicodePropertiesOption); // Because asian + // digits auto match = parser.match(mxidOrDomain); QUrl maybeBaseUrl = QUrl::fromUserInput(match.captured(2)); maybeBaseUrl.setScheme("https"); // Instead of the Qt-default "http" - if (!match.hasMatch() || !maybeBaseUrl.isValid()) - { - emit resolveError( - tr("%1 is not a valid homeserver address") - .arg(maybeBaseUrl.toString())); + if (!match.hasMatch() || !maybeBaseUrl.isValid()) { + emit resolveError(tr("%1 is not a valid homeserver address") + .arg(maybeBaseUrl.toString())); return; } @@ -188,16 +186,15 @@ void Connection::resolveServer(const QString& mxidOrDomain) dns->setType(QDnsLookup::SRV); dns->setName("_matrix._tcp." + domain); - connect(dns, &QDnsLookup::finished, [this,dns,maybeBaseUrl]() { + connect(dns, &QDnsLookup::finished, [this, dns, maybeBaseUrl]() { QUrl baseUrl { maybeBaseUrl }; - if (dns->error() == QDnsLookup::NoError && - dns->serviceRecords().isEmpty()) - { + if (dns->error() == QDnsLookup::NoError + && dns->serviceRecords().isEmpty()) { auto record = dns->serviceRecords().front(); baseUrl.setHost(record.target()); baseUrl.setPort(record.port()); - qCDebug(MAIN) << "SRV record for" << maybeBaseUrl.host() - << "is" << baseUrl.authority(); + qCDebug(MAIN) << "SRV record for" << maybeBaseUrl.host() << "is" + << baseUrl.authority(); } else { qCDebug(MAIN) << baseUrl.host() << "doesn't have SRV record" << dns->name() << "- using the hostname as is"; @@ -213,41 +210,37 @@ void Connection::connectToServer(const QString& user, const QString& password, const QString& initialDeviceName, const QString& deviceId) { - checkAndConnect(user, - [=] { - doConnectToServer(user, password, initialDeviceName, deviceId); - }); + checkAndConnect(user, [=] { + doConnectToServer(user, password, initialDeviceName, deviceId); + }); } void Connection::doConnectToServer(const QString& user, const QString& password, const QString& initialDeviceName, const QString& deviceId) { - auto loginJob = callApi<LoginJob>(QStringLiteral("m.login.password"), + auto loginJob = callApi<LoginJob>( + QStringLiteral("m.login.password"), UserIdentifier { QStringLiteral("m.id.user"), - {{ QStringLiteral("user"), user }} }, + { { QStringLiteral("user"), user } } }, password, /*token*/ "", deviceId, initialDeviceName); - connect(loginJob, &BaseJob::success, this, - [this, loginJob] { - d->connectWithToken(loginJob->userId(), loginJob->accessToken(), - loginJob->deviceId()); - }); - connect(loginJob, &BaseJob::failure, this, - [this, loginJob] { - emit loginError(loginJob->errorString(), loginJob->rawDataSample()); - }); + connect(loginJob, &BaseJob::success, this, [this, loginJob] { + d->connectWithToken(loginJob->userId(), loginJob->accessToken(), + loginJob->deviceId()); + }); + connect(loginJob, &BaseJob::failure, this, [this, loginJob] { + emit loginError(loginJob->errorString(), loginJob->rawDataSample()); + }); } -void Connection::syncLoopIteration() -{ - sync(d->syncLoopTimeout); -} +void Connection::syncLoopIteration() { sync(d->syncLoopTimeout); } void Connection::connectWithToken(const QString& userId, const QString& accessToken, const QString& deviceId) { - checkAndConnect(userId, - [=] { d->connectWithToken(userId, accessToken, deviceId); }); + checkAndConnect(userId, [=] { + d->connectWithToken(userId, accessToken, deviceId); + }); } void Connection::reloadCapabilities() @@ -259,18 +252,17 @@ void Connection::reloadCapabilities() else if (d->capabilitiesJob->error() == BaseJob::IncorrectRequestError) qCDebug(MAIN) << "Server doesn't support /capabilities"; - if (d->capabilities.roomVersions.omitted()) - { + if (d->capabilities.roomVersions.omitted()) { qCWarning(MAIN) << "Pinning supported room version to 1"; - d->capabilities.roomVersions = { "1", {{ "1", "stable" }} }; + d->capabilities.roomVersions = { "1", { { "1", "stable" } } }; } else { - qCDebug(MAIN) << "Room versions:" - << defaultRoomVersion() << "is default, full list:" - << availableRoomVersions(); + qCDebug(MAIN) << "Room versions:" << defaultRoomVersion() + << "is default, full list:" + << availableRoomVersions(); } Q_ASSERT(!d->capabilities.roomVersions.omitted()); emit capabilitiesLoaded(); - for (auto* r: d->roomMap) + for (auto* r : d->roomMap) if (r->joinState() == JoinState::Join && r->successorId().isEmpty()) r->checkVersion(); }); @@ -301,28 +293,26 @@ void Connection::Private::connectWithToken(const QString& user, void Connection::checkAndConnect(const QString& userId, std::function<void()> connectFn) { - if (d->data->baseUrl().isValid()) - { + if (d->data->baseUrl().isValid()) { connectFn(); return; } // Not good to go, try to fix the homeserver URL. - if (userId.startsWith('@') && userId.indexOf(':') != -1) - { - connectSingleShot(this, &Connection::homeserverChanged, this, connectFn); + if (userId.startsWith('@') && userId.indexOf(':') != -1) { + connectSingleShot(this, &Connection::homeserverChanged, this, + connectFn); // NB: doResolveServer can emit resolveError, so this is a part of // checkAndConnect function contract. resolveServer(userId); } else - emit resolveError( - tr("%1 is an invalid homeserver URL") - .arg(d->data->baseUrl().toString())); + emit resolveError(tr("%1 is an invalid homeserver URL") + .arg(d->data->baseUrl().toString())); } void Connection::logout() { auto job = callApi<LogoutJob>(); - connect( job, &LogoutJob::success, this, [this] { + connect(job, &LogoutJob::success, this, [this] { stopSync(); d->data->setToken({}); emit stateChanged(); @@ -338,28 +328,25 @@ void Connection::sync(int timeout) Filter filter; filter.room->timeline->limit = 100; filter.room->state->lazyLoadMembers = d->lazyLoading; - auto job = d->syncJob = callApi<SyncJob>(BackgroundRequest, - d->data->lastEvent(), filter, timeout); - connect( job, &SyncJob::success, this, [this, job] { + auto job = d->syncJob = callApi<SyncJob>( + BackgroundRequest, d->data->lastEvent(), filter, timeout); + connect(job, &SyncJob::success, this, [this, job] { onSyncSuccess(job->takeData()); d->syncJob = nullptr; emit syncDone(); }); - connect( job, &SyncJob::retryScheduled, this, - [this,job] (int retriesTaken, int nextInMilliseconds) - { - emit networkError(job->errorString(), job->rawDataSample(), - retriesTaken, nextInMilliseconds); - }); - connect( job, &SyncJob::failure, this, [this, job] { + connect(job, &SyncJob::retryScheduled, this, + [this, job](int retriesTaken, int nextInMilliseconds) { + emit networkError(job->errorString(), job->rawDataSample(), + retriesTaken, nextInMilliseconds); + }); + connect(job, &SyncJob::failure, this, [this, job] { d->syncJob = nullptr; - if (job->error() == BaseJob::ContentAccessError) - { - qCWarning(SYNCJOB) - << "Sync job failed with ContentAccessError - login expired?"; + if (job->error() == BaseJob::ContentAccessError) { + qCWarning(SYNCJOB) << "Sync job failed with ContentAccessError - " + "login expired?"; emit loginError(job->errorString(), job->rawDataSample()); - } - else + } else emit syncError(job->errorString(), job->rawDataSample()); }); } @@ -371,65 +358,59 @@ void Connection::syncLoop(int timeout) syncLoopIteration(); // initial sync to start the loop } -void Connection::onSyncSuccess(SyncData &&data, bool fromCache) { +void Connection::onSyncSuccess(SyncData&& data, bool fromCache) +{ d->data->setLastEvent(data.nextBatch()); - for (auto&& roomData: data.takeRoomData()) - { + for (auto&& roomData : data.takeRoomData()) { const auto forgetIdx = d->roomIdsToForget.indexOf(roomData.roomId); - if (forgetIdx != -1) - { + if (forgetIdx != -1) { d->roomIdsToForget.removeAt(forgetIdx); - if (roomData.joinState == JoinState::Leave) - { - qDebug(MAIN) << "Room" << roomData.roomId - << "has been forgotten, ignoring /sync response for it"; + if (roomData.joinState == JoinState::Leave) { + qDebug(MAIN) + << "Room" << roomData.roomId + << "has been forgotten, ignoring /sync response for it"; continue; } qWarning(MAIN) << "Room" << roomData.roomId - << "has just been forgotten but /sync returned it in" - << toCString(roomData.joinState) - << "state - suspiciously fast turnaround"; + << "has just been forgotten but /sync returned it in" + << toCString(roomData.joinState) + << "state - suspiciously fast turnaround"; } - if ( auto* r = provideRoom(roomData.roomId, roomData.joinState) ) - { + if (auto* r = provideRoom(roomData.roomId, roomData.joinState)) { d->pendingStateRoomIds.removeOne(roomData.roomId); r->updateData(std::move(roomData), fromCache); - if (d->firstTimeRooms.removeOne(r)) - { + if (d->firstTimeRooms.removeOne(r)) { emit loadedRoomState(r); if (!d->capabilities.roomVersions.omitted()) r->checkVersion(); - // Otherwise, the version will be checked in reloadCapabilities() + // Otherwise, the version will be checked in + // reloadCapabilities() } } // Let UI update itself after updating each room QCoreApplication::processEvents(); } - for (auto&& accountEvent: data.takeAccountData()) - { - if (is<DirectChatEvent>(*accountEvent)) - { + for (auto&& accountEvent : data.takeAccountData()) { + if (is<DirectChatEvent>(*accountEvent)) { const auto usersToDCs = ptrCast<DirectChatEvent>(move(accountEvent)) - ->usersToDirectChats(); + ->usersToDirectChats(); DirectChatsMap removals = - erase_if(d->directChats, [&usersToDCs] (auto it) { - return !usersToDCs.contains(it.key()->id(), it.value()); - }); - erase_if(d->directChatUsers, [&usersToDCs] (auto it) { + erase_if(d->directChats, [&usersToDCs](auto it) { + return !usersToDCs.contains(it.key()->id(), it.value()); + }); + erase_if(d->directChatUsers, [&usersToDCs](auto it) { return !usersToDCs.contains(it.value()->id(), it.key()); }); if (MAIN().isDebugEnabled()) for (auto it = removals.begin(); it != removals.end(); ++it) - qCDebug(MAIN) << it.value() - << "is no more a direct chat with" << it.key()->id(); + qCDebug(MAIN) + << it.value() << "is no more a direct chat with" + << it.key()->id(); DirectChatsMap additions; - for (auto it = usersToDCs.begin(); it != usersToDCs.end(); ++it) - { - if (auto* u = user(it.key())) - { - if (!d->directChats.contains(u, it.value())) - { + for (auto it = usersToDCs.begin(); it != usersToDCs.end(); ++it) { + if (auto* u = user(it.key())) { + if (!d->directChats.contains(u, it.value())) { Q_ASSERT(!d->directChatUsers.contains(it.value(), u)); additions.insert(u, it.value()); d->directChats.insert(u, it.value()); @@ -448,14 +429,13 @@ void Connection::onSyncSuccess(SyncData &&data, bool fromCache) { } if (is<IgnoredUsersEvent>(*accountEvent)) qCDebug(MAIN) << "Users ignored by" << d->userId << "updated:" - << QStringList::fromSet(ignoredUsers()).join(','); + << QStringList::fromSet(ignoredUsers()).join(','); auto& currentData = d->accountData[accountEvent->matrixType()]; // A polymorphic event-specific comparison might be a bit more // efficient; maaybe do it another day - if (!currentData || - currentData->contentJson() != accountEvent->contentJson()) - { + if (!currentData + || currentData->contentJson() != accountEvent->contentJson()) { currentData = std::move(accountEvent); qCDebug(MAIN) << "Updated account data of type" << currentData->matrixType(); @@ -467,8 +447,8 @@ void Connection::onSyncSuccess(SyncData &&data, bool fromCache) { void Connection::stopSync() { // If there's a sync loop, break it - disconnect(this, &Connection::syncDone, - this, &Connection::syncLoopIteration); + disconnect(this, &Connection::syncDone, this, + &Connection::syncLoopIteration); if (d->syncJob) // If there's an ongoing sync job, stop it too { d->syncJob->abandon(); @@ -476,10 +456,7 @@ void Connection::stopSync() } } -QString Connection::nextBatchToken() const -{ - return d->data->lastEvent(); -} +QString Connection::nextBatchToken() const { return d->data->lastEvent(); } PostReceiptJob* Connection::postReceipt(Room* room, RoomEvent* event) const { @@ -492,8 +469,8 @@ JoinRoomJob* Connection::joinRoom(const QString& roomAlias, auto job = callApi<JoinRoomJob>(roomAlias, serverNames); // Upon completion, ensure a room object in Join state is created but only // if it's not already there due to a sync completing earlier. - connect(job, &JoinRoomJob::success, - this, [this, job] { provideRoom(job->roomId()); }); + connect(job, &JoinRoomJob::success, this, + [this, job] { provideRoom(job->roomId()); }); return job; } @@ -501,15 +478,13 @@ LeaveRoomJob* Connection::leaveRoom(Room* room) { const auto& roomId = room->id(); const auto job = callApi<LeaveRoomJob>(roomId); - if (room->joinState() == JoinState::Invite) - { + if (room->joinState() == JoinState::Invite) { // Workaround matrix-org/synapse#2181 - if the room is in invite state // the invite may have been cancelled but Synapse didn't send it in // `/sync`. See also #273 for the discussion in the library context. d->pendingStateRoomIds.push_back(roomId); - connect(job, &LeaveRoomJob::success, this, [this,roomId] { - if (d->pendingStateRoomIds.removeOne(roomId)) - { + connect(job, &LeaveRoomJob::success, this, [this, roomId] { + if (d->pendingStateRoomIds.removeOne(roomId)) { qCDebug(MAIN) << "Forcing the room to Leave status"; provideRoom(roomId, JoinState::Leave); } @@ -522,40 +497,44 @@ inline auto splitMediaId(const QString& mediaId) { auto idParts = mediaId.split('/'); Q_ASSERT_X(idParts.size() == 2, __FUNCTION__, - ("'" + mediaId + - "' doesn't look like 'serverName/localMediaId'").toLatin1()); + ("'" + mediaId + "' doesn't look like 'serverName/localMediaId'") + .toLatin1()); return idParts; } MediaThumbnailJob* Connection::getThumbnail(const QString& mediaId, - QSize requestedSize, RunningPolicy policy) const + QSize requestedSize, + RunningPolicy policy) const { auto idParts = splitMediaId(mediaId); - return callApi<MediaThumbnailJob>(policy, - idParts.front(), idParts.back(), requestedSize); + return callApi<MediaThumbnailJob>(policy, idParts.front(), idParts.back(), + requestedSize); } MediaThumbnailJob* Connection::getThumbnail(const QUrl& url, - QSize requestedSize, RunningPolicy policy) const + QSize requestedSize, + RunningPolicy policy) const { return getThumbnail(url.authority() + url.path(), requestedSize, policy); } -MediaThumbnailJob* Connection::getThumbnail(const QUrl& url, - int requestedWidth, int requestedHeight, RunningPolicy policy) const +MediaThumbnailJob* Connection::getThumbnail(const QUrl& url, int requestedWidth, + int requestedHeight, + RunningPolicy policy) const { return getThumbnail(url, QSize(requestedWidth, requestedHeight), policy); } -UploadContentJob* Connection::uploadContent(QIODevice* contentSource, - const QString& filename, const QString& overrideContentType) const +UploadContentJob* +Connection::uploadContent(QIODevice* contentSource, const QString& filename, + const QString& overrideContentType) const { auto contentType = overrideContentType; - if (contentType.isEmpty()) - { + if (contentType.isEmpty()) { contentType = - QMimeDatabase().mimeTypeForFileNameAndData(filename, contentSource) - .name(); + QMimeDatabase() + .mimeTypeForFileNameAndData(filename, contentSource) + .name(); contentSource->open(QIODevice::ReadOnly); } return callApi<UploadContentJob>(contentSource, filename, contentType); @@ -565,8 +544,7 @@ UploadContentJob* Connection::uploadFile(const QString& fileName, const QString& overrideContentType) { auto sourceFile = new QFile(fileName); - if (!sourceFile->open(QIODevice::ReadOnly)) - { + if (!sourceFile->open(QIODevice::ReadOnly)) { qCWarning(MAIN) << "Couldn't open" << sourceFile->fileName() << "for reading"; return nullptr; @@ -596,13 +574,14 @@ DownloadFileJob* Connection::downloadFile(const QUrl& url, return job; } -CreateRoomJob* Connection::createRoom(RoomVisibility visibility, - const QString& alias, const QString& name, const QString& topic, - QStringList invites, const QString& presetName, - const QString& roomVersion, bool isDirect, - const QVector<CreateRoomJob::StateEvent>& initialState, - const QVector<CreateRoomJob::Invite3pid>& invite3pids, - const QJsonObject& creationContent) +CreateRoomJob* +Connection::createRoom(RoomVisibility visibility, const QString& alias, + const QString& name, const QString& topic, + QStringList invites, const QString& presetName, + const QString& roomVersion, bool isDirect, + const QVector<CreateRoomJob::StateEvent>& initialState, + const QVector<CreateRoomJob::Invite3pid>& invite3pids, + const QJsonObject& creationContent) { invites.removeOne(d->userId); // The creator is by definition in the room auto job = callApi<CreateRoomJob>( @@ -610,7 +589,7 @@ CreateRoomJob* Connection::createRoom(RoomVisibility visibility, : QStringLiteral("private"), alias, name, topic, invites, invite3pids, roomVersion, creationContent, initialState, presetName, isDirect); - connect(job, &BaseJob::success, this, [this,job] { + connect(job, &BaseJob::success, this, [this, job] { emit createdRoom(provideRoom(job->roomId(), JoinState::Join)); }); return job; @@ -621,14 +600,14 @@ void Connection::requestDirectChat(const QString& userId) if (auto* u = user(userId)) requestDirectChat(u); else - qCCritical(MAIN) - << "Connection::requestDirectChat: Couldn't get a user object for" - << userId; + qCCritical(MAIN) << "Connection::requestDirectChat: Couldn't get a " + "user object for" + << userId; } void Connection::requestDirectChat(User* u) { - doInDirectChat(u, [this] (Room* r) { emit directChatAvailable(r); }); + doInDirectChat(u, [this](Room* r) { emit directChatAvailable(r); }); } void Connection::doInDirectChat(const QString& userId, @@ -638,8 +617,8 @@ void Connection::doInDirectChat(const QString& userId, doInDirectChat(u, operation); else qCCritical(MAIN) - << "Connection::doInDirectChat: Couldn't get a user object for" - << userId; + << "Connection::doInDirectChat: Couldn't get a user object for" + << userId; } void Connection::doInDirectChat(User* u, @@ -651,11 +630,9 @@ void Connection::doInDirectChat(User* u, // (left/forgotten) ones along the way. DirectChatsMap removals; for (auto it = d->directChats.find(u); - it != d->directChats.end() && it.key() == u; ++it) - { + it != d->directChats.end() && it.key() == u; ++it) { const auto& roomId = *it; - if (auto r = room(roomId, JoinState::Join)) - { + if (auto r = room(roomId, JoinState::Join)) { Q_ASSERT(r->id() == roomId); // A direct chat with yourself should only involve yourself :) if (userId == d->userId && r->totalMemberCount() > 1) @@ -665,15 +642,16 @@ void Connection::doInDirectChat(User* u, operation(r); return; } - if (auto ir = invitation(roomId)) - { + if (auto ir = invitation(roomId)) { Q_ASSERT(ir->id() == roomId); auto j = joinRoom(ir->id()); - connect(j, &BaseJob::success, this, [this,roomId,userId,operation] { - qCDebug(MAIN) << "Joined the already invited direct chat with" - << userId << "as" << roomId; - operation(room(roomId, JoinState::Join)); - }); + connect(j, &BaseJob::success, this, + [this, roomId, userId, operation] { + qCDebug(MAIN) + << "Joined the already invited direct chat with" + << userId << "as" << roomId; + operation(room(roomId, JoinState::Join)); + }); return; } // Avoid reusing previously left chats but don't remove them @@ -686,10 +664,8 @@ void Connection::doInDirectChat(User* u, // Postpone actual deletion until we finish iterating d->directChats. removals.insert(it.key(), it.value()); } - if (!removals.isEmpty()) - { - for (auto it = removals.cbegin(); it != removals.cend(); ++it) - { + if (!removals.isEmpty()) { + for (auto it = removals.cbegin(); it != removals.cend(); ++it) { d->directChats.remove(it.key(), it.value()); d->directChatUsers.remove(it.value(), const_cast<User*>(it.key())); // FIXME @@ -698,18 +674,18 @@ void Connection::doInDirectChat(User* u, } auto j = createDirectChat(userId); - connect(j, &BaseJob::success, this, [this,j,userId,operation] { - qCDebug(MAIN) << "Direct chat with" << userId - << "has been created as" << j->roomId(); + connect(j, &BaseJob::success, this, [this, j, userId, operation] { + qCDebug(MAIN) << "Direct chat with" << userId << "has been created as" + << j->roomId(); operation(room(j->roomId(), JoinState::Join)); }); - } CreateRoomJob* Connection::createDirectChat(const QString& userId, - const QString& topic, const QString& name) + const QString& topic, + const QString& name) { - return createRoom(UnpublishRoom, "", name, topic, {userId}, + return createRoom(UnpublishRoom, "", name, topic, { userId }, "trusted_private_chat", {}, true); } @@ -723,11 +699,10 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) // a ForgetRoomJob is created in advance and can be returned in a probably // not-yet-started state (it will start once /leave completes). auto forgetJob = new ForgetRoomJob(id); - auto room = d->roomMap.value({id, false}); + auto room = d->roomMap.value({ id, false }); if (!room) - room = d->roomMap.value({id, true}); - if (room && room->joinState() != JoinState::Leave) - { + room = d->roomMap.value({ id, true }); + if (room && room->joinState() != JoinState::Leave) { auto leaveJob = room->leaveRoom(); connect(leaveJob, &BaseJob::success, this, [this, forgetJob, room] { forgetJob->start(connectionData()); @@ -737,18 +712,14 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) d->roomIdsToForget.push_back(room->id()); }); connect(leaveJob, &BaseJob::failure, forgetJob, &BaseJob::abandon); - } - else + } else forgetJob->start(connectionData()); - connect(forgetJob, &BaseJob::success, this, [this, id] - { + connect(forgetJob, &BaseJob::success, this, [this, id] { // Delete whatever instances of the room are still in the map. - for (auto f: {false, true}) - if (auto r = d->roomMap.take({ id, f })) - { - qCDebug(MAIN) << "Room" << r->objectName() - << "in state" << toCString(r->joinState()) - << "will be deleted"; + for (auto f : { false, true }) + if (auto r = d->roomMap.take({ id, f })) { + qCDebug(MAIN) << "Room" << r->objectName() << "in state" + << toCString(r->joinState()) << "will be deleted"; emit r->beforeDestruction(r); r->deleteLater(); } @@ -756,52 +727,52 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) return forgetJob; } -SendToDeviceJob* Connection::sendToDevices(const QString& eventType, - const UsersToDevicesToEvents& eventsMap) const +SendToDeviceJob* +Connection::sendToDevices(const QString& eventType, + const UsersToDevicesToEvents& eventsMap) const { QHash<QString, QHash<QString, QJsonObject>> json; json.reserve(int(eventsMap.size())); - std::for_each(eventsMap.begin(), eventsMap.end(), - [&json] (const auto& userTodevicesToEvents) { - auto& jsonUser = json[userTodevicesToEvents.first]; - const auto& devicesToEvents = userTodevicesToEvents.second; - std::for_each(devicesToEvents.begin(), devicesToEvents.end(), - [&jsonUser] (const auto& deviceToEvents) { - jsonUser.insert(deviceToEvents.first, - deviceToEvents.second.contentJson()); - }); - }); - return callApi<SendToDeviceJob>(BackgroundRequest, - eventType, generateTxnId(), json); + std::for_each( + eventsMap.begin(), eventsMap.end(), + [&json](const auto& userTodevicesToEvents) { + auto& jsonUser = json[userTodevicesToEvents.first]; + const auto& devicesToEvents = userTodevicesToEvents.second; + std::for_each(devicesToEvents.begin(), devicesToEvents.end(), + [&jsonUser](const auto& deviceToEvents) { + jsonUser.insert( + deviceToEvents.first, + deviceToEvents.second.contentJson()); + }); + }); + return callApi<SendToDeviceJob>(BackgroundRequest, eventType, + generateTxnId(), json); } SendMessageJob* Connection::sendMessage(const QString& roomId, const RoomEvent& event) const { - const auto txnId = event.transactionId().isEmpty() - ? generateTxnId() : event.transactionId(); - return callApi<SendMessageJob>(roomId, event.matrixType(), - txnId, event.contentJson()); + const auto txnId = event.transactionId().isEmpty() ? generateTxnId() + : event.transactionId(); + return callApi<SendMessageJob>(roomId, event.matrixType(), txnId, + event.contentJson()); } -QUrl Connection::homeserver() const -{ - return d->data->baseUrl(); -} +QUrl Connection::homeserver() const { return d->data->baseUrl(); } Room* Connection::room(const QString& roomId, JoinStates states) const { - Room* room = d->roomMap.value({roomId, false}, nullptr); - if (states.testFlag(JoinState::Join) && - room && room->joinState() == JoinState::Join) + Room* room = d->roomMap.value({ roomId, false }, nullptr); + if (states.testFlag(JoinState::Join) && room + && room->joinState() == JoinState::Join) return room; if (states.testFlag(JoinState::Invite)) if (Room* invRoom = invitation(roomId)) return invRoom; - if (states.testFlag(JoinState::Leave) && - room && room->joinState() == JoinState::Leave) + if (states.testFlag(JoinState::Leave) && room + && room->joinState() == JoinState::Leave) return room; return nullptr; @@ -821,22 +792,21 @@ void Connection::updateRoomAliases(const QString& roomId, const QStringList& previousRoomAliases, const QStringList& roomAliases) { - for (const auto& a: previousRoomAliases) + for (const auto& a : previousRoomAliases) if (d->roomAliasMap.remove(a) == 0) - qCWarning(MAIN) << "Alias" << a << "is not found (already deleted?)"; + qCWarning(MAIN) + << "Alias" << a << "is not found (already deleted?)"; - for (const auto& a: roomAliases) - { + for (const auto& a : roomAliases) { auto& mappedId = d->roomAliasMap[a]; - if (!mappedId.isEmpty()) - { + if (!mappedId.isEmpty()) { if (mappedId == roomId) qCDebug(MAIN) << "Alias" << a << "is already mapped to room" << roomId; else - qCWarning(MAIN) << "Alias" << a - << "will be force-remapped from room" - << mappedId << "to" << roomId; + qCWarning(MAIN) + << "Alias" << a << "will be force-remapped from room" + << mappedId << "to" << roomId; } mappedId = roomId; } @@ -844,19 +814,18 @@ void Connection::updateRoomAliases(const QString& roomId, Room* Connection::invitation(const QString& roomId) const { - return d->roomMap.value({roomId, true}, nullptr); + return d->roomMap.value({ roomId, true }, nullptr); } User* Connection::user(const QString& userId) { if (userId.isEmpty()) return nullptr; - if (!userId.startsWith('@') || !userId.contains(':')) - { + if (!userId.startsWith('@') || !userId.contains(':')) { qCCritical(MAIN) << "Malformed userId:" << userId; return nullptr; } - if( d->userMap.contains(userId) ) + if (d->userMap.contains(userId)) return d->userMap.value(userId); auto* user = userFactory()(this, userId); d->userMap.insert(userId, user); @@ -869,47 +838,29 @@ const User* Connection::user() const return d->userMap.value(d->userId, nullptr); } -User* Connection::user() -{ - return user(d->userId); -} +User* Connection::user() { return user(d->userId); } -QString Connection::userId() const -{ - return d->userId; -} +QString Connection::userId() const { return d->userId; } -QString Connection::deviceId() const -{ - return d->data->deviceId(); -} +QString Connection::deviceId() const { return d->data->deviceId(); } -QString Connection::token() const -{ - return accessToken(); -} +QString Connection::token() const { return accessToken(); } -QByteArray Connection::accessToken() const -{ - return d->data->accessToken(); -} +QByteArray Connection::accessToken() const { return d->data->accessToken(); } -SyncJob* Connection::syncJob() const -{ - return d->syncJob; -} +SyncJob* Connection::syncJob() const { return d->syncJob; } int Connection::millisToReconnect() const { return d->syncJob ? d->syncJob->millisToRetry() : 0; } -QHash< QPair<QString, bool>, Room* > Connection::roomMap() const +QHash<QPair<QString, bool>, Room*> Connection::roomMap() const { - // Copy-on-write-and-remove-elements is faster than copying elements one by one. - QHash< QPair<QString, bool>, Room* > roomMap = d->roomMap; - for (auto it = roomMap.begin(); it != roomMap.end(); ) - { + // Copy-on-write-and-remove-elements is faster than copying elements one by + // one. + QHash<QPair<QString, bool>, Room*> roomMap = d->roomMap; + for (auto it = roomMap.begin(); it != roomMap.end();) { if (it.value()->joinState() == JoinState::Leave) it = roomMap.erase(it); else @@ -949,24 +900,22 @@ void Connection::setAccountData(const QString& type, const QJsonObject& content) QHash<QString, QVector<Room*>> Connection::tagsToRooms() const { QHash<QString, QVector<Room*>> result; - for (auto* r: qAsConst(d->roomMap)) - { - for (const auto& tagName: r->tagNames()) + for (auto* r : qAsConst(d->roomMap)) { + for (const auto& tagName : r->tagNames()) result[tagName].push_back(r); } for (auto it = result.begin(); it != result.end(); ++it) - std::sort(it->begin(), it->end(), - [t=it.key()] (Room* r1, Room* r2) { - return r1->tags().value(t) < r2->tags().value(t); - }); + std::sort(it->begin(), it->end(), [t = it.key()](Room* r1, Room* r2) { + return r1->tags().value(t) < r2->tags().value(t); + }); return result; } QStringList Connection::tagNames() const { - QStringList tags ({FavouriteTag}); - for (auto* r: qAsConst(d->roomMap)) - for (const auto& tag: r->tagNames()) + QStringList tags({ FavouriteTag }); + for (auto* r : qAsConst(d->roomMap)) + for (const auto& tag : r->tagNames()) if (tag != LowPriorityTag && !tags.contains(tag)) tags.push_back(tag); tags.push_back(LowPriorityTag); @@ -976,8 +925,9 @@ QStringList Connection::tagNames() const QVector<Room*> Connection::roomsWithTag(const QString& tagName) const { QVector<Room*> rooms; - std::copy_if(d->roomMap.begin(), d->roomMap.end(), std::back_inserter(rooms), - [&tagName] (Room* r) { return r->tags().contains(tagName); }); + std::copy_if(d->roomMap.begin(), d->roomMap.end(), + std::back_inserter(rooms), + [&tagName](Room* r) { return r->tags().contains(tagName); }); return rooms; } @@ -989,8 +939,7 @@ Connection::DirectChatsMap Connection::directChats() const QJsonObject toJson(const Connection::DirectChatsMap& directChats) { QJsonObject json; - for (auto it = directChats.begin(); it != directChats.end();) - { + for (auto it = directChats.begin(); it != directChats.end();) { QJsonArray roomIds; const auto* user = it.key(); for (; it != directChats.end() && it.key() == user; ++it) @@ -1000,8 +949,8 @@ QJsonObject toJson(const Connection::DirectChatsMap& directChats) return json; } -void Connection::Private::broadcastDirectChatUpdates(const DirectChatsMap& additions, - const DirectChatsMap& removals) +void Connection::Private::broadcastDirectChatUpdates( + const DirectChatsMap& additions, const DirectChatsMap& removals) { q->callApi<SetAccountDataJob>(userId, QStringLiteral("m.direct"), toJson(directChats)); @@ -1023,19 +972,19 @@ void Connection::addToDirectChats(const Room* room, User* user) void Connection::removeFromDirectChats(const QString& roomId, User* user) { Q_ASSERT(!roomId.isEmpty()); - if ((user != nullptr && !d->directChats.contains(user, roomId)) || - d->directChats.key(roomId) == nullptr) + if ((user != nullptr && !d->directChats.contains(user, roomId)) + || d->directChats.key(roomId) == nullptr) return; DirectChatsMap removals; - if (user != nullptr) - { + if (user != nullptr) { removals.insert(user, roomId); d->directChats.remove(user, roomId); d->directChatUsers.remove(roomId, user); } else { - removals = erase_if(d->directChats, - [&roomId] (auto it) { return it.value() == roomId; }); + removals = erase_if(d->directChats, [&roomId](auto it) { + return it.value() == roomId; + }); d->directChatUsers.remove(roomId); } d->broadcastDirectChatUpdates({}, removals); @@ -1068,11 +1017,10 @@ void Connection::addToIgnoredUsers(const User* user) Q_ASSERT(user != nullptr); auto ignoreList = ignoredUsers(); - if (!ignoreList.contains(user->id())) - { + if (!ignoreList.contains(user->id())) { ignoreList.insert(user->id()); d->packAndSendAccountData<IgnoredUsersEvent>(ignoreList); - emit ignoredUsersListChanged({{ user->id() }}, {}); + emit ignoredUsersListChanged({ { user->id() } }, {}); } } @@ -1081,17 +1029,13 @@ void Connection::removeFromIgnoredUsers(const User* user) Q_ASSERT(user != nullptr); auto ignoreList = ignoredUsers(); - if (ignoreList.remove(user->id()) != 0) - { + if (ignoreList.remove(user->id()) != 0) { d->packAndSendAccountData<IgnoredUsersEvent>(ignoreList); - emit ignoredUsersListChanged({}, {{ user->id() }}); + emit ignoredUsersListChanged({}, { { user->id() } }); } } -QMap<QString, User*> Connection::users() const -{ - return d->userMap; -} +QMap<QString, User*> Connection::users() const { return d->userMap; } const ConnectionData* Connection::connectionData() const { @@ -1106,58 +1050,52 @@ Room* Connection::provideRoom(const QString& id, Omittable<JoinState> joinState) // If joinState.omitted(), all joinState == comparisons below are false. const auto roomKey = qMakePair(id, joinState == JoinState::Invite); auto* room = d->roomMap.value(roomKey, nullptr); - if (room) - { + if (room) { // Leave is a special case because in transition (5a) (see the .h file) // joinState == room->joinState but we still have to preempt the Invite // and emit a signal. For Invite and Join, there's no such problem. if (room->joinState() == joinState && joinState != JoinState::Leave) return room; - } else if (joinState.omitted()) - { + } else if (joinState.omitted()) { // No Join and Leave, maybe Invite? - room = d->roomMap.value({id, true}, nullptr); + room = d->roomMap.value({ id, true }, nullptr); if (room) return room; // No Invite either, setup a new room object below } - if (!room) - { + if (!room) { room = roomFactory()(this, id, - joinState.omitted() ? JoinState::Join : joinState.value()); - if (!room) - { + joinState.omitted() ? JoinState::Join + : joinState.value()); + if (!room) { qCCritical(MAIN) << "Failed to create a room" << id; return nullptr; } d->roomMap.insert(roomKey, room); d->firstTimeRooms.push_back(room); - connect(room, &Room::beforeDestruction, - this, &Connection::aboutToDeleteRoom); + connect(room, &Room::beforeDestruction, this, + &Connection::aboutToDeleteRoom); emit newRoom(room); } if (joinState.omitted()) return room; - if (joinState == JoinState::Invite) - { + if (joinState == JoinState::Invite) { // prev is either Leave or nullptr - auto* prev = d->roomMap.value({id, false}, nullptr); + auto* prev = d->roomMap.value({ id, false }, nullptr); emit invitedRoom(room, prev); - } - else - { + } else { room->setJoinState(joinState.value()); // Preempt the Invite room (if any) with a room in Join/Leave state. - auto* prevInvite = d->roomMap.take({id, true}); + auto* prevInvite = d->roomMap.take({ id, true }); if (joinState == JoinState::Join) emit joinedRoom(room, prevInvite); else if (joinState == JoinState::Leave) emit leftRoom(room, prevInvite); - if (prevInvite) - { - qCDebug(MAIN) << "Deleting Invite state for room" << prevInvite->id(); + if (prevInvite) { + qCDebug(MAIN) << "Deleting Invite state for room" + << prevInvite->id(); emit prevInvite->beforeDestruction(prevInvite); prevInvite->deleteLater(); } @@ -1176,15 +1114,9 @@ void Connection::setUserFactory(user_factory_t f) _userFactory = std::move(f); } -room_factory_t Connection::roomFactory() -{ - return _roomFactory; -} +room_factory_t Connection::roomFactory() { return _roomFactory; } -user_factory_t Connection::userFactory() -{ - return _userFactory; -} +user_factory_t Connection::userFactory() { return _userFactory; } room_factory_t Connection::_roomFactory = defaultRoomFactory<>(); user_factory_t Connection::_userFactory = defaultUserFactory<>(); @@ -1210,16 +1142,15 @@ void Connection::saveRoomState(Room* r) const return; QFile outRoomFile { stateCachePath() % SyncData::fileNameForRoom(r->id()) }; - if (outRoomFile.open(QFile::WriteOnly)) - { + if (outRoomFile.open(QFile::WriteOnly)) { QJsonDocument json { r->toJson() }; auto data = d->cacheToBinary ? json.toBinaryData() : json.toJson(QJsonDocument::Compact); outRoomFile.write(data.data(), data.size()); qCDebug(MAIN) << "Room state cache saved to" << outRoomFile.fileName(); } else { - qCWarning(MAIN) << "Error opening" << outRoomFile.fileName() - << ":" << outRoomFile.errorString(); + qCWarning(MAIN) << "Error opening" << outRoomFile.fileName() << ":" + << outRoomFile.errorString(); } } @@ -1228,29 +1159,31 @@ void Connection::saveState() const if (!d->cacheState) return; - QElapsedTimer et; et.start(); + QElapsedTimer et; + et.start(); QFile outFile { stateCachePath() % "state.json" }; - if (!outFile.open(QFile::WriteOnly)) - { - qCWarning(MAIN) << "Error opening" << outFile.fileName() - << ":" << outFile.errorString(); + if (!outFile.open(QFile::WriteOnly)) { + qCWarning(MAIN) << "Error opening" << outFile.fileName() << ":" + << outFile.errorString(); qCWarning(MAIN) << "Caching the rooms state disabled"; d->cacheState = false; return; } QJsonObject rootObj { - { QStringLiteral("cache_version"), QJsonObject { - { QStringLiteral("major"), SyncData::cacheVersion().first }, - { QStringLiteral("minor"), SyncData::cacheVersion().second } - }}}; + { QStringLiteral("cache_version"), + QJsonObject { + { QStringLiteral("major"), SyncData::cacheVersion().first }, + { QStringLiteral("minor"), + SyncData::cacheVersion().second } } } + }; { QJsonObject rooms; QJsonObject inviteRooms; for (const auto* i : roomMap()) // Pass on rooms in Leave state (i->joinState() == JoinState::Invite ? inviteRooms : rooms) - .insert(i->id(), QJsonValue::Null); + .insert(i->id(), QJsonValue::Null); QJsonObject roomObj; if (!rooms.isEmpty()) @@ -1262,20 +1195,20 @@ void Connection::saveState() const rootObj.insert("rooms", roomObj); } { - QJsonArray accountDataEvents { - basicEventJson(QStringLiteral("m.direct"), toJson(d->directChats)) - }; - for (const auto &e : d->accountData) + QJsonArray accountDataEvents { basicEventJson( + QStringLiteral("m.direct"), toJson(d->directChats)) }; + for (const auto& e : d->accountData) accountDataEvents.append( - basicEventJson(e.first, e.second->contentJson())); + basicEventJson(e.first, e.second->contentJson())); rootObj.insert("account_data", - QJsonObject {{ QStringLiteral("events"), accountDataEvents }}); + QJsonObject { { QStringLiteral("events"), + accountDataEvents } }); } QJsonDocument json { rootObj }; - auto data = d->cacheToBinary ? json.toBinaryData() : - json.toJson(QJsonDocument::Compact); + auto data = d->cacheToBinary ? json.toBinaryData() + : json.toJson(QJsonDocument::Compact); qCDebug(PROFILER) << "Cache for" << userId() << "generated in" << et; outFile.write(data.data(), data.size()); @@ -1287,14 +1220,14 @@ void Connection::loadState() if (!d->cacheState) return; - QElapsedTimer et; et.start(); + QElapsedTimer et; + et.start(); SyncData sync { stateCachePath() % "state.json" }; if (sync.nextBatch().isEmpty()) // No token means no cache by definition return; - if (!sync.unresolvedRooms().isEmpty()) - { + if (!sync.unresolvedRooms().isEmpty()) { qCWarning(MAIN) << "State cache incomplete, discarding"; return; } @@ -1302,7 +1235,8 @@ void Connection::loadState() // 1. Do initial sync on failed rooms without saving the nextBatch token // 2. Do the sync across all rooms as normal onSyncSuccess(std::move(sync), true); - qCDebug(PROFILER) << "*** Cached state for" << userId() << "loaded in" << et; + qCDebug(PROFILER) << "*** Cached state for" << userId() << "loaded in" + << et; } QString Connection::stateCachePath() const @@ -1312,29 +1246,21 @@ QString Connection::stateCachePath() const return cacheLocation(safeUserId); } -bool Connection::cacheState() const -{ - return d->cacheState; -} +bool Connection::cacheState() const { return d->cacheState; } void Connection::setCacheState(bool newValue) { - if (d->cacheState != newValue) - { + if (d->cacheState != newValue) { d->cacheState = newValue; emit cacheStateChanged(); } } -bool QMatrixClient::Connection::lazyLoading() const -{ - return d->lazyLoading; -} +bool QMatrixClient::Connection::lazyLoading() const { return d->lazyLoading; } void QMatrixClient::Connection::setLazyLoading(bool newValue) { - if (d->lazyLoading != newValue) - { + if (d->lazyLoading != newValue) { d->lazyLoading = newValue; emit lazyLoadingChanged(); } @@ -1343,8 +1269,8 @@ void QMatrixClient::Connection::setLazyLoading(bool newValue) void Connection::getTurnServers() { auto job = callApi<GetTurnServerJob>(); - connect(job, &GetTurnServerJob::success, - this, [=] { emit turnServersChanged(job->data()); }); + connect(job, &GetTurnServerJob::success, this, + [=] { emit turnServersChanged(job->data()); }); } const QString Connection::SupportedRoomVersion::StableTag = @@ -1376,7 +1302,8 @@ inline bool roomVersionLess(const Connection::SupportedRoomVersion& v1, return ok1 && ok2 ? vNum1 < vNum2 : v1.id < v2.id; } -QVector<Connection::SupportedRoomVersion> Connection::availableRoomVersions() const +QVector<Connection::SupportedRoomVersion> +Connection::availableRoomVersions() const { Q_ASSERT(!d->capabilities.roomVersions.omitted()); QVector<SupportedRoomVersion> result; @@ -1386,8 +1313,9 @@ QVector<Connection::SupportedRoomVersion> Connection::availableRoomVersions() co result.push_back({ it.key(), it.value() }); // Put stable versions over unstable; within each group, // sort numeric versions as numbers, the rest as strings. - const auto mid = std::partition(result.begin(), result.end(), - std::mem_fn(&SupportedRoomVersion::isStable)); + const auto mid = + std::partition(result.begin(), result.end(), + std::mem_fn(&SupportedRoomVersion::isStable)); std::sort(result.begin(), mid, roomVersionLess); std::sort(mid, result.end(), roomVersionLess); |