From 64c19e194e003821dd5e4fb6df91b1afd250b08b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Csaba=20Gy=C3=B6rgyi?= Date: Wed, 24 Apr 2024 17:36:34 +0200 Subject: [PATCH] Update models for subtasks upon changes The tid_to_subtask_model field keeps track of the ListStores created for subtasks. The _remove_from_parent_model and _append_to_model helper functions update these models when a change happens. This functionality helps to keep the UI up-to-date. This fixes one of the problems listed in GitHub issue #1018 --- GTG/core/tasks.py | 69 ++++++++++++++++++++++++++++++++---- GTG/gtk/browser/task_pane.py | 7 ---- 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/GTG/core/tasks.py b/GTG/core/tasks.py index 3f05287a7..f527e3b10 100644 --- a/GTG/core/tasks.py +++ b/GTG/core/tasks.py @@ -699,6 +699,7 @@ def __init__(self) -> None: self.model = Gio.ListStore.new(Task) self.tree_model = Gtk.TreeListModel.new(self.model, False, False, self.model_expand) + self.tid_to_subtask_model = dict() def model_expand(self, item): @@ -712,6 +713,7 @@ def model_expand(self, item): for child in item.children: model.append(child) + self.tid_to_subtask_model[item.id] = model return Gtk.TreeListModel.new(model, False, False, self.model_expand) @@ -893,6 +895,37 @@ def to_xml(self) -> Element: return root + + def _remove_from_parent_model(self,task_id: UUID) -> None: + """ + Remove the task indicated by task_id from the model of its parent's subtasks. + This is required to trigger a GUI update. + """ + item = self.lookup[task_id] + if item.parent is None: + return + if item.parent.id not in self.tid_to_subtask_model: + return + model = self.tid_to_subtask_model[item.parent.id] + pos = model.find(item) + if pos[0]: model.remove(pos[1]) + + + def _append_to_parent_model(self,task_id: UUID) -> None: + """ + Appends the task indicated by task_id to the model of its parent's subtasks. + This is required to trigger a GUI update. + """ + item = self.lookup[task_id] + if item.parent is None: + return + if item.parent.id not in self.tid_to_subtask_model: + return + model = self.tid_to_subtask_model[item.parent.id] + pos = model.find(item) + if not pos[0]: model.append(item) + + def add(self, item: Any, parent_id: UUID = None) -> None: """Add a task to the taskstore.""" @@ -900,6 +933,9 @@ def add(self, item: Any, parent_id: UUID = None) -> None: if not parent_id: self.model.append(item) + else: + self._append_to_parent_model(item.id) + self.lookup[parent_id].notify('has_children') item.duplicate_cb = self.duplicate_for_recurrent self.notify('task_count_all') @@ -913,8 +949,12 @@ def remove(self, item_id: UUID) -> None: # Remove from UI item = self.lookup[item_id] - pos = self.model.find(item) - self.model.remove(pos[1]) + if item.parent is not None: + self._remove_from_parent_model(item.id) + item.parent.notify('has_children') + else: + pos = self.model.find(item) + self.model.remove(pos[1]) super().remove(item_id) @@ -924,23 +964,38 @@ def remove(self, item_id: UUID) -> None: def parent(self, item_id: UUID, parent_id: UUID) -> None: - super().parent(item_id, parent_id) + item = self.lookup[item_id] # Remove from UI - item = self.lookup[item_id] - pos = self.model.find(item) - self.model.remove(pos[1]) + if item.parent is not None: + self._remove_from_parent_model(item_id) + item.parent.notify('has_children') + else: + pos = self.model.find(item) + self.model.remove(pos[1]) + + super().parent(item_id, parent_id) + + # Add back to UI + self._append_to_parent_model(item_id) + item.parent.notify('has_children') def unparent(self, item_id: UUID, parent_id: UUID) -> None: - super().unparent(item_id, parent_id) item = self.lookup[item_id] parent = self.lookup[parent_id] + # Remove from UI + self._remove_from_parent_model(item_id) + item.parent.notify('has_children') + + super().unparent(item_id, parent_id) + # remove inline references to the former subtask parent.content = re.sub(r'\{\!\s*'+str(item_id)+r'\s*\!\}','',parent.content) + # Add back to UI self.model.append(item) parent.notify('has_children') diff --git a/GTG/gtk/browser/task_pane.py b/GTG/gtk/browser/task_pane.py index 9e3924fec..ff23ed92d 100644 --- a/GTG/gtk/browser/task_pane.py +++ b/GTG/gtk/browser/task_pane.py @@ -629,8 +629,6 @@ def drag_drop(self, target, task, x, y): self.ds.tasks.parent(task.id, dropped.id) self.refresh() - self.emit('collapse-all') - self.emit('expand-all') def on_task_RMB_click(self, gesture, sequence) -> None: @@ -664,11 +662,6 @@ def on_toplevel_tag_drop(self, drop_target, task, x, y): self.ds.tasks.tree_model.emit('items-changed', 0, 0, 0) self.refresh() - # Not pretty, but needed to force the update of - # the parent task and it's remaining children - self.emit('collapse-all') - self.emit('expand-all') - return True else: return False