Protect proxy/filter models with write_lock
This commit is contained in:
parent
9862e39108
commit
de894ab4bb
|
@ -33,42 +33,47 @@ class ModelFilter(ModelProxy):
|
|||
value: "ModelItem",
|
||||
_changed_fields: Optional[Dict[str, Any]] = None,
|
||||
) -> None:
|
||||
if self.accept_source(source):
|
||||
value = self.convert_item(value)
|
||||
with self.write_lock:
|
||||
if self.accept_source(source):
|
||||
value = self.convert_item(value)
|
||||
|
||||
if self.accept_item(value):
|
||||
self.__setitem__((source.sync_id, key), value, _changed_fields)
|
||||
self.filtered_out.pop((source.sync_id, key), None)
|
||||
else:
|
||||
self.filtered_out[source.sync_id, key] = value
|
||||
self.pop((source.sync_id, key), None)
|
||||
if self.accept_item(value):
|
||||
self.__setitem__(
|
||||
(source.sync_id, key), value, _changed_fields,
|
||||
)
|
||||
self.filtered_out.pop((source.sync_id, key), None)
|
||||
else:
|
||||
self.filtered_out[source.sync_id, key] = value
|
||||
self.pop((source.sync_id, key), None)
|
||||
|
||||
for callback in self.items_changed_callbacks:
|
||||
callback()
|
||||
for callback in self.items_changed_callbacks:
|
||||
callback()
|
||||
|
||||
|
||||
def source_item_deleted(self, source: Model, key) -> None:
|
||||
if self.accept_source(source):
|
||||
try:
|
||||
del self[source.sync_id, key]
|
||||
except KeyError:
|
||||
del self.filtered_out[source.sync_id, key]
|
||||
with self.write_lock:
|
||||
if self.accept_source(source):
|
||||
try:
|
||||
del self[source.sync_id, key]
|
||||
except KeyError:
|
||||
del self.filtered_out[source.sync_id, key]
|
||||
|
||||
for callback in self.items_changed_callbacks:
|
||||
callback()
|
||||
for callback in self.items_changed_callbacks:
|
||||
callback()
|
||||
|
||||
|
||||
def source_cleared(self, source: Model) -> None:
|
||||
if self.accept_source(source):
|
||||
for source_sync_id, key in self.copy():
|
||||
if source_sync_id == source.sync_id:
|
||||
try:
|
||||
del self[source.sync_id, key]
|
||||
except KeyError:
|
||||
del self.filtered_out[source.sync_id, key]
|
||||
with self.write_lock:
|
||||
if self.accept_source(source):
|
||||
for source_sync_id, key in self.copy():
|
||||
if source_sync_id == source.sync_id:
|
||||
try:
|
||||
del self[source.sync_id, key]
|
||||
except KeyError:
|
||||
del self.filtered_out[source.sync_id, key]
|
||||
|
||||
for callback in self.items_changed_callbacks:
|
||||
callback()
|
||||
for callback in self.items_changed_callbacks:
|
||||
callback()
|
||||
|
||||
|
||||
def refilter(
|
||||
|
|
|
@ -188,27 +188,28 @@ class Model(MutableMapping):
|
|||
and one `ModelItemDeleted` pyotherside event is fired per sequence.
|
||||
"""
|
||||
|
||||
try:
|
||||
self._active_batch_remove_indice = []
|
||||
yield None
|
||||
finally:
|
||||
indice = self._active_batch_remove_indice
|
||||
groups = [list(group) for item, group in itertools.groupby(indice)]
|
||||
last = None
|
||||
with self.write_lock:
|
||||
try:
|
||||
self._active_batch_remove_indice = []
|
||||
yield None
|
||||
finally:
|
||||
indice = self._active_batch_remove_indice
|
||||
groups = [list(group) for item, group in itertools.groupby(indice)]
|
||||
last = None
|
||||
|
||||
if groups:
|
||||
last = groups[-1].pop()
|
||||
if not groups[-1]:
|
||||
del groups[-1]
|
||||
if groups:
|
||||
last = groups[-1].pop()
|
||||
if not groups[-1]:
|
||||
del groups[-1]
|
||||
|
||||
for grp in groups:
|
||||
ModelItemDeleted(self.sync_id, index=grp[0], count=len(grp))
|
||||
for grp in groups:
|
||||
ModelItemDeleted(self.sync_id, index=grp[0], count=len(grp))
|
||||
|
||||
# Seems QML ListView has an horrible bug where removing a large
|
||||
# amount of items at once will result in a corrupted empty display,
|
||||
# this dumb workaround is the only way I've found
|
||||
if last:
|
||||
time.sleep(0.2)
|
||||
ModelItemDeleted(self.sync_id, index=last, count=1)
|
||||
# Seems QML ListView has an horrible bug where removing a large
|
||||
# amount of items at once will result in a corrupted empty display,
|
||||
# this dumb workaround is the only way I've found
|
||||
if last:
|
||||
time.sleep(0.2)
|
||||
ModelItemDeleted(self.sync_id, index=last, count=1)
|
||||
|
||||
self._active_batch_remove_indice = None
|
||||
self._active_batch_remove_indice = None
|
||||
|
|
|
@ -17,10 +17,11 @@ class ModelProxy(Model):
|
|||
self.take_items_ownership = False
|
||||
Model.proxies[sync_id] = self
|
||||
|
||||
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)
|
||||
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)
|
||||
|
||||
|
||||
def accept_source(self, source: Model) -> bool:
|
||||
|
|
Loading…
Reference in New Issue
Block a user