File indexing completed on 2024-12-08 07:33:45

0001 // SPDX-FileCopyrightText: 2019-2020 Black Hat <bhat@encom.eu.org>
0002 // SPDX-License-Identifier: GPL-3.0-only
0003 
0004 #include "publicroomlistmodel.h"
0005 
0006 #include <Quotient/connection.h>
0007 
0008 using namespace Quotient;
0009 
0010 PublicRoomListModel::PublicRoomListModel(QObject *parent)
0011     : QAbstractListModel(parent)
0012 {
0013 }
0014 
0015 Quotient::Connection *PublicRoomListModel::connection() const
0016 {
0017     return m_connection;
0018 }
0019 
0020 void PublicRoomListModel::setConnection(Connection *conn)
0021 {
0022     if (m_connection == conn) {
0023         return;
0024     }
0025 
0026     beginResetModel();
0027 
0028     nextBatch = QString();
0029     attempted = false;
0030     rooms.clear();
0031     m_server.clear();
0032 
0033     if (m_connection) {
0034         m_connection->disconnect(this);
0035     }
0036 
0037     endResetModel();
0038 
0039     m_connection = conn;
0040 
0041     if (job) {
0042         job->abandon();
0043         job = nullptr;
0044         Q_EMIT loadingChanged();
0045     }
0046 
0047     if (m_connection) {
0048         next();
0049     }
0050 
0051     Q_EMIT connectionChanged();
0052     Q_EMIT serverChanged();
0053     Q_EMIT hasMoreChanged();
0054 }
0055 
0056 QString PublicRoomListModel::server() const
0057 {
0058     return m_server;
0059 }
0060 
0061 void PublicRoomListModel::setServer(const QString &value)
0062 {
0063     if (m_server == value) {
0064         return;
0065     }
0066 
0067     m_server = value;
0068 
0069     beginResetModel();
0070 
0071     nextBatch = QString();
0072     attempted = false;
0073     rooms.clear();
0074     Q_EMIT loadingChanged();
0075 
0076     endResetModel();
0077 
0078     if (job) {
0079         job->abandon();
0080         job = nullptr;
0081         Q_EMIT loadingChanged();
0082     }
0083 
0084     if (m_connection) {
0085         next();
0086     }
0087 
0088     Q_EMIT serverChanged();
0089     Q_EMIT hasMoreChanged();
0090 }
0091 
0092 QString PublicRoomListModel::keyword() const
0093 {
0094     return m_keyword;
0095 }
0096 
0097 void PublicRoomListModel::setKeyword(const QString &value)
0098 {
0099     if (m_keyword == value) {
0100         return;
0101     }
0102 
0103     m_keyword = value;
0104 
0105     beginResetModel();
0106 
0107     nextBatch = QString();
0108     attempted = false;
0109     rooms.clear();
0110 
0111     endResetModel();
0112 
0113     if (job) {
0114         job->abandon();
0115         job = nullptr;
0116         Q_EMIT loadingChanged();
0117     }
0118 
0119     if (m_connection) {
0120         next();
0121     }
0122 
0123     Q_EMIT keywordChanged();
0124     Q_EMIT hasMoreChanged();
0125 }
0126 
0127 bool PublicRoomListModel::showOnlySpaces() const
0128 {
0129     return m_showOnlySpaces;
0130 }
0131 
0132 void PublicRoomListModel::setShowOnlySpaces(bool showOnlySpaces)
0133 {
0134     if (showOnlySpaces == m_showOnlySpaces) {
0135         return;
0136     }
0137     m_showOnlySpaces = showOnlySpaces;
0138     Q_EMIT showOnlySpacesChanged();
0139 }
0140 
0141 void PublicRoomListModel::next(int count)
0142 {
0143     if (count < 1) {
0144         return;
0145     }
0146 
0147     if (job) {
0148         qDebug() << "PublicRoomListModel: Other jobs running, ignore";
0149 
0150         return;
0151     }
0152 
0153     QStringList roomTypes;
0154     if (m_showOnlySpaces) {
0155         roomTypes += QLatin1String("m.space");
0156     }
0157     job = m_connection->callApi<QueryPublicRoomsJob>(m_server, count, nextBatch, QueryPublicRoomsJob::Filter{m_keyword, roomTypes});
0158     Q_EMIT loadingChanged();
0159 
0160     connect(job, &BaseJob::finished, this, [this] {
0161         attempted = true;
0162 
0163         if (job->status() == BaseJob::Success) {
0164             nextBatch = job->nextBatch();
0165 
0166             this->beginInsertRows({}, rooms.count(), rooms.count() + job->chunk().count() - 1);
0167             rooms.append(job->chunk());
0168             this->endInsertRows();
0169 
0170             if (job->nextBatch().isEmpty()) {
0171                 Q_EMIT hasMoreChanged();
0172             }
0173         }
0174 
0175         this->job = nullptr;
0176         Q_EMIT loadingChanged();
0177     });
0178 }
0179 
0180 QVariant PublicRoomListModel::data(const QModelIndex &index, int role) const
0181 {
0182     if (!index.isValid()) {
0183         return QVariant();
0184     }
0185 
0186     if (index.row() >= rooms.count()) {
0187         qDebug() << "PublicRoomListModel, something's wrong: index.row() >= "
0188                     "rooms.count()";
0189         return {};
0190     }
0191     auto room = rooms.at(index.row());
0192     if (role == DisplayNameRole) {
0193         auto displayName = room.name;
0194         if (!displayName.isEmpty()) {
0195             return displayName;
0196         }
0197 
0198         displayName = room.canonicalAlias;
0199         if (!displayName.isEmpty()) {
0200             return displayName;
0201         }
0202 
0203         if (!displayName.isEmpty()) {
0204             return displayName;
0205         }
0206 
0207         return room.roomId;
0208     }
0209     if (role == AvatarUrlRole) {
0210         auto avatarUrl = room.avatarUrl;
0211         if (avatarUrl.isEmpty() || !m_connection) {
0212             return QUrl();
0213         }
0214         return m_connection->makeMediaUrl(avatarUrl);
0215     }
0216     if (role == TopicRole) {
0217         return room.topic;
0218     }
0219     if (role == RoomIdRole) {
0220         return room.roomId;
0221     }
0222     if (role == AliasRole) {
0223         if (!room.canonicalAlias.isEmpty()) {
0224             return room.canonicalAlias;
0225         }
0226         return {};
0227     }
0228     if (role == MemberCountRole) {
0229         return room.numJoinedMembers;
0230     }
0231     if (role == AllowGuestsRole) {
0232         return room.guestCanJoin;
0233     }
0234     if (role == WorldReadableRole) {
0235         return room.worldReadable;
0236     }
0237     if (role == IsJoinedRole) {
0238         if (!m_connection) {
0239             return {};
0240         }
0241 
0242         return m_connection->room(room.roomId, JoinState::Join) != nullptr;
0243     }
0244 
0245     return {};
0246 }
0247 
0248 QHash<int, QByteArray> PublicRoomListModel::roleNames() const
0249 {
0250     QHash<int, QByteArray> roles;
0251 
0252     roles[DisplayNameRole] = "displayName";
0253     roles[AvatarUrlRole] = "avatarUrl";
0254     roles[TopicRole] = "topic";
0255     roles[RoomIdRole] = "roomId";
0256     roles[MemberCountRole] = "memberCount";
0257     roles[AllowGuestsRole] = "allowGuests";
0258     roles[WorldReadableRole] = "worldReadable";
0259     roles[IsJoinedRole] = "isJoined";
0260     roles[AliasRole] = "alias";
0261 
0262     return roles;
0263 }
0264 
0265 int PublicRoomListModel::rowCount(const QModelIndex &parent) const
0266 {
0267     if (parent.isValid()) {
0268         return 0;
0269     }
0270 
0271     return rooms.count();
0272 }
0273 
0274 bool PublicRoomListModel::hasMore() const
0275 {
0276     return !(attempted && nextBatch.isEmpty());
0277 }
0278 
0279 bool PublicRoomListModel::loading() const
0280 {
0281     return job != nullptr;
0282 }
0283 
0284 #include "moc_publicroomlistmodel.cpp"