diff --git a/src/backend/models/model.py b/src/backend/models/model.py index 2cd36d1c..7dc85b5e 100644 --- a/src/backend/models/model.py +++ b/src/backend/models/model.py @@ -44,7 +44,8 @@ class Model(MutableMapping): self.take_items_ownership: bool = True - self._active_batch_remove_indice: Optional[List[int]] = None + # [(index, item.id), ...] + self._active_batch_removed: Optional[List[Tuple[int, Any]]] = None if self.sync_id: self.instances[self.sync_id] = self @@ -148,10 +149,10 @@ class Model(MutableMapping): proxy.source_item_deleted(self, key) if self.sync_id: - if self._active_batch_remove_indice is None: - ModelItemDeleted(self.sync_id, index) + if self._active_batch_removed is None: + ModelItemDeleted(self.sync_id, index, 1, (item.id,)) else: - self._active_batch_remove_indice.append(index) + self._active_batch_removed.append((index, item.id)) def __iter__(self) -> Iterator: @@ -189,17 +190,21 @@ class Model(MutableMapping): with self.write_lock: try: - self._active_batch_remove_indice = [] + self._active_batch_removed = [] yield None finally: - indice = self._active_batch_remove_indice + batch = self._active_batch_removed groups = [ - list(group) for item, group in itertools.groupby(indice) + list(group) for item, group in + itertools.groupby(batch, key=lambda x: x[0]) ] - for grp in groups: + for group in groups: ModelItemDeleted( - self.sync_id, index=grp[0], count=len(grp), + self.sync_id, + index = group[0][0], + count = len(group), + ids = [item[1] for item in group], ) - self._active_batch_remove_indice = None + self._active_batch_removed = None diff --git a/src/backend/pyotherside_events.py b/src/backend/pyotherside_events.py index 7e9daa3d..d586cd6b 100644 --- a/src/backend/pyotherside_events.py +++ b/src/backend/pyotherside_events.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: LGPL-3.0-or-later from dataclasses import dataclass, field -from typing import TYPE_CHECKING, Any, Dict, Optional +from typing import TYPE_CHECKING, Any, Dict, Optional, Sequence import pyotherside @@ -83,8 +83,9 @@ class ModelItemSet(ModelEvent): class ModelItemDeleted(ModelEvent): """Indicate the removal of a `ModelItem` from a `Backend` `Model`.""" - index: int = field() - count: int = 1 + index: int = field() + count: int = 1 + ids: Sequence[Any] = () @dataclass diff --git a/src/gui/ModelStore.qml b/src/gui/ModelStore.qml index 773ead26..20b0bb37 100644 --- a/src/gui/ModelStore.qml +++ b/src/gui/ModelStore.qml @@ -13,6 +13,7 @@ QtObject { readonly property Component model: Component { ListModel { property var modelId + property var idToItems: ({}) // Used by HFilterModel signal fieldsChanged(int index, var changes) @@ -25,10 +26,7 @@ QtObject { } function find(id, default_=null) { - for (let i = 0; i < count; i++) - if (get(i).id === id) return get(i) - - return default_ + return idToItems[id] || default_ } } } diff --git a/src/gui/Pages/Chat/Chat.qml b/src/gui/Pages/Chat/Chat.qml index 588f5aa7..0b8399e6 100644 --- a/src/gui/Pages/Chat/Chat.qml +++ b/src/gui/Pages/Chat/Chat.qml @@ -12,8 +12,8 @@ Item { property string userId property string roomId - property QtObject userInfo: null - property QtObject roomInfo: null + property QtObject userInfo: ModelStore.get("accounts").find(userId) + property QtObject roomInfo: ModelStore.get(userId, "rooms").find(roomId) property bool ready: Boolean(userInfo && roomInfo) property bool longLoading: false @@ -58,22 +58,6 @@ Item { ) } - Timer { - interval: 100 - running: ! userInfo - repeat: true - triggeredOnStart: true - onTriggered: userInfo = ModelStore.get("accounts").find(userId) - } - - Timer { - interval: 100 - running: ! roomInfo - repeat: true - triggeredOnStart: true - onTriggered: roomInfo = ModelStore.get(userId, "rooms").find(roomId) - } - Timer { interval: 300 running: ! ready diff --git a/src/gui/PythonBridge/EventHandlers.qml b/src/gui/PythonBridge/EventHandlers.qml index d545ceeb..b5e05b32 100644 --- a/src/gui/PythonBridge/EventHandlers.qml +++ b/src/gui/PythonBridge/EventHandlers.qml @@ -51,16 +51,19 @@ QtObject { py.showError(type, traceback, message) } - function onModelItemSet(syncId, indexThen, indexNow, changedFields){ + function onModelItemSet(syncId, indexThen, indexNow, changedFields) { + const model = ModelStore.get(syncId) + if (indexThen === undefined) { // print("insert", syncId, indexThen, indexNow, // JSON.stringify(changedFields)) - ModelStore.get(syncId).insert(indexNow, changedFields) + model.insert(indexNow, changedFields) + model.idToItems[changedFields.id] = model.get(indexNow) + model.idToItemsChanged() } else { // print("set", syncId, indexThen, indexNow, // JSON.stringify(changedFields)) - const model = ModelStore.get(syncId) model.set(indexThen, changedFields) if (indexThen !== indexNow) model.move(indexThen, indexNow, 1) @@ -69,14 +72,22 @@ QtObject { } } - function onModelItemDeleted(syncId, index, count=1) { - // print("delete", syncId, index, count) - ModelStore.get(syncId).remove(index, count) + function onModelItemDeleted(syncId, index, count=1, ids=[]) { + // print("delete", syncId, index, count, ids) + const model = ModelStore.get(syncId) + model.remove(index, count) + + for (let i = 0; i < ids.length; i++) { + delete model.idToItems[ids[i]] + } + + if (ids.length) model.idToItemsChanged() } function onModelCleared(syncId) { // print("clear", syncId) ModelStore.get(syncId).clear() + model.idToItems = {} } function onDevicesUpdated(forAccount) {