mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-27 21:48:48 +03:00
add user search to invite dialog
This commit is contained in:
parent
6529240be8
commit
b599f5c0c6
9 changed files with 365 additions and 67 deletions
|
@ -493,6 +493,8 @@ set(SRC_FILES
|
|||
src/SingleImagePackModel.h
|
||||
src/TrayIcon.cpp
|
||||
src/TrayIcon.h
|
||||
src/UserDirectoryModel.cpp
|
||||
src/UserDirectoryModel.h
|
||||
src/UserSettingsPage.cpp
|
||||
src/UserSettingsPage.h
|
||||
src/UsersModel.cpp
|
||||
|
@ -594,14 +596,14 @@ if(USE_BUNDLED_MTXCLIENT)
|
|||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
MatrixClient
|
||||
GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
|
||||
GIT_TAG d187c63a27710fa87a44ab44d43b7cfa2023132a
|
||||
GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
|
||||
GIT_TAG d187c63a27710fa87a44ab44d43b7cfa2023132a
|
||||
)
|
||||
set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "")
|
||||
set(BUILD_LIB_TESTS OFF CACHE INTERNAL "")
|
||||
FetchContent_MakeAvailable(MatrixClient)
|
||||
else()
|
||||
find_package(MatrixClient 0.8.1 REQUIRED)
|
||||
find_package(MatrixClient 0.8.3 REQUIRED)
|
||||
endif()
|
||||
|
||||
if (VOIP)
|
||||
|
|
|
@ -33,6 +33,10 @@ Pane {
|
|||
id: publicRooms
|
||||
}
|
||||
|
||||
UserDirectoryModel {
|
||||
id: userDirectory
|
||||
}
|
||||
|
||||
//Timer {
|
||||
// onTriggered: gc()
|
||||
// interval: 1000
|
||||
|
|
|
@ -15,17 +15,26 @@ ApplicationWindow {
|
|||
property string roomId
|
||||
property string plainRoomName
|
||||
property InviteesModel invitees
|
||||
property var friendsCompleter
|
||||
property var profile
|
||||
minimumWidth: 500
|
||||
|
||||
function addInvite() {
|
||||
if (inviteeEntry.isValidMxid) {
|
||||
invitees.addUser(inviteeEntry.text);
|
||||
inviteeEntry.clear();
|
||||
}
|
||||
Component.onCompleted: {
|
||||
friendsCompleter = TimelineManager.completerFor("user", "friends")
|
||||
}
|
||||
|
||||
function addInvite(mxid) {
|
||||
if (mxid.match("@.+?:.{3,}")) {
|
||||
invitees.addUser(mxid);
|
||||
if (mxid == inviteeEntry.text)
|
||||
inviteeEntry.clear();
|
||||
} else
|
||||
console.log("invalid mxid: " + mxid)
|
||||
}
|
||||
|
||||
function cleanUpAndClose() {
|
||||
if (inviteeEntry.isValidMxid)
|
||||
addInvite();
|
||||
addInvite(inviteeEntry.text);
|
||||
|
||||
invitees.accept();
|
||||
close();
|
||||
|
@ -72,7 +81,7 @@ ApplicationWindow {
|
|||
Layout.fillWidth: true
|
||||
onAccepted: {
|
||||
if (isValidMxid)
|
||||
addInvite();
|
||||
addInvite(text);
|
||||
|
||||
}
|
||||
Component.onCompleted: forceActiveFocus()
|
||||
|
@ -82,85 +91,198 @@ ApplicationWindow {
|
|||
cleanUpAndClose();
|
||||
|
||||
}
|
||||
onTextChanged: {
|
||||
searchTimer.restart()
|
||||
if(isValidMxid) {
|
||||
profile = TimelineManager.getGlobalUserProfile(text);
|
||||
} else
|
||||
profile = null;
|
||||
}
|
||||
Timer {
|
||||
id: searchTimer
|
||||
|
||||
interval: 350
|
||||
onTriggered: {
|
||||
userSearch.model.setSearchString(parent.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: qsTr("Add")
|
||||
enabled: inviteeEntry.isValidMxid
|
||||
onClicked: addInvite()
|
||||
CheckBox {
|
||||
id: searchOnServer
|
||||
text: qsTr("Search on Server")
|
||||
checked: false
|
||||
onClicked: userSearch.model.setSearchString(inviteeEntry.text)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: inviteesList
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
model: invitees
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: del
|
||||
|
||||
hoverEnabled: true
|
||||
width: ListView.view.width
|
||||
height: layout.implicitHeight + Nheko.paddingSmall * 2
|
||||
onClicked: TimelineManager.openGlobalUserProfile(model.mxid)
|
||||
RowLayout {
|
||||
ItemDelegate {
|
||||
visible: inviteeEntry.isValidMxid
|
||||
id: del3
|
||||
Layout.preferredWidth: inviteDialogRoot.width/2
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.preferredHeight: layout3.implicitHeight + Nheko.paddingSmall * 2
|
||||
onClicked: addInvite(inviteeEntry.text)
|
||||
background: Rectangle {
|
||||
color: del.hovered ? Nheko.colors.dark : inviteDialogRoot.color
|
||||
color: del3.hovered ? Nheko.colors.dark : inviteDialogRoot.color
|
||||
clip: true
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: layout
|
||||
|
||||
spacing: Nheko.paddingMedium
|
||||
GridLayout {
|
||||
id: layout3
|
||||
anchors.centerIn: parent
|
||||
width: del.width - Nheko.paddingSmall * 2
|
||||
width: del3.width - Nheko.paddingSmall * 2
|
||||
rows: 2
|
||||
columns: 2
|
||||
rowSpacing: Nheko.paddingSmall
|
||||
columnSpacing: Nheko.paddingMedium
|
||||
|
||||
Avatar {
|
||||
width: Nheko.avatarSize
|
||||
height: Nheko.avatarSize
|
||||
userid: model.mxid
|
||||
url: model.avatarUrl.replace("mxc://", "image://MxcImage/")
|
||||
displayName: model.displayName
|
||||
Layout.rowSpan: 2
|
||||
Layout.preferredWidth: Nheko.avatarSize
|
||||
Layout.preferredHeight: Nheko.avatarSize
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
userid: inviteeEntry.text
|
||||
url: profile? profile.avatarUrl.replace("mxc://", "image://MxcImage/") : ""
|
||||
displayName: profile? profile.displayName : ""
|
||||
enabled: false
|
||||
}
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: profile? profile.displayName : ""
|
||||
color: TimelineManager.userColor(inviteeEntry.text, Nheko.colors.window)
|
||||
font.pointSize: fontMetrics.font.pointSize
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: Nheko.paddingSmall
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop
|
||||
text: inviteeEntry.text
|
||||
color: Nheko.colors.buttonText
|
||||
font.pointSize: fontMetrics.font.pointSize * 0.9
|
||||
}
|
||||
}
|
||||
}
|
||||
ListView {
|
||||
visible: !inviteeEntry.isValidMxid
|
||||
id: userSearch
|
||||
model: searchOnServer.checked? userDirectory : friendsCompleter
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
delegate: ItemDelegate {
|
||||
id: del2
|
||||
width: ListView.view.width
|
||||
height: layout2.implicitHeight + Nheko.paddingSmall * 2
|
||||
onClicked: addInvite(model.userid)
|
||||
background: Rectangle {
|
||||
color: del2.hovered ? Nheko.colors.dark : inviteDialogRoot.color
|
||||
}
|
||||
GridLayout {
|
||||
id: layout2
|
||||
anchors.centerIn: parent
|
||||
width: del2.width - Nheko.paddingSmall * 2
|
||||
rows: 2
|
||||
columns: 2
|
||||
rowSpacing: Nheko.paddingSmall
|
||||
columnSpacing: Nheko.paddingMedium
|
||||
|
||||
Avatar {
|
||||
Layout.rowSpan: 2
|
||||
Layout.preferredWidth: Nheko.avatarSize
|
||||
Layout.preferredHeight: Nheko.avatarSize
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
userid: model.userid
|
||||
url: model.avatarUrl.replace("mxc://", "image://MxcImage/")
|
||||
displayName: model.displayName
|
||||
enabled: false
|
||||
}
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: model.displayName
|
||||
color: TimelineManager.userColor(model ? model.mxid : "", del.background.color)
|
||||
color: TimelineManager.userColor(model.userid, Nheko.colors.window)
|
||||
font.pointSize: fontMetrics.font.pointSize
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop
|
||||
text: model.userid
|
||||
color: Nheko.colors.buttonText
|
||||
font.pointSize: fontMetrics.font.pointSize * 0.9
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ListView {
|
||||
id: inviteesList
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
model: invitees
|
||||
clip: true
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: del
|
||||
|
||||
hoverEnabled: true
|
||||
width: ListView.view.width
|
||||
height: layout.implicitHeight + Nheko.paddingSmall * 2
|
||||
onClicked: TimelineManager.openGlobalUserProfile(model.mxid)
|
||||
background: Rectangle {
|
||||
color: del.hovered ? Nheko.colors.dark : inviteDialogRoot.color
|
||||
}
|
||||
GridLayout {
|
||||
id: layout
|
||||
anchors.centerIn: parent
|
||||
width: del.width - Nheko.paddingSmall * 2
|
||||
rows: 2
|
||||
columns: 3
|
||||
rowSpacing: Nheko.paddingSmall
|
||||
columnSpacing: Nheko.paddingMedium
|
||||
|
||||
Avatar {
|
||||
Layout.rowSpan: 2
|
||||
Layout.preferredWidth: Nheko.avatarSize
|
||||
Layout.preferredHeight: Nheko.avatarSize
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
userid: model.mxid
|
||||
url: model.avatarUrl.replace("mxc://", "image://MxcImage/")
|
||||
displayName: model.displayName
|
||||
enabled: false
|
||||
}
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: model.displayName
|
||||
color: TimelineManager.userColor(model.mxid, Nheko.colors.window)
|
||||
font.pointSize: fontMetrics.font.pointSize
|
||||
}
|
||||
|
||||
ImageButton {
|
||||
Layout.rowSpan: 2
|
||||
id: removeButton
|
||||
image: ":/icons/icons/ui/dismiss.svg"
|
||||
onClicked: invitees.removeUser(model.mxid)
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop
|
||||
text: model.mxid
|
||||
color: del.hovered ? Nheko.colors.brightText : Nheko.colors.buttonText
|
||||
color: Nheko.colors.buttonText
|
||||
font.pointSize: fontMetrics.font.pointSize * 0.9
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
CursorShape {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
ImageButton {
|
||||
image: ":/icons/icons/ui/dismiss.svg"
|
||||
onClicked: invitees.removeUser(model.mxid)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CursorShape {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "RoomsModel.h"
|
||||
#include "SingleImagePackModel.h"
|
||||
#include "TrayIcon.h"
|
||||
#include "UserDirectoryModel.h"
|
||||
#include "UserSettingsPage.h"
|
||||
#include "UsersModel.h"
|
||||
#include "Utils.h"
|
||||
|
@ -69,6 +70,7 @@ Q_DECLARE_METATYPE(std::vector<DeviceInfo>)
|
|||
Q_DECLARE_METATYPE(std::vector<mtx::responses::PublicRoomsChunk>)
|
||||
Q_DECLARE_METATYPE(mtx::responses::PublicRoom)
|
||||
Q_DECLARE_METATYPE(mtx::responses::Profile)
|
||||
Q_DECLARE_METATYPE(mtx::responses::User)
|
||||
|
||||
MainWindow *MainWindow::instance_ = nullptr;
|
||||
|
||||
|
@ -147,6 +149,7 @@ MainWindow::registerQmlTypes()
|
|||
qRegisterMetaType<mtx::events::msg::KeyVerificationRequest>();
|
||||
qRegisterMetaType<mtx::events::msg::KeyVerificationStart>();
|
||||
qRegisterMetaType<mtx::responses::PublicRoom>();
|
||||
qRegisterMetaType<mtx::responses::User>();
|
||||
qRegisterMetaType<mtx::responses::Profile>();
|
||||
qRegisterMetaType<CombinedImagePackModel *>();
|
||||
qRegisterMetaType<RoomSettingsAllowedRoomsModel *>();
|
||||
|
@ -154,7 +157,9 @@ MainWindow::registerQmlTypes()
|
|||
qRegisterMetaType<std::vector<DeviceInfo>>();
|
||||
|
||||
qRegisterMetaType<std::vector<mtx::responses::PublicRoomsChunk>>();
|
||||
qRegisterMetaType<std::vector<mtx::responses::User>>();
|
||||
|
||||
qRegisterMetaType<mtx::responses::User>();
|
||||
qmlRegisterUncreatableMetaObject(qml_mtx_events::staticMetaObject,
|
||||
"im.nheko",
|
||||
1,
|
||||
|
@ -184,6 +189,7 @@ MainWindow::registerQmlTypes()
|
|||
qmlRegisterType<MxcAnimatedImage>("im.nheko", 1, 0, "MxcAnimatedImage");
|
||||
qmlRegisterType<MxcMediaProxy>("im.nheko", 1, 0, "MxcMedia");
|
||||
qmlRegisterType<RoomDirectoryModel>("im.nheko", 1, 0, "RoomDirectoryModel");
|
||||
qmlRegisterType<UserDirectoryModel>("im.nheko", 1, 0, "UserDirectoryModel");
|
||||
qmlRegisterType<LoginPage>("im.nheko", 1, 0, "Login");
|
||||
qmlRegisterType<RegisterPage>("im.nheko", 1, 0, "Registration");
|
||||
qmlRegisterType<HiddenEvents>("im.nheko", 1, 0, "HiddenEvents");
|
||||
|
|
|
@ -57,7 +57,10 @@ public:
|
|||
void showChatPage();
|
||||
|
||||
#ifdef NHEKO_DBUS_SYS
|
||||
bool dbusAvailable() const { return dbusAvailable_; }
|
||||
bool dbusAvailable() const
|
||||
{
|
||||
return dbusAvailable_;
|
||||
}
|
||||
#endif
|
||||
|
||||
Q_INVOKABLE void addPerRoomWindow(const QString &room, QWindow *window);
|
||||
|
|
87
src/UserDirectoryModel.cpp
Normal file
87
src/UserDirectoryModel.cpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "UserDirectoryModel.h"
|
||||
|
||||
#include "Cache.h"
|
||||
#include "Logging.h"
|
||||
#include "MatrixClient.h"
|
||||
#include "mtx/responses/users.hpp"
|
||||
|
||||
UserDirectoryModel::UserDirectoryModel(QObject *parent)
|
||||
: QAbstractListModel{parent}
|
||||
{
|
||||
connect(this,
|
||||
&UserDirectoryModel::fetchedSearchResults,
|
||||
this,
|
||||
&UserDirectoryModel::displaySearchResults,
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray>
|
||||
UserDirectoryModel::roleNames() const
|
||||
{
|
||||
return {
|
||||
{Roles::DisplayName, "displayName"},
|
||||
{Roles::Mxid, "userid"},
|
||||
{Roles::AvatarUrl, "avatarUrl"},
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
UserDirectoryModel::setSearchString(const QString &f)
|
||||
{
|
||||
userSearchString_ = f.toStdString();
|
||||
nhlog::ui()->debug("Received user directory query: {}", userSearchString_);
|
||||
beginResetModel();
|
||||
results_.clear();
|
||||
endResetModel();
|
||||
searchingUsers_ = true;
|
||||
emit searchingUsersChanged();
|
||||
http::client()->search_user_directory(
|
||||
userSearchString_,
|
||||
[this](const mtx::responses::Users &res, mtx::http::RequestErr err) {
|
||||
searchingUsers_ = false;
|
||||
emit searchingUsersChanged();
|
||||
|
||||
if (err) {
|
||||
nhlog::net()->error("Failed to retrieve users from mtxclient - {} - {} - {}",
|
||||
mtx::errors::to_string(err->matrix_error.errcode),
|
||||
err->matrix_error.error,
|
||||
err->parse_error);
|
||||
} else {
|
||||
emit fetchedSearchResults(res.results);
|
||||
}
|
||||
},
|
||||
-1);
|
||||
}
|
||||
|
||||
QVariant
|
||||
UserDirectoryModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() >= (int)results_.size() || index.row() < 0)
|
||||
return {};
|
||||
switch (role) {
|
||||
case Roles::DisplayName:
|
||||
return QString::fromStdString(results_[index.row()].display_name);
|
||||
case Roles::Mxid:
|
||||
return QString::fromStdString(results_[index.row()].user_id);
|
||||
case Roles::AvatarUrl:
|
||||
return QString::fromStdString(results_[index.row()].avatar_url);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void
|
||||
UserDirectoryModel::displaySearchResults(std::vector<mtx::responses::User> results)
|
||||
{
|
||||
results_ = results;
|
||||
if (results_.empty()) {
|
||||
nhlog::net()->error("mtxclient helper thread yielded empty chunk!");
|
||||
return;
|
||||
}
|
||||
beginInsertRows(QModelIndex(), 0, static_cast<int>(results_.size()) - 1);
|
||||
endInsertRows();
|
||||
}
|
55
src/UserDirectoryModel.h
Normal file
55
src/UserDirectoryModel.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QString>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <mtx/responses/users.hpp>
|
||||
|
||||
class UserDirectoryModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool searchingUsers READ searchingUsers NOTIFY searchingUsersChanged)
|
||||
|
||||
public:
|
||||
explicit UserDirectoryModel(QObject *parent = nullptr);
|
||||
|
||||
enum Roles
|
||||
{
|
||||
DisplayName,
|
||||
Mxid,
|
||||
AvatarUrl,
|
||||
};
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
inline int rowCount(const QModelIndex &parent = QModelIndex()) const override
|
||||
{
|
||||
(void)parent;
|
||||
return static_cast<int>(results_.size());
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<mtx::responses::User> results_;
|
||||
std::string userSearchString_;
|
||||
bool searchingUsers_{false};
|
||||
|
||||
signals:
|
||||
void searchingUsersChanged();
|
||||
void fetchedSearchResults(std::vector<mtx::responses::User> results);
|
||||
|
||||
public slots:
|
||||
void setSearchString(const QString &f);
|
||||
bool searchingUsers() const { return searchingUsers_; }
|
||||
|
||||
private slots:
|
||||
void displaySearchResults(std::vector<mtx::responses::User> results);
|
||||
};
|
|
@ -8,6 +8,7 @@
|
|||
#include <QUrl>
|
||||
|
||||
#include "Cache.h"
|
||||
#include "Cache_p.h"
|
||||
#include "CompletionModelRoles.h"
|
||||
#include "UserSettingsPage.h"
|
||||
|
||||
|
@ -15,10 +16,29 @@ UsersModel::UsersModel(const std::string &roomId, QObject *parent)
|
|||
: QAbstractListModel(parent)
|
||||
, room_id(roomId)
|
||||
{
|
||||
roomMembers_ = cache::roomMembers(roomId);
|
||||
for (const auto &m : roomMembers_) {
|
||||
displayNames.push_back(QString::fromStdString(cache::displayName(room_id, m)));
|
||||
userids.push_back(QString::fromStdString(m));
|
||||
// obviously, "friends" isn't a room, but I felt this was the least invasive way
|
||||
if (roomId == "friends") {
|
||||
auto e = cache::client()->getAccountData(mtx::events::EventType::Direct);
|
||||
if (e) {
|
||||
if (auto event =
|
||||
std::get_if<mtx::events::AccountDataEvent<mtx::events::account_data::Direct>>(
|
||||
&e.value())) {
|
||||
for (const auto &[userId, roomIds] : event->content.user_to_rooms) {
|
||||
displayNames.push_back(
|
||||
QString::fromStdString(cache::displayName(roomIds[0], userId)));
|
||||
userids.push_back(QString::fromStdString(userId));
|
||||
avatarUrls.push_back(cache::avatarUrl(QString::fromStdString(roomIds[0]),
|
||||
QString::fromStdString(userId)));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const auto &m : cache::roomMembers(roomId)) {
|
||||
displayNames.push_back(QString::fromStdString(cache::displayName(room_id, m)));
|
||||
userids.push_back(QString::fromStdString(m));
|
||||
avatarUrls.push_back(
|
||||
cache::avatarUrl(QString::fromStdString(room_id), QString::fromStdString(m)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,8 +78,7 @@ UsersModel::data(const QModelIndex &index, int role) const
|
|||
case CompletionModel::SearchRole2:
|
||||
return userids[index.row()];
|
||||
case Roles::AvatarUrl:
|
||||
return cache::avatarUrl(QString::fromStdString(room_id),
|
||||
QString::fromStdString(roomMembers_[index.row()]));
|
||||
return avatarUrls[index.row()];
|
||||
case Roles::UserID:
|
||||
return userids[index.row()].toHtmlEscaped();
|
||||
}
|
||||
|
|
|
@ -22,13 +22,13 @@ public:
|
|||
int rowCount(const QModelIndex &parent = QModelIndex()) const override
|
||||
{
|
||||
(void)parent;
|
||||
return (int)roomMembers_.size();
|
||||
return (int)userids.size();
|
||||
}
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
private:
|
||||
std::string room_id;
|
||||
std::vector<std::string> roomMembers_;
|
||||
std::vector<QString> avatarUrls;
|
||||
std::vector<QString> displayNames;
|
||||
std::vector<QString> userids;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue