From 0e55c3b38f69ad13d5cead3ffd2bc5e894546d31 Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Sat, 4 Nov 2023 23:26:41 +0100 Subject: [PATCH] Port some things away from Controller::activeConnection --- src/controller.cpp | 9 ---- src/controller.h | 9 ---- src/matriximageprovider.cpp | 17 ++++---- src/matriximageprovider.h | 13 +++++- src/models/actionsmodel.cpp | 4 +- src/models/customemojimodel.cpp | 37 +++++++++++----- src/models/customemojimodel.h | 11 +++++ src/models/devicesmodel.cpp | 14 +++---- src/models/pushrulemodel.cpp | 65 ++++++++++++++++------------- src/models/pushrulemodel.h | 8 +++- src/models/serverlistmodel.cpp | 18 +++++++- src/models/serverlistmodel.h | 9 ++++ src/models/spacechildrenmodel.cpp | 8 ++-- src/models/spacetreeitem.cpp | 14 +++---- src/models/spacetreeitem.h | 6 ++- src/neochatroom.cpp | 22 ++++------ src/notificationsmanager.cpp | 4 +- src/qml/GlobalNotificationsPage.qml | 30 +++++++------ src/qml/JoinRoomPage.qml | 1 + src/qml/PushNotification.qml | 14 ++++--- src/qml/RoomListPage.qml | 2 + src/qml/SettingsPage.qml | 5 +++ src/qml/main.qml | 11 +++++ src/roommanager.cpp | 33 ++++++++++----- src/roommanager.h | 9 ++++ src/runner.cpp | 16 +++---- src/runner.h | 11 ++++- src/spacehierarchycache.cpp | 34 +++++++++------ src/spacehierarchycache.h | 9 ++++ 29 files changed, 289 insertions(+), 154 deletions(-) diff --git a/src/controller.cpp b/src/controller.cpp index 857aeccb6..190177646 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -99,10 +99,6 @@ Controller::Controller(QObject *parent) } oldAccountCount = m_accountRegistry.size(); }); - - QTimer::singleShot(0, this, [this] { - m_pushRuleModel = new PushRuleModel; - }); } Controller &Controller::instance() @@ -353,11 +349,6 @@ void Controller::setActiveConnection(NeoChatConnection *connection) Q_EMIT activeConnectionIndexChanged(); } -PushRuleModel *Controller::pushRuleModel() const -{ - return m_pushRuleModel; -} - void Controller::saveWindowGeometry() { WindowController::instance().saveGeometry(); diff --git a/src/controller.h b/src/controller.h index 0e33cfeb9..00b711fde 100644 --- a/src/controller.h +++ b/src/controller.h @@ -3,7 +3,6 @@ #pragma once -#include "models/pushrulemodel.h" #include #include #include @@ -47,11 +46,6 @@ class Controller : public QObject */ Q_PROPERTY(NeoChatConnection *activeConnection READ activeConnection WRITE setActiveConnection NOTIFY activeConnectionChanged) - /** - * @brief The PushRuleModel that has the active connection's push rules. - */ - Q_PROPERTY(PushRuleModel *pushRuleModel READ pushRuleModel CONSTANT) - /** * @brief The row number in the accounts directory of the active connection. */ @@ -95,8 +89,6 @@ public: void setActiveConnection(NeoChatConnection *connection); [[nodiscard]] NeoChatConnection *activeConnection() const; - [[nodiscard]] PushRuleModel *pushRuleModel() const; - /** * @brief Add a new connection to the account registry. */ @@ -154,7 +146,6 @@ private: bool m_isOnline = true; QMap m_notificationCounts; - QPointer m_pushRuleModel; Quotient::AccountRegistry m_accountRegistry; private Q_SLOTS: diff --git a/src/matriximageprovider.cpp b/src/matriximageprovider.cpp index 4d7056a1f..59b49aec0 100644 --- a/src/matriximageprovider.cpp +++ b/src/matriximageprovider.cpp @@ -13,11 +13,13 @@ #include #include "controller.h" +#include "neochatconnection.h" + #include using namespace Quotient; -ThumbnailResponse::ThumbnailResponse(QString id, QSize size) +ThumbnailResponse::ThumbnailResponse(QString id, QSize size, NeoChatConnection *connection) : mediaId(std::move(id)) , requestedSize(size) , localFile(QStringLiteral("%1/image_provider/%2-%3x%4.png") @@ -25,6 +27,7 @@ ThumbnailResponse::ThumbnailResponse(QString id, QSize size) mediaId, QString::number(requestedSize.width()), QString::number(requestedSize.height()))) + , m_connection(connection) , errorStr("Image request hasn't started"_ls) { if (requestedSize.isEmpty()) { @@ -51,24 +54,24 @@ ThumbnailResponse::ThumbnailResponse(QString id, QSize size) return; } - if (!Controller::instance().activeConnection()) { + if (!m_connection) { qWarning() << "Current connection is null"; return; } // Execute a request on the main thread asynchronously - moveToThread(Controller::instance().activeConnection()->thread()); + moveToThread(m_connection->thread()); QMetaObject::invokeMethod(this, &ThumbnailResponse::startRequest, Qt::QueuedConnection); } void ThumbnailResponse::startRequest() { - if (!Controller::instance().activeConnection()) { + if (!m_connection) { return; } // Runs in the main thread, not QML thread - Q_ASSERT(QThread::currentThread() == Controller::instance().activeConnection()->thread()); - job = Controller::instance().activeConnection()->getThumbnail(mediaId, requestedSize); + Q_ASSERT(QThread::currentThread() == m_connection->thread()); + job = m_connection->getThumbnail(mediaId, requestedSize); // Connect to any possible outcome including abandonment // to make sure the QML thread is not left stuck forever. connect(job, &BaseJob::finished, this, &ThumbnailResponse::prepareResult); @@ -118,7 +121,7 @@ QString ThumbnailResponse::errorString() const QQuickImageResponse *MatrixImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize) { - return new ThumbnailResponse(id, requestedSize); + return new ThumbnailResponse(id, requestedSize, m_connection); } #include "moc_matriximageprovider.cpp" diff --git a/src/matriximageprovider.h b/src/matriximageprovider.h index 9ace1ff21..20074eaa0 100644 --- a/src/matriximageprovider.h +++ b/src/matriximageprovider.h @@ -10,6 +10,8 @@ #include +class NeoChatConnection; + /** * @class ThumbnailResponse * @@ -21,7 +23,7 @@ class ThumbnailResponse : public QQuickImageResponse { Q_OBJECT public: - explicit ThumbnailResponse(QString mediaId, QSize requestedSize); + explicit ThumbnailResponse(QString mediaId, QSize requestedSize, NeoChatConnection *m_connection); ~ThumbnailResponse() override = default; private Q_SLOTS: @@ -33,6 +35,7 @@ private: QSize requestedSize; const QString localFile; Quotient::MediaThumbnailJob *job = nullptr; + NeoChatConnection *m_connection; QImage image; QString errorStr; @@ -51,6 +54,11 @@ private: */ class MatrixImageProvider : public QQuickAsyncImageProvider { + Q_OBJECT + QML_ELEMENT + QML_SINGLETON + + Q_PROPERTY(NeoChatConnection *connection MEMBER m_connection) public: /** * @brief Return a job to provide the image with the given ID. @@ -58,4 +66,7 @@ public: * @sa QQuickAsyncImageProvider::requestImageResponse */ QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override; + +private: + NeoChatConnection *m_connection = nullptr; }; diff --git a/src/models/actionsmodel.cpp b/src/models/actionsmodel.cpp index 48ff7f88d..29ec325b1 100644 --- a/src/models/actionsmodel.cpp +++ b/src/models/actionsmodel.cpp @@ -261,7 +261,7 @@ QList actions{ return QString(); } Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("Knocking room .", "Knocking room %1.", text)); - auto connection = Controller::instance().activeConnection(); + auto connection = room->connection(); const auto knownServer = roomName.mid(roomName.indexOf(":"_ls) + 1); if (parts.length() >= 2) { RoomManager::instance().knockRoom(connection, roomName, parts[1], QStringList{knownServer}); @@ -285,7 +285,7 @@ QList actions{ i18nc("'' does not look like a room id or alias.", "'%1' does not look like a room id or alias.", text)); return QString(); } - if (Controller::instance().activeConnection()->room(text) || Controller::instance().activeConnection()->roomByAlias(text)) { + if (room->connection()->room(text) || room->connection()->roomByAlias(text)) { Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("You are already in room .", "You are already in room %1.", text)); return QString(); } diff --git a/src/models/customemojimodel.cpp b/src/models/customemojimodel.cpp index 7ba0d890e..d5fef291b 100644 --- a/src/models/customemojimodel.cpp +++ b/src/models/customemojimodel.cpp @@ -15,13 +15,28 @@ using namespace Quotient; +void CustomEmojiModel::setConnection(NeoChatConnection *connection) +{ + if (connection == m_connection) { + return; + } + m_connection = connection; + Q_EMIT connectionChanged(); + fetchEmojis(); +} + +NeoChatConnection *CustomEmojiModel::connection() const +{ + return m_connection; +} + void CustomEmojiModel::fetchEmojis() { - if (!Controller::instance().activeConnection()) { + if (!m_connection) { return; } - const auto &data = Controller::instance().activeConnection()->accountData("im.ponies.user_emotes"_ls); + const auto &data = m_connection->accountData("im.ponies.user_emotes"_ls); if (data == nullptr) { return; } @@ -53,10 +68,10 @@ void CustomEmojiModel::addEmoji(const QString &name, const QUrl &location) { using namespace Quotient; - auto job = Controller::instance().activeConnection()->uploadFile(location.toLocalFile()); + auto job = m_connection->uploadFile(location.toLocalFile()); - connect(job, &BaseJob::success, this, [name, location, job] { - const auto &data = Controller::instance().activeConnection()->accountData("im.ponies.user_emotes"_ls); + connect(job, &BaseJob::success, this, [name, location, job, this] { + const auto &data = m_connection->accountData("im.ponies.user_emotes"_ls); auto json = data != nullptr ? data->contentJson() : QJsonObject(); auto emojiData = json["images"_ls].toObject(); @@ -78,7 +93,7 @@ void CustomEmojiModel::addEmoji(const QString &name, const QUrl &location) }); json["images"_ls] = emojiData; - Controller::instance().activeConnection()->setAccountData("im.ponies.user_emotes"_ls, json); + m_connection->setAccountData("im.ponies.user_emotes"_ls, json); }); } @@ -86,7 +101,7 @@ void CustomEmojiModel::removeEmoji(const QString &name) { using namespace Quotient; - const auto &data = Controller::instance().activeConnection()->accountData("im.ponies.user_emotes"_ls); + const auto &data = m_connection->accountData("im.ponies.user_emotes"_ls); Q_ASSERT(data); auto json = data->contentJson(); const QString _name = name.mid(1).chopped(1); @@ -109,18 +124,18 @@ void CustomEmojiModel::removeEmoji(const QString &name) emojiData.remove(_name); json["emoticons"_ls] = emojiData; } - Controller::instance().activeConnection()->setAccountData("im.ponies.user_emotes"_ls, json); + m_connection->setAccountData("im.ponies.user_emotes"_ls, json); } CustomEmojiModel::CustomEmojiModel(QObject *parent) : QAbstractListModel(parent) { - connect(&Controller::instance(), &Controller::activeConnectionChanged, this, [this]() { - if (!Controller::instance().activeConnection()) { + connect(this, &CustomEmojiModel::connectionChanged, this, [this]() { + if (!m_connection) { return; } CustomEmojiModel::fetchEmojis(); - connect(Controller::instance().activeConnection(), &Connection::accountDataChanged, this, [this](const QString &id) { + connect(m_connection, &Connection::accountDataChanged, this, [this](const QString &id) { if (id != QStringLiteral("im.ponies.user_emotes")) { return; } diff --git a/src/models/customemojimodel.h b/src/models/customemojimodel.h index c597af7d5..1b374a301 100644 --- a/src/models/customemojimodel.h +++ b/src/models/customemojimodel.h @@ -8,6 +8,8 @@ #include #include +class NeoChatConnection; + struct CustomEmoji { QString name; // with :semicolons: QString url; // mxc:// @@ -31,6 +33,8 @@ class CustomEmojiModel : public QAbstractListModel QML_ELEMENT QML_SINGLETON + Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged) + public: /** * @brief Defines the model roles. @@ -98,9 +102,16 @@ public: */ Q_INVOKABLE void removeEmoji(const QString &name); + void setConnection(NeoChatConnection *connection); + NeoChatConnection *connection() const; + +Q_SIGNALS: + void connectionChanged(); + private: explicit CustomEmojiModel(QObject *parent = nullptr); QList m_emojis; + NeoChatConnection *m_connection = nullptr; void fetchEmojis(); }; diff --git a/src/models/devicesmodel.cpp b/src/models/devicesmodel.cpp index 90514cefb..f03598544 100644 --- a/src/models/devicesmodel.cpp +++ b/src/models/devicesmodel.cpp @@ -24,8 +24,8 @@ DevicesModel::DevicesModel(QObject *parent) void DevicesModel::fetchDevices() { - if (Controller::instance().activeConnection()) { - auto job = Controller::instance().activeConnection()->callApi(); + if (m_connection) { + auto job = m_connection->callApi(); connect(job, &BaseJob::success, this, [this, job]() { beginResetModel(); m_devices = job->devices(); @@ -102,7 +102,7 @@ void DevicesModel::logout(const QString &deviceId, const QString &password) for (index = 0; m_devices[index].deviceId != deviceId; index++) ; - auto job = Controller::instance().activeConnection()->callApi(m_devices[index].deviceId); + auto job = m_connection->callApi(m_devices[index].deviceId); connect(job, &BaseJob::result, this, [this, job, password, index] { auto onSuccess = [this, index]() { @@ -117,9 +117,9 @@ void DevicesModel::logout(const QString &deviceId, const QString &password) authData["session"_ls] = replyData["session"_ls]; authData["password"_ls] = password; authData["type"_ls] = "m.login.password"_ls; - QJsonObject identifier = {{"type"_ls, "m.id.user"_ls}, {"user"_ls, Controller::instance().activeConnection()->user()->id()}}; + QJsonObject identifier = {{"type"_ls, "m.id.user"_ls}, {"user"_ls, m_connection->user()->id()}}; authData["identifier"_ls] = identifier; - auto *innerJob = Controller::instance().activeConnection()->callApi(m_devices[index].deviceId, authData); + auto *innerJob = m_connection->callApi(m_devices[index].deviceId, authData); connect(innerJob, &BaseJob::success, this, onSuccess); } else { onSuccess(); @@ -132,7 +132,7 @@ void DevicesModel::setName(const QString &deviceId, const QString &name) int index; for (index = 0; m_devices[index].deviceId != deviceId; index++); - auto job = Controller::instance().activeConnection()->callApi(m_devices[index].deviceId, name); + auto job = m_connection->callApi(m_devices[index].deviceId, name); QString oldName = m_devices[index].displayName; beginResetModel(); m_devices[index].displayName = name; @@ -160,7 +160,7 @@ void DevicesModel::setConnection(Connection *connection) connect(m_connection, &Connection::sessionVerified, this, [this](const QString &userId, const QString &deviceId) { Q_UNUSED(deviceId); - if (userId == Controller::instance().activeConnection()->userId()) { + if (userId == m_connection->userId()) { fetchDevices(); } }); diff --git a/src/models/pushrulemodel.cpp b/src/models/pushrulemodel.cpp index bf1e0e643..4111e9802 100644 --- a/src/models/pushrulemodel.cpp +++ b/src/models/pushrulemodel.cpp @@ -66,19 +66,6 @@ PushRuleModel::PushRuleModel(QObject *parent) : QAbstractListModel(parent) { m_defaultKeywordAction = static_cast(NeoChatConfig::self()->keywordPushRuleDefault()); - - if (Controller::instance().activeConnection()) { - controllerConnectionChanged(); - } - connect(&Controller::instance(), &Controller::activeConnectionChanged, this, &PushRuleModel::controllerConnectionChanged); -} - -void PushRuleModel::controllerConnectionChanged() -{ - if (Controller::instance().activeConnection()) { - connect(Controller::instance().activeConnection(), &Quotient::Connection::accountDataChanged, this, &PushRuleModel::updateNotificationRules); - updateNotificationRules(QStringLiteral("m.push_rules")); - } } void PushRuleModel::updateNotificationRules(const QString &type) @@ -87,7 +74,7 @@ void PushRuleModel::updateNotificationRules(const QString &type) return; } - const QJsonObject ruleDataJson = Controller::instance().activeConnection()->accountDataJson(QStringLiteral("m.push_rules")); + const QJsonObject ruleDataJson = m_connection->accountDataJson(QStringLiteral("m.push_rules")); const Quotient::PushRuleset ruleData = Quotient::fromJson(ruleDataJson[QStringLiteral("global")].toObject()); beginResetModel(); @@ -156,8 +143,7 @@ PushNotificationSection::Section PushRuleModel::getSection(Quotient::PushRule ru * * Rooms that the user hasn't joined shouldn't have a rule. */ - auto connection = Controller::instance().activeConnection(); - if (connection->room(ruleId) != nullptr) { + if (m_connection->room(ruleId) != nullptr) { return PushNotificationSection::Undefined; } /** @@ -171,7 +157,7 @@ PushNotificationSection::Section PushRuleModel::getSection(Quotient::PushRule ru if (!testUserId.startsWith(u'@')) { testUserId.prepend(u'@'); } - if (testUserId.startsWith(u'@') && !Quotient::serverPart(testUserId).isEmpty() && connection->user(testUserId) != nullptr) { + if (testUserId.startsWith(u'@') && !Quotient::serverPart(testUserId).isEmpty() && m_connection->user(testUserId) != nullptr) { return PushNotificationSection::Undefined; } // If the rule has push conditions and one is a room ID it is a room only keyword. @@ -325,14 +311,14 @@ void PushRuleModel::addKeyword(const QString &keyword, const QString &roomId) pushConditions.append(keywordCondition); } - auto job = Controller::instance().activeConnection()->callApi(QLatin1String("global"), - PushNotificationKind::kindString(kind), - keyword, - actions, - QString(), - QString(), - pushConditions, - roomId.isEmpty() ? keyword : QString()); + auto job = m_connection->callApi(QLatin1String("global"), + PushNotificationKind::kindString(kind), + keyword, + actions, + QString(), + QString(), + pushConditions, + roomId.isEmpty() ? keyword : QString()); connect(job, &Quotient::BaseJob::failure, this, [job, keyword]() { qWarning() << QLatin1String("Unable to set push rule for keyword %1: ").arg(keyword) << job->errorString(); }); @@ -351,7 +337,7 @@ void PushRuleModel::removeKeyword(const QString &keyword) } auto kind = PushNotificationKind::kindString(m_rules[index].kind); - auto job = Controller::instance().activeConnection()->callApi(QStringLiteral("global"), kind, m_rules[index].id); + auto job = m_connection->callApi(QStringLiteral("global"), kind, m_rules[index].id); connect(job, &Quotient::BaseJob::failure, this, [this, job, index]() { qWarning() << QLatin1String("Unable to remove push rule for keyword %1: ").arg(m_rules[index].id) << job->errorString(); }); @@ -359,10 +345,10 @@ void PushRuleModel::removeKeyword(const QString &keyword) void PushRuleModel::setNotificationRuleEnabled(const QString &kind, const QString &ruleId, bool enabled) { - auto job = Controller::instance().activeConnection()->callApi(QStringLiteral("global"), kind, ruleId); - connect(job, &Quotient::BaseJob::success, this, [job, kind, ruleId, enabled]() { + auto job = m_connection->callApi(QStringLiteral("global"), kind, ruleId); + connect(job, &Quotient::BaseJob::success, this, [job, kind, ruleId, enabled, this]() { if (job->enabled() != enabled) { - Controller::instance().activeConnection()->callApi(QStringLiteral("global"), kind, ruleId, enabled); + m_connection->callApi(QStringLiteral("global"), kind, ruleId, enabled); } }); } @@ -376,7 +362,7 @@ void PushRuleModel::setNotificationRuleActions(const QString &kind, const QStrin actions = actionToVariant(action); } - Controller::instance().activeConnection()->callApi(QStringLiteral("global"), kind, ruleId, actions); + m_connection->callApi(QStringLiteral("global"), kind, ruleId, actions); } PushNotificationAction::Action PushRuleModel::variantToAction(const QList &actions, bool enabled) @@ -453,4 +439,23 @@ QList PushRuleModel::actionToVariant(PushNotificationAction::Action ac return actions; } +NeoChatConnection *PushRuleModel::connection() const +{ + return m_connection; +} + +void PushRuleModel::setConnection(NeoChatConnection *connection) +{ + if (connection == m_connection) { + return; + } + m_connection = connection; + Q_EMIT connectionChanged(); + + if (m_connection) { + connect(m_connection, &Quotient::Connection::accountDataChanged, this, &PushRuleModel::updateNotificationRules); + updateNotificationRules(QStringLiteral("m.push_rules")); + } +} + #include "moc_pushrulemodel.cpp" diff --git a/src/models/pushrulemodel.h b/src/models/pushrulemodel.h index d0f5163b5..8c3f7aa34 100644 --- a/src/models/pushrulemodel.h +++ b/src/models/pushrulemodel.h @@ -157,6 +157,8 @@ class PushRuleModel : public QAbstractListModel */ Q_PROPERTY(bool globalNotificationsSet READ globalNotificationsSet NOTIFY globalNotificationsSetChanged) + Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged) + public: struct Rule { QString id; @@ -225,18 +227,22 @@ public: */ Q_INVOKABLE void removeKeyword(const QString &keyword); + void setConnection(NeoChatConnection *connection); + NeoChatConnection *connection() const; + Q_SIGNALS: void defaultStateChanged(); void globalNotificationsEnabledChanged(); void globalNotificationsSetChanged(); + void connectionChanged(); private Q_SLOTS: - void controllerConnectionChanged(); void updateNotificationRules(const QString &type); private: PushNotificationAction::Action m_defaultKeywordAction; QList m_rules; + NeoChatConnection *m_connection; void setRules(QList rules, PushNotificationKind::Kind kind); diff --git a/src/models/serverlistmodel.cpp b/src/models/serverlistmodel.cpp index 239004f84..e631a057a 100644 --- a/src/models/serverlistmodel.cpp +++ b/src/models/serverlistmodel.cpp @@ -19,7 +19,7 @@ ServerListModel::ServerListModel(QObject *parent) const auto stateConfig = KSharedConfig::openStateConfig(); const KConfigGroup serverGroup = stateConfig->group(QStringLiteral("Servers")); - QString domain = Controller::instance().activeConnection()->domain(); + QString domain = m_connection->domain(); // Add the user's homeserver m_servers.append(Server{ @@ -100,7 +100,7 @@ void ServerListModel::checkServer(const QString &url) m_checkServerJob->abandon(); } - m_checkServerJob = Controller::instance().activeConnection()->callApi(url, 1); + m_checkServerJob = m_connection->callApi(url, 1); connect(m_checkServerJob, &Quotient::BaseJob::success, this, [this, url] { Q_EMIT serverCheckComplete(url, true); }); @@ -153,4 +153,18 @@ QHash ServerListModel::roleNames() const }; } +NeoChatConnection *ServerListModel::connection() const +{ + return m_connection; +} + +void ServerListModel::setConnection(NeoChatConnection *connection) +{ + if (m_connection == connection) { + return; + } + m_connection = connection; + Q_EMIT connectionChanged(); +} + #include "moc_serverlistmodel.cpp" diff --git a/src/models/serverlistmodel.h b/src/models/serverlistmodel.h index 30a28eb32..c0d2d50c3 100644 --- a/src/models/serverlistmodel.h +++ b/src/models/serverlistmodel.h @@ -10,6 +10,8 @@ #include #include +class NeoChatConnection; + /** * @class ServerListModel * @@ -27,6 +29,8 @@ class ServerListModel : public QAbstractListModel Q_OBJECT QML_ELEMENT + Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged) + public: /** * @brief Define the data required to represent a server. @@ -96,10 +100,15 @@ public: */ Q_INVOKABLE void removeServerAtIndex(int index); + NeoChatConnection *connection() const; + void setConnection(NeoChatConnection *connection); + Q_SIGNALS: void serverCheckComplete(QString url, bool valid); + void connectionChanged(); private: QList m_servers; QPointer m_checkServerJob = nullptr; + NeoChatConnection *m_connection = nullptr; }; diff --git a/src/models/spacechildrenmodel.cpp b/src/models/spacechildrenmodel.cpp index f441c45b5..7f49fde65 100644 --- a/src/models/spacechildrenmodel.cpp +++ b/src/models/spacechildrenmodel.cpp @@ -12,7 +12,7 @@ SpaceChildrenModel::SpaceChildrenModel(QObject *parent) : QAbstractItemModel(parent) { - m_rootItem = new SpaceTreeItem(); + m_rootItem = new SpaceTreeItem(nullptr); } SpaceChildrenModel::~SpaceChildrenModel() @@ -71,7 +71,8 @@ void SpaceChildrenModel::refreshModel() delete m_rootItem; m_loading = true; Q_EMIT loadingChanged(); - m_rootItem = new SpaceTreeItem(nullptr, m_space->id(), m_space->displayName(), m_space->canonicalAlias()); + m_rootItem = + new SpaceTreeItem(dynamic_cast(m_space->connection()), nullptr, m_space->id(), m_space->displayName(), m_space->canonicalAlias()); endResetModel(); auto job = m_space->connection()->callApi(m_space->id(), Quotient::none, Quotient::none, 1); m_currentJobs.append(job); @@ -112,7 +113,8 @@ void SpaceChildrenModel::insertChildren(std::vectorinsertChild(insertRow, - new SpaceTreeItem(parentItem, + new SpaceTreeItem(dynamic_cast(m_space->connection()), + parentItem, children[i].roomId, children[i].name, children[i].canonicalAlias, diff --git a/src/models/spacetreeitem.cpp b/src/models/spacetreeitem.cpp index 2bd904549..036546d14 100644 --- a/src/models/spacetreeitem.cpp +++ b/src/models/spacetreeitem.cpp @@ -5,7 +5,8 @@ #include "controller.h" -SpaceTreeItem::SpaceTreeItem(SpaceTreeItem *parent, +SpaceTreeItem::SpaceTreeItem(NeoChatConnection *connection, + SpaceTreeItem *parent, const QString &id, const QString &name, const QString &canonicalAlias, @@ -15,7 +16,8 @@ SpaceTreeItem::SpaceTreeItem(SpaceTreeItem *parent, bool allowGuests, bool worldReadable, bool isSpace) - : m_parentItem(parent) + : m_connection(connection) + , m_parentItem(parent) , m_id(id) , m_name(name) , m_canonicalAlias(canonicalAlias) @@ -107,8 +109,7 @@ QUrl SpaceTreeItem::avatarUrl() const if (m_avatarUrl.isEmpty() || m_avatarUrl.scheme() != QLatin1String("mxc")) { return {}; } - auto connection = Controller::instance().activeConnection(); - auto url = connection->makeMediaUrl(m_avatarUrl); + auto url = m_connection->makeMediaUrl(m_avatarUrl); if (url.scheme() == QLatin1String("mxc")) { return url; } @@ -127,11 +128,10 @@ bool SpaceTreeItem::worldReadable() const bool SpaceTreeItem::isJoined() const { - auto connection = Controller::instance().activeConnection(); - if (!connection) { + if (!m_connection) { return false; } - return connection->room(id(), Quotient::JoinState::Join) != nullptr; + return m_connection->room(id(), Quotient::JoinState::Join) != nullptr; } bool SpaceTreeItem::isSpace() const diff --git a/src/models/spacetreeitem.h b/src/models/spacetreeitem.h index 32ea87a20..bfdfe87ab 100644 --- a/src/models/spacetreeitem.h +++ b/src/models/spacetreeitem.h @@ -3,6 +3,8 @@ #include +class NeoChatConnection; + /** * @class SpaceTreeItem * @@ -18,7 +20,8 @@ class SpaceTreeItem { public: - explicit SpaceTreeItem(SpaceTreeItem *parent = nullptr, + explicit SpaceTreeItem(NeoChatConnection *connection, + SpaceTreeItem *parent = nullptr, const QString &id = {}, const QString &name = {}, const QString &canonicalAlias = {}, @@ -121,6 +124,7 @@ public: bool isSpace() const; private: + NeoChatConnection *m_connection; QList m_children; SpaceTreeItem *m_parentItem; diff --git a/src/neochatroom.cpp b/src/neochatroom.cpp index 3d88c6df3..4ffa54660 100644 --- a/src/neochatroom.cpp +++ b/src/neochatroom.cpp @@ -1338,7 +1338,7 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state) for (const auto &i : roomRuleArray) { QJsonObject roomRule = i.toObject(); if (roomRule["rule_id"_ls] == id()) { - Controller::instance().activeConnection()->callApi("global"_ls, "room"_ls, id()); + connection()->callApi("global"_ls, "room"_ls, id()); } } } @@ -1349,7 +1349,7 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state) for (const auto &i : overrideRuleArray) { QJsonObject overrideRule = i.toObject(); if (overrideRule["rule_id"_ls] == id()) { - Controller::instance().activeConnection()->callApi("global"_ls, "override"_ls, id()); + connection()->callApi("global"_ls, "override"_ls, id()); } } } @@ -1385,11 +1385,9 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state) const QList conditions = {pushCondition}; // Add new override rule and make sure it's enabled - auto job = Controller::instance() - .activeConnection() - ->callApi("global"_ls, "override"_ls, id(), actions, QString(), QString(), conditions, QString()); + auto job = connection()->callApi("global"_ls, "override"_ls, id(), actions, QString(), QString(), conditions, QString()); connect(job, &BaseJob::success, this, [this]() { - auto enableJob = Controller::instance().activeConnection()->callApi("global"_ls, "override"_ls, id(), true); + auto enableJob = connection()->callApi("global"_ls, "override"_ls, id(), true); connect(enableJob, &BaseJob::success, this, [this]() { m_pushNotificationStateUpdating = false; }); @@ -1413,11 +1411,9 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state) // No conditions for a room rule const QList conditions; - auto setJob = Controller::instance() - .activeConnection() - ->callApi("global"_ls, "room"_ls, id(), actions, QString(), QString(), conditions, QString()); + auto setJob = connection()->callApi("global"_ls, "room"_ls, id(), actions, QString(), QString(), conditions, QString()); connect(setJob, &BaseJob::success, this, [this]() { - auto enableJob = Controller::instance().activeConnection()->callApi("global"_ls, "room"_ls, id(), true); + auto enableJob = connection()->callApi("global"_ls, "room"_ls, id(), true); connect(enableJob, &BaseJob::success, this, [this]() { m_pushNotificationStateUpdating = false; }); @@ -1446,11 +1442,9 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state) const QList conditions; // Add new room rule and make sure enabled - auto setJob = Controller::instance() - .activeConnection() - ->callApi("global"_ls, "room"_ls, id(), actions, QString(), QString(), conditions, QString()); + auto setJob = connection()->callApi("global"_ls, "room"_ls, id(), actions, QString(), QString(), conditions, QString()); connect(setJob, &BaseJob::success, this, [this]() { - auto enableJob = Controller::instance().activeConnection()->callApi("global"_ls, "room"_ls, id(), true); + auto enableJob = connection()->callApi("global"_ls, "room"_ls, id(), true); connect(enableJob, &BaseJob::success, this, [this]() { m_pushNotificationStateUpdating = false; }); diff --git a/src/notificationsmanager.cpp b/src/notificationsmanager.cpp index 86e2d758a..aec8cae81 100644 --- a/src/notificationsmanager.cpp +++ b/src/notificationsmanager.cpp @@ -210,9 +210,7 @@ void NotificationsManager::postNotification(NeoChatRoom *room, if (!room) { return; } - if (room->localUser()->id() != Controller::instance().activeConnection()->userId()) { - Controller::instance().setActiveConnection(dynamic_cast(Controller::instance().accounts().get(room->localUser()->id()))); - } + Controller::instance().setActiveConnection(dynamic_cast(Controller::instance().accounts().get(room->localUser()->id()))); RoomManager::instance().enterRoom(room); }); diff --git a/src/qml/GlobalNotificationsPage.qml b/src/qml/GlobalNotificationsPage.qml index a0260be95..02d6cfd1e 100644 --- a/src/qml/GlobalNotificationsPage.qml +++ b/src/qml/GlobalNotificationsPage.qml @@ -14,17 +14,23 @@ import org.kde.neochat FormCard.FormCardPage { id: root + required property NeoChatConnection connection + title: i18nc("@title:window", "Notifications") + property PushRuleModel pushRuleModel: PushRuleModel { + connection: root.connection + } + FormCard.FormCard { Layout.topMargin: Kirigami.Units.largeSpacing FormCard.FormCheckDelegate { text: i18n("Enable notifications for this account") description: i18n("Whether push notifications are generated by your Matrix server") - checked: Controller.pushRuleModel.globalNotificationsEnabled - enabled: Controller.pushRuleModel.globalNotificationsSet + checked: root.pushRuleModel.globalNotificationsEnabled + enabled: root.pushRuleModel.globalNotificationsSet onToggled: { - Controller.pushRuleModel.globalNotificationsEnabled = checked + root.pushRuleModel.globalNotificationsEnabled = checked } } } @@ -35,7 +41,7 @@ FormCard.FormCardPage { FormCard.FormCard { Repeater { model: KSortFilterProxyModel { - sourceModel: Controller.pushRuleModel + sourceModel: root.pushRuleModel filterRowCallback: function(source_row, source_parent) { let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) return sectionRole == PushNotificationSection.Room; @@ -52,7 +58,7 @@ FormCard.FormCardPage { FormCard.FormCard { Repeater { model: KSortFilterProxyModel { - sourceModel: Controller.pushRuleModel + sourceModel: root.pushRuleModel filterRowCallback: function(source_row, source_parent) { let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) return sectionRole == PushNotificationSection.Mentions; @@ -69,7 +75,7 @@ FormCard.FormCardPage { FormCard.FormCard { Repeater { model: KSortFilterProxyModel { - sourceModel: Controller.pushRuleModel + sourceModel: root.pushRuleModel filterRowCallback: function(source_row, source_parent) { let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) @@ -100,7 +106,7 @@ FormCard.FormCardPage { } onAccepted: { - Controller.pushRuleModel.addKeyword(keywordAddField.text) + root.pushRuleModel.addKeyword(keywordAddField.text) keywordAddField.text = "" } } @@ -114,7 +120,7 @@ FormCard.FormCardPage { enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown onClicked: { - Controller.pushRuleModel.addKeyword(keywordAddField.text) + root.pushRuleModel.addKeyword(keywordAddField.text) keywordAddField.text = "" } @@ -133,7 +139,7 @@ FormCard.FormCardPage { FormCard.FormCard { Repeater { model: KSortFilterProxyModel { - sourceModel: Controller.pushRuleModel + sourceModel: root.pushRuleModel filterRowCallback: function(source_row, source_parent) { let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) return sectionRole == PushNotificationSection.Invites; @@ -154,7 +160,7 @@ FormCard.FormCardPage { Repeater { model: KSortFilterProxyModel { id: unknownModel - sourceModel: Controller.pushRuleModel + sourceModel: root.pushRuleModel filterRowCallback: function(source_row, source_parent) { let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) return sectionRole == PushNotificationSection.Unknown; @@ -169,9 +175,9 @@ FormCard.FormCardPage { id: ruleDelegate NotificationRuleItem { onDeleteRule: { - Controller.pushRuleModel.removeKeyword(id) + root.pushRuleModel.removeKeyword(id) } - onActionChanged: (action) => Controller.pushRuleModel.setPushRuleAction(id, action) + onActionChanged: (action) => root.pushRuleModel.setPushRuleAction(id, action) } } } diff --git a/src/qml/JoinRoomPage.qml b/src/qml/JoinRoomPage.qml index b41d4617d..ebb7b9e1c 100644 --- a/src/qml/JoinRoomPage.qml +++ b/src/qml/JoinRoomPage.qml @@ -69,6 +69,7 @@ Kirigami.ScrollablePage { valueRole: "url" model: ServerListModel { id: serverListModel + connection: root.connection } delegate: Delegates.RoundedItemDelegate { diff --git a/src/qml/PushNotification.qml b/src/qml/PushNotification.qml index 594cadfa8..870a5e7d6 100644 --- a/src/qml/PushNotification.qml +++ b/src/qml/PushNotification.qml @@ -16,6 +16,10 @@ FormCard.FormCardPage { property NeoChatRoom room + property PushRuleModel pushRuleModel: PushRuleModel { + connection: root.room.connection + } + title: i18nc('@title:window', 'Notifications') FormCard.FormHeader { @@ -63,7 +67,7 @@ FormCard.FormCardPage { FormCard.FormCard { Repeater { model: KSortFilterProxyModel { - sourceModel: Controller.pushRuleModel + sourceModel: root.pushRuleModel filterRowCallback: function(source_row, source_parent) { let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) @@ -78,9 +82,9 @@ FormCard.FormCardPage { id: ruleDelegate NotificationRuleItem { onDeleteRule: { - Controller.pushRuleModel.removeKeyword(id) + root.pushRuleModel.removeKeyword(id) } - onActionChanged: (action) => Controller.pushRuleModel.setPushRuleAction(id, action) + onActionChanged: (action) => root.pushRuleModel.setPushRuleAction(id, action) } } } @@ -105,7 +109,7 @@ FormCard.FormCardPage { } onAccepted: { - Controller.pushRuleModel.addKeyword(keywordAddField.text, root.room.id) + root.pushRuleModel.addKeyword(keywordAddField.text, root.room.id) keywordAddField.text = "" } } @@ -119,7 +123,7 @@ FormCard.FormCardPage { enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown && keywordAddField.text.length > 0 onClicked: { - Controller.pushRuleModel.addKeyword(keywordAddField.text, root.room.id) + root.pushRuleModel.addKeyword(keywordAddField.text, root.room.id) keywordAddField.text = "" } diff --git a/src/qml/RoomListPage.qml b/src/qml/RoomListPage.qml index 9199b7a4e..4481579d5 100644 --- a/src/qml/RoomListPage.qml +++ b/src/qml/RoomListPage.qml @@ -39,6 +39,8 @@ Kirigami.Page { sortFilterRoomListModel.filterText = ""; } + Component.onCompleted: Runner.roomListModel = root.roomListModel + Connections { target: RoomManager function onCurrentRoomChanged() { diff --git a/src/qml/SettingsPage.qml b/src/qml/SettingsPage.qml index 4a537e68b..650f69f8d 100644 --- a/src/qml/SettingsPage.qml +++ b/src/qml/SettingsPage.qml @@ -32,6 +32,11 @@ KirigamiSettings.CategorizedSettings { text: i18n("Notifications") icon.name: "preferences-desktop-notification" page: Qt.resolvedUrl("GlobalNotificationsPage.qml") + initialProperties: { + return { + connection: root.connection + } + } }, KirigamiSettings.SettingAction { actionName: "security" diff --git a/src/qml/main.qml b/src/qml/main.qml index 77a22479c..c1e5303f9 100644 --- a/src/qml/main.qml +++ b/src/qml/main.qml @@ -40,6 +40,13 @@ Kirigami.ApplicationWindow { } } + onConnectionChanged: { + CustomEmojiModel.connection = root.connection + MatrixImageProvider.connection = root.connection + RoomManager.connection = root.connection + SpaceHierarchyCache.connection = root.connection + } + Connections { target: root.quitAction function onTriggered() { @@ -190,6 +197,10 @@ Kirigami.ApplicationWindow { } Component.onCompleted: { + CustomEmojiModel.connection = root.connection + MatrixImageProvider.connection = root.connection + RoomManager.connection = root.connection + SpaceHierarchyCache.connection = root.connection WindowController.setBlur(pageStack, Config.blur && !Config.compactLayout); if (Config.minimizeToSystemTrayOnStartup && !Kirigami.Settings.isMobile && Controller.supportSystemTray && Config.systemTray) { restoreWindowGeometryConnections.enabled = true; // To restore window size and position diff --git a/src/roommanager.cpp b/src/roommanager.cpp index 9d16e5252..c867ac482 100644 --- a/src/roommanager.cpp +++ b/src/roommanager.cpp @@ -77,10 +77,9 @@ void RoomManager::openResource(const QString &idOrUri, const QString &action) Q_EMIT warning(i18n("Malformed or empty Matrix id"), i18n("%1 is not a correct Matrix identifier", idOrUri)); return; } - auto account = Controller::instance().activeConnection(); if (uri.type() != Uri::NonMatrix) { - if (!account) { + if (!m_connection) { return; } if (!action.isEmpty()) { @@ -89,7 +88,7 @@ void RoomManager::openResource(const QString &idOrUri, const QString &action) // TODO we should allow the user to select a connection. } - const auto result = visitResource(account, uri); + const auto result = visitResource(m_connection, uri); if (result == Quotient::CouldNotResolve) { Q_EMIT warning(i18n("Room not found"), i18n("There's no room %1 in the room list. Check the spelling and the account.", idOrUri)); } else { // Invalid cases should have been eliminated earlier @@ -145,7 +144,7 @@ void RoomManager::setUrlArgument(const QString &arg) void RoomManager::loadInitialRoom() { - Q_ASSERT(Controller::instance().activeConnection()); + Q_ASSERT(m_connection); if (!m_arg.isEmpty()) { openResource(m_arg); @@ -158,16 +157,16 @@ void RoomManager::loadInitialRoom() openRoomForActiveConnection(); - connect(&Controller::instance(), &Controller::activeConnectionChanged, this, &RoomManager::openRoomForActiveConnection); + connect(this, &RoomManager::connectionChanged, this, &RoomManager::openRoomForActiveConnection); } void RoomManager::openRoomForActiveConnection() { - if (!Controller::instance().activeConnection()) { + if (!m_connection) { return; } // Read from last open room - QString roomId = m_lastRoomConfig.readEntry(Controller::instance().activeConnection()->userId(), QString()); + QString roomId = m_lastRoomConfig.readEntry(m_connection->userId(), QString()); // TODO remove legacy check at some point. if (roomId.isEmpty()) { @@ -177,7 +176,7 @@ void RoomManager::openRoomForActiveConnection() if (!roomId.isEmpty()) { // Here we can cast because the controller has been configured to // return NeoChatRoom instead of simple Quotient::Room - const auto room = qobject_cast(Controller::instance().activeConnection()->room(roomId)); + const auto room = qobject_cast(m_connection->room(roomId)); if (room) { if (room->isSpace()) { @@ -219,7 +218,7 @@ void RoomManager::enterRoom(NeoChatRoom *room) } // Save last open room - m_lastRoomConfig.writeEntry(Controller::instance().activeConnection()->userId(), room->id()); + m_lastRoomConfig.writeEntry(m_connection->userId(), room->id()); } void RoomManager::openWindow(NeoChatRoom *room) @@ -253,7 +252,7 @@ void RoomManager::enterSpaceHome(NeoChatRoom *spaceRoom) } // Save last open room - m_lastRoomConfig.writeEntry(Controller::instance().activeConnection()->userId(), spaceRoom->id()); + m_lastRoomConfig.writeEntry(m_connection->userId(), spaceRoom->id()); } UriResolveResult RoomManager::visitUser(User *user, const QString &action) @@ -381,4 +380,18 @@ void RoomManager::setChatDocumentHandler(ChatDocumentHandler *handler) Q_EMIT chatDocumentHandlerChanged(); } +NeoChatConnection *RoomManager::connection() const +{ + return m_connection; +} + +void RoomManager::setConnection(NeoChatConnection *connection) +{ + if (m_connection == connection) { + return; + } + m_connection = connection; + Q_EMIT connectionChanged(); +} + #include "moc_roommanager.cpp" diff --git a/src/roommanager.h b/src/roommanager.h index 21fb614dd..55c9b8d76 100644 --- a/src/roommanager.h +++ b/src/roommanager.h @@ -17,6 +17,7 @@ #include "models/messagefiltermodel.h" class NeoChatRoom; +class NeoChatConnection; namespace Quotient { @@ -37,6 +38,8 @@ class RoomManager : public QObject, public UriResolverBase QML_ELEMENT QML_SINGLETON + Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged) + /** * @brief The current open room in NeoChat, if any. * @@ -247,6 +250,9 @@ public: */ void setUrlArgument(const QString &arg); + NeoChatConnection *connection() const; + void setConnection(NeoChatConnection *connection); + Q_SIGNALS: void currentRoomChanged(); @@ -365,6 +371,8 @@ Q_SIGNALS: void chatDocumentHandlerChanged(); + void connectionChanged(); + private: void openRoomForActiveConnection(); @@ -378,4 +386,5 @@ private: MessageEventModel *m_messageEventModel; MessageFilterModel *m_messageFilterModel; MediaMessageFilterModel *m_mediaMessageFilterModel; + NeoChatConnection *m_connection; }; diff --git a/src/runner.cpp b/src/runner.cpp index f730303b0..be895b684 100644 --- a/src/runner.cpp +++ b/src/runner.cpp @@ -33,15 +33,17 @@ Runner::Runner() qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); - - m_model.setSourceModel(&m_sourceModel); - - connect(&Controller::instance(), &Controller::activeConnectionChanged, this, &Runner::activeConnectionChanged); } -void Runner::activeConnectionChanged() +void Runner::setRoomListModel(RoomListModel *roomListModel) { - m_sourceModel.setConnection(Controller::instance().activeConnection()); + m_model.setSourceModel(roomListModel); + Q_EMIT roomListModelChanged(); +} + +RoomListModel *Runner::roomListModel() const +{ + return dynamic_cast(m_model.sourceModel()); } RemoteActions Runner::Actions() @@ -84,7 +86,7 @@ void Runner::Run(const QString &id, const QString &actionId) { Q_UNUSED(actionId); - NeoChatRoom *room = qobject_cast(Controller::instance().activeConnection()->room(id)); + NeoChatRoom *room = qobject_cast(roomListModel()->connection()->room(id)); if (!room) { return; diff --git a/src/runner.h b/src/runner.h index 4e15b55da..5bf71c9c9 100644 --- a/src/runner.h +++ b/src/runner.h @@ -165,6 +165,10 @@ class Runner : public QObject, protected QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.krunner1") + QML_ELEMENT + QML_SINGLETON + + Q_PROPERTY(RoomListModel *roomListModel READ roomListModel WRITE setRoomListModel NOTIFY roomListModelChanged) public: Runner(); @@ -185,9 +189,14 @@ public: */ Q_SCRIPTABLE void Run(const QString &id, const QString &actionId); + void setRoomListModel(RoomListModel *roomListModel); + RoomListModel *roomListModel() const; + +Q_SIGNALS: + void roomListModelChanged(); + private: RemoteImage serializeImage(const QImage &image); - void activeConnectionChanged(); SortFilterRoomListModel m_model; RoomListModel m_sourceModel; diff --git a/src/spacehierarchycache.cpp b/src/spacehierarchycache.cpp index 515f733f9..5556b510e 100644 --- a/src/spacehierarchycache.cpp +++ b/src/spacehierarchycache.cpp @@ -14,22 +14,15 @@ using namespace Quotient; SpaceHierarchyCache::SpaceHierarchyCache(QObject *parent) : QObject{parent} { - cacheSpaceHierarchy(); - connect(&Controller::instance(), &Controller::activeConnectionChanged, this, [this]() { - cacheSpaceHierarchy(); - connect(Controller::instance().activeConnection(), &Connection::joinedRoom, this, &SpaceHierarchyCache::addSpaceToHierarchy); - connect(Controller::instance().activeConnection(), &Connection::aboutToDeleteRoom, this, &SpaceHierarchyCache::removeSpaceFromHierarchy); - }); } void SpaceHierarchyCache::cacheSpaceHierarchy() { - auto connection = Controller::instance().activeConnection(); - if (!connection) { + if (!m_connection) { return; } - const auto &roomList = connection->allRooms(); + const auto &roomList = m_connection->allRooms(); for (const auto &room : roomList) { const auto neoChatRoom = static_cast(room); if (neoChatRoom->isSpace()) { @@ -46,11 +39,10 @@ void SpaceHierarchyCache::cacheSpaceHierarchy() void SpaceHierarchyCache::populateSpaceHierarchy(const QString &spaceId) { - auto connection = Controller::instance().activeConnection(); - if (!connection) { + if (!m_connection) { return; } - auto job = connection->callApi(spaceId); + auto job = m_connection->callApi(spaceId); connect(job, &BaseJob::success, this, [this, job, spaceId]() { const auto rooms = job->rooms(); @@ -102,4 +94,22 @@ bool SpaceHierarchyCache::isChildSpace(const QString &spaceId) const return false; } +NeoChatConnection *SpaceHierarchyCache::connection() const +{ + return m_connection; +} + +void SpaceHierarchyCache::setConnection(NeoChatConnection *connection) +{ + if (m_connection == connection) { + return; + } + m_connection = connection; + Q_EMIT connectionChanged(); + m_spaceHierarchy.clear(); + cacheSpaceHierarchy(); + connect(connection, &Connection::joinedRoom, this, &SpaceHierarchyCache::addSpaceToHierarchy); + connect(connection, &Connection::aboutToDeleteRoom, this, &SpaceHierarchyCache::removeSpaceFromHierarchy); +} + #include "moc_spacehierarchycache.cpp" diff --git a/src/spacehierarchycache.h b/src/spacehierarchycache.h index 15aee8ee7..17b8e5314 100644 --- a/src/spacehierarchycache.h +++ b/src/spacehierarchycache.h @@ -10,6 +10,8 @@ #include #include +#include "neochatconnection.h" + namespace Quotient { class Room; @@ -28,6 +30,8 @@ class SpaceHierarchyCache : public QObject QML_ELEMENT QML_SINGLETON + Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged) + public: static SpaceHierarchyCache &instance() { @@ -50,8 +54,12 @@ public: */ [[nodiscard]] bool isChildSpace(const QString &spaceId) const; + NeoChatConnection *connection() const; + void setConnection(NeoChatConnection *connection); + Q_SIGNALS: void spaceHierarchyChanged(); + void connectionChanged(); private Q_SLOTS: void addSpaceToHierarchy(Quotient::Room *room); @@ -64,4 +72,5 @@ private: QHash> m_spaceHierarchy; void cacheSpaceHierarchy(); void populateSpaceHierarchy(const QString &spaceId); + NeoChatConnection *m_connection; };