File indexing completed on 2024-10-06 07:36:31

0001 /*
0002    SPDX-FileCopyrightText: 2017-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "usersmodel.h"
0008 #include "ruqola_debug.h"
0009 #include "utils.h"
0010 #include <KLocalizedString>
0011 #include <QJsonObject>
0012 
0013 UsersModel::UsersModel(QObject *parent)
0014     : QAbstractListModel(parent)
0015 {
0016 }
0017 
0018 UsersModel::~UsersModel() = default;
0019 
0020 int UsersModel::rowCount(const QModelIndex &parent) const
0021 {
0022     Q_UNUSED(parent)
0023     return mUsers.size();
0024 }
0025 
0026 QVariant UsersModel::data(const QModelIndex &index, int role) const
0027 {
0028     if (index.row() < 0 || index.row() >= mUsers.count()) {
0029         return {};
0030     }
0031     const User &user = mUsers.at(index.row());
0032     switch (role) {
0033     case UserName:
0034         return user.name();
0035     case UserId:
0036         return user.userId();
0037     case UserStatus:
0038         return Utils::presenceStatusToString(user.status());
0039     case UserIcon:
0040         return user.iconFromStatus();
0041     case UserStatusText:
0042         return user.statusText();
0043     }
0044 
0045     return {};
0046 }
0047 
0048 bool UsersModel::userIsOffline(const QString &name) const
0049 {
0050     const int userCount = mUsers.count();
0051     for (int i = 0; i < userCount; ++i) {
0052         const auto &user = mUsers.at(i);
0053         if (user.userName() == name) {
0054             return user.status() == User::PresenceStatus::PresenceOffline;
0055         }
0056     }
0057     return true;
0058 }
0059 
0060 QString UsersModel::userStatusStr(const QString &name) const
0061 {
0062     const int userCount = mUsers.count();
0063     for (int i = 0; i < userCount; ++i) {
0064         const auto &user = mUsers.at(i);
0065         if (user.userName() == name) {
0066             return user.generateStatusStr();
0067         }
0068     }
0069 
0070     // qCWarning(RUQOLA_LOG) << "User for name " << name << " not defined yet";
0071     return i18n("Offline");
0072 }
0073 
0074 QString UsersModel::userStatusIconFileName(const QString &name) const
0075 {
0076     const int userCount = mUsers.count();
0077     for (int i = 0; i < userCount; ++i) {
0078         const auto &user = mUsers.at(i);
0079         if (user.userName() == name) {
0080             return user.iconFromStatus();
0081         }
0082     }
0083 
0084     // qCWarning(RUQOLA_LOG) << "User for name " << name << " not defined yet";
0085     return QStringLiteral("user-offline");
0086 }
0087 
0088 User::PresenceStatus UsersModel::status(const QString &userId) const
0089 {
0090     const int userCount = mUsers.count();
0091 
0092     for (int i = 0; i < userCount; ++i) {
0093         const auto &user = mUsers.at(i);
0094         if (user.userId() == userId) {
0095             return user.status();
0096         }
0097     }
0098     // Return offline as default;
0099     return User::PresenceStatus::PresenceOffline;
0100 }
0101 
0102 User UsersModel::fullUserInfo(const QString &userName) const
0103 {
0104     const int userCount = mUsers.count();
0105 
0106     for (int i = 0; i < userCount; ++i) {
0107         const User user = mUsers.at(i);
0108         if (user.userName() == userName) {
0109             return user;
0110         }
0111     }
0112     return {};
0113 }
0114 
0115 void UsersModel::removeUser(const QString &userId)
0116 {
0117     qCDebug(RUQOLA_LOG) << " User removed " << userId;
0118     const int userCount = mUsers.count();
0119     for (int i = 0; i < userCount; ++i) {
0120         if (mUsers.at(i).userId() == userId) {
0121             qCDebug(RUQOLA_LOG) << " User removed " << mUsers.at(i).name();
0122             // Send info as it's disconnected. But don't remove it from list
0123             User &user = mUsers[i];
0124             user.setStatus(User::PresenceStatus::PresenceOffline);
0125             const QModelIndex idx = createIndex(i, 0);
0126             Q_EMIT userStatusChanged(user);
0127             Q_EMIT dataChanged(idx, idx);
0128             break;
0129         }
0130     }
0131 }
0132 
0133 void UsersModel::addUser(const User &newuser)
0134 {
0135     // It can be duplicate as we don't remove user from list when user is disconnected. Otherwise it will not sync with
0136     // user for room list
0137     qCDebug(RUQOLA_LOG) << " User added " << newuser;
0138     const int userCount = mUsers.count();
0139     bool found = false;
0140     for (int i = 0; i < userCount; ++i) {
0141         if (mUsers.at(i).userId() == newuser.userId()) {
0142             found = true;
0143             User &user = mUsers[i];
0144             user.setStatus(newuser.status());
0145             const QModelIndex idx = createIndex(i, 0);
0146             Q_EMIT userStatusChanged(user);
0147             Q_EMIT dataChanged(idx, idx);
0148             break;
0149         }
0150     }
0151     if (!found) {
0152         const int pos = mUsers.size();
0153         beginInsertRows(QModelIndex(), pos, pos);
0154         mUsers.append(newuser);
0155         endInsertRows();
0156     }
0157 }
0158 
0159 void UsersModel::updateUser(const QJsonObject &array)
0160 {
0161     const QString id = array.value(QLatin1String("id")).toString();
0162     const int userCount = mUsers.count();
0163     for (int i = 0; i < userCount; ++i) {
0164         if (mUsers.at(i).userId() == id) {
0165             User &user = mUsers[i];
0166             const QJsonObject fields = array.value(QLatin1String("fields")).toObject();
0167 
0168             const QString newStatus = fields.value(QLatin1String("status")).toString();
0169             bool userDataChanged = false;
0170             if (!newStatus.isEmpty()) {
0171                 user.setStatus(Utils::presenceStatusFromString(newStatus));
0172                 const QModelIndex idx = createIndex(i, 0);
0173                 Q_EMIT dataChanged(idx, idx);
0174                 Q_EMIT userStatusChanged(user);
0175                 userDataChanged = true;
0176             }
0177             const QString newName = fields.value(QLatin1String("name")).toString();
0178             if (!newName.isEmpty()) {
0179                 user.setName(newName);
0180                 const QModelIndex idx = createIndex(i, 0);
0181                 Q_EMIT dataChanged(idx, idx);
0182                 Q_EMIT userNameChanged(user);
0183                 userDataChanged = true;
0184             }
0185             const QString newuserName = fields.value(QLatin1String("username")).toString();
0186             if (!newuserName.isEmpty()) {
0187                 user.setUserName(newuserName);
0188                 const QModelIndex idx = createIndex(i, 0);
0189                 Q_EMIT dataChanged(idx, idx);
0190                 Q_EMIT nameChanged(user);
0191                 userDataChanged = true;
0192             }
0193             const QString statusMessage = fields.value(QLatin1String("statusText")).toString();
0194             if (!statusMessage.isEmpty()) {
0195                 user.setStatusText(statusMessage);
0196                 const QModelIndex idx = createIndex(i, 0);
0197                 Q_EMIT dataChanged(idx, idx);
0198                 Q_EMIT statusMessageChanged(user);
0199                 userDataChanged = true;
0200             }
0201             if (!userDataChanged) {
0202                 qCWarning(RUQOLA_LOG) << " Unsupported yet user data modification " << array;
0203             }
0204             break;
0205         }
0206     }
0207 }
0208 
0209 #include "moc_usersmodel.cpp"