diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5a5ad2f2c..c59a261cb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -194,6 +194,8 @@ add_library(neochat STATIC models/threadmodel.h enums/messagetype.h messagecomponent.h + enums/roomsortparameter.cpp + enums/roomsortparameter.h ) set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES diff --git a/src/enums/roomsortparameter.cpp b/src/enums/roomsortparameter.cpp new file mode 100644 index 000000000..62bab0c2a --- /dev/null +++ b/src/enums/roomsortparameter.cpp @@ -0,0 +1,85 @@ +// SPDX-FileCopyrightText: 2024 James Graham +// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL + +#include "roomsortparameter.h" + +namespace +{ +template +int typeCompare(T left, T right) +{ + return left == right ? 0 : left > right ? 1 : -1; +} + +template<> +int typeCompare(QString left, QString right) +{ + return left.localeAwareCompare(right); +} +} + +int RoomSortParameter::compareParameter(Parameter parameter, NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +{ + switch (parameter) { + case AlphabeticalAscending: + return compareParameter(leftRoom, rightRoom); + case AlphabeticalDescending: + return compareParameter(leftRoom, rightRoom); + case HasUnread: + return compareParameter(leftRoom, rightRoom); + case MostUnread: + return compareParameter(leftRoom, rightRoom); + case HasHighlight: + return compareParameter(leftRoom, rightRoom); + case MostHighlights: + return compareParameter(leftRoom, rightRoom); + case LastActive: + return compareParameter(leftRoom, rightRoom); + default: + return false; + } +} + +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +{ + return -typeCompare(leftRoom->displayName(), rightRoom->displayName()); +} + +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +{ + return typeCompare(leftRoom->displayName(), rightRoom->displayName()); +} + +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +{ + return typeCompare(leftRoom->contextAwareNotificationCount() > 0, rightRoom->contextAwareNotificationCount() > 0); +} + +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +{ + return typeCompare(leftRoom->contextAwareNotificationCount(), rightRoom->contextAwareNotificationCount()); +} + +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +{ + const auto leftHighlight = leftRoom->highlightCount() > 0 && leftRoom->contextAwareNotificationCount() > 0; + const auto rightHighlight = rightRoom->highlightCount() > 0 && rightRoom->contextAwareNotificationCount() > 0; + return typeCompare(leftHighlight, rightHighlight); +} + +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +{ + return typeCompare(int(leftRoom->highlightCount()), int(rightRoom->highlightCount())); +} + +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +{ + return typeCompare(leftRoom->lastActiveTime(), rightRoom->lastActiveTime()); +} diff --git a/src/enums/roomsortparameter.h b/src/enums/roomsortparameter.h new file mode 100644 index 000000000..b44bc9a75 --- /dev/null +++ b/src/enums/roomsortparameter.h @@ -0,0 +1,122 @@ +// SPDX-FileCopyrightText: 2024 James Graham +// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL + +#pragma once + +#include "neochatroom.h" +#include +#include + +#include + +/** + * @class RoomSortParameter + * + * A class with the Parameter enum for room sort parameters. + */ +class RoomSortParameter : public QObject +{ + Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("") + +public: + /** + * @brief Defines the available sort parameters. + */ + enum Parameter { + AlphabeticalAscending, + AlphabeticalDescending, + HasUnread, + MostUnread, + HasHighlight, + MostHighlights, + LastActive, + }; + Q_ENUM(Parameter) + + /** + * @brief Translate the Parameter enum value to a human readable name string. + * + * @sa Parameter + */ + static QString parameterName(Parameter parameter) + { + switch (parameter) { + case Parameter::AlphabeticalAscending: + return i18nc("As in sorting alphabetically with A first and Z last", "Alphabetical Ascending"); + case Parameter::AlphabeticalDescending: + return i18nc("As in sorting alphabetically with Z first and A last", "Alphabetical Descending"); + case Parameter::HasUnread: + return i18nc("As in sorting rooms with unread message above those without", "Has Unread Messages"); + case Parameter::MostUnread: + return i18nc("As in sorting rooms with the most unread messages higher", "Most Unread Messages"); + case Parameter::HasHighlight: + return i18nc("As in sorting rooms with highlighted message above those without", "Has Highlighted Messages"); + case Parameter::MostHighlights: + return i18nc("As in sorting rooms with the most highlighted messages higher", "Most Highlighted Messages"); + case Parameter::LastActive: + return i18nc("As in sorting the chat room with the newest meassage first", "Last Active"); + default: + return {}; + } + }; + + /** + * @brief Translate the Parameter enum value to a human readable description string. + * + * @sa Parameter + */ + static QString parameterDescription(Parameter parameter) + { + switch (parameter) { + case Parameter::AlphabeticalAscending: + return i18nc("@info", "Room names closer to A alphabetically are higher"); + case Parameter::AlphabeticalDescending: + return i18nc("@info", "Room names closer to Z alphabetically are higher"); + case Parameter::HasUnread: + return i18nc("@info", "Rooms with unread messages are higher"); + case Parameter::MostUnread: + return i18nc("@info", "Rooms with the most unread message are higher"); + case Parameter::HasHighlight: + return i18nc("@info", "Rooms with highlighted messages are higher"); + case Parameter::MostHighlights: + return i18nc("@info", "Rooms with the most highlighted messages are higher"); + case Parameter::LastActive: + return i18nc("@info", "Rooms with the newer messages are higher"); + default: + return {}; + } + }; + + /** + * @brief Compare the given parameter of the two given rooms. + * + * @return 0 if they are equal, 1 if the left is greater and -1 if the right is greater. + * + * @sa Parameter + */ + static int compareParameter(Parameter parameter, NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); + +private: + template + static int compareParameter(NeoChatRoom *, NeoChatRoom *) + { + return false; + } +}; + +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +template<> +int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); diff --git a/src/models/roomlistmodel.cpp b/src/models/roomlistmodel.cpp index 6e4db5c33..e6b9ecab7 100644 --- a/src/models/roomlistmodel.cpp +++ b/src/models/roomlistmodel.cpp @@ -129,7 +129,7 @@ void RoomListModel::connectRoomSignals(NeoChatRoom *room) refresh(room); }); connect(room, &Room::addedMessages, this, [this, room] { - refresh(room, {SubtitleTextRole, LastActiveTimeRole}); + refresh(room, {SubtitleTextRole}); }); connect(room, &Room::pendingEventMerged, this, [this, room] { refresh(room, {SubtitleTextRole}); @@ -229,9 +229,6 @@ QVariant RoomListModel::data(const QModelIndex &index, int role) const if (role == HasHighlightNotificationsRole) { return room->highlightCount() > 0 && room->contextAwareNotificationCount() > 0; } - if (role == LastActiveTimeRole) { - return room->lastActiveTime(); - } if (role == JoinStateRole) { if (!room->successorId().isEmpty()) { return QStringLiteral("upgraded"); @@ -291,7 +288,6 @@ QHash RoomListModel::roleNames() const roles[CategoryRole] = "category"; roles[ContextNotificationCountRole] = "contextNotificationCount"; roles[HasHighlightNotificationsRole] = "hasHighlightNotifications"; - roles[LastActiveTimeRole] = "lastActiveTime"; roles[JoinStateRole] = "joinState"; roles[CurrentRoomRole] = "currentRoom"; roles[SubtitleTextRole] = "subtitleText"; diff --git a/src/models/roomlistmodel.h b/src/models/roomlistmodel.h index ff3cb181f..9fc2c03f6 100644 --- a/src/models/roomlistmodel.h +++ b/src/models/roomlistmodel.h @@ -43,7 +43,6 @@ public: CategoryRole, /**< The room category, e.g favourite. */ ContextNotificationCountRole, /**< The context aware notification count for the room. */ HasHighlightNotificationsRole, /**< Whether there are any highlight notifications. */ - LastActiveTimeRole, /**< The timestamp of the last event sent in the room. */ JoinStateRole, /**< The local user's join state in the room. */ CurrentRoomRole, /**< The room object for the room. */ SubtitleTextRole, /**< The text to show as the room subtitle. */ diff --git a/src/models/roomtreemodel.cpp b/src/models/roomtreemodel.cpp index 0742c7988..dc450a3f6 100644 --- a/src/models/roomtreemodel.cpp +++ b/src/models/roomtreemodel.cpp @@ -176,7 +176,7 @@ void RoomTreeModel::connectRoomSignals(NeoChatRoom *room) refreshRoomRoles(room); }); connect(room, &Room::addedMessages, this, [this, room] { - refreshRoomRoles(room, {SubtitleTextRole, LastActiveTimeRole}); + refreshRoomRoles(room, {SubtitleTextRole}); }); connect(room, &Room::pendingEventMerged, this, [this, room] { refreshRoomRoles(room, {SubtitleTextRole}); @@ -274,7 +274,6 @@ QHash RoomTreeModel::roleNames() const roles[CategoryRole] = "category"; roles[ContextNotificationCountRole] = "contextNotificationCount"; roles[HasHighlightNotificationsRole] = "hasHighlightNotifications"; - roles[LastActiveTimeRole] = "lastActiveTime"; roles[JoinStateRole] = "joinState"; roles[CurrentRoomRole] = "currentRoom"; roles[SubtitleTextRole] = "subtitleText"; @@ -284,8 +283,6 @@ QHash RoomTreeModel::roleNames() const roles[IsDirectChat] = "isDirectChat"; roles[DelegateTypeRole] = "delegateType"; roles[IconRole] = "icon"; - roles[AttentionRole] = "attention"; - roles[FavouriteRole] = "favourite"; roles[RoomTypeRole] = "roomType"; return roles; } @@ -341,9 +338,6 @@ QVariant RoomTreeModel::data(const QModelIndex &index, int role) const if (role == HasHighlightNotificationsRole) { return room->highlightCount() > 0 && room->contextAwareNotificationCount() > 0; } - if (role == LastActiveTimeRole) { - return room->lastActiveTime(); - } if (role == JoinStateRole) { if (!room->successorId().isEmpty()) { return QStringLiteral("upgraded"); @@ -380,12 +374,6 @@ QVariant RoomTreeModel::data(const QModelIndex &index, int role) const if (role == DelegateTypeRole) { return QStringLiteral("normal"); } - if (role == AttentionRole) { - return room->notificationCount() + room->highlightCount() > 0; - } - if (role == FavouriteRole) { - return room->isFavourite(); - } if (role == RoomTypeRole) { if (room->creation()) { return room->creation()->contentPart("type"_L1); diff --git a/src/models/roomtreemodel.h b/src/models/roomtreemodel.h index 326f97359..0644db11e 100644 --- a/src/models/roomtreemodel.h +++ b/src/models/roomtreemodel.h @@ -36,7 +36,6 @@ public: CategoryRole, /**< The room category, e.g favourite. */ ContextNotificationCountRole, /**< The context aware notification count for the room. */ HasHighlightNotificationsRole, /**< Whether there are any highlight notifications. */ - LastActiveTimeRole, /**< The timestamp of the last event sent in the room. */ JoinStateRole, /**< The local user's join state in the room. */ CurrentRoomRole, /**< The room object for the room. */ SubtitleTextRole, /**< The text to show as the room subtitle. */ @@ -48,8 +47,6 @@ public: IsDirectChat, /**< Whether this room is a direct chat. */ DelegateTypeRole, IconRole, - AttentionRole, /**< Whether there are any notifications. */ - FavouriteRole, /**< Whether the room is favourited. */ RoomTypeRole, /**< The room's type. */ }; Q_ENUM(EventRoles) diff --git a/src/models/sortfilterroomtreemodel.cpp b/src/models/sortfilterroomtreemodel.cpp index a2bd05873..258d9861f 100644 --- a/src/models/sortfilterroomtreemodel.cpp +++ b/src/models/sortfilterroomtreemodel.cpp @@ -6,6 +6,7 @@ #include "neochatconfig.h" #include "neochatconnection.h" +#include "neochatroom.h" #include "neochatroomtype.h" #include "roommanager.h" #include "roomtreemodel.h" @@ -44,67 +45,49 @@ SortFilterRoomTreeModel::SortFilterRoomTreeModel(RoomTreeModel *sourceModel, QOb void SortFilterRoomTreeModel::setRoomSortOrder(SortFilterRoomTreeModel::RoomSortOrder sortOrder) { m_sortOrder = sortOrder; - if (sortOrder == SortFilterRoomTreeModel::Alphabetical) { - setSortRole(RoomTreeModel::DisplayNameRole); - } else if (sortOrder == SortFilterRoomTreeModel::Activity) { - setSortRole(RoomTreeModel::LastActiveTimeRole); - } invalidate(); } -static const QVector alphabeticalSortPriorities{ +static const QVector alphabeticalSortPriorities{ // Does exactly what it says on the tin. - RoomTreeModel::DisplayNameRole, + RoomSortParameter::AlphabeticalAscending, }; -static const QVector activitySortPriorities{ - // Anything useful at the top, quiet rooms at the bottom - RoomTreeModel::AttentionRole, - // Organize by highlights, notifications, unread favorites, all other unread, in that order - RoomTreeModel::HasHighlightNotificationsRole, - RoomTreeModel::ContextNotificationCountRole, - RoomTreeModel::FavouriteRole, +static const QVector activitySortPriorities{ + RoomSortParameter::HasHighlight, + RoomSortParameter::MostHighlights, + RoomSortParameter::HasUnread, + RoomSortParameter::MostUnread, + RoomSortParameter::LastActive, }; -static const QVector lastMessageSortPriorities{ - // Sort by last activity time - RoomTreeModel::LastActiveTimeRole, - // Anything useful at the top, quiet rooms at the bottom - RoomTreeModel::AttentionRole, - // Organize by highlights, notifications, unread favorites, all other unread, in that order - RoomTreeModel::HasHighlightNotificationsRole, - RoomTreeModel::ContextNotificationCountRole, - RoomTreeModel::FavouriteRole, +static const QVector lastMessageSortPriorities{ + RoomSortParameter::LastActive, }; -bool SortFilterRoomTreeModel::roleCmp(const QVariant &sortLeft, const QVariant &sortRight) const -{ - switch (sortLeft.typeId()) { - case QMetaType::Bool: - return (sortLeft == sortRight) ? false : sortLeft.toBool(); - case QMetaType::QString: - return sortLeft.toString() < sortRight.toString(); - case QMetaType::Int: - return sortLeft.toInt() > sortRight.toInt(); - case QMetaType::QDateTime: - return sortLeft.toDateTime() > sortRight.toDateTime(); - default: - return false; - } -} - -bool SortFilterRoomTreeModel::prioritiesCmp(const QVector &priorities, +bool SortFilterRoomTreeModel::prioritiesCmp(const QVector &priorities, const QModelIndex &source_left, const QModelIndex &source_right) const { - for (RoomTreeModel::EventRoles sortRole : priorities) { - const auto sortLeft = sourceModel()->data(source_left, sortRole); - const auto sortRight = sourceModel()->data(source_right, sortRole); - if (sortLeft != sortRight) { - return roleCmp(sortLeft, sortRight); + const auto treeModel = dynamic_cast(sourceModel()); + if (treeModel == nullptr) { + return false; + } + + const auto leftRoom = dynamic_cast(treeModel->connection()->room(source_left.data(RoomTreeModel::RoomIdRole).toString())); + const auto rightRoom = dynamic_cast(treeModel->connection()->room(source_right.data(RoomTreeModel::RoomIdRole).toString())); + if (leftRoom == nullptr || rightRoom == nullptr) { + return false; + } + + for (auto sortRole : priorities) { + auto result = RoomSortParameter::compareParameter(sortRole, leftRoom, rightRoom); + + if (result != 0) { + return result > 0; } } - return QSortFilterProxyModel::lessThan(source_left, source_right); + return false; } bool SortFilterRoomTreeModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const diff --git a/src/models/sortfilterroomtreemodel.h b/src/models/sortfilterroomtreemodel.h index 3368d4af6..db17b7b9c 100644 --- a/src/models/sortfilterroomtreemodel.h +++ b/src/models/sortfilterroomtreemodel.h @@ -7,6 +7,7 @@ #include #include +#include "enums/roomsortparameter.h" #include "models/roomtreemodel.h" /** @@ -105,6 +106,5 @@ private: QString m_filterText; QString m_activeSpaceId; - bool roleCmp(const QVariant &left, const QVariant &right) const; - bool prioritiesCmp(const QVector &priorities, const QModelIndex &left, const QModelIndex &right) const; + bool prioritiesCmp(const QVector &priorities, const QModelIndex &left, const QModelIndex &right) const; };