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"