[meld/ui-next] dirdiff: Move custom filter actions to dynamically populated GActions
- From: Kai Willadsen <kaiw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [meld/ui-next] dirdiff: Move custom filter actions to dynamically populated GActions
- Date: Sat, 23 Mar 2019 02:01:26 +0000 (UTC)
commit 8e3090802ad41531902da5ba37630f486f882be9
Author: Kai Willadsen <kai willadsen gmail com>
Date: Sat Feb 23 08:09:09 2019 +1000
dirdiff: Move custom filter actions to dynamically populated GActions
This really feels like bending `GAction` to do a thing that it wasn't
really intended to do, but I can't think of any other way to make the
appropriate UI happen. It's unpleasant here that we have dynamic action
creation as a window-level concern, but the dynamic action creation
occurs in `DirDiff` itself. I mean... this is correct, but it doesn't
feel great.
data/ui/dirdiff-ui.xml | 9 -----
data/ui/meldapp-ui.xml | 3 --
meld/const.py | 2 ++
meld/dirdiff.py | 85 +++++++++-----------------------------------
meld/meldwindow.py | 25 ++++++++++++-
meld/menuhelpers.py | 23 ++++++++++++
meld/resources/gtk/menus.ui | 3 ++
meld/resources/ui/dirdiff.ui | 8 -----
8 files changed, 69 insertions(+), 89 deletions(-)
---
diff --git a/data/ui/dirdiff-ui.xml b/data/ui/dirdiff-ui.xml
index c5a7e1e7..f1efab76 100644
--- a/data/ui/dirdiff-ui.xml
+++ b/data/ui/dirdiff-ui.xml
@@ -1,16 +1,7 @@
<ui>
- <toolbar name="Toolbar">
- <placeholder name="FilterActions">
- <toolitem action="CustomFilterMenu"/>
- </placeholder>
- </toolbar>
-
<popup name="Popup">
<menuitem action="DirCollapseRecursively" />
<menuitem action="DirExpandRecursively" />
</popup>
-
- <popup name="CustomPopup">
- </popup>
</ui>
diff --git a/data/ui/meldapp-ui.xml b/data/ui/meldapp-ui.xml
index 9f0299b0..c2cabadc 100644
--- a/data/ui/meldapp-ui.xml
+++ b/data/ui/meldapp-ui.xml
@@ -17,13 +17,10 @@
</menu>
<menu action="ViewMenu">
<placeholder name="ViewPlaceholder" />
- <separator/>
- <menu action="FileFilters" />
</menu>
</menubar>
<toolbar action="Toolbar">
- <placeholder name="FilterActions" />
</toolbar>
<popup name="Popup">
diff --git a/meld/const.py b/meld/const.py
index 419319cc..762024a7 100644
--- a/meld/const.py
+++ b/meld/const.py
@@ -26,3 +26,5 @@ NEWLINES = {
GtkSource.NewlineType.CR_LF: ('\r\n', _("DOS/Windows (CR-LF)")),
GtkSource.NewlineType.CR: ('\r', _("Mac OS (CR)")),
}
+
+FILE_FILTER_ACTION_FORMAT = 'folder-custom-filter-{}'
diff --git a/meld/dirdiff.py b/meld/dirdiff.py
index eea08309..38b8323f 100644
--- a/meld/dirdiff.py
+++ b/meld/dirdiff.py
@@ -36,6 +36,7 @@ from gi.repository import Gtk
from meld import misc
from meld import tree
from meld.conf import _, ui_file
+from meld.const import FILE_FILTER_ACTION_FORMAT
from meld.iohelpers import trash_or_confirm
from meld.melddoc import MeldDoc
from meld.misc import all_same, apply_text_filters, with_focused_pane
@@ -593,49 +594,8 @@ class DirDiff(Gtk.VBox, tree.TreeviewCommon, MeldDoc):
last_column = current_column
treeview.set_headers_visible(extra_cols)
- @Template.Callback()
- def on_custom_filter_menu_toggled(self, item):
- if item.get_active():
- self.custom_popup.connect(
- "deactivate", lambda popup: item.set_active(False))
- self.custom_popup.popup_at_widget(
- self.filter_menu_button,
- Gdk.Gravity.SOUTH_WEST,
- Gdk.Gravity.NORTH_WEST,
- None,
- )
-
- def _cleanup_filter_menu_button(self, ui):
- if self.custom_merge_id:
- ui.remove_ui(self.custom_merge_id)
- if self.filter_actiongroup in ui.get_action_groups():
- ui.remove_action_group(self.filter_actiongroup)
-
- def _create_filter_menu_button(self, ui):
- ui.insert_action_group(self.filter_actiongroup, -1)
- self.custom_merge_id = ui.new_merge_id()
- for x in self.filter_ui:
- ui.add_ui(self.custom_merge_id, *x)
- self.custom_popup = ui.get_widget("/CustomPopup")
- self.filter_menu_button = ui.get_widget(
- "/Toolbar/FilterActions/CustomFilterMenu")
- label = misc.make_tool_button_widget(
- self.filter_menu_button.props.label)
- self.filter_menu_button.set_label_widget(label)
-
- def on_container_switch_in_event(self, ui, window):
- MeldDoc.on_container_switch_in_event(self, ui, window)
- self._create_filter_menu_button(ui)
- self.ui_manager = ui
-
- def on_container_switch_out_event(self, ui, window):
- self._cleanup_filter_menu_button(ui)
- MeldDoc.on_container_switch_out_event(self, ui, window)
-
def on_file_filters_changed(self, app):
- self._cleanup_filter_menu_button(self.ui_manager)
relevant_change = self.create_name_filters()
- self._create_filter_menu_button(self.ui_manager)
if relevant_change:
self.refresh()
@@ -647,32 +607,20 @@ class DirDiff(Gtk.VBox, tree.TreeviewCommon, MeldDoc):
if f.active])
active_filters_changed = old_active != new_active
+ # TODO: Rework name_filters to use a map-like structure so that we
+ # don't need _action_name_filter_map.
+ self._action_name_filter_map = {}
self.name_filters = [copy.copy(f) for f in meldsettings.file_filters]
- actions = []
- disabled_actions = []
- self.filter_ui = []
- for i, f in enumerate(self.name_filters):
- name = "Hide%d" % i
- callback = functools.partial(self._update_name_filter, idx=i)
- actions.append((
- name, None, f.label, None, _("Hide %s") % f.label,
- callback, f.active
- ))
- self.filter_ui.append([
- "/CustomPopup", name, name,
- Gtk.UIManagerItemType.MENUITEM, False
- ])
- self.filter_ui.append([
- "/Menubar/ViewMenu/FileFilters", name, name,
- Gtk.UIManagerItemType.MENUITEM, False
- ])
- if f.filter is None:
- disabled_actions.append(name)
-
- self.filter_actiongroup = Gtk.ActionGroup(name="DirdiffFilterActions")
- self.filter_actiongroup.add_toggle_actions(actions)
- for name in disabled_actions:
- self.filter_actiongroup.get_action(name).set_sensitive(False)
+ for i, filt in enumerate(self.name_filters):
+ action = Gio.SimpleAction.new_stateful(
+ name=FILE_FILTER_ACTION_FORMAT.format(i),
+ parameter_type=None,
+ state=GLib.Variant.new_boolean(filt.active),
+ )
+ action.connect('change-state', self._update_name_filter)
+ action.set_enabled(filt.filter is not None)
+ self.view_action_group.add_action(action)
+ self._action_name_filter_map[action] = filt
return active_filters_changed
@@ -1403,8 +1351,9 @@ class DirDiff(Gtk.VBox, tree.TreeviewCommon, MeldDoc):
self.props.status_filters = state_strs
self.refresh()
- def _update_name_filter(self, button, idx):
- self.name_filters[idx].active = button.get_active()
+ def _update_name_filter(self, action, state):
+ self._action_name_filter_map[action].active = state.get_boolean()
+ action.set_state(state)
self.refresh()
#
diff --git a/meld/meldwindow.py b/meld/meldwindow.py
index 8e3f1e7c..fcd4c1fd 100644
--- a/meld/meldwindow.py
+++ b/meld/meldwindow.py
@@ -36,6 +36,12 @@ from meld.ui.notebooklabel import NotebookLabel
from meld.vcview import VcView
from meld.windowstate import SavedWindowState
+
+from meld.const import FILE_FILTER_ACTION_FORMAT
+from meld.settings import meldsettings
+from meld.menuhelpers import replace_menu_section
+
+
log = logging.getLogger(__name__)
@@ -86,7 +92,6 @@ class MeldWindow(Gtk.ApplicationWindow):
("ViewMenu", None, _("_View")),
("FileStatus", None, _("File Status")),
("VcStatus", None, _("Version Status")),
- ("FileFilters", None, _("File Filters")),
)
self.actiongroup = Gtk.ActionGroup(name='MainActions')
self.actiongroup.set_translation_domain("meld")
@@ -179,8 +184,26 @@ class MeldWindow(Gtk.ApplicationWindow):
self.vc_filter_button.set_popover(
Gtk.Popover.new_from_model(self.vc_filter_button, vc_filter_model))
+ self.update_filename_filters()
+ self.settings_handlers = [
+ meldsettings.connect(
+ "file-filters-changed", self.update_filename_filters),
+ ]
+
meld.ui.util.extract_accels_from_menu(menu, self.get_application())
+ def update_filename_filters(self, *args):
+ filter_items_model = Gio.Menu()
+ for i, filt in enumerate(meldsettings.file_filters):
+ name = FILE_FILTER_ACTION_FORMAT.format(i)
+ filter_items_model.append(
+ label=filt.label, detailed_action=f'view.{name}')
+ section = Gio.MenuItem.new_section(_("Filename"), filter_items_model)
+ section.set_attribute([("id", "s", "custom-filter-section")])
+ app = self.get_application()
+ filter_model = app.get_menu_by_id("folder-status-filter-menu")
+ replace_menu_section(filter_model, section)
+
def on_widget_drag_data_received(
self, wid, context, x, y, selection_data, info, time):
uris = selection_data.get_uris()
diff --git a/meld/menuhelpers.py b/meld/menuhelpers.py
new file mode 100644
index 00000000..c7835971
--- /dev/null
+++ b/meld/menuhelpers.py
@@ -0,0 +1,23 @@
+
+from gi.repository import Gio
+
+
+def replace_menu_section(menu: Gio.Menu, section: Gio.MenuItem):
+ """Replaces an existing section in GMenu `menu` with `section`
+
+ The sections are compared by their `id` attributes, with the
+ matching section in `menu` being replaced by the passed `section`.
+
+ If there is no section in `menu` that matches `section`'s `id`
+ attribute, a ValueError is raised.
+ """
+ section_id = section.get_attribute_value("id").get_string()
+ for idx in range(menu.get_n_items()):
+ item_id = menu.get_item_attribute_value(idx, "id").get_string()
+ if item_id == section_id:
+ break
+ else:
+ # FIXME: Better exception
+ raise ValueError("Section %s not found" % section_id)
+ menu.remove(idx)
+ menu.insert_item(idx, section)
diff --git a/meld/resources/gtk/menus.ui b/meld/resources/gtk/menus.ui
index ee0a239e..e5a2635c 100644
--- a/meld/resources/gtk/menus.ui
+++ b/meld/resources/gtk/menus.ui
@@ -143,6 +143,9 @@
<attribute name="action">view.folder-status-modified</attribute>
</item>
</section>
+ <section>
+ <attribute name="id">custom-filter-section</attribute>
+ </section>
<section>
<attribute name="id">options-section</attribute>
<item>
diff --git a/meld/resources/ui/dirdiff.ui b/meld/resources/ui/dirdiff.ui
index 6dff7aa1..e575ce38 100644
--- a/meld/resources/ui/dirdiff.ui
+++ b/meld/resources/ui/dirdiff.ui
@@ -21,14 +21,6 @@
<signal name="activate" handler="on_expand_recursive_clicked" swapped="no"/>
</object>
</child>
- <child>
- <object class="GtkToggleAction" id="CustomFilterMenu">
- <property name="label" translatable="yes">Filters</property>
- <property name="tooltip" translatable="yes">Set active filters</property>
- <property name="is_important">True</property>
- <signal name="toggled" handler="on_custom_filter_menu_toggled" swapped="no"/>
- </object>
- </child>
</object>
<template class="DirDiff" parent="GtkVBox">
<property name="visible">True</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]