moment/src/backend/models/proxy.py

74 lines
2.3 KiB
Python
Raw Normal View History

2020-05-06 14:26:52 +10:00
# SPDX-License-Identifier: LGPL-3.0-or-later
from typing import TYPE_CHECKING, Any, Dict, Optional
2020-05-06 14:26:52 +10:00
from . import SyncId
from .model import Model
if TYPE_CHECKING:
from .model_item import ModelItem
class ModelProxy(Model):
2020-05-22 10:45:02 +10:00
"""Proxies data from one or more `Model` objects."""
2020-05-06 14:26:52 +10:00
def __init__(self, sync_id: SyncId) -> None:
super().__init__(sync_id)
self.take_items_ownership = False
2020-05-06 14:26:52 +10:00
Model.proxies[sync_id] = self
with self.write_lock:
for sync_id, model in Model.instances.items():
if sync_id != self.sync_id and self.accept_source(model):
for key, item in model.items():
self.source_item_set(model, key, item)
2020-05-06 14:26:52 +10:00
def accept_source(self, source: Model) -> bool:
2020-05-22 10:45:02 +10:00
"""Return whether passed `Model` should be proxied by this proxy."""
2020-05-06 14:26:52 +10:00
return True
def convert_item(self, item: "ModelItem") -> "ModelItem":
2020-05-22 10:45:02 +10:00
"""Take a source `ModelItem`, return an appropriate one for proxy.
By default, this returns the passed item unchanged.
Due to QML `ListModel` restrictions, if multiple source models
containing different subclasses of `ModelItem` are proxied,
they should be converted to a same `ModelItem`
subclass by overriding this function.
"""
return item
def source_item_set(
self,
source: Model,
key,
value: "ModelItem",
_changed_fields: Optional[Dict[str, Any]] = None,
) -> None:
2020-05-22 10:45:02 +10:00
"""Called when a source model item is added or changed."""
2020-05-06 14:26:52 +10:00
if self.accept_source(source):
value = self.convert_item(value)
self.__setitem__((source.sync_id, key), value, _changed_fields)
2020-05-06 14:26:52 +10:00
def source_item_deleted(self, source: Model, key) -> None:
2020-05-22 10:45:02 +10:00
"""Called when a source model item is removed."""
2020-05-06 14:26:52 +10:00
if self.accept_source(source):
del self[source.sync_id, key]
def source_cleared(self, source: Model) -> None:
2020-05-22 10:45:02 +10:00
"""Called when a source model is cleared."""
2020-05-06 14:26:52 +10:00
if self.accept_source(source):
with self.batch_remove():
for source_sync_id, key in self.copy():
if source_sync_id == source.sync_id:
del self[source_sync_id, key]