diff --git a/src/roomlistmodel.cpp b/src/roomlistmodel.cpp index 606f56aa8..8184a3046 100644 --- a/src/roomlistmodel.cpp +++ b/src/roomlistmodel.cpp @@ -340,6 +340,12 @@ QVariant RoomListModel::data(const QModelIndex &index, int role) const if (role == TopicRole) { return room->topic(); } + if (role == FavoritedRole) { + return room->isFavourite(); + } + if (role == AttentionRole) { + return room->notificationCount() + room->unreadCount() + room->highlightCount() > 0; + } if (role == CategoryRole) { if (room->joinState() == JoinState::Invite) { return NeoChatRoomType::Invited; diff --git a/src/roomlistmodel.h b/src/roomlistmodel.h index 169eb22f9..f4fbd49ab 100644 --- a/src/roomlistmodel.h +++ b/src/roomlistmodel.h @@ -56,6 +56,10 @@ public: AvatarImageRole, IdRole, IsSpaceRole, + // Whether or not the room is favorited + FavoritedRole, + // Whether or not the room needs attention, ie, pings, mentions, unread + AttentionRole, }; Q_ENUM(EventRoles) diff --git a/src/sortfilterroomlistmodel.cpp b/src/sortfilterroomlistmodel.cpp index 4378bd553..41c4fce7f 100644 --- a/src/sortfilterroomlistmodel.cpp +++ b/src/sortfilterroomlistmodel.cpp @@ -33,34 +33,72 @@ SortFilterRoomListModel::RoomSortOrder SortFilterRoomListModel::roomSortOrder() return m_sortOrder; } +static const QVector categorySortPriorities{ + // Favorites at the top + RoomListModel::FavoritedRole, + // Group by categories + RoomListModel::CategoryRole, + // Within each category, pull relevant ones to the top + RoomListModel::AttentionRole, + RoomListModel::HighlightCountRole, + RoomListModel::NotificationCountRole, + RoomListModel::UnreadCountRole, + // Finally sort by last activity time + RoomListModel::LastActiveTimeRole +}; + +static const QVector alphabeticalSortPriorities { + // Does exactly what it says on the tin. + (RoomListModel::EventRoles)Qt::DisplayRole +}; + +static const QVector activitySortPriorities{ + // Anything useful at the top, quiet rooms at the bottom + RoomListModel::AttentionRole, + // Organize by highlights, notifications, unread favorites, all other unread, in that order + RoomListModel::HighlightCountRole, + RoomListModel::NotificationCountRole, + RoomListModel::FavoritedRole, + RoomListModel::UnreadCountRole, + // Finally sort by last activity time + RoomListModel::LastActiveTimeRole +}; + +bool SortFilterRoomListModel::roleCmp(RoomListModel::EventRoles role, const QVariant &sortLeft, const QVariant &sortRight) const +{ + switch(role) { + case RoomListModel::FavoritedRole: + return (sortLeft == sortRight) ? false : sortLeft.toBool(); + case RoomListModel::CategoryRole: + return sortLeft < sortRight; + default: + return sortLeft > sortRight; + } +} + +bool SortFilterRoomListModel::prioritiesCmp(const QVector& priorities, const QModelIndex &source_left, const QModelIndex &source_right) const +{ + for(RoomListModel::EventRoles sortRole : priorities) { + const auto sortLeft = sourceModel()->data(source_left, sortRole); + const auto sortRight = sourceModel()->data(source_right, sortRole); + if (sortLeft != sortRight) { + return roleCmp(sortRole, sortLeft, sortRight); + } + } + return QSortFilterProxyModel::lessThan(source_left, source_right); +} + bool SortFilterRoomListModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const { - if (m_sortOrder == SortFilterRoomListModel::LastActivity) { - // display favorite rooms always on top - const auto categoryLeft = static_cast(sourceModel()->data(source_left, RoomListModel::CategoryRole).toInt()); - const auto categoryRight = static_cast(sourceModel()->data(source_right, RoomListModel::CategoryRole).toInt()); - - if (categoryLeft == NeoChatRoomType::Types::Favorite && categoryRight == NeoChatRoomType::Types::Favorite) { - return sourceModel()->data(source_left, RoomListModel::LastActiveTimeRole).toDateTime() - > sourceModel()->data(source_right, RoomListModel::LastActiveTimeRole).toDateTime(); - } - if (categoryLeft == NeoChatRoomType::Types::Favorite) { - return true; - } else if (categoryRight == NeoChatRoomType::Types::Favorite) { - return false; - } - - return sourceModel()->data(source_left, RoomListModel::LastActiveTimeRole).toDateTime() - > sourceModel()->data(source_right, RoomListModel::LastActiveTimeRole).toDateTime(); + switch(m_sortOrder) { + case SortFilterRoomListModel::Alphabetical: + return prioritiesCmp(alphabeticalSortPriorities, source_left, source_right); + case SortFilterRoomListModel::Categories: + return prioritiesCmp(categorySortPriorities, source_left, source_right); + case SortFilterRoomListModel::LastActivity: + return prioritiesCmp(activitySortPriorities, source_left, source_right); } - if (m_sortOrder != SortFilterRoomListModel::Categories) { - return QSortFilterProxyModel::lessThan(source_left, source_right); - } - if (sourceModel()->data(source_left, RoomListModel::CategoryRole) != sourceModel()->data(source_right, RoomListModel::CategoryRole)) { - return sourceModel()->data(source_left, RoomListModel::CategoryRole).toInt() < sourceModel()->data(source_right, RoomListModel::CategoryRole).toInt(); - } - return sourceModel()->data(source_left, RoomListModel::LastActiveTimeRole).toDateTime() - > sourceModel()->data(source_right, RoomListModel::LastActiveTimeRole).toDateTime(); + return QSortFilterProxyModel::lessThan(source_left, source_right); } void SortFilterRoomListModel::setFilterText(const QString &text) diff --git a/src/sortfilterroomlistmodel.h b/src/sortfilterroomlistmodel.h index 8e7b84d0c..79c50a948 100644 --- a/src/sortfilterroomlistmodel.h +++ b/src/sortfilterroomlistmodel.h @@ -4,6 +4,7 @@ #pragma once #include +#include "roomlistmodel.h" class SortFilterRoomListModel : public QSortFilterProxyModel { @@ -46,4 +47,7 @@ private: RoomSortOrder m_sortOrder = Categories; QString m_filterText; QString m_activeSpaceId; + + bool prioritiesCmp(const QVector& priorities, const QModelIndex &left, const QModelIndex &right) const; + bool roleCmp(RoomListModel::EventRoles role, const QVariant& left, const QVariant& right) const; };