Port some things away from Controller::activeConnection

This commit is contained in:
Tobias Fella
2023-11-04 23:26:41 +01:00
parent ff4cf86ea5
commit 0e55c3b38f
29 changed files with 289 additions and 154 deletions

View File

@@ -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();

View File

@@ -3,7 +3,6 @@
#pragma once
#include "models/pushrulemodel.h"
#include <QObject>
#include <QQmlEngine>
#include <QQuickItem>
@@ -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<Quotient::Room *, int> m_notificationCounts;
QPointer<PushRuleModel> m_pushRuleModel;
Quotient::AccountRegistry m_accountRegistry;
private Q_SLOTS:

View File

@@ -13,11 +13,13 @@
#include <KLocalizedString>
#include "controller.h"
#include "neochatconnection.h"
#include <Quotient/connection.h>
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"

View File

@@ -10,6 +10,8 @@
#include <QReadWriteLock>
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;
};

View File

@@ -261,7 +261,7 @@ QList<ActionsModel::Action> actions{
return QString();
}
Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("Knocking room <roomname>.", "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<ActionsModel::Action> actions{
i18nc("'<text>' 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 <roomname>.", "You are already in room %1.", text));
return QString();
}

View File

@@ -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;
}

View File

@@ -8,6 +8,8 @@
#include <QRegularExpression>
#include <memory>
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<CustomEmoji> m_emojis;
NeoChatConnection *m_connection = nullptr;
void fetchEmojis();
};

View File

@@ -24,8 +24,8 @@ DevicesModel::DevicesModel(QObject *parent)
void DevicesModel::fetchDevices()
{
if (Controller::instance().activeConnection()) {
auto job = Controller::instance().activeConnection()->callApi<GetDevicesJob>();
if (m_connection) {
auto job = m_connection->callApi<GetDevicesJob>();
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<NeochatDeleteDeviceJob>(m_devices[index].deviceId);
auto job = m_connection->callApi<NeochatDeleteDeviceJob>(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<NeochatDeleteDeviceJob>(m_devices[index].deviceId, authData);
auto *innerJob = m_connection->callApi<NeochatDeleteDeviceJob>(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<UpdateDeviceJob>(m_devices[index].deviceId, name);
auto job = m_connection->callApi<UpdateDeviceJob>(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();
}
});

View File

@@ -66,19 +66,6 @@ PushRuleModel::PushRuleModel(QObject *parent)
: QAbstractListModel(parent)
{
m_defaultKeywordAction = static_cast<PushNotificationAction::Action>(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<Quotient::PushRuleset>(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<Quotient::SetPushRuleJob>(QLatin1String("global"),
PushNotificationKind::kindString(kind),
keyword,
actions,
QString(),
QString(),
pushConditions,
roomId.isEmpty() ? keyword : QString());
auto job = m_connection->callApi<Quotient::SetPushRuleJob>(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<Quotient::DeletePushRuleJob>(QStringLiteral("global"), kind, m_rules[index].id);
auto job = m_connection->callApi<Quotient::DeletePushRuleJob>(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<Quotient::IsPushRuleEnabledJob>(QStringLiteral("global"), kind, ruleId);
connect(job, &Quotient::BaseJob::success, this, [job, kind, ruleId, enabled]() {
auto job = m_connection->callApi<Quotient::IsPushRuleEnabledJob>(QStringLiteral("global"), kind, ruleId);
connect(job, &Quotient::BaseJob::success, this, [job, kind, ruleId, enabled, this]() {
if (job->enabled() != enabled) {
Controller::instance().activeConnection()->callApi<Quotient::SetPushRuleEnabledJob>(QStringLiteral("global"), kind, ruleId, enabled);
m_connection->callApi<Quotient::SetPushRuleEnabledJob>(QStringLiteral("global"), kind, ruleId, enabled);
}
});
}
@@ -376,7 +362,7 @@ void PushRuleModel::setNotificationRuleActions(const QString &kind, const QStrin
actions = actionToVariant(action);
}
Controller::instance().activeConnection()->callApi<Quotient::SetPushRuleActionsJob>(QStringLiteral("global"), kind, ruleId, actions);
m_connection->callApi<Quotient::SetPushRuleActionsJob>(QStringLiteral("global"), kind, ruleId, actions);
}
PushNotificationAction::Action PushRuleModel::variantToAction(const QList<QVariant> &actions, bool enabled)
@@ -453,4 +439,23 @@ QList<QVariant> 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"

View File

@@ -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<Rule> m_rules;
NeoChatConnection *m_connection;
void setRules(QList<Quotient::PushRule> rules, PushNotificationKind::Kind kind);

View File

@@ -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<Quotient::QueryPublicRoomsJob>(url, 1);
m_checkServerJob = m_connection->callApi<Quotient::QueryPublicRoomsJob>(url, 1);
connect(m_checkServerJob, &Quotient::BaseJob::success, this, [this, url] {
Q_EMIT serverCheckComplete(url, true);
});
@@ -153,4 +153,18 @@ QHash<int, QByteArray> 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"

View File

@@ -10,6 +10,8 @@
#include <QQmlEngine>
#include <QUrl>
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<Server> m_servers;
QPointer<Quotient::QueryPublicRoomsJob> m_checkServerJob = nullptr;
NeoChatConnection *m_connection = nullptr;
};

View File

@@ -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<NeoChatConnection *>(m_space->connection()), nullptr, m_space->id(), m_space->displayName(), m_space->canonicalAlias());
endResetModel();
auto job = m_space->connection()->callApi<Quotient::GetSpaceHierarchyJob>(m_space->id(), Quotient::none, Quotient::none, 1);
m_currentJobs.append(job);
@@ -112,7 +113,8 @@ void SpaceChildrenModel::insertChildren(std::vector<Quotient::GetSpaceHierarchyJ
}
}
parentItem->insertChild(insertRow,
new SpaceTreeItem(parentItem,
new SpaceTreeItem(dynamic_cast<NeoChatConnection *>(m_space->connection()),
parentItem,
children[i].roomId,
children[i].name,
children[i].canonicalAlias,

View File

@@ -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

View File

@@ -3,6 +3,8 @@
#include <Quotient/csapi/space_hierarchy.h>
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<SpaceTreeItem *> m_children;
SpaceTreeItem *m_parentItem;

View File

@@ -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<DeletePushRuleJob>("global"_ls, "room"_ls, id());
connection()->callApi<DeletePushRuleJob>("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<DeletePushRuleJob>("global"_ls, "override"_ls, id());
connection()->callApi<DeletePushRuleJob>("global"_ls, "override"_ls, id());
}
}
}
@@ -1385,11 +1385,9 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state)
const QList<PushCondition> conditions = {pushCondition};
// Add new override rule and make sure it's enabled
auto job = Controller::instance()
.activeConnection()
->callApi<SetPushRuleJob>("global"_ls, "override"_ls, id(), actions, QString(), QString(), conditions, QString());
auto job = connection()->callApi<SetPushRuleJob>("global"_ls, "override"_ls, id(), actions, QString(), QString(), conditions, QString());
connect(job, &BaseJob::success, this, [this]() {
auto enableJob = Controller::instance().activeConnection()->callApi<SetPushRuleEnabledJob>("global"_ls, "override"_ls, id(), true);
auto enableJob = connection()->callApi<SetPushRuleEnabledJob>("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<PushCondition> conditions;
auto setJob = Controller::instance()
.activeConnection()
->callApi<SetPushRuleJob>("global"_ls, "room"_ls, id(), actions, QString(), QString(), conditions, QString());
auto setJob = connection()->callApi<SetPushRuleJob>("global"_ls, "room"_ls, id(), actions, QString(), QString(), conditions, QString());
connect(setJob, &BaseJob::success, this, [this]() {
auto enableJob = Controller::instance().activeConnection()->callApi<SetPushRuleEnabledJob>("global"_ls, "room"_ls, id(), true);
auto enableJob = connection()->callApi<SetPushRuleEnabledJob>("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<PushCondition> conditions;
// Add new room rule and make sure enabled
auto setJob = Controller::instance()
.activeConnection()
->callApi<SetPushRuleJob>("global"_ls, "room"_ls, id(), actions, QString(), QString(), conditions, QString());
auto setJob = connection()->callApi<SetPushRuleJob>("global"_ls, "room"_ls, id(), actions, QString(), QString(), conditions, QString());
connect(setJob, &BaseJob::success, this, [this]() {
auto enableJob = Controller::instance().activeConnection()->callApi<SetPushRuleEnabledJob>("global"_ls, "room"_ls, id(), true);
auto enableJob = connection()->callApi<SetPushRuleEnabledJob>("global"_ls, "room"_ls, id(), true);
connect(enableJob, &BaseJob::success, this, [this]() {
m_pushNotificationStateUpdating = false;
});

View File

@@ -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<NeoChatConnection *>(Controller::instance().accounts().get(room->localUser()->id())));
}
Controller::instance().setActiveConnection(dynamic_cast<NeoChatConnection *>(Controller::instance().accounts().get(room->localUser()->id())));
RoomManager::instance().enterRoom(room);
});

View File

@@ -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)
}
}
}

View File

@@ -69,6 +69,7 @@ Kirigami.ScrollablePage {
valueRole: "url"
model: ServerListModel {
id: serverListModel
connection: root.connection
}
delegate: Delegates.RoundedItemDelegate {

View File

@@ -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 = ""
}

View File

@@ -39,6 +39,8 @@ Kirigami.Page {
sortFilterRoomListModel.filterText = "";
}
Component.onCompleted: Runner.roomListModel = root.roomListModel
Connections {
target: RoomManager
function onCurrentRoomChanged() {

View File

@@ -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"

View File

@@ -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

View File

@@ -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<NeoChatRoom *>(Controller::instance().activeConnection()->room(roomId));
const auto room = qobject_cast<NeoChatRoom *>(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"

View File

@@ -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;
};

View File

@@ -33,15 +33,17 @@ Runner::Runner()
qDBusRegisterMetaType<RemoteAction>();
qDBusRegisterMetaType<RemoteActions>();
qDBusRegisterMetaType<RemoteImage>();
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<RoomListModel *>(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<NeoChatRoom *>(Controller::instance().activeConnection()->room(id));
NeoChatRoom *room = qobject_cast<NeoChatRoom *>(roomListModel()->connection()->room(id));
if (!room) {
return;

View File

@@ -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;

View File

@@ -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<NeoChatRoom *>(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<GetSpaceHierarchyJob>(spaceId);
auto job = m_connection->callApi<GetSpaceHierarchyJob>(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"

View File

@@ -10,6 +10,8 @@
#include <QQmlEngine>
#include <QString>
#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<QString, QList<QString>> m_spaceHierarchy;
void cacheSpaceHierarchy();
void populateSpaceHierarchy(const QString &spaceId);
NeoChatConnection *m_connection;
};