From d83471009fd28071ec09fb9aa64152ff492f29f6 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Mon, 15 Aug 2022 21:53:56 -0400 Subject: [PATCH] Reformat code --- .clang-format | 33 ++ .editorconfig | 8 + CMakeLists.txt | 44 +- README.md | 30 +- include/appcore.h | 2 +- include/desktop.h | 9 +- include/directorymodel.h | 4 +- include/emotelistmodel.h | 7 +- include/encryption.h | 2 +- include/eventmodel.h | 11 +- include/matrixcore.h | 32 +- include/membermodel.h | 7 +- include/network.h | 148 +++--- include/requestsender.h | 11 +- include/room.h | 15 +- include/roomlistmodel.h | 7 +- include/roomlistsortmodel.h | 15 +- src/directorymodel.cpp | 5 +- src/emotelistmodel.cpp | 4 +- src/encryption.cpp | 66 +-- src/eventmodel.cpp | 34 +- src/main.cpp | 42 +- src/matrixcore.cpp | 907 ++++++++++++++++++++---------------- src/membermodel.cpp | 20 +- src/roomlistmodel.cpp | 28 +- src/roomlistsortmodel.cpp | 17 +- 26 files changed, 810 insertions(+), 698 deletions(-) create mode 100644 .clang-format create mode 100644 .editorconfig diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..359c7ac --- /dev/null +++ b/.clang-format @@ -0,0 +1,33 @@ +--- +AllowShortIfStatementsOnASingleLine: Never +CompactNamespaces: 'false' +DisableFormat: 'false' +IndentCaseLabels: 'true' +IndentPPDirectives: BeforeHash +IndentWidth: '4' +Language: Cpp +NamespaceIndentation: All +PointerAlignment: Left +ReflowComments: 'true' +SortIncludes: 'true' +SortUsingDeclarations: 'true' +SpacesInCStyleCastParentheses: 'false' +Standard: Cpp11 +TabWidth: '0' +UseTab: Never +AllowShortEnumsOnASingleLine: false +BraceWrapping: + AfterEnum: true +AccessModifierOffset: -4 +SpaceAfterTemplateKeyword: 'false' +AllowAllParametersOfDeclarationOnNextLine: false +AlignAfterOpenBracket: AlwaysBreak +BinPackArguments: false +BinPackParameters: false +ColumnLimit: 120 +AllowShortBlocksOnASingleLine: 'false' +AllowShortCaseLabelsOnASingleLine: 'false' +AllowShortFunctionsOnASingleLine: 'Empty' +AllowShortLambdasOnASingleLine: 'Empty' +AllowShortLoopsOnASingleLine: 'false' +SeparateDefinitionBlocks : 'Always' diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ce0d2bb --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +insert_final_newline = true +indent_style = space +indent_size = 4 +tab_width = 4 +max_line_length = 120 diff --git a/CMakeLists.txt b/CMakeLists.txt index 581308a..aa0955f 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,28 +7,28 @@ set(CMAKE_AUTORCC ON) find_package(Qt5 COMPONENTS Core Quick Widgets WebEngine REQUIRED) add_executable(${PROJECT_NAME} - src/main.cpp - qml.qrc - src/eventmodel.cpp - include/eventmodel.h - src/matrixcore.cpp - include/matrixcore.h - include/network.h - include/requestsender.h - include/room.h - include/roomlistmodel.h - src/roomlistmodel.cpp - include/desktop.h - include/membermodel.h - src/membermodel.cpp - src/roomlistsortmodel.cpp - include/roomlistsortmodel.h - include/emotelistmodel.h - src/emotelistmodel.cpp - include/emote.h - include/appcore.h - include/encryption.h - src/encryption.cpp) + src/main.cpp + qml.qrc + src/eventmodel.cpp + include/eventmodel.h + src/matrixcore.cpp + include/matrixcore.h + include/network.h + include/requestsender.h + include/room.h + include/roomlistmodel.h + src/roomlistmodel.cpp + include/desktop.h + include/membermodel.h + src/membermodel.cpp + src/roomlistsortmodel.cpp + include/roomlistsortmodel.h + include/emotelistmodel.h + src/emotelistmodel.cpp + include/emote.h + include/appcore.h + include/encryption.h + src/encryption.cpp) find_package(Olm REQUIRED) find_package(cmark REQUIRED) diff --git a/README.md b/README.md index 4c333a9..20cd007 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Trinity A Qt5 QML Matrix client, which supports end-to-end encryption (WIP) and has a Discord-like interface. +![Screenshot](misc/screenshot.png) + ## Features * Basic messaging capabilities * Sending and recieving markdown messages, formatting can be disabled @@ -13,28 +15,18 @@ A Qt5 QML Matrix client, which supports end-to-end encryption (WIP) and has a Di * Start direct chats with other members * Custom emote support -## Screenshots -![Screenshot](misc/screenshot.png) +## Installation -*Note: This is an outdated screenshot :-)* +I'm not providing any pre-built binaries yet, so you must compile from source. -## Dependencies +If you use Arch Linux, I maintain the [AUR package](https://aur.archlinux.org/packages/trinity-matrix-git). + +## Building + +Building Trinity is very easy, simply call CMake. Please make sure all the dependencies below are met. + +### Dependencies * Qt5 * WebEngine is also required * CMark * libolm - -## Installation -There's no pre-compiled binaries yet, but compiling from source is easily provided you have Qt5 installed. If you use -Arch Linux, there's a [PKGBUILD available from the AUR](https://aur.archlinux.org/packages/trinity-matrix-git). Simply call it from `makepkg` or through your favorite AUR helper: - -``` -$ aur sync trinity-matrix-git -``` - -Since there's not a tagged release yet, there's only the git version available as a PKGBUILD at the moment. - -## Licensing -Trinity's source code is distributed under the GPLv3 license. See the `LICENSE` file for more details. - -`resources/background.jpg` shown on the login page is from Death to Stock. diff --git a/include/appcore.h b/include/appcore.h index 20e2410..6be9117 100755 --- a/include/appcore.h +++ b/include/appcore.h @@ -1,8 +1,8 @@ #pragma once #include -#include #include +#include class MatrixCore; diff --git a/include/desktop.h b/include/desktop.h index fcc3bf1..93fbe08 100755 --- a/include/desktop.h +++ b/include/desktop.h @@ -1,16 +1,15 @@ #pragma once -#include #include +#include -class Desktop : public QObject -{ +class Desktop : public QObject { Q_OBJECT public: Q_INVOKABLE void showTrayIcon(const bool shouldHide) { QApplication::setQuitOnLastWindowClosed(shouldHide); - if(shouldHide) + if (shouldHide) icon->show(); else icon->hide(); @@ -21,7 +20,7 @@ public: } Q_INVOKABLE bool isTrayIconEnabled() { - return icon->isVisible();; + return icon->isVisible(); } QSystemTrayIcon* icon; diff --git a/include/directorymodel.h b/include/directorymodel.h index c49fb1a..2ec73ac 100644 --- a/include/directorymodel.h +++ b/include/directorymodel.h @@ -1,9 +1,7 @@ #ifndef DIRECTORYMODEL_H #define DIRECTORYMODEL_H - -class DirectoryModel -{ +class DirectoryModel { public: DirectoryModel(); }; diff --git a/include/emotelistmodel.h b/include/emotelistmodel.h index 189b0e1..ddc107c 100644 --- a/include/emotelistmodel.h +++ b/include/emotelistmodel.h @@ -5,13 +5,12 @@ #include "emote.h" -class EmoteListModel : public QAbstractListModel -{ +class EmoteListModel : public QAbstractListModel { Q_OBJECT public: - int rowCount(const QModelIndex &parent) const override; + int rowCount(const QModelIndex& parent) const override; - QVariant data(const QModelIndex &index, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; void setList(QList* emotes) { this->emotes = emotes; diff --git a/include/encryption.h b/include/encryption.h index a31b1ca..02e22c6 100755 --- a/include/encryption.h +++ b/include/encryption.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include diff --git a/include/eventmodel.h b/include/eventmodel.h index 2c52160..fff8d84 100644 --- a/include/eventmodel.h +++ b/include/eventmodel.h @@ -6,8 +6,7 @@ class MatrixCore; struct Room; class Event; -class EventModel : public QAbstractListModel -{ +class EventModel : public QAbstractListModel { Q_OBJECT public: enum EventRoles { @@ -17,21 +16,21 @@ public: EventModel(MatrixCore& matrix); - int rowCount(const QModelIndex &parent) const override; + int rowCount(const QModelIndex& parent) const override; - QVariant data(const QModelIndex &index, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; void beginUpdate(const unsigned int num); void endUpdate() { - if(room) + if (room) endInsertRows(); } void beginHistory(int size); void endHistory() { - if(room) + if (room) endInsertRows(); } diff --git a/include/matrixcore.h b/include/matrixcore.h index 3d76e3e..1212958 100755 --- a/include/matrixcore.h +++ b/include/matrixcore.h @@ -1,23 +1,22 @@ #pragma once -#include +#include #include #include -#include +#include -#include "eventmodel.h" -#include "room.h" -#include "roomlistmodel.h" -#include "membermodel.h" -#include "roomlistsortmodel.h" #include "emote.h" #include "emotelistmodel.h" #include "encryption.h" +#include "eventmodel.h" +#include "membermodel.h" +#include "room.h" +#include "roomlistmodel.h" +#include "roomlistsortmodel.h" class Network; -class MatrixCore : public QObject -{ +class MatrixCore : public QObject { Q_OBJECT Q_PROPERTY(QString profileName MEMBER profileName CONSTANT) Q_PROPERTY(bool initialSyncComplete READ isInitialSyncComplete NOTIFY initialSyncFinished) @@ -39,7 +38,11 @@ public: Encryption* encryption = nullptr; // account - Q_INVOKABLE void registerAccount(const QString& username, const QString& password, const QString& session = "", const QString& type = ""); + Q_INVOKABLE void registerAccount( + const QString& username, + const QString& password, + const QString& session = "", + const QString& type = ""); Q_INVOKABLE void login(const QString& username, const QString& password); Q_INVOKABLE void logout(); @@ -94,7 +97,14 @@ public: void setMarkdownEnabled(const bool enabled); - void sendKeyToDevice(QString roomId, QString senderCurveIdentity, QString senderEdIdentity, QString session_id, QString session_key, QString user_id, QString device_id); + void sendKeyToDevice( + QString roomId, + QString senderCurveIdentity, + QString senderEdIdentity, + QString session_id, + QString session_key, + QString user_id, + QString device_id); OlmOutboundGroupSession* currentSession = nullptr; QString currentSessionId, currentSessionKey; diff --git a/include/membermodel.h b/include/membermodel.h index b0ecb34..e17fab7 100755 --- a/include/membermodel.h +++ b/include/membermodel.h @@ -4,8 +4,7 @@ class Room; -class MemberModel : public QAbstractListModel -{ +class MemberModel : public QAbstractListModel { Q_OBJECT public: enum EventRoles { @@ -15,9 +14,9 @@ public: SectionRole }; - int rowCount(const QModelIndex &parent) const override; + int rowCount(const QModelIndex& parent) const override; - QVariant data(const QModelIndex &index, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; void beginUpdate(const unsigned int num) { beginInsertRows(QModelIndex(), 0, num); diff --git a/include/network.h b/include/network.h index 77dd4d9..920cac0 100755 --- a/include/network.h +++ b/include/network.h @@ -1,9 +1,9 @@ #pragma once +#include +#include #include #include -#include -#include #include #include "requestsender.h" @@ -17,112 +17,110 @@ public: QNetworkAccessManager* manager; QString homeserverURL, accessToken; - template - inline void postJSON(const QString& path, const QJsonObject object, Fn&& fn) { - QNetworkRequest request(homeserverURL + path); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request.setRawHeader("Authorization", accessToken.toLocal8Bit()); + template inline void postJSON(const QString& path, const QJsonObject object, Fn&& fn) { + QNetworkRequest request(homeserverURL + path); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + request.setRawHeader("Authorization", accessToken.toLocal8Bit()); - const QByteArray jsonPost = QJsonDocument(object).toJson(); + const QByteArray jsonPost = QJsonDocument(object).toJson(); - request.setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(jsonPost.size())); + request.setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(jsonPost.size())); - RequestSender* sender = new RequestSender(manager); - sender->fn = fn; + RequestSender* sender = new RequestSender(manager); + sender->fn = fn; - request.setOriginatingObject(sender); + request.setOriginatingObject(sender); - QObject::connect(manager, &QNetworkAccessManager::finished, sender, &RequestSender::finished); + QObject::connect(manager, &QNetworkAccessManager::finished, sender, &RequestSender::finished); - manager->post(request, jsonPost); - } + manager->post(request, jsonPost); + } - template - inline void postBinary(const QString& path, const QByteArray data, const QString mimeType, Fn&& fn, ProgressFn&& progressFn) { - QNetworkRequest request(homeserverURL + path); - request.setHeader(QNetworkRequest::ContentTypeHeader, mimeType); - request.setRawHeader("Authorization", accessToken.toLocal8Bit()); + template + inline void + postBinary(const QString& path, const QByteArray data, const QString mimeType, Fn&& fn, ProgressFn&& progressFn) { + QNetworkRequest request(homeserverURL + path); + request.setHeader(QNetworkRequest::ContentTypeHeader, mimeType); + request.setRawHeader("Authorization", accessToken.toLocal8Bit()); - request.setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(data.size())); + request.setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(data.size())); - RequestSender* sender = new RequestSender(manager); - sender->fn = fn; + RequestSender* sender = new RequestSender(manager); + sender->fn = fn; - request.setOriginatingObject(sender); + request.setOriginatingObject(sender); - QObject::connect(manager, &QNetworkAccessManager::finished, sender, &RequestSender::finished); + QObject::connect(manager, &QNetworkAccessManager::finished, sender, &RequestSender::finished); - QNetworkReply* reply = manager->post(request, data); - QObject::connect(reply, &QNetworkReply::uploadProgress, progressFn); - } + QNetworkReply* reply = manager->post(request, data); + QObject::connect(reply, &QNetworkReply::uploadProgress, progressFn); + } - template - inline void post(const QString& path, Fn&& fn) { - QNetworkRequest request(homeserverURL + path); - request.setRawHeader("Authorization", accessToken.toLocal8Bit()); + template inline void post(const QString& path, Fn&& fn) { + QNetworkRequest request(homeserverURL + path); + request.setRawHeader("Authorization", accessToken.toLocal8Bit()); - RequestSender* sender = new RequestSender(manager); - sender->fn = fn; + RequestSender* sender = new RequestSender(manager); + sender->fn = fn; - request.setOriginatingObject(sender); + request.setOriginatingObject(sender); - QObject::connect(manager, &QNetworkAccessManager::finished, sender, &RequestSender::finished); + QObject::connect(manager, &QNetworkAccessManager::finished, sender, &RequestSender::finished); - manager->post(request, QByteArray()); - } + manager->post(request, QByteArray()); + } - inline void post(const QString& path) { - QNetworkRequest request(homeserverURL + path); - request.setRawHeader("Authorization", accessToken.toLocal8Bit()); + inline void post(const QString& path) { + QNetworkRequest request(homeserverURL + path); + request.setRawHeader("Authorization", accessToken.toLocal8Bit()); - manager->post(request, QByteArray()); - } + manager->post(request, QByteArray()); + } - inline void putJSON(const QString& path, const QJsonObject object) { - QNetworkRequest request(homeserverURL + path); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request.setRawHeader("Authorization", accessToken.toLocal8Bit()); + inline void putJSON(const QString& path, const QJsonObject object) { + QNetworkRequest request(homeserverURL + path); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + request.setRawHeader("Authorization", accessToken.toLocal8Bit()); - const QByteArray jsonPost = QJsonDocument(object).toJson(); + const QByteArray jsonPost = QJsonDocument(object).toJson(); - request.setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(jsonPost.size())); + request.setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(jsonPost.size())); - manager->put(request, jsonPost); - } + manager->put(request, jsonPost); + } - template - inline void putJSON(const QString& path, const QJsonObject object, Fn&& fn) { - QNetworkRequest request(homeserverURL + path); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request.setRawHeader("Authorization", accessToken.toLocal8Bit()); + template inline void putJSON(const QString& path, const QJsonObject object, Fn&& fn) { + QNetworkRequest request(homeserverURL + path); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + request.setRawHeader("Authorization", accessToken.toLocal8Bit()); - RequestSender* sender = new RequestSender(manager); - sender->fn = fn; + RequestSender* sender = new RequestSender(manager); + sender->fn = fn; - request.setOriginatingObject(sender); + request.setOriginatingObject(sender); - const QByteArray jsonPost = QJsonDocument(object).toJson(); + const QByteArray jsonPost = QJsonDocument(object).toJson(); - request.setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(jsonPost.size())); + request.setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(jsonPost.size())); - QObject::connect(manager, &QNetworkAccessManager::finished, sender, &RequestSender::finished); + QObject::connect(manager, &QNetworkAccessManager::finished, sender, &RequestSender::finished); - manager->put(request, jsonPost); - } + manager->put(request, jsonPost); + } - template - inline void get(const QString& path, Fn&& fn, const QString contentType = "application/json") { - QNetworkRequest request(homeserverURL + path); - request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); - request.setRawHeader("Authorization", accessToken.toLocal8Bit()); + template + inline void get(const QString& path, Fn&& fn, const QString contentType = "application/json") { + QNetworkRequest request(homeserverURL + path); + request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); + request.setRawHeader("Authorization", accessToken.toLocal8Bit()); - RequestSender* sender = new RequestSender(manager); - sender->fn = fn; + RequestSender* sender = new RequestSender(manager); + sender->fn = fn; - request.setOriginatingObject(sender); + request.setOriginatingObject(sender); - QObject::connect(manager, &QNetworkAccessManager::finished, sender, &RequestSender::finished); + QObject::connect(manager, &QNetworkAccessManager::finished, sender, &RequestSender::finished); - manager->get(request); - } + manager->get(request); + } }; diff --git a/include/requestsender.h b/include/requestsender.h index ea04baa..441e67b 100755 --- a/include/requestsender.h +++ b/include/requestsender.h @@ -1,12 +1,11 @@ #pragma once -#include -#include #include #include +#include +#include -class RequestSender : public QObject -{ +class RequestSender : public QObject { Q_OBJECT public: RequestSender(QObject* parent = nullptr) : QObject(parent) {} @@ -22,8 +21,8 @@ public: std::function fn; void finished(QNetworkReply* reply) { - if(reply->request().originatingObject() == this) { - //qDebug() << reply->errorString(); + if (reply->request().originatingObject() == this) { + // qDebug() << reply->errorString(); fn(reply); diff --git a/include/room.h b/include/room.h index 7e6ea3e..a727953 100755 --- a/include/room.h +++ b/include/room.h @@ -1,9 +1,9 @@ #pragma once -#include -#include #include +#include #include +#include class EncryptionInformation : public QObject { Q_OBJECT @@ -12,8 +12,7 @@ public: QString sessionId; }; -class Event : public QObject -{ +class Event : public QObject { Q_OBJECT Q_PROPERTY(QString sender READ getSender NOTIFY senderChanged) Q_PROPERTY(QString msg READ getMsg NOTIFY msgChanged) @@ -175,8 +174,7 @@ private: QString id, displayName, avatarURL; }; -class Room : public QObject -{ +class Room : public QObject { Q_OBJECT Q_PROPERTY(QString id MEMBER id NOTIFY idChanged) Q_PROPERTY(QString topic MEMBER topic NOTIFY topicChanged) @@ -188,7 +186,8 @@ class Room : public QObject Q_PROPERTY(QString highlightCount READ getHighlightCount NOTIFY highlightCountChanged) Q_PROPERTY(QString notificationCount READ getNotificationCount NOTIFY notificationCountChanged) Q_PROPERTY(bool direct READ getDirect NOTIFY directChanged) - Q_PROPERTY(int notificationLevel READ getNotificationLevel WRITE setNotificationLevel NOTIFY notificationLevelChanged) + Q_PROPERTY( + int notificationLevel READ getNotificationLevel WRITE setNotificationLevel NOTIFY notificationLevelChanged) Q_PROPERTY(bool encrypted READ getEncrypted NOTIFY encryptionChanged) public: Room(QObject* parent = nullptr) : QObject(parent) {} @@ -255,7 +254,7 @@ public: void setNotificationLevel(const int level, const bool skipSave = false) { notificationLevel = level; - if(!skipSave) { + if (!skipSave) { QSettings settings; settings.beginGroup(id); settings.setValue("notificationLevel", notificationLevel); diff --git a/include/roomlistmodel.h b/include/roomlistmodel.h index 304ffc7..3a4c97b 100644 --- a/include/roomlistmodel.h +++ b/include/roomlistmodel.h @@ -4,8 +4,7 @@ class Room; -class RoomListModel : public QAbstractListModel -{ +class RoomListModel : public QAbstractListModel { Q_OBJECT public: enum EventRoles { @@ -22,9 +21,9 @@ public: RoomListModel(QList& rooms); - int rowCount(const QModelIndex &parent) const override; + int rowCount(const QModelIndex& parent) const override; - QVariant data(const QModelIndex &index, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; void beginInsertRoom() { beginInsertRows(QModelIndex(), rooms.size(), rooms.size()); diff --git a/include/roomlistsortmodel.h b/include/roomlistsortmodel.h index 773de93..f9623e8 100755 --- a/include/roomlistsortmodel.h +++ b/include/roomlistsortmodel.h @@ -2,37 +2,34 @@ #include -class RoomListSortModel : public QSortFilterProxyModel -{ +class RoomListSortModel : public QSortFilterProxyModel { Q_OBJECT public: - bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; + bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const; Q_INVOKABLE unsigned int getOriginalIndex(const unsigned int i) const { auto const proxyIndex = index(i, 0); auto const sourceIndex = mapToSource(proxyIndex); - if(!sourceIndex.isValid()) + if (!sourceIndex.isValid()) return 0; else return sourceIndex.row(); } }; -class MemberListSortModel : public QSortFilterProxyModel -{ +class MemberListSortModel : public QSortFilterProxyModel { Q_OBJECT public: - bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; + bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const; Q_INVOKABLE unsigned int getOriginalIndex(const unsigned int i) const { auto const proxyIndex = index(i, 0); auto const sourceIndex = mapToSource(proxyIndex); - if(!sourceIndex.isValid()) + if (!sourceIndex.isValid()) return 0; else return sourceIndex.row(); } }; - diff --git a/src/directorymodel.cpp b/src/directorymodel.cpp index a747c79..0422156 100644 --- a/src/directorymodel.cpp +++ b/src/directorymodel.cpp @@ -1,6 +1,3 @@ #include "directorymodel.h" -DirectoryModel::DirectoryModel() -{ - -} +DirectoryModel::DirectoryModel() {} diff --git a/src/emotelistmodel.cpp b/src/emotelistmodel.cpp index e5f9f4f..e21423f 100644 --- a/src/emotelistmodel.cpp +++ b/src/emotelistmodel.cpp @@ -1,10 +1,10 @@ #include "emotelistmodel.h" -int EmoteListModel::rowCount(const QModelIndex &parent) const { +int EmoteListModel::rowCount(const QModelIndex& parent) const { return emotes->size(); } -QVariant EmoteListModel::data(const QModelIndex &index, int role) const { +QVariant EmoteListModel::data(const QModelIndex& index, int role) const { if (role == Qt::DisplayRole) return QVariant::fromValue(emotes->at(index.row())); diff --git a/src/encryption.cpp b/src/encryption.cpp index f210acb..58aa072 100755 --- a/src/encryption.cpp +++ b/src/encryption.cpp @@ -1,10 +1,10 @@ #include "encryption.h" -#include #include -#include -#include #include #include +#include +#include +#include void Encryption::createNewDeviceKeys() { initAccount(); @@ -35,7 +35,6 @@ void Encryption::createNewDeviceKeys() { qDebug() << "identity keys: " << (char*)identity_memory; qDebug() << "identity keys (parsed): " << identityKey; - } QString Encryption::saveDeviceKeys() { @@ -108,11 +107,7 @@ QString Encryption::signMessage(QString message) { void* memory = malloc(length); - olm_account_sign( - account, - message.data(), message.length(), - memory, length - ); + olm_account_sign(account, message.data(), message.length(), memory, length); qDebug() << "Signed: " << (char*)memory; @@ -169,8 +164,16 @@ OlmSession* Encryption::beginOutboundOlmSession(std::string identityKey, std::st int fd = open("/dev/random", O_RDONLY); read(fd, memory, length); - olm_create_outbound_session(outboundSession, account, identityKey.data(), identityKey.length(), oneTimeKey.data(), oneTimeKey.length(), (uint8_t*)memory, length); - //qDebug() << "ERR: " << olm_session_last_error(outboundSession); + olm_create_outbound_session( + outboundSession, + account, + identityKey.data(), + identityKey.length(), + oneTimeKey.data(), + oneTimeKey.length(), + (uint8_t*)memory, + length); + // qDebug() << "ERR: " << olm_session_last_error(outboundSession); return outboundSession; @@ -181,7 +184,6 @@ OlmSession* Encryption::beginOutboundOlmSession(std::string identityKey, std::st void const * their_one_time_key, size_t their_one_time_key_length, void * random, size_t random_length );*/ - } std::string Encryption::getSessionId(OlmSession* session) { @@ -192,10 +194,7 @@ std::string Encryption::getSessionId(OlmSession* session) { /** An identifier for this session. Will be the same for both ends of the * conversation. If the id buffer is too small then olm_session_last_error() * will be "OUTPUT_BUFFER_TOO_SMALL". */ - olm_session_id( - session, - memory, length - ); + olm_session_id(session, memory, length); return memory; } @@ -229,23 +228,24 @@ OlmSession* Encryption::createInboundSession(std::string senderKey, std::string void* inboundMemory = malloc(olm_session_size()); auto inboundSession = olm_session(inboundMemory); - olm_create_inbound_session_from(inboundSession, account, (void*)senderKey.c_str(), senderKey.length(), (void*)body.c_str(), body.length()); + olm_create_inbound_session_from( + inboundSession, account, (void*)senderKey.c_str(), senderKey.length(), (void*)body.c_str(), body.length()); return inboundSession; } -std::vector Encryption::decrypt(OlmSession* session, int msgType, std::string cipherText) { +std::vector Encryption::decrypt(OlmSession* session, int msgType, std::string cipherText) { /*std::string maxPlaintextLengthBuffer = cipherText; - size_t maxPlaintextLength = olm_decrypt_max_plaintext_length(session, msgType, (void*)maxPlaintextLengthBuffer.data(), maxPlaintextLengthBuffer.length());; - qDebug() << "THE ERROR YOU ARE LOOKING FOR " << olm_session_last_error(session); - if(maxPlaintextLength == olm_error()) - return ""; + size_t maxPlaintextLength = olm_decrypt_max_plaintext_length(session, msgType, + (void*)maxPlaintextLengthBuffer.data(), maxPlaintextLengthBuffer.length());; qDebug() << "THE ERROR YOU ARE LOOKING + FOR " << olm_session_last_error(session); if(maxPlaintextLength == olm_error()) return ""; char* plaintext = new char[maxPlaintextLength]; //plaintext[maxPlaintextLength] = '\0'; memset(plaintext, '\0', maxPlaintextLength); - int size = olm_decrypt(session, msgType, (void*)cipherText.data(), cipherText.length(), (void*)plaintext, maxPlaintextLength); + int size = olm_decrypt(session, msgType, (void*)cipherText.data(), cipherText.length(), (void*)plaintext, + maxPlaintextLength); //plaintext[size] = '\0'; plaintext[size + 1] = '\0'; @@ -257,8 +257,9 @@ std::vector Encryption::decrypt(OlmSession* session, int msgType, std::copy(cipherText.begin(), cipherText.end(), tmp_plaintext_buffer.begin()); // create the result buffer - size_t length = olm_decrypt_max_plaintext_length(session, msgType, tmp_plaintext_buffer.data(), tmp_plaintext_buffer.size()); - if(length == olm_error()) + size_t length = + olm_decrypt_max_plaintext_length(session, msgType, tmp_plaintext_buffer.data(), tmp_plaintext_buffer.size()); + if (length == olm_error()) return {}; auto result_buffer = std::vector(length); @@ -267,8 +268,9 @@ std::vector Encryption::decrypt(OlmSession* session, int msgType, auto tmp_buffer = std::vector(cipherText.size()); std::copy(cipherText.begin(), cipherText.end(), tmp_buffer.begin()); - auto size = olm_decrypt(session, msgType, tmp_buffer.data(), tmp_buffer.size(), result_buffer.data(), result_buffer.size()); - if(size == olm_error()) + auto size = + olm_decrypt(session, msgType, tmp_buffer.data(), tmp_buffer.size(), result_buffer.data(), result_buffer.size()); + if (size == olm_error()) return {}; auto output = std::vector(size); @@ -315,8 +317,9 @@ std::vector Encryption::decrypt(OlmInboundGroupSession* session, s std::copy(cipherText.begin(), cipherText.end(), tmp_plaintext_buffer.begin()); // create the result buffer - size_t length = olm_group_decrypt_max_plaintext_length(session, tmp_plaintext_buffer.data(), tmp_plaintext_buffer.size()); - if(length == olm_error()) + size_t length = + olm_group_decrypt_max_plaintext_length(session, tmp_plaintext_buffer.data(), tmp_plaintext_buffer.size()); + if (length == olm_error()) return {}; auto result_buffer = std::vector(length); @@ -326,8 +329,9 @@ std::vector Encryption::decrypt(OlmInboundGroupSession* session, s std::copy(cipherText.begin(), cipherText.end(), tmp_buffer.begin()); uint32_t msgIndex; - auto size = olm_group_decrypt(session, tmp_buffer.data(), tmp_buffer.size(), result_buffer.data(), result_buffer.size(), &msgIndex); - if(size == olm_error()) + auto size = olm_group_decrypt( + session, tmp_buffer.data(), tmp_buffer.size(), result_buffer.data(), result_buffer.size(), &msgIndex); + if (size == olm_error()) return {}; auto output = std::vector(size); diff --git a/src/eventmodel.cpp b/src/eventmodel.cpp index 9c3b926..7bc5a8d 100644 --- a/src/eventmodel.cpp +++ b/src/eventmodel.cpp @@ -2,33 +2,33 @@ #include -#include "room.h" #include "matrixcore.h" +#include "room.h" EventModel::EventModel(MatrixCore& matrix) : matrix(matrix) {} -int EventModel::rowCount(const QModelIndex &parent) const { - if(!room) +int EventModel::rowCount(const QModelIndex& parent) const { + if (!room) return 0; return room->events.size(); } -QVariant EventModel::data(const QModelIndex &index, int role) const { - if(!room || index.row() >= room->events.size()) +QVariant EventModel::data(const QModelIndex& index, int role) const { + if (!room || index.row() >= room->events.size()) return ""; Event* event = room->events[index.row()]; - if(role == Qt::DisplayRole) { + if (role == Qt::DisplayRole) { return QVariant::fromValue(event); - } else if(role == CondenseRole) { - if(index.row() + 1 >= room->events.size()) + } else if (role == CondenseRole) { + if (index.row() + 1 >= room->events.size()) return false; const Event* previousEvent = room->events[index.row() + 1]; return previousEvent->getSender() == event->getSender(); - } else if(role == TimestampRole) + } else if (role == TimestampRole) return event->timestamp.toString(Qt::DefaultLocaleShortDate); return ""; @@ -48,21 +48,21 @@ void EventModel::setRoom(Room* room) { } void EventModel::beginUpdate(const unsigned int num) { - if(room) + if (room) beginInsertRows(QModelIndex(), 0, num); } void EventModel::beginHistory(int size) { - if(room) + if (room) beginInsertRows(QModelIndex(), room->events.size(), room->events.size() + size); } void EventModel::updateEvent(const Event* event) { - if(!room) + if (!room) return; - for(size_t i = 0; i < room->events.size(); i++) { - if(room->events[i] == event) { + for (size_t i = 0; i < room->events.size(); i++) { + if (room->events[i] == event) { emit dataChanged(createIndex(i, 0), createIndex(i, 0)); return; } @@ -70,11 +70,11 @@ void EventModel::updateEvent(const Event* event) { } void EventModel::updateEventsByMember(const QString& id) { - if(!room) + if (!room) return; - for(size_t i = 0; i < room->events.size(); i++) { - if(room->events[i]->getSender() == id) + for (size_t i = 0; i < room->events.size(); i++) { + if (room->events[i]->getSender() == id) emit dataChanged(createIndex(i, 0), createIndex(i, 0)); } } diff --git a/src/main.cpp b/src/main.cpp index 1c5ed6d..079c52d 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,26 +1,26 @@ -#include -#include -#include -#include -#include #include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include "eventmodel.h" -#include "membermodel.h" -#include "matrixcore.h" -#include "network.h" -#include "desktop.h" -#include "roomlistsortmodel.h" -#include "emote.h" #include "appcore.h" +#include "desktop.h" +#include "emote.h" +#include "eventmodel.h" +#include "matrixcore.h" +#include "membermodel.h" +#include "network.h" +#include "roomlistsortmodel.h" -void AppCore::addAccount(QString profileName) { +void AppCore::addAccount(QString profileName) { accounts.push_back(new MatrixCore(profileName)); context->setContextProperty("matrix", accounts.back()); @@ -28,11 +28,11 @@ void AppCore::addAccount(QString profileName) { emit accountChange(); } -void AppCore::switchAccount(QString profileName) { +void AppCore::switchAccount(QString profileName) { qDebug() << "switching to " << profileName; - for(auto account : accounts) { - if(account->profileName == profileName) { + for (auto account : accounts) { + if (account->profileName == profileName) { qDebug() << account->profileName << " = " << profileName; context->setContextProperty("matrix", account); } @@ -43,7 +43,7 @@ void AppCore::switchAccount(QString profileName) { QVariantList AppCore::getAccounts() { QVariantList list; - for(auto account : accounts) + for (auto account : accounts) list.push_back(QVariant::fromValue(account)); return list; @@ -86,7 +86,7 @@ int main(int argc, char* argv[]) { AppCore* core = new AppCore(); core->context = context; - if(parser.isSet(profileOption)) { + if (parser.isSet(profileOption)) { core->addAccount(parser.value(profileOption)); } else { core->addAccount(); diff --git a/src/matrixcore.cpp b/src/matrixcore.cpp index f09e362..225816f 100755 --- a/src/matrixcore.cpp +++ b/src/matrixcore.cpp @@ -2,19 +2,21 @@ #include +#include "network.h" +#include #include +#include +#include +#include #include #include -#include #include -#include -#include -#include #include #include -#include "network.h" -MatrixCore::MatrixCore(QString profileName, QObject* parent) : QObject(parent), profileName(profileName), roomListModel(rooms), directoryListModel(publicRooms), eventModel(*this) { +MatrixCore::MatrixCore(QString profileName, QObject* parent) + : QObject(parent), profileName(profileName), roomListModel(rooms), directoryListModel(publicRooms), + eventModel(*this) { network = new Network(); encryption = new Encryption(); @@ -25,10 +27,10 @@ MatrixCore::MatrixCore(QString profileName, QObject* parent) : QObject(parent), network->homeserverURL = "https://" + homeserverURL; deviceId = settings.value("deviceId").toString(); - if(settings.contains("accessToken")) + if (settings.contains("accessToken")) network->accessToken = "Bearer " + settings.value("accessToken").toString(); - if(settings.contains("accountPickle")) { + if (settings.contains("accountPickle")) { encryption->loadDeviceKeys(settings.value("accountPickle").toString()); qDebug() << "testing identity key: " << encryption->identityKey; } @@ -57,17 +59,17 @@ MatrixCore::MatrixCore(QString profileName, QObject* parent) : QObject(parent), updateAccountInformation(); QString appDir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); - if(!QDir(appDir).exists()) + if (!QDir(appDir).exists()) QDir().mkdir(appDir); QString emotesDir = appDir + "/emotes"; - if(!QDir(emotesDir).exists()) + if (!QDir(emotesDir).exists()) QDir().mkdir(emotesDir); - if(QDir(emotesDir).exists()) { - for(auto emote : QDir(emotesDir).entryInfoList()) { + if (QDir(emotesDir).exists()) { + for (auto emote : QDir(emotesDir).entryInfoList()) { // TODO: add support for more than just .png emotes - if(emote.fileName().contains(".png")) { + if (emote.fileName().contains(".png")) { Emote* e = new Emote(); e->name = emote.fileName().remove(".png"); e->path = emote.absoluteFilePath(); @@ -80,39 +82,41 @@ MatrixCore::MatrixCore(QString profileName, QObject* parent) : QObject(parent), localEmoteModel.setList(&emotes); } -void MatrixCore::registerAccount(const QString &username, const QString &password, const QString& session, const QString& type) { +void MatrixCore::registerAccount( + const QString& username, + const QString& password, + const QString& session, + const QString& type) { QJsonObject authObject; - if(!session.isEmpty()) { - authObject["type"] = type; + if (!session.isEmpty()) { + authObject["type"] = type; authObject["session"] = session; } - const QJsonObject registerObject { - {"auth", authObject}, - {"username", username}, - {"password", password} - }; + const QJsonObject registerObject{{"auth", authObject}, {"username", username}, {"password", password}}; network->postJSON("/_matrix/client/r0/register?kind=user", registerObject, [this](QNetworkReply* reply) { const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - if(reply->error()) { - if(document.object().contains("flows")) { - const QString stage = document.object()["flows"].toArray()[0].toObject()["stages"].toArray()[0].toString(); + if (reply->error()) { + if (document.object().contains("flows")) { + const QString stage = + document.object()["flows"].toArray()[0].toObject()["stages"].toArray()[0].toString(); - if(stage == "m.login.recaptcha") { - const QJsonObject data { - {"public_key", document.object()["params"].toObject()["m.login.recaptcha"].toObject()["public_key"].toString()}, + if (stage == "m.login.recaptcha") { + const QJsonObject data{ + {"public_key", + document.object()["params"] + .toObject()["m.login.recaptcha"] + .toObject()["public_key"] + .toString()}, {"session", document.object()["session"].toString()}, - {"type", "m.login.recaptcha"} - }; + {"type", "m.login.recaptcha"}}; emit registerFlow(data); - } else if(stage == "m.login.dummy") { - const QJsonObject data { - {"session", document.object()["session"].toString()}, - {"type", "m.login.dummy"} - }; + } else if (stage == "m.login.dummy") { + const QJsonObject data{ + {"session", document.object()["session"].toString()}, {"type", "m.login.dummy"}}; emit registerFlow(data); } else { @@ -137,17 +141,16 @@ void MatrixCore::registerAccount(const QString &username, const QString &passwor } void MatrixCore::login(const QString& username, const QString& password) { - const QJsonObject loginObject { - {"type", "m.login.password"}, - {"user", username}, - {"password", password}, - {"initial_device_display_name", "Trinity"} - }; + const QJsonObject loginObject{ + {"type", "m.login.password"}, + {"user", username}, + {"password", password}, + {"initial_device_display_name", "Trinity"}}; network->postJSON("/_matrix/client/r0/login", loginObject, [this](QNetworkReply* reply) { const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - if(reply->error()) { + if (reply->error()) { emit loginAttempt(true, document.object()["error"].toString()); } else { network->accessToken = "Bearer " + document.object()["access_token"].toString(); @@ -161,48 +164,41 @@ void MatrixCore::login(const QString& username, const QString& password) { // upload keys encryption->createNewDeviceKeys(); - QJsonObject keysObject { + QJsonObject keysObject{ {"curve25519:" + document.object()["device_id"].toString(), encryption->identityKey["curve25519"]}, - {"ed25519:" + document.object()["device_id"].toString(), encryption->identityKey["ed25519"]} - }; + {"ed25519:" + document.object()["device_id"].toString(), encryption->identityKey["ed25519"]}}; - QJsonObject deviceKeysObject { + QJsonObject deviceKeysObject{ {"user_id", document.object()["user_id"].toString()}, {"device_id", document.object()["device_id"].toString()}, {"algorithms", QJsonArray({"m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"})}, - {"keys", keysObject} - }; + {"keys", keysObject}}; - QJsonObject signature { - {"ed25519:" + document.object()["device_id"].toString(), encryption->signMessage(QJsonDocument(deviceKeysObject).toJson(QJsonDocument::Compact)) }}; + QJsonObject signature{ + {"ed25519:" + document.object()["device_id"].toString(), + encryption->signMessage(QJsonDocument(deviceKeysObject).toJson(QJsonDocument::Compact))}}; - deviceKeysObject["signatures"] = QJsonObject { - {document.object()["user_id"].toString(), signature}}; + deviceKeysObject["signatures"] = QJsonObject{{document.object()["user_id"].toString(), signature}}; QJsonObject oneTimeKeyObject; auto one_time_keys = encryption->generateOneTimeKeys(encryption->getRecommendedNumberOfOneTimeKeys()); - for(auto key : one_time_keys["curve25519"].toObject().keys()) { - QJsonObject keyObject { - {"key", one_time_keys["curve25519"].toObject()[key]} - }; + for (auto key : one_time_keys["curve25519"].toObject().keys()) { + QJsonObject keyObject{{"key", one_time_keys["curve25519"].toObject()[key]}}; - QJsonObject signature { - {"ed25519:" + document.object()["device_id"].toString(), encryption->signMessage(QJsonDocument(keyObject).toJson(QJsonDocument::Compact)) }}; + QJsonObject signature{ + {"ed25519:" + document.object()["device_id"].toString(), + encryption->signMessage(QJsonDocument(keyObject).toJson(QJsonDocument::Compact))}}; - keyObject["signatures"] = QJsonObject { - {document.object()["user_id"].toString(), signature}}; + keyObject["signatures"] = QJsonObject{{document.object()["user_id"].toString(), signature}}; oneTimeKeyObject["signed_curve25519:" + key] = keyObject; } - QJsonObject masterKeysObject { - {"device_keys", deviceKeysObject}, - {"one_time_keys", oneTimeKeyObject} - }; + QJsonObject masterKeysObject{{"device_keys", deviceKeysObject}, {"one_time_keys", oneTimeKeyObject}}; - //qDebug() << masterKeysObject; + // qDebug() << masterKeysObject; auto keys = encryption->saveDeviceKeys(); @@ -241,90 +237,119 @@ void MatrixCore::updateAccountInformation() { void MatrixCore::setDisplayName(const QString& name) { displayName = name; - const QJsonObject displayNameObject { - {"displayname", name} - }; + const QJsonObject displayNameObject{{"displayname", name}}; - network->putJSON("/_matrix/client/r0/profile/" + userId + "/displayname", displayNameObject, [this, name](QNetworkReply* reply) { - emit displayNameChanged(); - }); + network->putJSON( + "/_matrix/client/r0/profile/" + userId + "/displayname", displayNameObject, [this, name](QNetworkReply* reply) { + emit displayNameChanged(); + }); } void MatrixCore::sync() { - if(network->accessToken.isEmpty()) + if (network->accessToken.isEmpty()) return; QString url = "/_matrix/client/r0/sync"; - if(!nextBatch.isEmpty()) + if (!nextBatch.isEmpty()) url += "?since=" + nextBatch; network->get(url, [this](QNetworkReply* reply) { const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - if(!document.object()["next_batch"].isNull()) - nextBatch = document.object()["next_batch"].toString(); + if (!document.object()["next_batch"].isNull()) + nextBatch = document.object()["next_batch"].toString(); - //qDebug() << document.object()["to_device"]; - //qDebug() << document.object()["device_one_time_keys_count"]; + // qDebug() << document.object()["to_device"]; + // qDebug() << document.object()["device_one_time_keys_count"]; - for(auto event : document.object()["to_device"].toObject()["events"].toArray()) { - if(event.toObject()["type"] == "m.room_key_request" && event.toObject()["content"].toObject()["action"] == "request") { + for (auto event : document.object()["to_device"].toObject()["events"].toArray()) { + if (event.toObject()["type"] == "m.room_key_request" && + event.toObject()["content"].toObject()["action"] == "request") { auto sender = event.toObject()["sender"].toString(); auto device_id = event.toObject()["content"].toObject()["requesting_device_id"].toString(); auto room_id = event.toObject()["content"].toObject()["body"].toObject()["room_id"].toString(); - QJsonObject queryObject { + QJsonObject queryObject{ {"timeout", 10000}, - {"device_keys", QJsonObject{ - {sender, QJsonArray({device_id})} - }}, - {"token", "string"}, + {"device_keys", QJsonObject{{sender, QJsonArray({device_id})}}}, + {"token", "string"}, }; - network->postJSON("/_matrix/client/r0/keys/query", queryObject, [this, event, sender, device_id, room_id](QNetworkReply* reply) { - const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + network->postJSON( + "/_matrix/client/r0/keys/query", + queryObject, + [this, event, sender, device_id, room_id](QNetworkReply* reply) { + const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - auto senderCurveKey = document.object()["device_keys"].toObject()[sender].toObject()[device_id].toObject()["keys"].toObject()["curve25519:" + device_id].toString(); - auto senderEdKey = document.object()["device_keys"].toObject()[sender].toObject()[device_id].toObject()["keys"].toObject()["ed25519:" + device_id].toString(); + auto senderCurveKey = document.object()["device_keys"] + .toObject()[sender] + .toObject()[device_id] + .toObject()["keys"] + .toObject()["curve25519:" + device_id] + .toString(); + auto senderEdKey = document.object()["device_keys"] + .toObject()[sender] + .toObject()[device_id] + .toObject()["keys"] + .toObject()["ed25519:" + device_id] + .toString(); - qDebug() << "sending keys to " << device_id; + qDebug() << "sending keys to " << device_id; - createOrLoadSession(); + createOrLoadSession(); - sendKeyToDevice(room_id, senderCurveKey, senderEdKey, currentSessionId, currentSessionKey, sender, device_id); - }); - } else if(event.toObject()["type"] == "m.room_key") { + sendKeyToDevice( + room_id, + senderCurveKey, + senderEdKey, + currentSessionId, + currentSessionKey, + sender, + device_id); + }); + } else if (event.toObject()["type"] == "m.room_key") { qDebug() << "we recieved a new key from a user in the room :-)"; - } else if(event.toObject()["type"] == "m.forwarded_room_key") { + } else if (event.toObject()["type"] == "m.forwarded_room_key") { qDebug() << "we recieved a new key from a user in the room :-)"; - } else if(event.toObject()["type"] == "m.room.encrypted") { + } else if (event.toObject()["type"] == "m.room.encrypted") { auto curveKey = event.toObject()["content"].toObject()["ciphertext"].toObject().keys()[0]; auto senderKey = event.toObject()["content"].toObject()["sender_key"].toString(); - int type = event.toObject()["content"].toObject()["ciphertext"].toObject()[curveKey].toObject()["type"].toInt(); - auto body = event.toObject()["content"].toObject()["ciphertext"].toObject()[curveKey].toObject()["body"].toString(); + int type = event.toObject()["content"] + .toObject()["ciphertext"] + .toObject()[curveKey] + .toObject()["type"] + .toInt(); + auto body = event.toObject()["content"] + .toObject()["ciphertext"] + .toObject()[curveKey] + .toObject()["body"] + .toString(); // create a new inbound session auto session = encryption->createInboundSession(senderKey.toStdString(), body.toStdString()); auto decryptedMsg = encryption->decrypt(session, type, body.toStdString()); - const QJsonDocument document = QJsonDocument::fromJson(QByteArray(reinterpret_cast(decryptedMsg.data()), decryptedMsg.size())); + const QJsonDocument document = QJsonDocument::fromJson( + QByteArray(reinterpret_cast(decryptedMsg.data()), decryptedMsg.size())); auto id = document.object()["content"].toObject()["session_id"].toString(); qDebug() << "NEW KEY " << id << " = " << document; // create new inbound session, append to list - auto sess = encryption->beginInboundSession(document.object()["content"].toObject()["session_key"].toString().toStdString()); + auto sess = encryption->beginInboundSession( + document.object()["content"].toObject()["session_key"].toString().toStdString()); inboundSessions[id] = sess; // if we recieved a new key, let's see if we can decrypt some old messages! - for(auto room : rooms) { - if(room->getId() == document.object()["content"].toObject()["room_id"].toString()) { - for(auto event : room->events) { - if(event->encryptionInfo != nullptr && event->encryptionInfo->sessionId == id) { + for (auto room : rooms) { + if (room->getId() == document.object()["content"].toObject()["room_id"].toString()) { + for (auto event : room->events) { + if (event->encryptionInfo != nullptr && event->encryptionInfo->sessionId == id) { auto msg = encryption->decrypt(sess, event->encryptionInfo->cipherText.toStdString()); - const QJsonDocument document = QJsonDocument::fromJson(QByteArray(reinterpret_cast(msg.data()), msg.size())); + const QJsonDocument document = QJsonDocument::fromJson( + QByteArray(reinterpret_cast(msg.data()), msg.size())); populateEvent(document.object(), event); @@ -345,70 +370,78 @@ void MatrixCore::sync() { QSettings settings; settings.beginGroup(id); - if(settings.contains("notificationLevel")) + if (settings.contains("notificationLevel")) room->setNotificationLevel(settings.value("notificationLevel").toInt(), true); else room->setNotificationLevel(1); settings.endGroup(); - if(autofill_data) { - network->get("/_matrix/client/r0/rooms/" + id + "/state/m.room.name", [this, room](QNetworkReply* reply) { - const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - if(document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") { - room->setGuestDenied(true); - return; - } else if(document.object()["errcode"].toString() == "M_NOT_FOUND") - return; + if (autofill_data) { + network->get( + "/_matrix/client/r0/rooms/" + id + "/state/m.room.name", [this, room](QNetworkReply* reply) { + const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + if (document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") { + room->setGuestDenied(true); + return; + } else if (document.object()["errcode"].toString() == "M_NOT_FOUND") + return; - room->setName(document.object()["name"].toString()); + room->setName(document.object()["name"].toString()); - roomListModel.updateRoom(room); - }); + roomListModel.updateRoom(room); + }); - network->get("/_matrix/client/r0/rooms/" + id + "/state/m.room.topic", [this, room](QNetworkReply* reply) { - const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - if(document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") { - room->setGuestDenied(true); - return; - } + network->get( + "/_matrix/client/r0/rooms/" + id + "/state/m.room.topic", [this, room](QNetworkReply* reply) { + const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + if (document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") { + room->setGuestDenied(true); + return; + } - room->setTopic(document.object()["topic"].toString()); + room->setTopic(document.object()["topic"].toString()); - roomListModel.updateRoom(room); - }); + roomListModel.updateRoom(room); + }); - network->get("/_matrix/client/r0/rooms/" + id + "/state/m.room.avatar", [this, room](QNetworkReply* reply) { - const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - if(document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") { - room->setGuestDenied(true); - return; - } + network->get( + "/_matrix/client/r0/rooms/" + id + "/state/m.room.avatar", [this, room](QNetworkReply* reply) { + const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + if (document.object()["errcode"].toString() == "M_GUEST_ACCESS_FORBIDDEN") { + room->setGuestDenied(true); + return; + } - if(document.object().contains("url")) { - const QString imageId = document.object()["url"].toString().remove("mxc://"); - room->setAvatar(network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + "?width=64&height=64&method=scale"); - } + if (document.object().contains("url")) { + const QString imageId = document.object()["url"].toString().remove("mxc://"); + room->setAvatar( + network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + + "?width=64&height=64&method=scale"); + } - roomListModel.updateRoom(room); - }); + roomListModel.updateRoom(room); + }); - network->get("/_matrix/client/r0/rooms/" + id + "/state/m.room.power_levels", [this, room](QNetworkReply* reply) { - const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + network->get( + "/_matrix/client/r0/rooms/" + id + "/state/m.room.power_levels", + [this, room](QNetworkReply* reply) { + const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - for(auto user : document.object()["users"].toObject().keys()) { - room->powerLevelList[user] = document.object()["users"].toObject()[user].toInt(); - } - }); + for (auto user : document.object()["users"].toObject().keys()) { + room->powerLevelList[user] = document.object()["users"].toObject()[user].toInt(); + } + }); - network->get("/_matrix/client/r0/rooms/" + id + "/state/m.room.encryption", [this, room](QNetworkReply* reply) { - const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + network->get( + "/_matrix/client/r0/rooms/" + id + "/state/m.room.encryption", [this, room](QNetworkReply* reply) { + const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - if(document.object().contains("algorithm")) { - room->setEncrypted(); - } + if (document.object().contains("algorithm")) { + room->setEncrypted(); + } - //qDebug() << document; - }); + // qDebug() << document; + }); } rooms.push_back(room); @@ -423,21 +456,29 @@ void MatrixCore::sync() { return room; }; - for(const auto id : document.object()["rooms"].toObject()["invite"].toObject().keys()) { - if(!invitedRooms.count(id)) { + for (const auto id : document.object()["rooms"].toObject()["invite"].toObject().keys()) { + if (!invitedRooms.count(id)) { Room* room = createRoom(id, "Invited", false); room->setGuestDenied(true); - for(auto event : document.object()["rooms"].toObject()["invite"].toObject()[id].toObject()["invite_state"].toObject()["events"].toArray()) { + for (auto event : document.object()["rooms"] + .toObject()["invite"] + .toObject()[id] + .toObject()["invite_state"] + .toObject()["events"] + .toArray()) { const QString type = event.toObject()["type"].toString(); - if(type == "m.room.member") + if (type == "m.room.member") room->setInvitedBy(event.toObject()["sender"].toString()); - else if(type == "m.room.name") { + else if (type == "m.room.name") { room->setName(event.toObject()["content"].toObject()["name"].toString()); - } else if(type == "m.room.avatar") { - const QString imageId = event.toObject()["content"].toObject()["url"].toString().remove("mxc://"); - room->setAvatar(network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + "?width=64&height=64&method=scale"); + } else if (type == "m.room.avatar") { + const QString imageId = + event.toObject()["content"].toObject()["url"].toString().remove("mxc://"); + room->setAvatar( + network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + + "?width=64&height=64&method=scale"); } roomListModel.updateRoom(room); @@ -447,16 +488,16 @@ void MatrixCore::sync() { } } - for(const auto id : document.object()["rooms"].toObject()["join"].toObject().keys()) { - if(!joinedRooms.count(id)) { + for (const auto id : document.object()["rooms"].toObject()["join"].toObject().keys()) { + if (!joinedRooms.count(id)) { createRoom(id, "Joined"); joinedRooms.push_back(id); } } - for(const auto id : document.object()["rooms"].toObject()["leave"].toObject().keys()) { + for (const auto id : document.object()["rooms"].toObject()["leave"].toObject().keys()) { - if(joinedRooms.count(id)) { + if (joinedRooms.count(id)) { Room* room = resolveRoomId(id); room->setJoinState("left"); @@ -468,51 +509,52 @@ void MatrixCore::sync() { } unsigned int i = 0; - for(const auto& room : document.object()["rooms"].toObject()["join"].toObject()) { + for (const auto& room : document.object()["rooms"].toObject()["join"].toObject()) { Room* roomState = nullptr; - for(auto& r : rooms) { - if(r->getId() == document.object()["rooms"].toObject()["join"].toObject().keys()[i]) - roomState = r; + for (auto& r : rooms) { + if (r->getId() == document.object()["rooms"].toObject()["join"].toObject().keys()[i]) + roomState = r; } - if(!roomState) + if (!roomState) continue; - if(firstSync) + if (firstSync) roomState->prevBatch = room.toObject()["timeline"].toObject()["prev_batch"].toString(); const int highlightCount = room.toObject()["unread_notifications"].toObject()["highlight_count"].toInt(); - const int notificationCount = room.toObject()["unread_notifications"].toObject()["notification_count"].toInt(); + const int notificationCount = + room.toObject()["unread_notifications"].toObject()["notification_count"].toInt(); - if(highlightCount != roomState->getHighlightCount()) { + if (highlightCount != roomState->getHighlightCount()) { roomState->setNotificationCount(highlightCount); roomListModel.updateRoom(roomState); } - if(notificationCount != roomState->getNotificationCount()) { + if (notificationCount != roomState->getNotificationCount()) { roomState->setNotificationCount(notificationCount); roomListModel.updateRoom(roomState); } - for(const auto event : room.toObject()["ephemeral"].toObject()["events"].toArray()) { + for (const auto event : room.toObject()["ephemeral"].toObject()["events"].toArray()) { const QString eventType = event.toObject()["type"].toString(); - if(eventType == "m.typing") { + if (eventType == "m.typing") { auto typing = event.toObject()["content"].toObject()["user_ids"].toArray(); QString typingText; int trueSize = 0; - if(typing.size() < 4) { - for(int i = 0; i < typing.size(); i++) { - if(typing[i].toString() == userId) + if (typing.size() < 4) { + for (int i = 0; i < typing.size(); i++) { + if (typing[i].toString() == userId) continue; const Member* member = resolveMemberId(typing[i].toString()); - if(!member) + if (!member) continue; typingText += member->getDisplayName(); - if(i != typing.size() - 1) + if (i != typing.size() - 1) typingText += ", "; trueSize++; @@ -523,7 +565,7 @@ void MatrixCore::sync() { typingText = "Several people are"; } - if(trueSize != 0) + if (trueSize != 0) this->typingText = typingText + " typing..."; else this->typingText.clear(); @@ -532,13 +574,13 @@ void MatrixCore::sync() { } } - for(const auto event : room.toObject()["timeline"].toObject()["events"].toArray()) + for (const auto event : room.toObject()["timeline"].toObject()["events"].toArray()) consumeEvent(event.toObject(), *roomState); i++; } - if(firstSync) { + if (firstSync) { firstSync = false; emit initialSyncFinished(); } @@ -552,7 +594,7 @@ bool MatrixCore::isInitialSyncComplete() { } void MatrixCore::sendMessage(Room* room, const QString& message) { - if(message.isEmpty()) + if (message.isEmpty()) return; Event* e = new Event(room); @@ -564,7 +606,7 @@ void MatrixCore::sendMessage(Room* room, const QString& message) { e->setMsgType("text"); QString msg = e->getMsg(); - for(const auto& emote : emotes) { + for (const auto& emote : emotes) { msg.replace(":" + emote->name + ":", ""); } e->setMsg(msg); @@ -576,9 +618,9 @@ void MatrixCore::sendMessage(Room* room, const QString& message) { unsentMessages.push_back(e); const auto onMessageFeedbackReceived = [this, e](QNetworkReply* reply) { - if(!reply->error()) { - for(size_t i = 0; i < unsentMessages.size(); i++) { - if(unsentMessages[i] == e) + if (!reply->error()) { + for (size_t i = 0; i < unsentMessages.size(); i++) { + if (unsentMessages[i] == e) e->setSent(true); } } else { @@ -589,32 +631,29 @@ void MatrixCore::sendMessage(Room* room, const QString& message) { bool shouldSendAsMarkdown = false; char* formatted = nullptr; - if(markdownEnabled) { - formatted = cmark_markdown_to_html(message.toStdString().c_str(), message.length(), CMARK_OPT_DEFAULT | CMARK_OPT_HARDBREAKS); + if (markdownEnabled) { + formatted = cmark_markdown_to_html( + message.toStdString().c_str(), message.length(), CMARK_OPT_DEFAULT | CMARK_OPT_HARDBREAKS); shouldSendAsMarkdown = strlen(formatted) > 8 + message.length(); } QJsonObject messageObject; - if(shouldSendAsMarkdown) { - messageObject = QJsonObject { + if (shouldSendAsMarkdown) { + messageObject = QJsonObject{ {"msgtype", "m.text"}, {"formatted_body", formatted}, {"body", message}, - {"format", "org.matrix.custom.html"} - }; + {"format", "org.matrix.custom.html"}}; e->setMsg(formatted); } else { - messageObject = QJsonObject { - {"msgtype", "m.text"}, - {"body", message} - }; + messageObject = QJsonObject{{"msgtype", "m.text"}, {"body", message}}; e->setMsg(message); } - if(room->getEncrypted()) { + if (room->getEncrypted()) { // create megolm session createOrLoadSession(); @@ -645,19 +684,22 @@ void MatrixCore::sendMessage(Room* room, const QString& message) { }} }; - std::string identityKey = document.object()["device_keys"].toObject()[user_id].toObject()[device_id].toObject()["keys"].toObject()[QString("curve25519:") + device_id].toString().toStdString(); + std::string identityKey = + document.object()["device_keys"].toObject()[user_id].toObject()[device_id].toObject()["keys"].toObject()[QString("curve25519:") + + device_id].toString().toStdString(); - std::string edIdentityKey = document.object()["device_keys"].toObject()[user_id].toObject()[device_id].toObject()["keys"].toObject()[QString("ed25519:") + device_id].toString().toStdString(); + std::string edIdentityKey = + document.object()["device_keys"].toObject()[user_id].toObject()[device_id].toObject()["keys"].toObject()[QString("ed25519:") + + device_id].toString().toStdString(); - sendKeyToDevice(room->getId(), identityKey.c_str(), edIdentityKey.c_str(), currentSessionId, currentSessionKey, user_id, device_id); + sendKeyToDevice(room->getId(), identityKey.c_str(), edIdentityKey.c_str(), currentSessionId, + currentSessionKey, user_id, device_id); } } });*/ - QJsonObject trueObject { - {"room_id", room->getId()}, - {"type", "m.room.message"}, - {"content", messageObject} + QJsonObject trueObject{ + {"room_id", room->getId()}, {"type", "m.room.message"}, {"content", messageObject} /*{"keys", QJsonObject { {"ed25519", encryption->identityKey["ed25519"]} }}, @@ -666,39 +708,52 @@ void MatrixCore::sendMessage(Room* room, const QString& message) { }; // construct the m.room.encrypted event - const QJsonObject roomEncryptedObject { + const QJsonObject roomEncryptedObject{ {"algorithm", "m.megolm.v1.aes-sha2"}, - {"ciphertext", encryption->encryptGroup(currentSession, QString(QJsonDocument(trueObject).toJson(QJsonDocument::Compact)).toStdString()).c_str()}, + {"ciphertext", + encryption + ->encryptGroup( + currentSession, QString(QJsonDocument(trueObject).toJson(QJsonDocument::Compact)).toStdString()) + .c_str()}, {"sender_key", encryption->identityKey["curve25519"]}, {"session_id", currentSessionId}, - {"device_id", deviceId} - }; + {"device_id", deviceId}}; - network->putJSON("/_matrix/client/r0/rooms/" + room->getId() + "/send/m.room.encrypted/" + QRandomGenerator::global()->generate(), roomEncryptedObject, [](QNetworkReply* reply) { - //qDebug() << "reply from room send: " << reply->readAll(); - }); + network->putJSON( + "/_matrix/client/r0/rooms/" + room->getId() + "/send/m.room.encrypted/" + + QRandomGenerator::global()->generate(), + roomEncryptedObject, + [](QNetworkReply* reply) { + // qDebug() << "reply from room send: " << reply->readAll(); + }); } else { - network->putJSON(QString("/_matrix/client/r0/rooms/" + room->getId() + "/send/m.room.message/") + QString::number(QRandomGenerator::global()->generate()), messageObject, onMessageFeedbackReceived); + network->putJSON( + QString("/_matrix/client/r0/rooms/" + room->getId() + "/send/m.room.message/") + + QString::number(QRandomGenerator::global()->generate()), + messageObject, + onMessageFeedbackReceived); } } void MatrixCore::removeMessage(const QString& eventId) { - const QJsonObject reasonObject { - {"reason", ""} - }; + const QJsonObject reasonObject{{"reason", ""}}; - network->putJSON("/_matrix/client/r0/rooms/" + currentRoom->getId() + "/redact/" + eventId + "/" + QString::number(QRandomGenerator::global()->generate()), reasonObject, [this, eventId](QNetworkReply* reply) { - auto& events = currentRoom->events; - for(int i = 0; i < events.size(); i++) { - if(events[i]->eventId == eventId) { - eventModel.beginRemoveEvent(i, 0); + network->putJSON( + "/_matrix/client/r0/rooms/" + currentRoom->getId() + "/redact/" + eventId + "/" + + QString::number(QRandomGenerator::global()->generate()), + reasonObject, + [this, eventId](QNetworkReply* reply) { + auto& events = currentRoom->events; + for (int i = 0; i < events.size(); i++) { + if (events[i]->eventId == eventId) { + eventModel.beginRemoveEvent(i, 0); - events.removeAt(i); + events.removeAt(i); - eventModel.endRemoveEvent(); + eventModel.endRemoveEvent(); + } } - } - }); + }); } void MatrixCore::uploadAttachment(Room* room, const QString& path) { @@ -730,62 +785,65 @@ void MatrixCore::uploadAttachment(Room* room, const QString& path) { e->setMsg(fileName); e->setMsgType(mimeType.name().contains("image") ? "image" : "file"); - network->postBinary("/_matrix/media/r0/upload?filename=" + f.fileName(), f.readAll(), mimeType.name(), [this, mimeType, fileName, fileSize, e](QNetworkReply* reply) { - if(!reply->error()) { - e->setSent(true); + network->postBinary( + "/_matrix/media/r0/upload?filename=" + f.fileName(), + f.readAll(), + mimeType.name(), + [this, mimeType, fileName, fileSize, e](QNetworkReply* reply) { + if (!reply->error()) { + e->setSent(true); - const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - QJsonObject infoObject { - {"mimetype", mimeType.name()}, - {"size", fileSize}, - }; + QJsonObject infoObject{ + {"mimetype", mimeType.name()}, + {"size", fileSize}, + }; - const QJsonObject imageObject { - {"msgtype", mimeType.name().contains("image") ? "m.image" : "m.file"}, - {"body", fileName}, - {"url", document.object()["content_uri"].toString()}, - {"info", infoObject} - }; + const QJsonObject imageObject{ + {"msgtype", mimeType.name().contains("image") ? "m.image" : "m.file"}, + {"body", fileName}, + {"url", document.object()["content_uri"].toString()}, + {"info", infoObject}}; - network->putJSON("/_matrix/client/r0/rooms/" + currentRoom->getId() + "/send/m.room.message/" + QString::number(QRandomGenerator::global()->generate()), imageObject); - } - }, [e](qint64 sent, qint64 total) { - e->setSentProgress((double)sent / (double)total); - }); + network->putJSON( + "/_matrix/client/r0/rooms/" + currentRoom->getId() + "/send/m.room.message/" + + QString::number(QRandomGenerator::global()->generate()), + imageObject); + } + }, + [e](qint64 sent, qint64 total) { + e->setSentProgress((double)sent / (double)total); + }); } void MatrixCore::startDirectChat(const QString& id) { - const QJsonObject roomObject { + const QJsonObject roomObject{ {"visibility", "private"}, {"creation_content", QJsonObject{{"m.federate", false}}}, {"preset", "private_chat"}, {"is_direct", true}, - {"invite", QJsonArray{id}} - }; + {"invite", QJsonArray{id}}}; network->postJSON("/_matrix/client/r0/createRoom", roomObject, [](QNetworkReply*) {}); } void MatrixCore::setTyping(Room* room) { - const QJsonObject typingObject { - {"typing", true}, - {"timeout", 15000} - }; + const QJsonObject typingObject{{"typing", true}, {"timeout", 15000}}; network->putJSON("/_matrix/client/r0/rooms/" + room->getId() + "/typing/" + userId, typingObject); } void MatrixCore::joinRoom(const QString& id) { network->post("/_matrix/client/r0/rooms/" + id + "/join", [this, id](QNetworkReply* reply) { - if(!reply->error()) { - //check if its by an invite - if(invitedRooms.contains(id)) { + if (!reply->error()) { + // check if its by an invite + if (invitedRooms.contains(id)) { invitedRooms.removeOne(id); joinedRooms.push_back(id); - for(const auto roomObject : rooms) { - if(roomObject->getId() == id) { + for (const auto roomObject : rooms) { + if (roomObject->getId() == id) { roomObject->setJoinState("Joined"); roomObject->setGuestDenied(false); @@ -804,15 +862,13 @@ void MatrixCore::leaveRoom(const QString& id) { } void MatrixCore::inviteToRoom(Room* room, const QString& userId) { - const QJsonObject inviteObject { - {"user_id", userId} - }; + const QJsonObject inviteObject{{"user_id", userId}}; network->postJSON("/_matrix/client/r0/rooms/" + room->getId() + "/invite", inviteObject, [](QNetworkReply*) {}); } void MatrixCore::updateMembers(Room* room) { - if(!room) + if (!room) return; network->get("/_matrix/client/r0/rooms/" + room->getId() + "/members", [this, room](QNetworkReply* reply) { @@ -821,30 +877,33 @@ void MatrixCore::updateMembers(Room* room) { const QJsonArray& chunk = document.object()["chunk"].toArray(); size_t realSize = 0; - for(const auto& member : chunk) { - if(member.toObject()["content"].toObject()["membership"].toString() == "join") + for (const auto& member : chunk) { + if (member.toObject()["content"].toObject()["membership"].toString() == "join") realSize++; } - if(room->members.size() != realSize) { + if (room->members.size() != realSize) { room->members.clear(); room->members.reserve(realSize); - for(const auto& member : chunk) { + for (const auto& member : chunk) { const QJsonObject& memberJson = member.toObject(); - if(memberJson["content"].toObject()["membership"].toString() == "join") { + if (memberJson["content"].toObject()["membership"].toString() == "join") { const QString& id = memberJson["state_key"].toString(); Member* m = nullptr; - if(!idToMember.contains(id)) { + if (!idToMember.contains(id)) { m = new Member(this); m->setId(id); m->setDisplayName(memberJson["content"].toObject()["displayname"].toString()); - if(!memberJson["content"].toObject()["avatar_url"].isNull()) { - const QString imageId = memberJson["content"].toObject()["avatar_url"].toString().remove("mxc://"); - m->setAvatar(network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + "?width=64&height=64&method=scale"); + if (!memberJson["content"].toObject()["avatar_url"].isNull()) { + const QString imageId = + memberJson["content"].toObject()["avatar_url"].toString().remove("mxc://"); + m->setAvatar( + network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + + "?width=64&height=64&method=scale"); } idToMember.insert(id, m); @@ -852,7 +911,7 @@ void MatrixCore::updateMembers(Room* room) { m = idToMember[id]; } - if(currentRoom == room) { + if (currentRoom == room) { eventModel.updateEventsByMember(id); memberModel.beginUpdate(0); @@ -860,7 +919,7 @@ void MatrixCore::updateMembers(Room* room) { room->members.push_back(m); - if(currentRoom == room) + if (currentRoom == room) memberModel.endUpdate(); } } @@ -869,23 +928,25 @@ void MatrixCore::updateMembers(Room* room) { } void MatrixCore::readMessageHistory(Room* room) { - if(!room || room->prevBatch.isEmpty()) + if (!room || room->prevBatch.isEmpty()) return; qDebug() << "Reading message history..."; - network->get("/_matrix/client/r0/rooms/" + room->getId() + "/messages?from=" + room->prevBatch + "&dir=b", [this, room](QNetworkReply* reply) { - const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + network->get( + "/_matrix/client/r0/rooms/" + room->getId() + "/messages?from=" + room->prevBatch + "&dir=b", + [this, room](QNetworkReply* reply) { + const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - room->prevBatch = document.object()["end"].toString(); + room->prevBatch = document.object()["end"].toString(); - traversingHistory = true; + traversingHistory = true; - for(const auto event : document.object()["chunk"].toArray()) - consumeEvent(event.toObject(), *room, false); + for (const auto event : document.object()["chunk"].toArray()) + consumeEvent(event.toObject(), *room, false); - traversingHistory = false; - }); + traversingHistory = false; + }); } bool MatrixCore::settingsValid() { @@ -896,18 +957,18 @@ void MatrixCore::setHomeserver(const QString& url) { network->homeserverURL = "https://" + url; network->get("/_matrix/client/versions", [this, url](QNetworkReply* reply) { - if(!reply->error()) { - homeserverURL = url; + if (!reply->error()) { + homeserverURL = url; - QSettings settings; - settings.beginGroup(profileName); - settings.setValue("homeserver", url); - settings.endGroup(); - } + QSettings settings; + settings.beginGroup(profileName); + settings.setValue("homeserver", url); + settings.endGroup(); + } - network->homeserverURL = "https://" + homeserverURL; + network->homeserverURL = "https://" + homeserverURL; - emit homeserverChanged(reply->error() == 0, reply->errorString()); + emit homeserverChanged(reply->error() == 0, reply->errorString()); }); } @@ -924,7 +985,7 @@ void MatrixCore::changeCurrentRoom(Room* room) { } void MatrixCore::changeCurrentRoom(const unsigned int index) { - if(index < rooms.size()) + if (index < rooms.size()) changeCurrentRoom(rooms[index]); else changeCurrentRoom(&emptyRoom); @@ -939,11 +1000,11 @@ void MatrixCore::addEmote(const QString& url) { QUrl file(newUrl); QString appDir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); - if(!QDir(appDir).exists()) + if (!QDir(appDir).exists()) QDir().mkdir(appDir); QString emotesDir = appDir + "/emotes"; - if(!QDir(emotesDir).exists()) + if (!QDir(emotesDir).exists()) QDir().mkdir(emotesDir); QPixmap pixmap(newUrl); @@ -973,8 +1034,7 @@ Member* MatrixCore::resolveMemberId(const QString& id) const { return idToMember.value(id); } - -Room* MatrixCore::resolveRoomId(const QString &id) const { +Room* MatrixCore::resolveRoomId(const QString& id) const { return idToRoom.value(id); } @@ -993,23 +1053,25 @@ void MatrixCore::loadDirectory(const QString& homeserver) { network->postJSON("/_matrix/client/r0/publicRooms?server=" + homeserver, bodyObject, [this](QNetworkReply* reply) { const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - if(publicRooms.size() != document.object()["chunk"].toArray().size()) { + if (publicRooms.size() != document.object()["chunk"].toArray().size()) { publicRooms.clear(); publicRooms.reserve(document.object()["chunk"].toArray().size()); - for(const auto room : document.object()["chunk"].toArray()) { + for (const auto room : document.object()["chunk"].toArray()) { const QJsonObject& roomObject = room.toObject(); const QString& roomId = roomObject["room_id"].toString(); Room* r = nullptr; - if(!idToRoom.contains(roomId)) { + if (!idToRoom.contains(roomId)) { r = new Room(this); r->setId(roomId); r->setName(roomObject["name"].toString()); - if(!roomObject["avatar_url"].isNull()) { + if (!roomObject["avatar_url"].isNull()) { const QString imageId = roomObject["avatar_url"].toString().remove("mxc://"); - r->setAvatar(network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + "?width=64&height=64&method=scale"); + r->setAvatar( + network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + + "?width=64&height=64&method=scale"); } r->setTopic(roomObject["topic"].toString()); @@ -1030,13 +1092,13 @@ void MatrixCore::loadDirectory(const QString& homeserver) { } void MatrixCore::readUpTo(Room* room, const int index) { - if(!room) + if (!room) return; - if(room->events.size() == 0) + if (room->events.size() == 0) return; - if(index < 0) + if (index < 0) return; network->post("/_matrix/client/r0/rooms/" + room->getId() + "/receipt/m.read/" + room->events[index]->eventId); @@ -1079,33 +1141,33 @@ void MatrixCore::consumeEvent(const QJsonObject& event, Room& room, const bool i const QString eventType = event["type"].toString(); const auto addEvent = [&room, insertFront, this](Event* object) { - if(insertFront) { - if(&room == currentRoom) + if (insertFront) { + if (&room == currentRoom) eventModel.beginUpdate(0); room.events.push_front(object); - if(&room == currentRoom) + if (&room == currentRoom) eventModel.endHistory(); } else { - if(&room == currentRoom) + if (&room == currentRoom) eventModel.beginHistory(0); room.events.push_back(object); - if(&room == currentRoom) + if (&room == currentRoom) eventModel.endHistory(); } }; bool found = false; - if(eventType == "m.room.message" || eventType == "m.room.encrypted") { - for(size_t i = 0; i < unsentMessages.size(); i++) { - if(event["sender"].toString() == userId && unsentMessages[i]->getRoom() == room.getId()) { + if (eventType == "m.room.message" || eventType == "m.room.encrypted") { + for (size_t i = 0; i < unsentMessages.size(); i++) { + if (event["sender"].toString() == userId && unsentMessages[i]->getRoom() == room.getId()) { found = true; unsentMessages[i]->setSent(true); - if(currentRoom == &room) + if (currentRoom == &room) eventModel.updateEvent(unsentMessages[i]); unsentMessages.removeAt(i); @@ -1115,35 +1177,37 @@ void MatrixCore::consumeEvent(const QJsonObject& event, Room& room, const bool i } } - if(eventType == "m.room.member") { + if (eventType == "m.room.member") { // avoid events tied to us - if(event["state_key"].toString() == userId) + if (event["state_key"].toString() == userId) return; - if(event["content"].toObject().contains("is_direct")) + if (event["content"].toObject().contains("is_direct")) room.setDirect(event["content"].toObject()["is_direct"].toBool()); - if(room.getDirect()) { + if (room.getDirect()) { room.setName(event["content"].toObject()["displayname"].toString()); - if(!event["content"].toObject()["avatar_url"].isNull()) { + if (!event["content"].toObject()["avatar_url"].isNull()) { const QString imageId = event["content"].toObject()["avatar_url"].toString().remove("mxc://"); - room.setAvatar(network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + "?width=64&height=64&method=scale"); + room.setAvatar( + network->homeserverURL + "/_matrix/media/r0/thumbnail/" + imageId + + "?width=64&height=64&method=scale"); } } roomListModel.updateRoom(&room); - } else if(eventType == "m.room.encrypted") { + } else if (eventType == "m.room.encrypted") { Event* e = new Event(&room); - if(event["content"].toObject()["device_id"] != deviceId) { + if (event["content"].toObject()["device_id"] != deviceId) { EncryptionInformation* info = new EncryptionInformation(); e->encryptionInfo = info; info->cipherText = event["content"].toObject()["ciphertext"].toString(); info->sessionId = event["content"].toObject()["session_id"].toString(); - if(!inboundSessions.contains(event["content"].toObject()["session_id"].toString())) { - //qDebug() << "new encrypted event " << event; + if (!inboundSessions.contains(event["content"].toObject()["session_id"].toString())) { + // qDebug() << "new encrypted event " << event; e->setMsg("** ERR: we can't decrypt this yet, we do not have the key."); qDebug() << "the failed id: " << event["content"].toObject()["session_id"].toString(); @@ -1151,39 +1215,41 @@ void MatrixCore::consumeEvent(const QJsonObject& event, Room& room, const bool i // let's send a room key request event // construct m.room.key event - const QJsonObject roomKeyObject { + const QJsonObject roomKeyObject{ {"action", "request"}, - {"body", QJsonObject { - {"algorithm", event["content"].toObject()["algorithm"]}, - {"room_id", room.getId()}, - {"sender_key", event["content"].toObject()["sender_key"]}, - {"session_id", event["content"].toObject()["session_id"]} - }}, + {"body", + QJsonObject{ + {"algorithm", event["content"].toObject()["algorithm"]}, + {"room_id", room.getId()}, + {"sender_key", event["content"].toObject()["sender_key"]}, + {"session_id", event["content"].toObject()["session_id"]}}}, {"requesting_device_id", deviceId}, - {"request_id", QString("lololol") + QString::number(QRandomGenerator::global()->generate())} - }; + {"request_id", QString("lololol") + QString::number(QRandomGenerator::global()->generate())}}; - const QJsonObject sendToDeviceObject { - {"messages", QJsonObject { - { event["sender"].toString(), QJsonObject { - { event["content"].toObject()["device_id"].toString(), roomKeyObject} - }} - }} - }; + const QJsonObject sendToDeviceObject{ + {"messages", + QJsonObject{ + {event["sender"].toString(), + QJsonObject{{event["content"].toObject()["device_id"].toString(), roomKeyObject}}}}}}; - //qDebug() << QJsonDocument(sendToDeviceObject).toJson(QJsonDocument::Compact); + // qDebug() << QJsonDocument(sendToDeviceObject).toJson(QJsonDocument::Compact); - network->putJSON(QString("/_matrix/client/r0/sendToDevice/m.room_key_request/") + QString::number(QRandomGenerator::global()->generate()), sendToDeviceObject, [](QNetworkReply* reply) { - //qDebug() << "REPLY FROM KEY REQUEST SEND: " << reply->readAll(); - }); + network->putJSON( + QString("/_matrix/client/r0/sendToDevice/m.room_key_request/") + + QString::number(QRandomGenerator::global()->generate()), + sendToDeviceObject, + [](QNetworkReply* reply) { + // qDebug() << "REPLY FROM KEY REQUEST SEND: " << reply->readAll(); + }); } else { auto session = inboundSessions[event["content"].toObject()["session_id"].toString()]; - auto msg = encryption->decrypt(session, event["content"].toObject()["ciphertext"].toString().toStdString()); + auto msg = + encryption->decrypt(session, event["content"].toObject()["ciphertext"].toString().toStdString()); - const QJsonDocument document = QJsonDocument::fromJson(QByteArray(reinterpret_cast(msg.data()), msg.size())); + const QJsonDocument document = + QJsonDocument::fromJson(QByteArray(reinterpret_cast(msg.data()), msg.size())); populateEvent(document.object(), e); - } } else { e->setMsg("** ERR: messages sent from the same device are not supported yet."); @@ -1195,22 +1261,22 @@ void MatrixCore::consumeEvent(const QJsonObject& event, Room& room, const bool i addEvent(e); - if(!firstSync && !traversingHistory) + if (!firstSync && !traversingHistory) emit message(&room, e->getSender(), e->getMsg()); } // don't show redacted messages - if(event["unsigned"].toObject().keys().contains("redacted_because")) + if (event["unsigned"].toObject().keys().contains("redacted_because")) return; - if(!found && eventType == "m.room.message") { + if (!found && eventType == "m.room.message") { Event* e = new Event(&room); populateEvent(event, e); addEvent(e); - if(!firstSync && !traversingHistory) + if (!firstSync && !traversingHistory) emit message(&room, e->getSender(), e->getMsg()); } } @@ -1222,24 +1288,25 @@ void MatrixCore::populateEvent(const QJsonObject& event, Event* e) { e->setSender(event["sender"].toString()); e->eventId = event["event_id"].toString(); - if(msgType == "m.text" && !event["content"].toObject().contains("formatted_body")) { + if (msgType == "m.text" && !event["content"].toObject().contains("formatted_body")) { e->setMsgType("text"); e->setMsg(event["content"].toObject()["body"].toString()); - } else if(msgType == "m.text" && event["content"].toObject().contains("formatted_body")) { + } else if (msgType == "m.text" && event["content"].toObject().contains("formatted_body")) { e->setMsgType("text"); e->setMsg(event["content"].toObject()["formatted_body"].toString()); - } else if(msgType == "m.image") { + } else if (msgType == "m.image") { e->setMsgType("image"); e->setAttachment(getMXCMediaURL(event["content"].toObject()["url"].toString())); e->setAttachmentSize(event["content"].toObject()["info"].toObject()["size"].toInt()); - if(event["content"].toObject()["info"].toObject().contains("thumbnail_url")) - e->setThumbnail(getMXCThumbnailURL(event["content"].toObject()["info"].toObject()["thumbnail_url"].toString())); + if (event["content"].toObject()["info"].toObject().contains("thumbnail_url")) + e->setThumbnail( + getMXCThumbnailURL(event["content"].toObject()["info"].toObject()["thumbnail_url"].toString())); else e->setThumbnail(getMXCMediaURL(event["content"].toObject()["url"].toString())); e->setMsg(event["content"].toObject()["body"].toString()); - } else if(msgType == "m.file") { + } else if (msgType == "m.file") { e->setMsgType("file"); e->setAttachment(getMXCMediaURL(event["content"].toObject()["url"].toString())); e->setAttachmentSize(event["content"].toObject()["info"].toObject()["size"].toInt()); @@ -1248,7 +1315,7 @@ void MatrixCore::populateEvent(const QJsonObject& event, Event* e) { e->setMsg(event["content"].toObject()["body"].toString()); QString msg = e->getMsg(); - for(const auto& emote : emotes) { + for (const auto& emote : emotes) { msg.replace(":" + emote->name + ":", ""); } @@ -1277,87 +1344,101 @@ bool MatrixCore::getMarkdownEnabled() const { return markdownEnabled; } -void MatrixCore::sendKeyToDevice(QString roomId, QString senderCurveIdentity, QString senderEdIdentity, QString session_id, QString session_key, QString user_id, QString device_id) -{ +void MatrixCore::sendKeyToDevice( + QString roomId, + QString senderCurveIdentity, + QString senderEdIdentity, + QString session_id, + QString session_key, + QString user_id, + QString device_id) { // why we would we send ourselves a key? - if(device_id == deviceId) + if (device_id == deviceId) return; - QJsonObject claimObject { - {"timeout", 10000}, - {"one_time_keys", QJsonObject { - {user_id, QJsonObject { - {device_id, "signed_curve25519"} - }} - }} - }; + QJsonObject claimObject{ + {"timeout", 10000}, {"one_time_keys", QJsonObject{{user_id, QJsonObject{{device_id, "signed_curve25519"}}}}}}; - network->postJSON("/_matrix/client/r0/keys/claim", claimObject, [this, device_id, user_id, senderCurveIdentity, senderEdIdentity, roomId, session_id, session_key](QNetworkReply* reply) { - const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + network->postJSON( + "/_matrix/client/r0/keys/claim", + claimObject, + [this, device_id, user_id, senderCurveIdentity, senderEdIdentity, roomId, session_id, session_key]( + QNetworkReply* reply) { + const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - std::string identityKey = senderCurveIdentity.toStdString(); + std::string identityKey = senderCurveIdentity.toStdString(); - // we couldnt claim a key, skip - if(document.object()["one_time_keys"].toObject()[user_id].toObject()[device_id].toObject().keys().empty()) - return; + // we couldnt claim a key, skip + if (document.object()["one_time_keys"].toObject()[user_id].toObject()[device_id].toObject().keys().empty()) + return; - std::string oneTimeKey = document.object()["one_time_keys"].toObject()[user_id].toObject()[device_id].toObject()[document.object()["one_time_keys"].toObject()[user_id].toObject()[device_id].toObject().keys()[0]].toObject()["key"].toString().toStdString(); + std::string oneTimeKey = document.object()["one_time_keys"] + .toObject()[user_id] + .toObject()[device_id] + .toObject()[document.object()["one_time_keys"] + .toObject()[user_id] + .toObject()[device_id] + .toObject() + .keys()[0]] + .toObject()["key"] + .toString() + .toStdString(); - auto session = encryption->beginOutboundOlmSession(identityKey, oneTimeKey); + auto session = encryption->beginOutboundOlmSession(identityKey, oneTimeKey); - // construct m.room.key event - const QJsonObject roomKeyObject { - {"content", QJsonObject { - {"algorithm", "m.megolm.v1.aes-sha2"}, - {"room_id", roomId}, - {"session_id", session_id}, - {"session_key", session_key} - }}, - {"type", "m.room_key"}, - {"keys", QJsonObject { - {"ed25519", encryption->identityKey["ed25519"]} - }}, - {"sender", userId}, - {"sender_device", deviceId}, - {"recipient", user_id}, - {"recipient_keys", QJsonObject { - {"ed25519", senderEdIdentity} - }} - }; + // construct m.room.key event + const QJsonObject roomKeyObject{ + {"content", + QJsonObject{ + {"algorithm", "m.megolm.v1.aes-sha2"}, + {"room_id", roomId}, + {"session_id", session_id}, + {"session_key", session_key}}}, + {"type", "m.room_key"}, + {"keys", QJsonObject{{"ed25519", encryption->identityKey["ed25519"]}}}, + {"sender", userId}, + {"sender_device", deviceId}, + {"recipient", user_id}, + {"recipient_keys", QJsonObject{{"ed25519", senderEdIdentity}}}}; - // construct the m.room.encrypted event - const QJsonObject roomEncryptedObject { - {"algorithm", "m.olm.v1.curve25519-aes-sha2"}, - {"ciphertext", QJsonObject { - {identityKey.c_str(), QJsonObject { - {"body", encryption->encrypt(session, QString(QJsonDocument(roomKeyObject).toJson(QJsonDocument::Compact)).toStdString()).c_str()}, - {"type", (int)olm_encrypt_message_type(session)} - }}}}, + // construct the m.room.encrypted event + const QJsonObject roomEncryptedObject{ + {"algorithm", "m.olm.v1.curve25519-aes-sha2"}, + {"ciphertext", + QJsonObject{ + {identityKey.c_str(), + QJsonObject{ + {"body", + encryption + ->encrypt( + session, + QString(QJsonDocument(roomKeyObject).toJson(QJsonDocument::Compact)).toStdString()) + .c_str()}, + {"type", (int)olm_encrypt_message_type(session)}}}}}, {"sender_key", encryption->identityKey["curve25519"]}, - }; + }; - const QJsonObject sendToDeviceObject { - {"messages", QJsonObject { - { user_id, QJsonObject { - { device_id, roomEncryptedObject} - }} - }} - }; + const QJsonObject sendToDeviceObject{ + {"messages", QJsonObject{{user_id, QJsonObject{{device_id, roomEncryptedObject}}}}}}; - network->putJSON(QString("/_matrix/client/r0/sendToDevice/m.room.encrypted/") + QString::number(QRandomGenerator::global()->generate()), sendToDeviceObject, [](QNetworkReply* reply) { - //qDebug() << "REPLY FROM KEY SEND: " << reply->readAll(); + network->putJSON( + QString("/_matrix/client/r0/sendToDevice/m.room.encrypted/") + + QString::number(QRandomGenerator::global()->generate()), + sendToDeviceObject, + [](QNetworkReply* reply) { + // qDebug() << "REPLY FROM KEY SEND: " << reply->readAll(); + }); }); - }); } void MatrixCore::createOrLoadSession() { - if(currentSession != nullptr) + if (currentSession != nullptr) return; QSettings settings; settings.beginGroup(profileName); - if(settings.contains("sessionPickle")) { + if (settings.contains("sessionPickle")) { currentSession = encryption->loadSession(settings.value("sessionPickle").toString()); currentSessionId = encryption->getGroupSessionId(currentSession).c_str(); currentSessionKey = encryption->getGroupSessionKey(currentSession).c_str(); @@ -1367,7 +1448,7 @@ void MatrixCore::createOrLoadSession() { auto session_id = encryption->getGroupSessionId(currentSession); auto session_key = encryption->getGroupSessionKey(currentSession); - //qDebug () << "CREATING NEW SESSION WITH ID " << session_id.c_str(); + // qDebug () << "CREATING NEW SESSION WITH ID " << session_id.c_str(); currentSessionId = session_id.c_str(); currentSessionKey = session_key.c_str(); diff --git a/src/membermodel.cpp b/src/membermodel.cpp index 8997b88..e0055d7 100755 --- a/src/membermodel.cpp +++ b/src/membermodel.cpp @@ -2,31 +2,31 @@ #include "room.h" -int MemberModel::rowCount(const QModelIndex &parent) const { - if(!room) +int MemberModel::rowCount(const QModelIndex& parent) const { + if (!room) return 0; return room->members.size(); } -QVariant MemberModel::data(const QModelIndex &index, int role) const { - if(!room) +QVariant MemberModel::data(const QModelIndex& index, int role) const { + if (!room) return ""; - if(index.row() >= room->members.size()) + if (index.row() >= room->members.size()) return ""; - if(role == DisplayNameRole) + if (role == DisplayNameRole) return room->members.at(index.row())->getDisplayName(); - else if(role == AvatarURLRole) + else if (role == AvatarURLRole) return room->members.at(index.row())->getAvatar(); - else if(role == IdRole) + else if (role == IdRole) return room->members.at(index.row())->getId(); else { int powerLevel = room->powerLevelList[room->members.at(index.row())->getId()]; - if(powerLevel == 100) + if (powerLevel == 100) return "Admin"; - else if(powerLevel == 50) + else if (powerLevel == 50) return "Moderator"; else return "User"; diff --git a/src/roomlistmodel.cpp b/src/roomlistmodel.cpp index da6f556..5fe6400 100644 --- a/src/roomlistmodel.cpp +++ b/src/roomlistmodel.cpp @@ -4,29 +4,29 @@ RoomListModel::RoomListModel(QList& rooms) : rooms(rooms) {} -int RoomListModel::rowCount(const QModelIndex &parent) const { +int RoomListModel::rowCount(const QModelIndex& parent) const { return rooms.size(); } -QVariant RoomListModel::data(const QModelIndex &index, int role) const { - if(role == AliasRole) +QVariant RoomListModel::data(const QModelIndex& index, int role) const { + if (role == AliasRole) return rooms[index.row()]->getName(); - else if(role == AvatarRole) + else if (role == AvatarRole) return rooms[index.row()]->getAvatar(); - else if(role == JoinStateRole) + else if (role == JoinStateRole) return rooms[index.row()]->getJoinState(); - else if(role == TopicRole) + else if (role == TopicRole) return rooms[index.row()]->getTopic(); - else if(role == IdRole) + else if (role == IdRole) return rooms[index.row()]->getId(); - else if(role == HighlightCountRole) + else if (role == HighlightCountRole) return rooms[index.row()]->getHighlightCount(); - else if(role == NotificationCountRole) + else if (role == NotificationCountRole) return rooms[index.row()]->getNotificationCount(); - else if(role == DirectRole) + else if (role == DirectRole) return rooms[index.row()]->getDirect(); else { - if(rooms[index.row()]->getDirect()) + if (rooms[index.row()]->getDirect()) return "Direct Chats"; else return rooms[index.row()]->getJoinState(); @@ -48,9 +48,9 @@ QHash RoomListModel::roleNames() const { return roles; } -void RoomListModel::updateRoom(Room *room) { - for(unsigned i = 0; i < rooms.size(); i++) { - if(room == rooms[i]) +void RoomListModel::updateRoom(Room* room) { + for (unsigned i = 0; i < rooms.size(); i++) { + if (room == rooms[i]) emit dataChanged(createIndex(i, 0), createIndex(i, 0)); } } diff --git a/src/roomlistsortmodel.cpp b/src/roomlistsortmodel.cpp index 230b293..f763e22 100755 --- a/src/roomlistsortmodel.cpp +++ b/src/roomlistsortmodel.cpp @@ -1,17 +1,17 @@ #include "roomlistsortmodel.h" +#include "membermodel.h" #include "room.h" #include "roomlistmodel.h" -#include "membermodel.h" bool RoomListSortModel::lessThan(const QModelIndex& left, const QModelIndex& right) const { const QString sectionLeft = sourceModel()->data(left, RoomListModel::SectionRole).toString(); const QString sectionRight = sourceModel()->data(right, RoomListModel::SectionRole).toString(); - if(sectionRight == "Direct Chats") + if (sectionRight == "Direct Chats") return false; - if(sectionLeft == "Direct Chats") + if (sectionLeft == "Direct Chats") return true; return false; @@ -21,15 +21,16 @@ bool MemberListSortModel::lessThan(const QModelIndex& left, const QModelIndex& r const QString sectionLeft = sourceModel()->data(left, MemberModel::SectionRole).toString(); const QString sectionRight = sourceModel()->data(right, MemberModel::SectionRole).toString(); - if(sectionLeft == "Admin" && sectionRight == "Moderator") + if (sectionLeft == "Admin" && sectionRight == "Moderator") return true; - else if(sectionLeft == "Moderator" && sectionRight == "User") + else if (sectionLeft == "Moderator" && sectionRight == "User") return true; - else if(sectionLeft == "Admin" && sectionRight == "User") + else if (sectionLeft == "Admin" && sectionRight == "User") return true; - if(sectionLeft == sectionRight) - return sourceModel()->data(left, MemberModel::DisplayNameRole).toString() < sourceModel()->data(right, MemberModel::DisplayNameRole).toString(); + if (sectionLeft == sectionRight) + return sourceModel()->data(left, MemberModel::DisplayNameRole).toString() < + sourceModel()->data(right, MemberModel::DisplayNameRole).toString(); return false; }