Add a batch set_fields method to Model

This commit is contained in:
miruka
2020-07-01 12:00:50 -04:00
parent 5476e00b9b
commit 4752abf6e5
4 changed files with 75 additions and 43 deletions

View File

@@ -33,32 +33,34 @@ class ModelItem:
def __setattr__(self, name: str, value) -> None:
"""If this item is in a `Model`, alert it of attribute changes."""
if name == "parent_model" or not self.parent_model:
if (
name == "parent_model" or
not self.parent_model or
getattr(self, name) == value
):
super().__setattr__(name, value)
return
if getattr(self, name) == value:
return
super().__setattr__(name, value)
self._notify_parent_model({name: self.serialize_field(name)})
def _notify_parent_model(self, changed_fields: Dict[str, Any]) -> None:
parent = self.parent_model
if not parent.sync_id:
if not parent or not parent.sync_id or not changed_fields:
return
fields = {name: self.serialize_field(name)}
with parent.write_lock:
index_then = parent._sorted_data.index(self)
parent._sorted_data.sort()
index_now = parent._sorted_data.index(self)
ModelItemSet(parent.sync_id, index_then, index_now, fields)
ModelItemSet(parent.sync_id, index_then, index_now, changed_fields)
for sync_id, proxy in parent.proxies.items():
if sync_id != parent.sync_id:
proxy.source_item_set(parent, self.id, self, fields)
proxy.source_item_set(parent, self.id, self, changed_fields)
def __delattr__(self, name: str) -> None:
@@ -82,3 +84,20 @@ class ModelItem:
name.startswith("_") or name in ("parent_model", "serialized")
)
}
def set_fields(self, **fields: Any) -> None:
"""Set multiple fields's values at once.
The parent model will be resorted only once, and one `ModelItemSet`
event will be sent informing QML of all the changed fields.
"""
for name, value in fields.copy().items():
if getattr(self, name) == value:
del fields[name]
else:
super().__setattr__(name, value)
fields[name] = self.serialize_field(name)
self._notify_parent_model(fields)