From 200f25d23e1a0639155330322e6d03b5526c7935 Mon Sep 17 00:00:00 2001 From: miruka Date: Sun, 10 May 2020 14:26:26 -0400 Subject: [PATCH] Python filter for AccountsBar --- TODO.md | 2 + src/backend/backend.py | 10 ++-- src/backend/models/filters.py | 17 +++++- src/backend/models/special_models.py | 24 ++++++++- src/gui/MainPane/AccountsBar.qml | 77 ++++++++++++---------------- 5 files changed, 81 insertions(+), 49 deletions(-) diff --git a/TODO.md b/TODO.md index a6cc70d7..8bbb5005 100644 --- a/TODO.md +++ b/TODO.md @@ -24,6 +24,8 @@ - rooms without messages on first sync - avatar loading performance problem? +- docstrings + ## Refactoring - Rewrite account settings using `HTabbedContainer` diff --git a/src/backend/backend.py b/src/backend/backend.py index 49955cea..5ba71ab6 100644 --- a/src/backend/backend.py +++ b/src/backend/backend.py @@ -20,7 +20,7 @@ from .models.filters import FieldSubstringFilter from .models.items import Account from .models.model import Model from .models.model_store import ModelStore -from .models.special_models import AllRooms +from .models.special_models import AllRooms, MatchingAccounts from .user_files import Accounts, History, Theme, UISettings, UIState # Logging configuration @@ -81,9 +81,11 @@ class Backend: self.ui_state: UIState = UIState(self) self.history: History = History(self) - self.all_rooms: AllRooms = AllRooms() - self.models: ModelStore = ModelStore() - self.clients: Dict[str, MatrixClient] = {} + self.all_rooms = AllRooms() + self.matching_accounts = MatchingAccounts(self.all_rooms) + self.models = ModelStore() + + self.clients: Dict[str, MatrixClient] = {} self.profile_cache: Dict[str, nio.ProfileGetResponse] = {} self.get_profile_locks: DefaultDict[str, asyncio.Lock] = \ diff --git a/src/backend/models/filters.py b/src/backend/models/filters.py index 648b7472..3ba376e2 100644 --- a/src/backend/models/filters.py +++ b/src/backend/models/filters.py @@ -1,6 +1,8 @@ # SPDX-License-Identifier: LGPL-3.0-or-later -from typing import TYPE_CHECKING, Any, Collection, Dict, Optional, Tuple +from typing import ( + TYPE_CHECKING, Any, Callable, Collection, Dict, List, Optional, Tuple, +) from . import SyncId from .model import Model @@ -13,6 +15,7 @@ if TYPE_CHECKING: class ModelFilter(ModelProxy): def __init__(self, sync_id: SyncId) -> None: self.filtered_out: Dict[Tuple[Optional[SyncId], str], "ModelItem"] = {} + self.items_changed_callbacks: List[Callable[[], None]] = [] super().__init__(sync_id) @@ -35,6 +38,9 @@ class ModelFilter(ModelProxy): self.filtered_out[source.sync_id, key] = value self.pop((source.sync_id, key), None) + for callback in self.items_changed_callbacks: + callback() + def source_item_deleted(self, source: Model, key) -> None: if self.accept_source(source): @@ -43,6 +49,9 @@ class ModelFilter(ModelProxy): except KeyError: del self.filtered_out[source.sync_id, key] + for callback in self.items_changed_callbacks: + callback() + def source_cleared(self, source: Model) -> None: if self.accept_source(source): @@ -53,6 +62,9 @@ class ModelFilter(ModelProxy): except KeyError: del self.filtered_out[source.sync_id, key] + for callback in self.items_changed_callbacks: + callback() + def refilter(self) -> None: with self._write_lock: @@ -74,6 +86,9 @@ class ModelFilter(ModelProxy): for key in bring_back: self[key] = self.filtered_out.pop(key) + for callback in self.items_changed_callbacks: + callback() + class FieldSubstringFilter(ModelFilter): def __init__(self, sync_id: SyncId, fields: Collection[str]) -> None: diff --git a/src/backend/models/special_models.py b/src/backend/models/special_models.py index 01007760..567876f7 100644 --- a/src/backend/models/special_models.py +++ b/src/backend/models/special_models.py @@ -1,7 +1,8 @@ # SPDX-License-Identifier: LGPL-3.0-or-later -from .filters import FieldSubstringFilter +from .filters import FieldSubstringFilter, ModelFilter from .model import Model +from .model_item import ModelItem class AllRooms(FieldSubstringFilter): @@ -15,3 +16,24 @@ class AllRooms(FieldSubstringFilter): len(source.sync_id) == 2 and source.sync_id[1] == "rooms" # type: ignore ) + + +class MatchingAccounts(ModelFilter): + def __init__(self, all_rooms: AllRooms) -> None: + super().__init__(sync_id="matching_accounts") + self.all_rooms = all_rooms + self.all_rooms.items_changed_callbacks.append(self.refilter) + + + def accept_source(self, source: Model) -> bool: + return source.sync_id == "accounts" + + + def accept_item(self, item: ModelItem) -> bool: + if not self.all_rooms.filter: + return True + + return next( + (r for r in self.all_rooms.values() if r.for_account == item.id), + False, + ) diff --git a/src/gui/MainPane/AccountsBar.qml b/src/gui/MainPane/AccountsBar.qml index bbf5c0b7..a82e6d35 100644 --- a/src/gui/MainPane/AccountsBar.qml +++ b/src/gui/MainPane/AccountsBar.qml @@ -39,61 +39,52 @@ HColumnLayout { -1, ) - model: HFilterModel { - model: ModelStore.get("accounts") - acceptItem: item => - ! roomFilter || item.id in roomList.sectionIndice + model: ModelStore.get("matching_accounts") - delegate: HTileDelegate { - id: tile - width: accountList.width - backgroundColor: - theme.accountsBar.accountList.account.background + delegate: HTileDelegate { + id: tile + width: accountList.width + backgroundColor: + theme.accountsBar.accountList.account.background - topPadding: (accountList.width - avatar.width) / 4 - bottomPadding: topPadding - leftPadding: 0 - rightPadding: leftPadding + topPadding: (accountList.width - avatar.width) / 4 + bottomPadding: topPadding + leftPadding: 0 + rightPadding: leftPadding - contentItem: Item { - implicitHeight: avatar.height + contentItem: Item { + implicitHeight: avatar.height - HUserAvatar { - id: avatar - anchors.horizontalCenter: parent.horizontalCenter - userId: model.id - displayName: model.display_name - mxc: model.avatar_url - // compact: tile.compact + HUserAvatar { + id: avatar + anchors.horizontalCenter: parent.horizontalCenter + userId: model.id + displayName: model.display_name + mxc: model.avatar_url + // compact: tile.compact - radius: - theme.accountsBar.accountList.account.avatarRadius - } - - MessageIndicator { - anchors.right: parent.right - anchors.bottom: parent.bottom - - indicatorTheme: - theme.accountView.account.unreadIndicator - unreads: model.total_unread - mentions: model.total_mentions - } + radius: + theme.accountsBar.accountList.account.avatarRadius } - contextMenu: AccountContextMenu { userId: model.id } + MessageIndicator { + anchors.right: parent.right + anchors.bottom: parent.bottom - onLeftClicked: { - model.id in roomList.sectionIndice ? - roomList.goToAccount(model.id) : - pageLoader.showPage("AddChat/AddChat", {userId: model.id}) + indicatorTheme: + theme.accountView.account.unreadIndicator + unreads: model.total_unread + mentions: model.total_mentions } } + contextMenu: AccountContextMenu { userId: model.id } - onRoomFilterChanged: refilterAll() - - readonly property string roomFilter: roomList.filter + onLeftClicked: { + model.id in roomList.sectionIndice ? + roomList.goToAccount(model.id) : + pageLoader.showPage("AddChat/AddChat", {userId: model.id}) + } } highlight: Item {