[meld/ui-next] ui.recentselector: New implementation of a recent comparison selector



commit 2abd8e02c37c3d70906a3f0d9c79435a7e22df5b
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Fri Feb 22 10:16:27 2019 +1000

    ui.recentselector: New implementation of a recent comparison selector
    
    This is a relatively small widget template whose entire purpose is to be
    put into a popover so that we have recent selection from a headerbar
    button.

 meld/recent.py                       |  2 +-
 meld/resources/meld.gresource.xml    |  1 +
 meld/resources/ui/recent-selector.ui | 58 ++++++++++++++++++++++
 meld/ui/recentselector.py            | 95 ++++++++++++++++++++++++++++++++++++
 4 files changed, 155 insertions(+), 1 deletion(-)
---
diff --git a/meld/recent.py b/meld/recent.py
index ad8bfc80..4a63607e 100644
--- a/meld/recent.py
+++ b/meld/recent.py
@@ -211,7 +211,7 @@ class RecentFiles:
             for attr in attrs:
                 filter_data[attr] = getattr(i, "get_" + attr)()
             filter_info = Gtk.RecentFilterInfo()
-            filter_info.contains = recent_filter.get_needed()
+            filter_info.contains = needed
             for f, v in filter_data.items():
                 # https://bugzilla.gnome.org/show_bug.cgi?id=695970
                 if isinstance(v, list):
diff --git a/meld/resources/meld.gresource.xml b/meld/resources/meld.gresource.xml
index f9f418d5..ae89d70c 100644
--- a/meld/resources/meld.gresource.xml
+++ b/meld/resources/meld.gresource.xml
@@ -22,6 +22,7 @@
     <file>ui/patch-dialog.ui</file>
     <file>ui/preferences.ui</file>
     <file>ui/push-dialog.ui</file>
+    <file>ui/recent-selector.ui</file>
     <file>ui/revert-dialog.ui</file>
     <file>ui/save-confirm-dialog.ui</file>
     <file>ui/vcview.ui</file>
diff --git a/meld/resources/ui/recent-selector.ui b/meld/resources/ui/recent-selector.ui
new file mode 100644
index 00000000..ba63ed55
--- /dev/null
+++ b/meld/resources/ui/recent-selector.ui
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <template class="RecentSelector" parent="GtkGrid">
+    <property name="width_request">400</property>
+    <property name="height_request">500</property>
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="border_width">6</property>
+    <property name="row_spacing">6</property>
+    <child>
+      <object class="GtkSearchEntry" id="search_entry">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="has_focus">True</property>
+        <property name="activates_default">True</property>
+        <property name="placeholder_text" translatable="yes">Search recent comparisons…</property>
+        <signal name="changed" handler="on_filter_text_changed" swapped="no"/>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkRecentChooserWidget" id="recent_chooser">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="hexpand">True</property>
+        <property name="show_icons">False</property>
+        <property name="show_not_found">False</property>
+        <property name="show_private">True</property>
+        <property name="sort_type">mru</property>
+        <signal name="item-activated" handler="on_activate" swapped="no"/>
+        <signal name="selection-changed" handler="on_selection_changed" swapped="no"/>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkButton" id="open_button">
+        <property name="label">gtk-open</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="can_default">True</property>
+        <property name="use_stock">True</property>
+        <signal name="clicked" handler="on_activate" swapped="no"/>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">2</property>
+      </packing>
+    </child>
+  </template>
+</interface>
diff --git a/meld/ui/recentselector.py b/meld/ui/recentselector.py
new file mode 100644
index 00000000..fc4e3e14
--- /dev/null
+++ b/meld/ui/recentselector.py
@@ -0,0 +1,95 @@
+# Copyright (C) 2019 Kai Willadsen <kai willadsen gmail com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+from gi.repository import GObject
+from gi.repository import Gtk
+
+from meld.recent import RecentFiles
+from meld.ui._gtktemplate import Template
+
+
+@Template(resource_path='/org/gnome/meld/ui/recent-selector.ui')
+class RecentSelector(Gtk.Grid):
+
+    __gtype_name__ = 'RecentSelector'
+
+    @GObject.Signal(
+        flags=(
+            GObject.SignalFlags.RUN_FIRST |
+            GObject.SignalFlags.ACTION
+        ),
+        arg_types=(str,),
+    )
+    def open_recent(self, uri: str) -> None:
+        ...
+
+    recent_chooser = Template.Child()
+    search_entry = Template.Child()
+    open_button = Template.Child()
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.init_template()
+
+        self.filter_text = ''
+        self.recent_chooser.set_filter(self.make_recent_filter())
+
+    def custom_recent_filter_func(
+            self, filter_info: Gtk.RecentFilterInfo) -> bool:
+        """Filter function for Meld-specific files
+
+        Normal GTK recent filter rules are all OR-ed together to check
+        whether an entry should be shown. This filter instead only ever
+        shows Meld-specific entries, and then filters down from there.
+        """
+
+        if filter_info.mime_type != RecentFiles.mime_type:
+            return False
+
+        if self.filter_text not in filter_info.display_name.lower():
+            return False
+
+        return True
+
+    def make_recent_filter(self) -> Gtk.RecentFilter:
+        recent_filter = Gtk.RecentFilter()
+        recent_filter.add_custom(
+            (
+                Gtk.RecentFilterFlags.MIME_TYPE |
+                Gtk.RecentFilterFlags.DISPLAY_NAME
+            ),
+            self.custom_recent_filter_func,
+        )
+        return recent_filter
+
+    @Template.Callback()
+    def on_filter_text_changed(self, *args):
+        self.filter_text = self.search_entry.get_text().lower()
+
+        # This feels unnecessary, but there's no other good way to get
+        # the RecentChooser to re-evaluate the filter.
+        self.recent_chooser.set_filter(self.make_recent_filter())
+
+    @Template.Callback()
+    def on_selection_changed(self, *args):
+        have_selection = bool(self.recent_chooser.get_current_uri())
+        self.open_button.set_sensitive(have_selection)
+
+    @Template.Callback()
+    def on_activate(self, *args):
+        uri = self.recent_chooser.get_current_uri()
+        if uri:
+            self.open_recent.emit(uri)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]