summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/MainWindow.cpp9
-rw-r--r--src/MainWindow.h2
-rw-r--r--src/dialogs/UserProfile.cpp305
-rw-r--r--src/dialogs/UserProfile.h69
-rw-r--r--src/timeline/TimelineModel.cpp4
-rw-r--r--src/timeline/TimelineModel.h10
-rw-r--r--src/timeline/TimelineViewManager.cpp20
-rw-r--r--src/ui/UserProfile.cpp108
-rw-r--r--src/ui/UserProfile.h120
-rw-r--r--src/ui/UserProfileModel.cpp63
-rw-r--r--src/ui/UserProfileModel.h30
11 files changed, 168 insertions, 572 deletions
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp

index cc1d868b..63b524c8 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp
@@ -318,15 +318,6 @@ MainWindow::hasActiveUser() } void -MainWindow::openUserProfile(const QString &user_id, const QString &room_id) -{ - auto dialog = new dialogs::UserProfile(this); - dialog->init(user_id, room_id); - - showDialog(dialog); -} - -void MainWindow::openRoomSettings(const QString &room_id) { const auto roomToSearch = room_id.isEmpty() ? chat_page_->currentRoom() : ""; diff --git a/src/MainWindow.h b/src/MainWindow.h
index e3e04698..2fc2d00f 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h
@@ -25,7 +25,6 @@ #include <QSystemTrayIcon> #include "UserSettingsPage.h" -#include "dialogs/UserProfile.h" #include "ui/OverlayModal.h" #include "jdenticoninterface.h" @@ -76,7 +75,6 @@ public: void openLogoutDialog(); void openRoomSettings(const QString &room_id = ""); void openMemberListDialog(const QString &room_id = ""); - void openUserProfile(const QString &user_id, const QString &room_id); void openReadReceiptsDialog(const QString &event_id); void hideOverlay(); diff --git a/src/dialogs/UserProfile.cpp b/src/dialogs/UserProfile.cpp deleted file mode 100644
index 3415b127..00000000 --- a/src/dialogs/UserProfile.cpp +++ /dev/null
@@ -1,305 +0,0 @@ -#include <QHBoxLayout> -#include <QLabel> -#include <QListWidget> -#include <QShortcut> -#include <QVBoxLayout> - -#include "Cache.h" -#include "ChatPage.h" -#include "Logging.h" -#include "MatrixClient.h" -#include "Utils.h" -#include "dialogs/UserProfile.h" -#include "ui/Avatar.h" -#include "ui/FlatButton.h" - -using namespace dialogs; - -Q_DECLARE_METATYPE(std::vector<DeviceInfo>) - -constexpr int BUTTON_SIZE = 36; -constexpr int BUTTON_RADIUS = BUTTON_SIZE / 2; -constexpr int WIDGET_MARGIN = 20; -constexpr int TOP_WIDGET_MARGIN = 2 * WIDGET_MARGIN; -constexpr int WIDGET_SPACING = 15; -constexpr int TEXT_SPACING = 4; -constexpr int DEVICE_SPACING = 5; - -DeviceItem::DeviceItem(DeviceInfo device, QWidget *parent) - : QWidget(parent) - , info_(std::move(device)) -{ - QFont font; - font.setBold(true); - - auto deviceIdLabel = new QLabel(info_.device_id, this); - deviceIdLabel->setFont(font); - - auto layout = new QVBoxLayout{this}; - layout->addWidget(deviceIdLabel); - - if (!info_.display_name.isEmpty()) - layout->addWidget(new QLabel(info_.display_name, this)); - - layout->setMargin(0); - layout->setSpacing(4); -} - -UserProfile::UserProfile(QWidget *parent) - : QWidget(parent) -{ - setAutoFillBackground(true); - setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); - setAttribute(Qt::WA_DeleteOnClose, true); - - QIcon banIcon, kickIcon, ignoreIcon, startChatIcon; - - banIcon.addFile(":/icons/icons/ui/do-not-disturb-rounded-sign.png"); - banBtn_ = new FlatButton(this); - banBtn_->setFixedSize(BUTTON_SIZE, BUTTON_SIZE); - banBtn_->setCornerRadius(BUTTON_RADIUS); - banBtn_->setIcon(banIcon); - banBtn_->setIconSize(QSize(BUTTON_RADIUS, BUTTON_RADIUS)); - banBtn_->setToolTip(tr("Ban the user from the room")); - - ignoreIcon.addFile(":/icons/icons/ui/volume-off-indicator.png"); - ignoreBtn_ = new FlatButton(this); - ignoreBtn_->setFixedSize(BUTTON_SIZE, BUTTON_SIZE); - ignoreBtn_->setCornerRadius(BUTTON_RADIUS); - ignoreBtn_->setIcon(ignoreIcon); - ignoreBtn_->setIconSize(QSize(BUTTON_RADIUS, BUTTON_RADIUS)); - ignoreBtn_->setToolTip(tr("Ignore messages from this user")); - ignoreBtn_->setDisabled(true); // Not used yet. - - kickIcon.addFile(":/icons/icons/ui/round-remove-button.png"); - kickBtn_ = new FlatButton(this); - kickBtn_->setFixedSize(BUTTON_SIZE, BUTTON_SIZE); - kickBtn_->setCornerRadius(BUTTON_RADIUS); - kickBtn_->setIcon(kickIcon); - kickBtn_->setIconSize(QSize(BUTTON_RADIUS, BUTTON_RADIUS)); - kickBtn_->setToolTip(tr("Kick the user from the room")); - - startChatIcon.addFile(":/icons/icons/ui/black-bubble-speech.png"); - startChat_ = new FlatButton(this); - startChat_->setFixedSize(BUTTON_SIZE, BUTTON_SIZE); - startChat_->setCornerRadius(BUTTON_RADIUS); - startChat_->setIcon(startChatIcon); - startChat_->setIconSize(QSize(BUTTON_RADIUS, BUTTON_RADIUS)); - startChat_->setToolTip(tr("Start a conversation")); - - connect(startChat_, &QPushButton::clicked, this, [this]() { - auto user_id = userIdLabel_->text(); - - mtx::requests::CreateRoom req; - req.preset = mtx::requests::Preset::PrivateChat; - req.visibility = mtx::requests::Visibility::Private; - - if (utils::localUser() != user_id) - req.invite = {user_id.toStdString()}; - - emit ChatPage::instance()->createRoom(req); - }); - - connect(banBtn_, &QPushButton::clicked, this, [this] { - ChatPage::instance()->banUser(userIdLabel_->text(), ""); - }); - connect(kickBtn_, &QPushButton::clicked, this, [this] { - ChatPage::instance()->kickUser(userIdLabel_->text(), ""); - }); - - // Button line - auto btnLayout = new QHBoxLayout; - btnLayout->addStretch(1); - btnLayout->addWidget(startChat_); - btnLayout->addWidget(ignoreBtn_); - - btnLayout->addWidget(kickBtn_); - btnLayout->addWidget(banBtn_); - btnLayout->addStretch(1); - btnLayout->setSpacing(8); - btnLayout->setMargin(0); - - avatar_ = new Avatar(this, 128); - avatar_->setLetter("X"); - - QFont font; - font.setPointSizeF(font.pointSizeF() * 2); - - userIdLabel_ = new QLabel(this); - displayNameLabel_ = new QLabel(this); - displayNameLabel_->setFont(font); - - auto textLayout = new QVBoxLayout; - textLayout->addWidget(displayNameLabel_); - textLayout->addWidget(userIdLabel_); - textLayout->setAlignment(displayNameLabel_, Qt::AlignCenter | Qt::AlignTop); - textLayout->setAlignment(userIdLabel_, Qt::AlignCenter | Qt::AlignTop); - textLayout->setSpacing(TEXT_SPACING); - textLayout->setMargin(0); - - devices_ = new QListWidget{this}; - devices_->setFrameStyle(QFrame::NoFrame); - devices_->setSelectionMode(QAbstractItemView::NoSelection); - devices_->setAttribute(Qt::WA_MacShowFocusRect, 0); - devices_->setSpacing(DEVICE_SPACING); - - QFont descriptionLabelFont; - descriptionLabelFont.setWeight(65); - - devicesLabel_ = new QLabel(tr("Devices").toUpper(), this); - devicesLabel_->setFont(descriptionLabelFont); - devicesLabel_->hide(); - devicesLabel_->setFixedSize(devicesLabel_->sizeHint()); - - auto okBtn = new QPushButton("OK", this); - - auto closeLayout = new QHBoxLayout(); - closeLayout->setSpacing(15); - closeLayout->addStretch(1); - closeLayout->addWidget(okBtn); - - auto vlayout = new QVBoxLayout{this}; - vlayout->addWidget(avatar_, 0, Qt::AlignCenter | Qt::AlignTop); - vlayout->addLayout(textLayout); - vlayout->addLayout(btnLayout); - vlayout->addWidget(devicesLabel_, 0, Qt::AlignLeft); - vlayout->addWidget(devices_, 1); - vlayout->addLayout(closeLayout); - - QFont largeFont; - largeFont.setPointSizeF(largeFont.pointSizeF() * 1.5); - - setMinimumWidth( - std::max(devices_->sizeHint().width() + 4 * WIDGET_MARGIN, conf::window::minModalWidth)); - setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); - - vlayout->setSpacing(WIDGET_SPACING); - vlayout->setContentsMargins(WIDGET_MARGIN, TOP_WIDGET_MARGIN, WIDGET_MARGIN, WIDGET_MARGIN); - - qRegisterMetaType<std::vector<DeviceInfo>>(); - - auto closeShortcut = new QShortcut(QKeySequence(QKeySequence::Cancel), this); - connect(closeShortcut, &QShortcut::activated, this, &UserProfile::close); - connect(okBtn, &QPushButton::clicked, this, &UserProfile::close); -} - -void -UserProfile::resetToDefaults() -{ - avatar_->setLetter("X"); - devices_->clear(); - - ignoreBtn_->show(); - devices_->hide(); - devicesLabel_->hide(); -} - -void -UserProfile::init(const QString &userId, const QString &roomId) -{ - resetToDefaults(); - - auto displayName = cache::displayName(roomId, userId); - - userIdLabel_->setText(userId); - displayNameLabel_->setText(displayName); - avatar_->setLetter(utils::firstChar(displayName)); - - avatar_->setImage(roomId, userId); - - auto localUser = utils::localUser(); - - try { - bool hasMemberRights = - cache::hasEnoughPowerLevel({mtx::events::EventType::RoomMember}, - roomId.toStdString(), - localUser.toStdString()); - if (!hasMemberRights) { - kickBtn_->hide(); - banBtn_->hide(); - } else { - kickBtn_->show(); - banBtn_->show(); - } - } catch (const lmdb::error &e) { - nhlog::db()->warn("lmdb error: {}", e.what()); - } - - if (localUser == userId) { - // TODO: click on display name & avatar to change. - kickBtn_->hide(); - banBtn_->hide(); - ignoreBtn_->hide(); - } - - mtx::requests::QueryKeys req; - req.device_keys[userId.toStdString()] = {}; - - // A proxy object is used to emit the signal instead of the original object - // which might be destroyed by the time the http call finishes. - auto proxy = std::make_shared<Proxy>(); - QObject::connect(proxy.get(), &Proxy::done, this, &UserProfile::updateDeviceList); - - http::client()->query_keys( - req, - [user_id = userId.toStdString(), proxy = std::move(proxy)]( - const mtx::responses::QueryKeys &res, mtx::http::RequestErr err) { - if (err) { - nhlog::net()->warn("failed to query device keys: {} {}", - err->matrix_error.error, - static_cast<int>(err->status_code)); - // TODO: Notify the UI. - return; - } - - if (res.device_keys.empty() || - (res.device_keys.find(user_id) == res.device_keys.end())) { - nhlog::net()->warn("no devices retrieved {}", user_id); - return; - } - - auto devices = res.device_keys.at(user_id); - - std::vector<DeviceInfo> deviceInfo; - for (const auto &d : devices) { - auto device = d.second; - - // TODO: Verify signatures and ignore those that don't pass. - deviceInfo.emplace_back(DeviceInfo{ - QString::fromStdString(d.first), - QString::fromStdString(device.unsigned_info.device_display_name)}); - } - - std::sort(deviceInfo.begin(), - deviceInfo.end(), - [](const DeviceInfo &a, const DeviceInfo &b) { - return a.device_id > b.device_id; - }); - - if (!deviceInfo.empty()) - emit proxy->done(QString::fromStdString(user_id), deviceInfo); - }); -} - -void -UserProfile::updateDeviceList(const QString &user_id, const std::vector<DeviceInfo> &devices) -{ - if (user_id != userIdLabel_->text()) - return; - - for (const auto &dev : devices) { - auto deviceItem = new DeviceItem(dev, this); - auto item = new QListWidgetItem; - - item->setSizeHint(deviceItem->minimumSizeHint()); - item->setFlags(Qt::NoItemFlags); - item->setTextAlignment(Qt::AlignCenter); - - devices_->insertItem(devices_->count() - 1, item); - devices_->setItemWidget(item, deviceItem); - } - - devicesLabel_->show(); - devices_->show(); - adjustSize(); -} diff --git a/src/dialogs/UserProfile.h b/src/dialogs/UserProfile.h deleted file mode 100644
index 81276d2a..00000000 --- a/src/dialogs/UserProfile.h +++ /dev/null
@@ -1,69 +0,0 @@ -#pragma once - -#include <QString> -#include <QWidget> - -class Avatar; -class FlatButton; -class QLabel; -class QListWidget; -class Toggle; - -struct DeviceInfo -{ - QString device_id; - QString display_name; -}; - -class Proxy : public QObject -{ - Q_OBJECT - -signals: - void done(const QString &user_id, const std::vector<DeviceInfo> &devices); -}; - -namespace dialogs { - -class DeviceItem : public QWidget -{ - Q_OBJECT - -public: - explicit DeviceItem(DeviceInfo device, QWidget *parent); - -private: - DeviceInfo info_; - - // Toggle *verifyToggle_; -}; - -class UserProfile : public QWidget -{ - Q_OBJECT -public: - explicit UserProfile(QWidget *parent = nullptr); - - void init(const QString &userId, const QString &roomId); - -private slots: - void updateDeviceList(const QString &user_id, const std::vector<DeviceInfo> &devices); - -private: - void resetToDefaults(); - - Avatar *avatar_; - - QLabel *userIdLabel_; - QLabel *displayNameLabel_; - - FlatButton *banBtn_; - FlatButton *kickBtn_; - FlatButton *ignoreBtn_; - FlatButton *startChat_; - - QLabel *devicesLabel_; - QListWidget *devices_; -}; - -} // dialogs diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index f41e7712..773a5a23 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp
@@ -654,9 +654,9 @@ TimelineModel::viewDecryptedRawMessage(QString id) const } void -TimelineModel::openUserProfile(QString userid) const +TimelineModel::openUserProfile(QString userid) { - MainWindow::instance()->openUserProfile(userid, room_id_); + emit openProfile(new UserProfile(room_id_, userid, this)); } void diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index f8a84f17..104a475c 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h
@@ -9,7 +9,12 @@ #include <mtxclient/http/errors.hpp> #include "CacheCryptoStructs.h" +<<<<<<< HEAD #include "EventStore.h" +======= +#include "ReactionsModel.h" +#include "ui/UserProfile.h" +>>>>>>> Refactor UserProfile namespace mtx::http { using RequestErr = const std::optional<mtx::http::ClientError> &; @@ -188,7 +193,7 @@ public: Q_INVOKABLE QString escapeEmoji(QString str) const; Q_INVOKABLE void viewRawMessage(QString id) const; Q_INVOKABLE void viewDecryptedRawMessage(QString id) const; - Q_INVOKABLE void openUserProfile(QString userid) const; + Q_INVOKABLE void openUserProfile(QString userid); Q_INVOKABLE void replyAction(QString id); Q_INVOKABLE void readReceiptsAction(QString id) const; Q_INVOKABLE void redactEvent(QString id); @@ -256,8 +261,7 @@ signals: void replyChanged(QString reply); void paginationInProgressChanged(const bool); - void newMessageToSend(mtx::events::collections::TimelineEvents event); - void addPendingMessageToStore(mtx::events::collections::TimelineEvents event); + void openProfile(UserProfile *profile); private: void sendEncryptedMessage(const std::string txn_id, nlohmann::json content); diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 0b732232..81c8d6d3 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp
@@ -16,10 +16,9 @@ #include "dialogs/ImageOverlay.h" #include "emoji/EmojiModel.h" #include "emoji/Provider.h" -#include "src/ui/UserProfile.h" -#include "src/ui/UserProfileModel.h" Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents) +Q_DECLARE_METATYPE(std::vector<DeviceInfo>) namespace msgs = mtx::events::msg; @@ -109,15 +108,28 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettin 0, "MtxEvent", "Can't instantiate enum!"); + qmlRegisterUncreatableMetaObject(verification::staticMetaObject, + "im.nheko", + 1, + 0, + "VerificationStatus", + "Can't instantiate enum!"); + qmlRegisterType<DelegateChoice>("im.nheko", 1, 0, "DelegateChoice"); qmlRegisterType<DelegateChooser>("im.nheko", 1, 0, "DelegateChooser"); qmlRegisterType<DeviceVerificationFlow>("im.nheko", 1, 0, "DeviceVerificationFlow"); - qmlRegisterType<UserProfileModel>("im.nheko", 1, 0, "UserProfileModel"); - qmlRegisterType<UserProfile>("im.nheko", 1, 0, "UserProfileList"); + qmlRegisterUncreatableType<UserProfile>( + "im.nheko", + 1, + 0, + "UserProfileModel", + "UserProfile needs to be instantiated on the C++ side"); qmlRegisterSingletonInstance("im.nheko", 1, 0, "TimelineManager", this); qmlRegisterSingletonInstance("im.nheko", 1, 0, "Settings", settings.data()); qRegisterMetaType<mtx::events::collections::TimelineEvents>(); + qRegisterMetaType<std::vector<DeviceInfo>>(); + qmlRegisterType<emoji::EmojiModel>("im.nheko.EmojiModel", 1, 0, "EmojiModel"); qmlRegisterType<emoji::EmojiProxyModel>("im.nheko.EmojiModel", 1, 0, "EmojiProxyModel"); qmlRegisterUncreatableType<QAbstractItemModel>( diff --git a/src/ui/UserProfile.cpp b/src/ui/UserProfile.cpp
index 8c6fb8e4..fde0044b 100644 --- a/src/ui/UserProfile.cpp +++ b/src/ui/UserProfile.cpp
@@ -5,47 +5,72 @@ #include "Utils.h" #include "mtx/responses/crypto.hpp" -#include <iostream> // only for debugging +UserProfile::UserProfile(QString roomid, QString userid, QObject *parent) + : QObject(parent) + , roomid_(roomid) + , userid_(userid) +{ + fetchDeviceList(this->userid_); +} -Q_DECLARE_METATYPE(UserProfile::Status) +QHash<int, QByteArray> +DeviceInfoModel::roleNames() const +{ + return { + {DeviceId, "deviceId"}, + {DeviceName, "deviceName"}, + {VerificationStatus, "verificationStatus"}, + }; +} -UserProfile::UserProfile(QObject *parent) - : QObject(parent) +QVariant +DeviceInfoModel::data(const QModelIndex &index, int role) const { - qRegisterMetaType<UserProfile::Status>(); - connect( - this, &UserProfile::updateDeviceList, this, [this]() { fetchDeviceList(this->userId); }); - connect( - this, - &UserProfile::appendDeviceList, - this, - [this](QString device_id, QString device_name, UserProfile::Status verification_status) { - this->deviceList.push_back( - DeviceInfo{device_id, device_name, verification_status}); - }); + if (!index.isValid() || index.row() >= (int)deviceList_.size() || index.row() < 0) + return {}; + + switch (role) { + case DeviceId: + return deviceList_[index.row()].device_id; + case DeviceName: + return deviceList_[index.row()].display_name; + case VerificationStatus: + return QVariant::fromValue(deviceList_[index.row()].verification_status); + default: + return {}; + } } -std::vector<DeviceInfo> -UserProfile::getDeviceList() +void +DeviceInfoModel::reset(const std::vector<DeviceInfo> &deviceList) { - return this->deviceList; + beginResetModel(); + this->deviceList_ = std::move(deviceList); + endResetModel(); +} + +DeviceInfoModel * +UserProfile::deviceList() +{ + return &this->deviceList_; } QString -UserProfile::getUserId() +UserProfile::userid() { - return this->userId; + return this->userid_; } -void -UserProfile::setUserId(const QString &user_id) +QString +UserProfile::displayName() { - if (this->userId != userId) - return; - else { - this->userId = user_id; - emit UserProfile::userIdChanged(); - } + return cache::displayName(roomid_, userid_); +} + +QString +UserProfile::avatarUrl() +{ + return cache::avatarUrl(roomid_, userid_); } void @@ -74,27 +99,27 @@ UserProfile::callback_fn(const mtx::responses::QueryKeys &res, auto device = d.second; // TODO: Verify signatures and ignore those that don't pass. - UserProfile::Status verified = UserProfile::Status::UNVERIFIED; + verification::Status verified = verification::Status::UNVERIFIED; if (cross_verified.has_value()) { if (std::find(cross_verified->begin(), cross_verified->end(), d.first) != cross_verified->end()) - verified = UserProfile::Status::VERIFIED; + verified = verification::Status::VERIFIED; } else if (device_verified.has_value()) { if (std::find(device_verified->device_verified.begin(), device_verified->device_verified.end(), d.first) != device_verified->device_verified.end()) - verified = UserProfile::Status::VERIFIED; + verified = verification::Status::VERIFIED; } else if (device_verified.has_value()) { if (std::find(device_verified->device_blocked.begin(), device_verified->device_blocked.end(), d.first) != device_verified->device_blocked.end()) - verified = UserProfile::Status::BLOCKED; + verified = verification::Status::BLOCKED; } - emit UserProfile::appendDeviceList( - QString::fromStdString(d.first), - QString::fromStdString(device.unsigned_info.device_display_name), - verified); + deviceInfo.push_back( + {QString::fromStdString(d.first), + QString::fromStdString(device.unsigned_info.device_display_name), + verified}); } // std::sort( @@ -102,8 +127,7 @@ UserProfile::callback_fn(const mtx::responses::QueryKeys &res, // return a.device_id > b.device_id; // }); - this->deviceList = std::move(deviceInfo); - emit UserProfile::deviceListUpdated(); + this->deviceList_.queueReset(std::move(deviceInfo)); } void @@ -130,7 +154,7 @@ UserProfile::fetchDeviceList(const QString &userID) void UserProfile::banUser() { - ChatPage::instance()->banUser(this->userId, ""); + ChatPage::instance()->banUser(this->userid_, ""); } // void ignoreUser(){ @@ -140,7 +164,7 @@ UserProfile::banUser() void UserProfile::kickUser() { - ChatPage::instance()->kickUser(this->userId, ""); + ChatPage::instance()->kickUser(this->userid_, ""); } void @@ -149,7 +173,7 @@ UserProfile::startChat() mtx::requests::CreateRoom req; req.preset = mtx::requests::Preset::PrivateChat; req.visibility = mtx::requests::Visibility::Private; - if (utils::localUser() != this->userId) - req.invite = {this->userId.toStdString()}; + if (utils::localUser() != this->userid_) + req.invite = {this->userid_.toStdString()}; emit ChatPage::instance()->createRoom(req); } diff --git a/src/ui/UserProfile.h b/src/ui/UserProfile.h
index 1725b961..38002fff 100644 --- a/src/ui/UserProfile.h +++ b/src/ui/UserProfile.h
@@ -1,34 +1,92 @@ #pragma once +#include <QAbstractListModel> #include <QObject> #include <QString> #include <QVector> #include "MatrixClient.h" -class DeviceInfo; +namespace verification { +Q_NAMESPACE -class UserProfile : public QObject +enum Status +{ + VERIFIED, + UNVERIFIED, + BLOCKED +}; +Q_ENUM_NS(Status) +} + +class DeviceInfo +{ +public: + DeviceInfo(const QString deviceID, + const QString displayName, + verification::Status verification_status_) + : device_id(deviceID) + , display_name(displayName) + , verification_status(verification_status_) + {} + DeviceInfo() + : verification_status(verification::UNVERIFIED) + {} + + QString device_id; + QString display_name; + + verification::Status verification_status; +}; + +class DeviceInfoModel : public QAbstractListModel { Q_OBJECT - Q_PROPERTY(QString userId READ getUserId WRITE setUserId NOTIFY userIdChanged) - Q_PROPERTY(std::vector<DeviceInfo> deviceList READ getDeviceList NOTIFY deviceListUpdated) public: - // constructor - explicit UserProfile(QObject *parent = 0); - // getters - std::vector<DeviceInfo> getDeviceList(); - QString getUserId(); - // setters - void setUserId(const QString &userId); - - enum Status + enum Roles { - VERIFIED, - UNVERIFIED, - BLOCKED + DeviceId, + DeviceName, + VerificationStatus, }; - Q_ENUM(Status) + + explicit DeviceInfoModel(QObject *parent = nullptr) + { + (void)parent; + connect(this, &DeviceInfoModel::queueReset, this, &DeviceInfoModel::reset); + }; + QHash<int, QByteArray> roleNames() const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const + { + (void)parent; + return (int)deviceList_.size(); + } + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + +signals: + void queueReset(const std::vector<DeviceInfo> &deviceList); +public slots: + void reset(const std::vector<DeviceInfo> &deviceList); + +private: + std::vector<DeviceInfo> deviceList_; +}; + +class UserProfile : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString displayName READ displayName CONSTANT) + Q_PROPERTY(QString userid READ userid CONSTANT) + Q_PROPERTY(QString avatarUrl READ avatarUrl CONSTANT) + Q_PROPERTY(DeviceInfoModel *deviceList READ deviceList CONSTANT) +public: + UserProfile(QString roomid, QString userid, QObject *parent = 0); + + DeviceInfoModel *deviceList(); + + QString userid(); + QString displayName(); + QString avatarUrl(); void fetchDeviceList(const QString &userID); Q_INVOKABLE void banUser(); @@ -36,37 +94,13 @@ public: Q_INVOKABLE void kickUser(); Q_INVOKABLE void startChat(); -signals: - void userIdChanged(); - void deviceListUpdated(); - void updateDeviceList(); - void appendDeviceList(const QString device_id, - const QString device_naem, - const UserProfile::Status verification_status); - private: - std::vector<DeviceInfo> deviceList; - QString userId; + QString roomid_, userid_; std::optional<std::string> cross_verified; + DeviceInfoModel deviceList_; void callback_fn(const mtx::responses::QueryKeys &res, mtx::http::RequestErr err, std::string user_id, std::optional<std::vector<std::string>> cross_verified); }; - -class DeviceInfo -{ -public: - DeviceInfo(const QString deviceID, - const QString displayName, - UserProfile::Status verification_status_) - : device_id(deviceID) - , display_name(displayName) - , verification_status(verification_status_) - {} - - QString device_id; - QString display_name; - UserProfile::Status verification_status; -}; \ No newline at end of file diff --git a/src/ui/UserProfileModel.cpp b/src/ui/UserProfileModel.cpp deleted file mode 100644
index 3fa8fe2d..00000000 --- a/src/ui/UserProfileModel.cpp +++ /dev/null
@@ -1,63 +0,0 @@ -#include "UserProfileModel.h" -#include <QModelIndex> - -UserProfileModel::UserProfileModel(QObject *parent) - : QAbstractListModel(parent) - , deviceList(nullptr) -{ - this->deviceList = new UserProfile(this); - - connect(this->deviceList, &UserProfile::userIdChanged, this, [this]() { - emit this->deviceList->updateDeviceList(); - }); - connect(this->deviceList, &UserProfile::deviceListUpdated, this, [this]() { - beginResetModel(); - this->beginInsertRows( - QModelIndex(), 0, this->deviceList->getDeviceList().size() - 1); - this->endInsertRows(); - endResetModel(); - }); -} - -int -UserProfileModel::rowCount(const QModelIndex &parent) const -{ - if (parent.isValid() || !this->deviceList) - return 0; - return this->deviceList->getDeviceList().size(); -} - -QVariant -UserProfileModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() && - static_cast<int>(this->deviceList->getDeviceList().size()) <= index.row()) - return QVariant(); - - const DeviceInfo device = this->deviceList->getDeviceList().at(index.row()); - switch (role) { - case DEVICEID: - return QVariant(device.device_id); - case DISPLAYNAME: - return QVariant(device.display_name); - case VERIFIED_STATUS: - return device.verification_status; - } - return QVariant(); -} - -QHash<int, QByteArray> -UserProfileModel::roleNames() const -{ - QHash<int, QByteArray> names; - names[DEVICEID] = "deviceID"; - names[DISPLAYNAME] = "displayName"; - names[VERIFIED_STATUS] = "verified_status"; - return names; -} - -UserProfile * -UserProfileModel::getList() const -{ - return (this->deviceList); -} diff --git a/src/ui/UserProfileModel.h b/src/ui/UserProfileModel.h deleted file mode 100644
index ba7a2525..00000000 --- a/src/ui/UserProfileModel.h +++ /dev/null
@@ -1,30 +0,0 @@ -#pragma once - -#include "UserProfile.h" -#include <QAbstractListModel> - -class UserProfile; // forward declaration of the class UserProfile - -class UserProfileModel : public QAbstractListModel -{ - Q_OBJECT - Q_PROPERTY(UserProfile *deviceList READ getList) - -public: - explicit UserProfileModel(QObject *parent = nullptr); - - enum - { - DEVICEID, - DISPLAYNAME, - VERIFIED_STATUS - }; - UserProfile *getList() const; - - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role) const override; - virtual QHash<int, QByteArray> roleNames() const override; - -private: - UserProfile *deviceList; -}; \ No newline at end of file