diff --git a/harmonyqml/backend/model/sort_filter_proxy.py b/harmonyqml/backend/model/sort_filter_proxy.py index 4069676a..757108ca 100644 --- a/harmonyqml/backend/model/sort_filter_proxy.py +++ b/harmonyqml/backend/model/sort_filter_proxy.py @@ -1,7 +1,8 @@ -from typing import Dict +from typing import Any, Callable, Dict, Optional from PyQt5.QtCore import ( - QObject, QSortFilterProxyModel, Qt, pyqtProperty, pyqtSignal, pyqtSlot + QModelIndex, QObject, QSortFilterProxyModel, Qt, pyqtProperty, pyqtSignal, + pyqtSlot ) from .list_model import ListModel @@ -15,9 +16,10 @@ class SortFilterProxy(QSortFilterProxyModel): def __init__(self, source_model: ListModel, - sort_by_role: str, - filter_by_role: str, + sort_by_role: str = "", + filter_by_role: str = "", ascending: bool = True, + sort_func: Optional[Callable[[Any, Any], bool]] = None, parent: QObject = None) -> None: super().__init__(parent) self.setDynamicSortFilter(False) @@ -28,6 +30,8 @@ class SortFilterProxy(QSortFilterProxyModel): source_model.countChanged.connect(self.countChanged.emit) source_model.changed.connect(self._apply_sort) + self.sort_func = sort_func + self._sort_by_role = "" self.sortByRole = sort_by_role self.ascending = ascending @@ -83,9 +87,15 @@ class SortFilterProxy(QSortFilterProxyModel): numbers = self.sourceModel().roleNumbers() try: self.setSortRole(numbers[self.sortByRole]) + except (AttributeError, KeyError): + # Model doesn't have its roles set yet (empty model), or no + # self.sortByRole passed + pass + + try: self.setFilterRole(numbers[self.filterByRole]) - except KeyError: - pass # Model doesn't have its roles set yet (empty model) + except (AttributeError, KeyError): + pass def _apply_sort(self) -> None: @@ -93,6 +103,24 @@ class SortFilterProxy(QSortFilterProxyModel): self.sort(0, order) + # Sorting/filtering implementations + + + def lessThan(self, source_left: QModelIndex, source_right: QModelIndex + ) -> bool: + left = self.sourceModel()[source_left.row()] + right = self.sourceModel()[source_right.row()] + + if self.sort_func: + return self.sort_func(left, right) + + role = self.sortByRole + try: + return getattr(left, role) < getattr(right, role) + except TypeError: # comparison between the two types not supported + return False + + # The rest def __repr__(self) -> str: diff --git a/harmonyqml/backend/pyqt_future.py b/harmonyqml/backend/pyqt_future.py index 957bb88a..c9cbcd3d 100644 --- a/harmonyqml/backend/pyqt_future.py +++ b/harmonyqml/backend/pyqt_future.py @@ -39,6 +39,11 @@ class PyQtFuture(QObject): ) + def __lt__(self, other: "PyQtFuture") -> bool: + # This is to allow sorting, e.g. from SortFilterProxy.lessThan() + return self.value < other.value + + @pyqtSlot() def cancel(self): self.future.cancel() diff --git a/harmonyqml/backend/signal_manager.py b/harmonyqml/backend/signal_manager.py index 694106ac..1d08f20d 100644 --- a/harmonyqml/backend/signal_manager.py +++ b/harmonyqml/backend/signal_manager.py @@ -153,6 +153,11 @@ class SignalManager(QObject): ) + def _members_sort_func(self, left: RoomMember, right: RoomMember) -> bool: + users = self.backend.users + return users[left.userId].displayName < users[right.userId].displayName + + def onRoomInvited(self, client: Client, room_id: str, @@ -169,8 +174,8 @@ class SignalManager(QObject): members = ListModel() sorted_members = SortFilterProxy( source_model = members, - sort_by_role = "userId", # TODO - filter_by_role = "userId", + filter_by_role = "displayName", + sort_func = self._members_sort_func, ) categories["Invites"].rooms.upsert( @@ -209,8 +214,8 @@ class SignalManager(QObject): members = ListModel() sorted_members = SortFilterProxy( source_model = members, - sort_by_role = "userId", # TODO - filter_by_role = "userId", + filter_by_role = "displayName", + sort_func = self._members_sort_func, ) categories["Rooms"].rooms.upsert( @@ -252,8 +257,8 @@ class SignalManager(QObject): members = ListModel() sorted_members = SortFilterProxy( source_model = members, - sort_by_role = "userId", # TODO - filter_by_role = "userId", + sort_by_role = "displayName", + filter_by_role = "displayName", ) categories["Left"].rooms.upsert( diff --git a/harmonyqml/components/Chat/RoomSidePane/MemberDelegate.qml b/harmonyqml/components/Chat/RoomSidePane/MemberDelegate.qml index 637bbc8c..3803a525 100644 --- a/harmonyqml/components/Chat/RoomSidePane/MemberDelegate.qml +++ b/harmonyqml/components/Chat/RoomSidePane/MemberDelegate.qml @@ -7,7 +7,7 @@ MouseArea { width: memberList.width height: childrenRect.height - property var member: Backend.users.get(modelData) + property var member: Backend.users.get(userId) HRowLayout { width: parent.width