Implement room filtering

This commit is contained in:
miruka 2019-05-11 17:13:53 -04:00
parent bb86c39fe7
commit d82cb50e30
5 changed files with 71 additions and 19 deletions

View File

@ -49,6 +49,7 @@
- Links preview
- Client improvements
- Filtering rooms: smart case, fuzzy filter, search more than display names
- nio.MatrixRoom has `typing_users`, no need to handle it on our own
- Don't send setTypingState False when focus lost if nothing in sendbox
- Initial sync filter and lazy load, see weechat-matrix `_handle_login()`

View File

@ -113,6 +113,14 @@ class Backend(QObject):
)
break
@pyqtSlot(str)
def setRoomFilter(self, pattern: str) -> None:
for account in self.accounts:
for categ in account.roomCategories:
categ.sortedRooms.filter = pattern
@staticmethod
def getDir(standard_dir: QStandardPaths.StandardLocation) -> str:
path = QStandardPaths.writableLocation(standard_dir)

View File

@ -9,11 +9,14 @@ from .list_model import ListModel
class SortFilterProxy(QSortFilterProxyModel):
sortByRoleChanged = pyqtSignal()
filterByRoleChanged = pyqtSignal()
filterChanged = pyqtSignal()
countChanged = pyqtSignal(int)
def __init__(self,
source_model: ListModel,
sort_by_role: str,
filter_by_role: str,
ascending: bool = True,
parent: QObject = None) -> None:
super().__init__(parent)
@ -21,14 +24,24 @@ class SortFilterProxy(QSortFilterProxyModel):
self.setFilterCaseSensitivity(Qt.CaseInsensitive)
self.setSourceModel(source_model)
source_model.rolesSet.connect(self._set_internal_sort_role)
source_model.rolesSet.connect(self._set_internal_sort_filter_role)
source_model.countChanged.connect(self.countChanged.emit)
source_model.changed.connect(self._sort)
source_model.changed.connect(self._apply_sort)
self._sort_by_role = ""
self.sortByRole = sort_by_role
self.ascending = ascending
self._filter_by_role = ""
self.filterByRole = filter_by_role
self._filter = None
self.filterChanged.connect(
lambda: self.countChanged.emit(self.rowCount())
)
# Sorting and filtering
@pyqtProperty(str, notify=sortByRoleChanged)
def sortByRole(self) -> str:
@ -38,18 +51,50 @@ class SortFilterProxy(QSortFilterProxyModel):
@sortByRole.setter # type: ignore
def sortByRole(self, role: str) -> None:
self._sort_by_role = role
self._set_internal_sort_role()
self._set_internal_sort_filter_role()
self.sortByRoleChanged.emit()
def _set_internal_sort_role(self) -> None:
@pyqtProperty(str, notify=filterByRoleChanged)
def filterByRole(self) -> str:
return self._filter_by_role
@filterByRole.setter # type: ignore
def filterByRole(self, role: str) -> None:
self._filter_by_role = role
self._set_internal_sort_filter_role()
self.filterByRoleChanged.emit()
@pyqtProperty(str, notify=filterChanged)
def filter(self) -> str:
return self._filter
@filter.setter # type: ignore
def filter(self, pattern: str) -> None:
self._filter = pattern
self.setFilterWildcard(pattern or "*")
self.filterChanged.emit()
def _set_internal_sort_filter_role(self) -> None:
numbers = self.sourceModel().roleNumbers()
try:
self.setSortRole(numbers[self._sort_by_role])
self.setSortRole(numbers[self.sortByRole])
self.setFilterRole(numbers[self.filterByRole])
except KeyError:
pass # Model doesn't have its roles set yet (empty model)
def _apply_sort(self) -> None:
order = Qt.AscendingOrder if self.ascending else Qt.DescendingOrder
self.sort(0, order)
# The rest
def __repr__(self) -> str:
return "%s(sortByRole=%r, sourceModel=%s)" % (
type(self).__name__,
@ -73,8 +118,3 @@ class SortFilterProxy(QSortFilterProxyModel):
def roleNames(self) -> Dict[int, bytes]:
return self.sourceModel().roleNames()
def _sort(self) -> None:
order = Qt.AscendingOrder if self.ascending else Qt.DescendingOrder
self.sort(0, order)

View File

@ -68,6 +68,7 @@ class SignalManager(QObject):
proxy = SortFilterProxy(
source_model = room_categories_kwargs[i]["rooms"],
sort_by_role = "lastEventDateTime",
filter_by_role = "displayName",
ascending = False,
)
room_categories_kwargs[i]["sortedRooms"] = proxy

View File

@ -17,6 +17,8 @@ HRowLayout {
placeholderText: qsTr("Filter rooms")
backgroundColor: HStyle.sidePane.filterRooms.background
onTextChanged: Backend.setRoomFilter(text)
Layout.fillWidth: true
Layout.preferredHeight: 32
}