summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorLoren Burkholder <55629213+LorenDB@users.noreply.github.com>2022-04-22 19:59:40 -0400
committerGitHub <noreply@github.com>2022-04-22 23:59:40 +0000
commit6672e765d7a1f51381521538d6c53abb6303f079 (patch)
treec09936eae0bdb118c5d6069e98bfcb46a44f9559 /src
parentMerge pull request #1054 from tastytea/image-pack-changes/pack-id (diff)
downloadnheko-6672e765d7a1f51381521538d6c53abb6303f079.tar.xz
Search room members (#1049)
Diffstat (limited to 'src')
-rw-r--r--src/MemberList.cpp69
-rw-r--r--src/MemberList.h61
2 files changed, 121 insertions, 9 deletions
diff --git a/src/MemberList.cpp b/src/MemberList.cpp
index fb4ae76b..f5154da4 100644
--- a/src/MemberList.cpp
+++ b/src/MemberList.cpp
@@ -6,15 +6,20 @@
 #include "MemberList.h"
 
 #include "Cache.h"
+#include "Cache_p.h"
 #include "ChatPage.h"
 #include "Config.h"
 #include "Logging.h"
 #include "Utils.h"
 #include "timeline/TimelineViewManager.h"
 
-MemberList::MemberList(const QString &room_id, QObject *parent)
+MemberListBackend::MemberListBackend(const QString &room_id, QObject *parent)
   : QAbstractListModel{parent}
   , room_id_{room_id}
+  , powerLevels_{cache::client()
+                   ->getStateEvent<mtx::events::state::PowerLevels>(room_id_.toStdString())
+                   .value_or(mtx::events::StateEvent<mtx::events::state::PowerLevels>{})
+                   .content}
 {
     try {
         info_ = cache::singleRoomInfo(room_id_.toStdString());
@@ -23,7 +28,8 @@ MemberList::MemberList(const QString &room_id, QObject *parent)
     }
 
     try {
-        auto members = cache::getMembers(room_id_.toStdString());
+        // HACK: due to QTBUG-1020169, we'll load a big chunk to speed things up
+        auto members = cache::getMembers(room_id_.toStdString(), 0, -1);
         addUsers(members);
         numUsersLoaded_ = members.size();
     } catch (const lmdb::error &e) {
@@ -32,7 +38,7 @@ MemberList::MemberList(const QString &room_id, QObject *parent)
 }
 
 void
-MemberList::addUsers(const std::vector<RoomMember> &members)
+MemberListBackend::addUsers(const std::vector<RoomMember> &members)
 {
     beginInsertRows(QModelIndex{}, m_memberList.count(), m_memberList.count() + members.size() - 1);
 
@@ -46,7 +52,7 @@ MemberList::addUsers(const std::vector<RoomMember> &members)
 }
 
 QHash<int, QByteArray>
-MemberList::roleNames() const
+MemberListBackend::roleNames() const
 {
     return {
       {Mxid, "mxid"},
@@ -57,7 +63,7 @@ MemberList::roleNames() const
 }
 
 QVariant
-MemberList::data(const QModelIndex &index, int role) const
+MemberListBackend::data(const QModelIndex &index, int role) const
 {
     if (!index.isValid() || index.row() >= (int)m_memberList.size() || index.row() < 0)
         return {};
@@ -80,13 +86,16 @@ MemberList::data(const QModelIndex &index, int role) const
         else
             return stat->user_verified;
     }
+    case Powerlevel:
+        return static_cast<qlonglong>(
+          powerLevels_.user_level(m_memberList[index.row()].first.user_id.toStdString()));
     default:
         return {};
     }
 }
 
 bool
-MemberList::canFetchMore(const QModelIndex &) const
+MemberListBackend::canFetchMore(const QModelIndex &) const
 {
     const size_t numMembers = rowCount();
     if (numMembers > 1 && numMembers < info_.member_count)
@@ -96,7 +105,7 @@ MemberList::canFetchMore(const QModelIndex &) const
 }
 
 void
-MemberList::fetchMore(const QModelIndex &)
+MemberListBackend::fetchMore(const QModelIndex &)
 {
     loadingMoreMembers_ = true;
     emit loadingMoreMembersChanged();
@@ -109,3 +118,49 @@ MemberList::fetchMore(const QModelIndex &)
     loadingMoreMembers_ = false;
     emit loadingMoreMembersChanged();
 }
+
+MemberList::MemberList(const QString &room_id, QObject *parent)
+  : QSortFilterProxyModel{parent}
+  , m_model{room_id, this}
+{
+    connect(&m_model, &MemberListBackend::roomNameChanged, this, &MemberList::roomNameChanged);
+    connect(
+      &m_model, &MemberListBackend::memberCountChanged, this, &MemberList::memberCountChanged);
+    connect(&m_model, &MemberListBackend::avatarUrlChanged, this, &MemberList::avatarUrlChanged);
+    connect(&m_model, &MemberListBackend::roomIdChanged, this, &MemberList::roomIdChanged);
+    connect(&m_model,
+            &MemberListBackend::numUsersLoadedChanged,
+            this,
+            &MemberList::numUsersLoadedChanged);
+    connect(&m_model,
+            &MemberListBackend::loadingMoreMembersChanged,
+            this,
+            &MemberList::loadingMoreMembersChanged);
+
+    setSourceModel(&m_model);
+    setSortRole(MemberSortRoles::Mxid);
+    sort(0, Qt::AscendingOrder);
+    setDynamicSortFilter(true);
+    setFilterCaseSensitivity(Qt::CaseInsensitive);
+}
+
+void
+MemberList::setFilterString(const QString &text)
+{
+    setFilterRegExp(QRegExp::escape(text));
+}
+
+void
+MemberList::sortBy(const MemberSortRoles role)
+{
+    setSortRole(role);
+    // Unfortunately, Qt doesn't provide a "setSortOrder" function.
+    sort(0, role == MemberSortRoles::Powerlevel ? Qt::DescendingOrder : Qt::AscendingOrder);
+}
+
+bool
+MemberList::filterAcceptsRow(int source_row, const QModelIndex &) const
+{
+    return m_model.m_memberList[source_row].first.user_id.contains(filterRegExp()) ||
+           m_model.m_memberList[source_row].first.display_name.contains(filterRegExp());
+}
diff --git a/src/MemberList.h b/src/MemberList.h
index be345d41..2f90e5e8 100644
--- a/src/MemberList.h
+++ b/src/MemberList.h
@@ -6,10 +6,13 @@
 #pragma once
 
 #include <QAbstractListModel>
+#include <QSortFilterProxyModel>
+
+#include <mtx/events/power_levels.hpp>
 
 #include "CacheStructs.h"
 
-class MemberList : public QAbstractListModel
+class MemberListBackend : public QAbstractListModel
 {
     Q_OBJECT
 
@@ -27,8 +30,10 @@ public:
         DisplayName,
         AvatarUrl,
         Trustlevel,
+        Powerlevel,
     };
-    MemberList(const QString &room_id, QObject *parent = nullptr);
+
+    MemberListBackend(const QString &room_id, QObject *parent = nullptr);
 
     QHash<int, QByteArray> roleNames() const override;
     int rowCount(const QModelIndex &parent = QModelIndex()) const override
@@ -66,4 +71,56 @@ private:
     RoomInfo info_;
     int numUsersLoaded_{0};
     bool loadingMoreMembers_{false};
+
+    mtx::events::state::PowerLevels powerLevels_;
+
+    friend class MemberList;
+};
+
+class MemberList : public QSortFilterProxyModel
+{
+    Q_OBJECT
+
+    Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
+    Q_PROPERTY(int memberCount READ memberCount NOTIFY memberCountChanged)
+    Q_PROPERTY(QString avatarUrl READ avatarUrl NOTIFY avatarUrlChanged)
+    Q_PROPERTY(QString roomId READ roomId NOTIFY roomIdChanged)
+    Q_PROPERTY(int numUsersLoaded READ numUsersLoaded NOTIFY numUsersLoadedChanged)
+    Q_PROPERTY(bool loadingMoreMembers READ loadingMoreMembers NOTIFY loadingMoreMembersChanged)
+
+public:
+    enum MemberSortRoles
+    {
+        Mxid        = MemberListBackend::Roles::Mxid,
+        DisplayName = MemberListBackend::Roles::DisplayName,
+        Powerlevel  = MemberListBackend::Roles::Powerlevel,
+    };
+    Q_ENUM(MemberSortRoles)
+
+    MemberList(const QString &room_id, QObject *parent = nullptr);
+
+    QString roomName() const { return m_model.roomName(); }
+    int memberCount() const { return m_model.memberCount(); }
+    QString avatarUrl() const { return m_model.avatarUrl(); }
+    QString roomId() const { return m_model.roomId(); }
+    int numUsersLoaded() const { return m_model.numUsersLoaded(); }
+    bool loadingMoreMembers() const { return m_model.loadingMoreMembers(); }
+
+signals:
+    void roomNameChanged();
+    void memberCountChanged();
+    void avatarUrlChanged();
+    void roomIdChanged();
+    void numUsersLoadedChanged();
+    void loadingMoreMembersChanged();
+
+public slots:
+    void setFilterString(const QString &text);
+    void sortBy(const MemberSortRoles role);
+
+protected:
+    bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
+
+private:
+    MemberListBackend m_model;
 };