diff --git a/GTG/gtk/browser/main_window.py b/GTG/gtk/browser/main_window.py index 04fdfc162b..98f07d465a 100644 --- a/GTG/gtk/browser/main_window.py +++ b/GTG/gtk/browser/main_window.py @@ -283,11 +283,9 @@ def _init_ui_widget(self): quickadd_focus_controller.connect('leave', self.on_quickadd_focus_out) self.quickadd_entry.add_controller(quickadd_focus_controller) - # TODO: Re-enable with Gtk 4.6 - # tag_completion = TagCompletion(self.req.get_tag_tree()) - # self.modifytags_dialog = ModifyTagsDialog(tag_completion, self.req, self.app) - # self.modifytags_dialog.set_transient_for(self) - self.modifytags_dialog = None + tag_completion = TagCompletion(self.app.ds.tags) + self.modifytags_dialog = ModifyTagsDialog(tag_completion, self.app) + self.modifytags_dialog.set_transient_for(self) self.deletetags_dialog = DeleteTagsDialog(self) self.calendar = GTGCalendar() @@ -1320,7 +1318,7 @@ def on_date_changed(self, calendar): def on_modify_tags(self, action, params): """Open modify tags dialog for selected tasks.""" - tasks = self.get_selected_tasks() + tasks = self.task_pane.get_selection() self.modifytags_dialog.modify_tags(tasks) def close_all_task_editors(self, task_id): diff --git a/GTG/gtk/browser/modify_tags.py b/GTG/gtk/browser/modify_tags.py index b7a1afcde3..d307d54bdd 100644 --- a/GTG/gtk/browser/modify_tags.py +++ b/GTG/gtk/browser/modify_tags.py @@ -35,10 +35,9 @@ class ModifyTagsDialog(Gtk.Dialog): _tag_entry = Gtk.Template.Child() _apply_to_subtasks_check = Gtk.Template.Child() - def __init__(self, tag_completion, req, app): + def __init__(self, tag_completion, app): super().__init__() - self.req = req self.app = app self.tasks = [] @@ -48,9 +47,31 @@ def __init__(self, tag_completion, req, app): self.last_tag_entry = _("NewTag") self.last_apply_to_subtasks = False + + def parse_tag_list(self, text): + """ Parse a line of a list of tasks. User can specify if the tag is + positive or not by prepending '!'. + + @param text: string entry from user + @return: list of tupples (tag, is_positive) + """ + + result = [] + for tag in text.split(): + if tag.startswith('!'): + tag = tag[1:] + is_positive = False + else: + is_positive = True + + result.append((tag, is_positive)) + return result + + def modify_tags(self, tasks): """ Show and run dialog for selected tasks """ - if len(tasks) == 0: + + if not tasks: return self.tasks = tasks @@ -61,54 +82,36 @@ def modify_tags(self, tasks): self.show() - self.tasks = [] - @Gtk.Template.Callback() def on_response(self, widget, response): if response == Gtk.ResponseType.APPLY: self.apply_changes() + self.hide() def apply_changes(self): """ Apply changes """ - tags = parse_tag_list(self._tag_entry.get_text()) + + tags = self.parse_tag_list(self._tag_entry.get_text()) # If the checkbox is checked, find all subtasks if self._apply_to_subtasks_check.get_active(): - for task_id in self.tasks: - task = self.req.get_task(task_id) - # FIXME: Python not reinitialize the default value of its - # parameter therefore it must be done manually. This function - # should be refractored # as far it is marked as depricated - for subtask in task.get_subtasks(): - subtask_id = subtask.get_id() - if subtask_id not in self.tasks: - self.tasks.append(subtask_id) - - for task_id in self.tasks: - task = self.req.get_task(task_id) - for tag, is_positive in tags: - if is_positive: - task.add_tag(tag) - else: - task.remove_tag(tag) - task.sync() - - # TODO: New Core - for tid in self.tasks: - t = self.app.ds.tasks.get(tid) + for task in self.tasks: + for subtask in task.children: + if subtask not in self.tasks: + self.tasks.append(subtask) + for task in self.tasks: for tag, is_positive in tags: _tag = self.app.ds.tags.new(tag) if is_positive: - t.add_tag(_tag) + task.add_tag(_tag) else: - t.remove_tag(_tag) + task.remove_tag(_tag) self.app.ds.save() # Rember the last actions self.last_tag_entry = self._tag_entry.get_text() self.last_apply_to_subtasks = self._apply_to_subtasks_check.get_active() -# ----------------------------------------------------------------------------- diff --git a/GTG/gtk/tag_completion.py b/GTG/gtk/tag_completion.py index 84c9ab2589..febe71c561 100644 --- a/GTG/gtk/tag_completion.py +++ b/GTG/gtk/tag_completion.py @@ -63,7 +63,7 @@ class TagCompletion(Gtk.EntryCompletion): The list of tasks is updated by LibLarch callbacks """ - def __init__(self, tree): + def __init__(self, tagstore): """ Initialize entry completion Create a list store which is connected to a LibLarch and @@ -72,13 +72,6 @@ def __init__(self, tree): self.tags = Gtk.ListStore(str) - tree = tree.get_basetree() - tree.add_filter(FILTER_NAME, tag_filter, {'flat': True}) - tag_tree = tree.get_viewtree('tag_completion', False) - tag_tree.register_cllbck('node-added-inview', self._on_tag_added) - tag_tree.register_cllbck('node-deleted-inview', self._on_tag_deleted) - tag_tree.apply_filter(FILTER_NAME) - self.set_model(self.tags) self.set_text_column(0) self.set_match_func(tag_match, 0) @@ -86,9 +79,14 @@ def __init__(self, tree): self.set_inline_selection(True) self.set_popup_single_match(False) + for tag in tagstore.lookup.values(): + self._on_tag_added(tag.name) + + def _try_insert(self, name): """ Insert an item into ListStore if it is not already there. It keeps the list sorted. """ + position = 0 for position, row in enumerate(self.tags, 1): if row[0] == name: @@ -97,25 +95,32 @@ def _try_insert(self, name): elif row[0] > name: position -= 1 break + self.tags.insert(position, (name, )) - def _on_tag_added(self, tag, path): + + def _on_tag_added(self, tag): """ Add all variants of tag """ + tag = normalize_unicode(tag) self._try_insert(tag) self._try_insert('!' + tag) self._try_insert(tag[1:]) self._try_insert('!' + tag[1:]) + def _try_delete(self, name): """ Delete an item if it is in the list """ + for row in self.tags: if row[0] == name: self.tags.remove(row.iter) break + def _on_tag_deleted(self, tag, path): """ Delete all variants of tag """ + tag = normalize_unicode(tag) self._try_delete(tag) self._try_delete('!' + tag)