File indexing completed on 2024-05-12 05:02:09

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 "usersforroommodel.h"
0008 #include "ruqola_debug.h"
0009 #include "usersmodel.h"
0010 #include "utils.h"
0011 
0012 #include <QIcon>
0013 #include <QJsonArray>
0014 #include <QJsonObject>
0015 
0016 UsersForRoomModel::UsersForRoomModel(QObject *parent)
0017     : QAbstractListModel(parent)
0018 {
0019 }
0020 
0021 UsersForRoomModel::~UsersForRoomModel() = default;
0022 
0023 void UsersForRoomModel::setUsers(const QVector<User> &users)
0024 {
0025     if (mUsers.isEmpty()) {
0026         if (!users.isEmpty()) {
0027             beginInsertRows(QModelIndex(), 0, users.count() - 1);
0028             mUsers = users;
0029             endInsertRows();
0030         }
0031     } else {
0032         const int numberOfElement = mUsers.count();
0033         mUsers << users;
0034         beginInsertRows(QModelIndex(), numberOfElement, mUsers.count() - 1);
0035         endInsertRows();
0036     }
0037     checkFullList();
0038 }
0039 
0040 void UsersForRoomModel::clear()
0041 {
0042     if (!mUsers.isEmpty()) {
0043         beginResetModel();
0044         mUsers.clear();
0045         endResetModel();
0046     }
0047 }
0048 
0049 int UsersForRoomModel::rowCount(const QModelIndex &parent) const
0050 {
0051     Q_UNUSED(parent)
0052     return mUsers.count();
0053 }
0054 
0055 QVariant UsersForRoomModel::data(const QModelIndex &index, int role) const
0056 {
0057     if (index.row() < 0 || index.row() >= mUsers.count()) {
0058         return {};
0059     }
0060 
0061     const User &user = mUsers.at(index.row());
0062     switch (role) {
0063     case DisplayName:
0064         return generateDisplayName(user);
0065     case Qt::DisplayRole:
0066     case UserName:
0067         return user.userName();
0068     case IconStatus:
0069         return user.iconFromStatus();
0070     case UserId:
0071         return user.userId();
0072     case Name:
0073         return user.name();
0074     case Status:
0075         return Utils::presenceStatusToString(user.status()); // Translate it ?
0076     case Qt::DecorationRole:
0077         return QIcon::fromTheme(user.iconFromStatus());
0078     }
0079 
0080     return {};
0081 }
0082 
0083 QString UsersForRoomModel::generateDisplayName(const User &user) const
0084 {
0085     const QString displayName = QStringLiteral("<a href=\'%1\'>%1</a>").arg(user.userName().isEmpty() ? user.name() : user.userName());
0086     return displayName;
0087 }
0088 
0089 void UsersForRoomModel::checkFullList()
0090 {
0091     setHasFullList(mUsers.count() == mTotal);
0092 }
0093 
0094 bool UsersForRoomModel::hasFullList() const
0095 {
0096     return mHasFullList;
0097 }
0098 
0099 void UsersForRoomModel::setHasFullList(bool hasFullList)
0100 {
0101     if (mHasFullList != hasFullList) {
0102         mHasFullList = hasFullList;
0103         Q_EMIT hasFullListChanged();
0104     }
0105 }
0106 
0107 int UsersForRoomModel::usersCount() const
0108 {
0109     return mUsers.count();
0110 }
0111 
0112 int UsersForRoomModel::offset() const
0113 {
0114     return mOffset;
0115 }
0116 
0117 void UsersForRoomModel::setOffset(int offset)
0118 {
0119     mOffset = offset;
0120 }
0121 
0122 int UsersForRoomModel::total() const
0123 {
0124     return mTotal;
0125 }
0126 
0127 void UsersForRoomModel::setTotal(int total)
0128 {
0129     mTotal = total;
0130 }
0131 
0132 void UsersForRoomModel::parseUsersForRooms(const QJsonObject &root, UsersModel *model, bool restapi)
0133 {
0134     if (restapi) {
0135         mTotal = root[QLatin1String("total")].toInt();
0136         mOffset = root[QLatin1String("offset")].toInt();
0137         const QJsonArray members = root[QLatin1String("members")].toArray();
0138         QVector<User> users;
0139         users.reserve(members.count());
0140         for (const QJsonValue &current : members) {
0141             if (current.type() == QJsonValue::Object) {
0142                 const QJsonObject userObject = current.toObject();
0143                 const QString userName = userObject[QLatin1String("username")].toString();
0144                 const QString name = userObject[QLatin1String("name")].toString();
0145                 const QString id = userObject[QLatin1String("_id")].toString();
0146                 const double utcOffset = userObject[QLatin1String("utcOffset")].toDouble();
0147                 const QString status = userObject[QLatin1String("status")].toString();
0148                 User user;
0149                 user.setName(name);
0150                 user.setUserName(userName);
0151                 user.setUserId(id);
0152                 user.setUtcOffset(utcOffset);
0153                 user.setStatus(Utils::presenceStatusFromString(status));
0154                 if (user.isValid()) {
0155                     users.append(std::move(user));
0156                 } else {
0157                     qCWarning(RUQOLA_LOG) << "Invalid user" << user;
0158                     mTotal--;
0159                 }
0160             } else {
0161                 qCWarning(RUQOLA_LOG) << "Parse records: Error in users for rooms json" << root;
0162             }
0163         }
0164         setUsers(users);
0165     } else {
0166         const QJsonObject result = root[QLatin1String("result")].toObject();
0167         if (!result.isEmpty()) {
0168             const QJsonArray records = result[QLatin1String("records")].toArray();
0169             mTotal = result[QLatin1String("total")].toInt();
0170             mOffset = root[QLatin1String("offset")].toInt(); // TODO verify if a day we use no rest api
0171 
0172             QVector<User> users;
0173             users.reserve(records.count());
0174             for (const QJsonValue &current : records) {
0175                 if (current.type() == QJsonValue::Object) {
0176                     const QJsonObject userObject = current.toObject();
0177                     const QString userName = userObject[QLatin1String("username")].toString();
0178                     const QString name = userObject[QLatin1String("name")].toString();
0179                     const QString id = userObject[QLatin1String("_id")].toString();
0180                     User user;
0181                     user.setName(name);
0182                     user.setUserName(userName);
0183                     user.setUserId(id);
0184                     if (model) {
0185                         user.setStatus(model->status(id));
0186                     }
0187                     // Add status!
0188                     if (user.isValid()) {
0189                         users.append(std::move(user));
0190                     } else {
0191                         qCWarning(RUQOLA_LOG) << "Invalid user" << user;
0192                         mTotal--;
0193                     }
0194                 } else {
0195                     qCWarning(RUQOLA_LOG) << "Parse records: Error in users for rooms json" << root;
0196                 }
0197             }
0198             setUsers(users);
0199         } else {
0200             qCWarning(RUQOLA_LOG) << "Error in users for rooms json" << root;
0201         }
0202     }
0203 }
0204 
0205 void UsersForRoomModel::setUserStatusChanged(const User &newuser)
0206 {
0207     const int roomCount = mUsers.count();
0208     for (int i = 0; i < roomCount; ++i) {
0209         User &user = mUsers[i];
0210         if (newuser.userId() == user.userId()) {
0211             user.setStatus(newuser.status());
0212             const QModelIndex idx = createIndex(i, 0);
0213             Q_EMIT dataChanged(idx, idx);
0214             Q_EMIT userStatusChanged(user.userId());
0215             break;
0216         }
0217     }
0218 }
0219 
0220 void UsersForRoomModel::setLoadMoreUsersInProgress(bool inProgress)
0221 {
0222     if (mLoadingInProgress != inProgress) {
0223         mLoadingInProgress = inProgress;
0224         Q_EMIT loadingInProgressChanged();
0225     }
0226 }
0227 
0228 bool UsersForRoomModel::loadMoreUsersInProgress() const
0229 {
0230     return mLoadingInProgress;
0231 }
0232 
0233 #include "moc_usersforroommodel.cpp"