File indexing completed on 2024-05-05 05:01:25

0001 // SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
0002 // SPDX-License-Identifier: GPL-2.0-or-later
0003 
0004 #include "sortfilterroomlistmodel.h"
0005 
0006 #include "neochatconnection.h"
0007 #include "roomlistmodel.h"
0008 #include "spacehierarchycache.h"
0009 
0010 SortFilterRoomListModel::SortFilterRoomListModel(QObject *parent)
0011     : QSortFilterProxyModel(parent)
0012 {
0013     sort(0);
0014     invalidateFilter();
0015     connect(this, &SortFilterRoomListModel::filterTextChanged, this, [this]() {
0016         invalidateFilter();
0017     });
0018     connect(this, &SortFilterRoomListModel::sourceModelChanged, this, [this]() {
0019         connect(sourceModel(), &QAbstractListModel::rowsInserted, this, &SortFilterRoomListModel::invalidateRowsFilter);
0020         connect(sourceModel(), &QAbstractListModel::rowsRemoved, this, &SortFilterRoomListModel::invalidateRowsFilter);
0021     });
0022 }
0023 
0024 void SortFilterRoomListModel::setRoomSortOrder(SortFilterRoomListModel::RoomSortOrder sortOrder)
0025 {
0026     m_sortOrder = sortOrder;
0027     Q_EMIT roomSortOrderChanged();
0028     if (sortOrder == SortFilterRoomListModel::Alphabetical) {
0029         setSortRole(RoomListModel::DisplayNameRole);
0030     } else if (sortOrder == SortFilterRoomListModel::LastActivity) {
0031         setSortRole(RoomListModel::LastActiveTimeRole);
0032     }
0033     invalidate();
0034 }
0035 
0036 SortFilterRoomListModel::RoomSortOrder SortFilterRoomListModel::roomSortOrder() const
0037 {
0038     return m_sortOrder;
0039 }
0040 
0041 bool SortFilterRoomListModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
0042 {
0043     if (m_sortOrder == SortFilterRoomListModel::LastActivity) {
0044         // display favorite rooms always on top
0045         const auto categoryLeft = static_cast<NeoChatRoomType::Types>(sourceModel()->data(source_left, RoomListModel::CategoryRole).toInt());
0046         const auto categoryRight = static_cast<NeoChatRoomType::Types>(sourceModel()->data(source_right, RoomListModel::CategoryRole).toInt());
0047 
0048         if (categoryLeft == NeoChatRoomType::Types::Favorite && categoryRight == NeoChatRoomType::Types::Favorite) {
0049             return sourceModel()->data(source_left, RoomListModel::LastActiveTimeRole).toDateTime()
0050                 > sourceModel()->data(source_right, RoomListModel::LastActiveTimeRole).toDateTime();
0051         }
0052         if (categoryLeft == NeoChatRoomType::Types::Favorite) {
0053             return true;
0054         } else if (categoryRight == NeoChatRoomType::Types::Favorite) {
0055             return false;
0056         }
0057 
0058         return sourceModel()->data(source_left, RoomListModel::LastActiveTimeRole).toDateTime()
0059             > sourceModel()->data(source_right, RoomListModel::LastActiveTimeRole).toDateTime();
0060     }
0061     if (m_sortOrder != SortFilterRoomListModel::Categories) {
0062         return QSortFilterProxyModel::lessThan(source_left, source_right);
0063     }
0064     if (sourceModel()->data(source_left, RoomListModel::CategoryRole) != sourceModel()->data(source_right, RoomListModel::CategoryRole)) {
0065         return sourceModel()->data(source_left, RoomListModel::CategoryRole).toInt() < sourceModel()->data(source_right, RoomListModel::CategoryRole).toInt();
0066     }
0067     return sourceModel()->data(source_left, RoomListModel::LastActiveTimeRole).toDateTime()
0068         > sourceModel()->data(source_right, RoomListModel::LastActiveTimeRole).toDateTime();
0069 }
0070 
0071 void SortFilterRoomListModel::setFilterText(const QString &text)
0072 {
0073     m_filterText = text;
0074     Q_EMIT filterTextChanged();
0075 }
0076 
0077 QString SortFilterRoomListModel::filterText() const
0078 {
0079     return m_filterText;
0080 }
0081 
0082 bool SortFilterRoomListModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
0083 {
0084     Q_UNUSED(source_parent);
0085 
0086     bool acceptRoom =
0087         sourceModel()->data(sourceModel()->index(source_row, 0), RoomListModel::DisplayNameRole).toString().contains(m_filterText, Qt::CaseInsensitive)
0088         && sourceModel()->data(sourceModel()->index(source_row, 0), RoomListModel::IsSpaceRole).toBool() == false;
0089 
0090     bool isDirectChat = sourceModel()->data(sourceModel()->index(source_row, 0), RoomListModel::IsDirectChat).toBool();
0091     // In `show direct chats` mode we only care about whether or not it's a direct chat or if the filter string matches.'
0092     if (m_mode == DirectChats) {
0093         return isDirectChat && acceptRoom;
0094     }
0095 
0096     // When not in `show direct chats` mode, filter them out.
0097     if (isDirectChat && m_mode == Rooms) {
0098         return false;
0099     }
0100 
0101     if (sourceModel()->data(sourceModel()->index(source_row, 0), RoomListModel::JoinStateRole).toString() == QStringLiteral("upgraded")
0102         && dynamic_cast<RoomListModel *>(sourceModel())
0103                ->connection()
0104                ->room(sourceModel()->data(sourceModel()->index(source_row, 0), RoomListModel::ReplacementIdRole).toString())) {
0105         return false;
0106     }
0107 
0108     if (m_activeSpaceId.isEmpty()) {
0109         if (!SpaceHierarchyCache::instance().isChild(sourceModel()->data(sourceModel()->index(source_row, 0), RoomListModel::RoomIdRole).toString())) {
0110             return acceptRoom;
0111         }
0112         return false;
0113     } else {
0114         const auto &rooms = SpaceHierarchyCache::instance().getRoomListForSpace(m_activeSpaceId, false);
0115         return std::find(rooms.begin(), rooms.end(), sourceModel()->data(sourceModel()->index(source_row, 0), RoomListModel::RoomIdRole).toString())
0116             != rooms.end()
0117             && acceptRoom;
0118     }
0119 }
0120 
0121 QString SortFilterRoomListModel::activeSpaceId() const
0122 {
0123     return m_activeSpaceId;
0124 }
0125 
0126 void SortFilterRoomListModel::setActiveSpaceId(const QString &spaceId)
0127 {
0128     m_activeSpaceId = spaceId;
0129     Q_EMIT activeSpaceIdChanged();
0130     invalidate();
0131 }
0132 
0133 SortFilterRoomListModel::Mode SortFilterRoomListModel::mode() const
0134 {
0135     return m_mode;
0136 }
0137 
0138 void SortFilterRoomListModel::setMode(SortFilterRoomListModel::Mode mode)
0139 {
0140     if (m_mode == mode) {
0141         return;
0142     }
0143 
0144     m_mode = mode;
0145     Q_EMIT modeChanged();
0146     invalidate();
0147 }
0148 
0149 #include "moc_sortfilterroomlistmodel.cpp"