File indexing completed on 2024-05-12 16:25:49

0001 /*
0002    SPDX-FileCopyrightText: 2018-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "inputcompletermodel.h"
0008 #include "rocketchataccount.h"
0009 #include <KLocalizedString>
0010 
0011 #include <QJsonArray>
0012 
0013 #include <QIcon>
0014 #include <QModelIndex>
0015 
0016 InputCompleterModel::InputCompleterModel(RocketChatAccount *account, QObject *parent)
0017     : QAbstractListModel(parent)
0018     , mRocketChatAccount(account)
0019 {
0020 }
0021 
0022 InputCompleterModel::~InputCompleterModel() = default;
0023 
0024 QString InputCompleterModel::here()
0025 {
0026     return QStringLiteral("here");
0027 }
0028 
0029 QString InputCompleterModel::all()
0030 {
0031     return QStringLiteral("all");
0032 }
0033 
0034 ChannelUserCompleter InputCompleterModel::createHereChannel()
0035 {
0036     ChannelUserCompleter here;
0037     here.setName(InputCompleterModel::here());
0038     here.setDescription(i18n("Notify all in this room"));
0039     here.setType(ChannelUserCompleter::ChannelUserCompleterType::Notification);
0040     return here;
0041 }
0042 
0043 ChannelUserCompleter InputCompleterModel::noFoundChannelUser()
0044 {
0045     ChannelUserCompleter noFound;
0046     noFound.setDescription(i18n("No result found."));
0047     noFound.setType(ChannelUserCompleter::ChannelUserCompleterType::Unknown);
0048     return noFound;
0049 }
0050 
0051 ChannelUserCompleter InputCompleterModel::createAllChannel()
0052 {
0053     ChannelUserCompleter all;
0054     all.setName(InputCompleterModel::all());
0055     all.setDescription(i18n("Notify active users in this room"));
0056     all.setType(ChannelUserCompleter::ChannelUserCompleterType::Notification);
0057     return all;
0058 }
0059 
0060 void InputCompleterModel::setDefaultUserCompletion()
0061 {
0062     // Show here/all when we only use "@"
0063     QVector<ChannelUserCompleter> customCompletion;
0064 
0065     customCompletion.append(createHereChannel());
0066     customCompletion.append(createAllChannel());
0067 
0068     setChannels(customCompletion);
0069 }
0070 
0071 void InputCompleterModel::setChannels(const QVector<ChannelUserCompleter> &channels)
0072 {
0073     clear();
0074     if (!channels.isEmpty()) {
0075         beginInsertRows(QModelIndex(), 0, channels.count() - 1);
0076         mChannelUserCompleters = channels;
0077         endInsertRows();
0078     }
0079 }
0080 
0081 QVector<ChannelUserCompleter> InputCompleterModel::searchOpenedRooms()
0082 {
0083     QVector<ChannelUserCompleter> channels;
0084     if (mRocketChatAccount) {
0085         if (!mSearchInfo.searchString.isEmpty()) {
0086             const QVector<Room *> rooms = mRocketChatAccount->roomModel()->findRoomNameConstains(mSearchInfo.searchString);
0087             for (const Room *room : rooms) {
0088                 if (room->channelType() == Room::RoomType::Channel) { // Only direct channel.
0089                     ChannelUserCompleter channel;
0090                     channel.setType(ChannelUserCompleter::ChannelUserCompleterType::Room);
0091                     channel.setName(room->displayFName());
0092                     channel.setIdentifier(room->roomId());
0093                     channel.setChannelIcon();
0094                     channel.setAvatarInfo(room->avatarInfo());
0095                     channels.append(std::move(channel));
0096                 }
0097             }
0098         }
0099     }
0100     return channels;
0101 }
0102 
0103 void InputCompleterModel::setSearchInfo(const SearchInfo &newSearchInfo)
0104 {
0105     mSearchInfo = newSearchInfo;
0106 }
0107 
0108 void InputCompleterModel::parseSearchChannels(const QJsonObject &obj)
0109 {
0110     QVector<ChannelUserCompleter> channelList;
0111     const QJsonArray rooms = obj.value(QLatin1String("items")).toArray();
0112     const auto roomsSize(rooms.size());
0113     channelList.reserve(roomsSize);
0114     for (auto i = 0; i < roomsSize; i++) {
0115         const QJsonObject o = rooms.at(i).toObject();
0116         ChannelUserCompleter channel;
0117         channel.parseChannel(o, ChannelUserCompleter::ChannelUserCompleterType::Room);
0118         // Verify that it's valid
0119         channelList.append(std::move(channel));
0120     }
0121     if (channelList.isEmpty()) {
0122         channelList.append(noFoundChannelUser());
0123     }
0124     setChannels(channelList);
0125 }
0126 
0127 void InputCompleterModel::parseChannels(const QJsonObject &obj)
0128 {
0129     QVector<ChannelUserCompleter> channelList;
0130     if (mSearchInfo.searchType == SearchInfo::Channels || mSearchInfo.searchType == SearchInfo::ChannelsAndUsers) {
0131         const QJsonArray rooms = obj.value(QLatin1String("rooms")).toArray();
0132         channelList.reserve(rooms.size());
0133         for (int i = 0; i < rooms.size(); i++) {
0134             const QJsonObject o = rooms.at(i).toObject();
0135             ChannelUserCompleter channel;
0136             channel.parseChannel(o, ChannelUserCompleter::ChannelUserCompleterType::Room);
0137             // Verify that it's valid
0138             channelList.append(std::move(channel));
0139         }
0140         channelList.append(searchOpenedRooms());
0141     }
0142     if (mSearchInfo.searchType == SearchInfo::Users || mSearchInfo.searchType == SearchInfo::ChannelsAndUsers) {
0143         const QJsonArray users = obj.value(QLatin1String("users")).toArray();
0144         bool needToAddAll = false;
0145         bool needToAddHere = false;
0146         for (int i = 0; i < users.size(); i++) {
0147             const QJsonObject o = users.at(i).toObject();
0148             ChannelUserCompleter user;
0149             user.parseChannel(o, ChannelUserCompleter::ChannelUserCompleterType::DirectChannel);
0150             if (!mSearchInfo.searchString.isEmpty()) {
0151                 if (!needToAddAll && InputCompleterModel::all().startsWith(mSearchInfo.searchString)) {
0152                     needToAddAll = true;
0153                 }
0154                 if (!needToAddHere && InputCompleterModel::here().startsWith(mSearchInfo.searchString)) {
0155                     needToAddHere = true;
0156                 }
0157             }
0158             // Verify that it's valid
0159             channelList.append(std::move(user));
0160         }
0161         if (needToAddAll) {
0162             channelList.append(createAllChannel());
0163         }
0164         if (needToAddHere) {
0165             channelList.append(createHereChannel());
0166         }
0167     }
0168     if (channelList.isEmpty()) {
0169         channelList.append(noFoundChannelUser());
0170     }
0171     setChannels(channelList);
0172 }
0173 
0174 void InputCompleterModel::clear()
0175 {
0176     if (!mChannelUserCompleters.isEmpty()) {
0177         beginResetModel();
0178         mChannelUserCompleters.clear();
0179         endResetModel();
0180     }
0181 }
0182 
0183 int InputCompleterModel::rowCount(const QModelIndex &parent) const
0184 {
0185     Q_UNUSED(parent)
0186     return mChannelUserCompleters.count();
0187 }
0188 
0189 QVariant InputCompleterModel::data(const QModelIndex &index, int role) const
0190 {
0191     if (index.row() < 0 || index.row() >= mChannelUserCompleters.count()) {
0192         return {};
0193     }
0194     const ChannelUserCompleter channelUserCompleter = mChannelUserCompleters.at(index.row());
0195     switch (role) {
0196     case InputCompleterModel::DisplayName:
0197     case Qt::DisplayRole:
0198         return channelUserCompleter.name();
0199     case InputCompleterModel::CompleterName:
0200         return channelUserCompleter.completerName();
0201     case InputCompleterModel::IconStatus:
0202     case Qt::DecorationRole:
0203         return channelUserCompleter.statusIcon();
0204     case InputCompleterModel::AvatarInfo:
0205         return QVariant::fromValue(channelUserCompleter.avatarInfo());
0206     case InputCompleterModel::Description:
0207         return channelUserCompleter.description();
0208     case InputCompleterModel::UserName:
0209         return channelUserCompleter.userName();
0210     case InputCompleterModel::OutsideRoom:
0211         return channelUserCompleter.outsideRoom();
0212     case InputCompleterModel::ChannelType:
0213         return channelUserCompleter.type();
0214     case InputCompleterModel::Identifier:
0215         return channelUserCompleter.identifier();
0216     }
0217     return {};
0218 }
0219 
0220 #include "moc_inputcompletermodel.cpp"