File indexing completed on 2024-12-08 07:33:47
0001 // SPDX-FileCopyrightText: 2018-2020 Black Hat <bhat@encom.eu.org> 0002 // SPDX-License-Identifier: GPL-3.0-only 0003 0004 #include "userlistmodel.h" 0005 0006 #include <QGuiApplication> 0007 0008 #include <Quotient/connection.h> 0009 #include <Quotient/events/roompowerlevelsevent.h> 0010 0011 #include "neochatroom.h" 0012 0013 using namespace Quotient; 0014 0015 UserListModel::UserListModel(QObject *parent) 0016 : QAbstractListModel(parent) 0017 , m_currentRoom(nullptr) 0018 { 0019 } 0020 0021 void UserListModel::setRoom(NeoChatRoom *room) 0022 { 0023 if (m_currentRoom == room) { 0024 return; 0025 } 0026 0027 if (m_currentRoom) { 0028 m_currentRoom->disconnect(this); 0029 } 0030 m_currentRoom = room; 0031 0032 if (m_currentRoom) { 0033 connect(m_currentRoom, &Room::userAdded, this, &UserListModel::userAdded); 0034 connect(m_currentRoom, &Room::userRemoved, this, &UserListModel::userRemoved); 0035 connect(m_currentRoom, &Room::memberAboutToRename, this, &UserListModel::userRemoved); 0036 connect(m_currentRoom, &Room::memberRenamed, this, &UserListModel::userAdded); 0037 connect(m_currentRoom, &Room::changed, this, &UserListModel::refreshAllUsers); 0038 } 0039 0040 refreshAllUsers(); 0041 Q_EMIT roomChanged(); 0042 } 0043 0044 NeoChatRoom *UserListModel::room() const 0045 { 0046 return m_currentRoom; 0047 } 0048 0049 Quotient::User *UserListModel::userAt(QModelIndex index) const 0050 { 0051 if (index.row() < 0 || index.row() >= m_users.size()) { 0052 return nullptr; 0053 } 0054 return m_users.at(index.row()); 0055 } 0056 0057 QVariant UserListModel::data(const QModelIndex &index, int role) const 0058 { 0059 if (!index.isValid()) { 0060 return QVariant(); 0061 } 0062 0063 if (index.row() >= m_users.count()) { 0064 qDebug() << "UserListModel, something's wrong: index.row() >= " 0065 "users.count()"; 0066 return {}; 0067 } 0068 auto user = m_users.at(index.row()); 0069 if (role == DisplayNameRole) { 0070 return user->displayname(m_currentRoom); 0071 } 0072 if (role == UserIdRole) { 0073 return user->id(); 0074 } 0075 if (role == AvatarRole) { 0076 return m_currentRoom->avatarForMember(user); 0077 } 0078 if (role == ObjectRole) { 0079 return QVariant::fromValue(user); 0080 } 0081 if (role == PowerLevelRole) { 0082 auto plEvent = m_currentRoom->currentState().get<RoomPowerLevelsEvent>(); 0083 if (!plEvent) { 0084 return 0; 0085 } 0086 return plEvent->powerLevelForUser(user->id()); 0087 } 0088 if (role == PowerLevelStringRole) { 0089 auto pl = m_currentRoom->currentState().get<RoomPowerLevelsEvent>(); 0090 // User might not in the room yet, in this case pl can be nullptr. 0091 // e.g. When invited but user not accepted or denied the invitation. 0092 if (!pl) { 0093 return QStringLiteral("Not Available"); 0094 } 0095 0096 auto userPl = pl->powerLevelForUser(user->id()); 0097 0098 switch (userPl) { 0099 case 0: 0100 return QStringLiteral("Member"); 0101 case 50: 0102 return QStringLiteral("Moderator"); 0103 case 100: 0104 return QStringLiteral("Admin"); 0105 default: 0106 return QStringLiteral("Custom"); 0107 } 0108 } 0109 0110 return {}; 0111 } 0112 0113 int UserListModel::rowCount(const QModelIndex &parent) const 0114 { 0115 if (parent.isValid()) { 0116 return 0; 0117 } 0118 return m_users.count(); 0119 } 0120 0121 bool UserListModel::event(QEvent *event) 0122 { 0123 if (event->type() == QEvent::ApplicationPaletteChange) { 0124 refreshAllUsers(); 0125 } 0126 return QObject::event(event); 0127 } 0128 0129 void UserListModel::userAdded(Quotient::User *user) 0130 { 0131 auto pos = findUserPos(user); 0132 beginInsertRows(QModelIndex(), pos, pos); 0133 m_users.insert(pos, user); 0134 endInsertRows(); 0135 connect(user, &User::defaultAvatarChanged, this, [this, user]() { 0136 refreshUser(user, {AvatarRole}); 0137 }); 0138 } 0139 0140 void UserListModel::userRemoved(Quotient::User *user) 0141 { 0142 auto pos = findUserPos(user); 0143 if (pos != m_users.size()) { 0144 beginRemoveRows(QModelIndex(), pos, pos); 0145 m_users.removeAt(pos); 0146 endRemoveRows(); 0147 user->disconnect(this); 0148 } else { 0149 qWarning() << "Trying to remove a room member not in the user list"; 0150 } 0151 } 0152 0153 void UserListModel::refreshUser(Quotient::User *user, const QList<int> &roles) 0154 { 0155 auto pos = findUserPos(user); 0156 if (pos != m_users.size()) { 0157 Q_EMIT dataChanged(index(pos), index(pos), roles); 0158 } else { 0159 qWarning() << "Trying to access a room member not in the user list"; 0160 } 0161 } 0162 0163 void UserListModel::refreshAllUsers() 0164 { 0165 beginResetModel(); 0166 for (User *user : std::as_const(m_users)) { 0167 user->disconnect(this); 0168 } 0169 m_users.clear(); 0170 0171 if (m_currentRoom != nullptr) { 0172 m_users = m_currentRoom->users(); 0173 std::sort(m_users.begin(), m_users.end(), m_currentRoom->memberSorter()); 0174 0175 for (User *user : std::as_const(m_users)) { 0176 connect(user, &User::defaultAvatarChanged, this, [this, user]() { 0177 refreshUser(user, {AvatarRole}); 0178 }); 0179 } 0180 connect(m_currentRoom->connection(), &Connection::loggedOut, this, [this]() { 0181 setRoom(nullptr); 0182 }); 0183 } 0184 endResetModel(); 0185 Q_EMIT usersRefreshed(); 0186 } 0187 0188 int UserListModel::findUserPos(Quotient::User *user) const 0189 { 0190 return findUserPos(m_currentRoom->safeMemberName(user->id())); 0191 } 0192 0193 int UserListModel::findUserPos(const QString &username) const 0194 { 0195 if (!m_currentRoom) { 0196 return 0; 0197 } 0198 return m_currentRoom->memberSorter().lowerBoundIndex(m_users, username); 0199 } 0200 0201 QHash<int, QByteArray> UserListModel::roleNames() const 0202 { 0203 QHash<int, QByteArray> roles; 0204 0205 roles[DisplayNameRole] = "name"; 0206 roles[UserIdRole] = "userId"; 0207 roles[AvatarRole] = "avatar"; 0208 roles[ObjectRole] = "user"; 0209 roles[PowerLevelRole] = "powerLevel"; 0210 roles[PowerLevelStringRole] = "powerLevelString"; 0211 0212 return roles; 0213 } 0214 0215 #include "moc_userlistmodel.cpp"