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