[pygobject/wip/jfelder/gtk4-sort-list-model] gtk: Add override for Gtk.SortListModel.set_sort_func



commit 80505fe8f3862ce6055314fa34b7d8c42afa0734
Author: Jean Felder <jfelder src gnome org>
Date:   Sat Apr 4 13:09:37 2020 +0200

    gtk: Add override for Gtk.SortListModel.set_sort_func
    
    This function use CompareDataFunc which works with pointers and
    doesn't know anything about GObjects.
    
    The same logic as in Gio.List.sort and Gio.List.insert_sorted is
    used.
    
    An associated unit_test is also added.

 gi/overrides/Gio.py         | 17 +++---------
 gi/overrides/Gtk.py         | 20 +++++++++++++-
 gi/overrides/__init__.py    | 12 ++++++++-
 tests/test_overrides_gtk.py | 66 ++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 98 insertions(+), 17 deletions(-)
---
diff --git a/gi/overrides/Gio.py b/gi/overrides/Gio.py
index 5cc12a6c..c807fe0b 100644
--- a/gi/overrides/Gio.py
+++ b/gi/overrides/Gio.py
@@ -21,9 +21,8 @@
 import warnings
 
 from .._ossighelper import wakeup_on_signal, register_sigint_fallback
-from ..overrides import override, deprecated_init
+from ..overrides import override, deprecated_init, wrap_list_store_sort_func
 from ..module import get_introspection_module
-from gi._gi import pygobject_new_full
 from gi import PyGIWarning
 
 from gi.repository import GLib
@@ -461,16 +460,6 @@ ListModel = override(ListModel)
 __all__.append('ListModel')
 
 
-def _wrap_list_store_sort_func(func):
-
-    def wrap(a, b, *user_data):
-        a = pygobject_new_full(a, False)
-        b = pygobject_new_full(b, False)
-        return func(a, b, *user_data)
-
-    return wrap
-
-
 if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION, GLib.MICRO_VERSION) < (2, 57, 1):
     # The "additions" functionality in splice() was broken in older glib
     # https://bugzilla.gnome.org/show_bug.cgi?id=795307
@@ -487,11 +476,11 @@ else:
 class ListStore(Gio.ListStore):
 
     def sort(self, compare_func, *user_data):
-        compare_func = _wrap_list_store_sort_func(compare_func)
+        compare_func = wrap_list_store_sort_func(compare_func)
         return super(ListStore, self).sort(compare_func, *user_data)
 
     def insert_sorted(self, item, compare_func, *user_data):
-        compare_func = _wrap_list_store_sort_func(compare_func)
+        compare_func = wrap_list_store_sort_func(compare_func)
         return super(ListStore, self).insert_sorted(
             item, compare_func, *user_data)
 
diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py
index 64a5088e..458b0128 100644
--- a/gi/overrides/Gtk.py
+++ b/gi/overrides/Gtk.py
@@ -26,7 +26,8 @@ from collections import abc
 from gi.repository import GObject
 from .._ossighelper import wakeup_on_signal, register_sigint_fallback
 from .._gtktemplate import Template
-from ..overrides import override, strip_boolean_result, deprecated_init
+from ..overrides import (override, strip_boolean_result, deprecated_init,
+                         wrap_list_store_sort_func)
 from ..module import get_introspection_module
 from gi import PyGIDeprecationWarning
 
@@ -1626,6 +1627,23 @@ class TreeModelFilter(Gtk.TreeModelFilter):
 TreeModelFilter = override(TreeModelFilter)
 __all__.append('TreeModelFilter')
 
+
+if Gtk._version == "4.0":
+    class SortListModel(Gtk.SortListModel):
+
+        def __init__(self, model=None, sort_func=None):
+            Gtk.SortListModel.__init__(self, model=model)
+            if sort_func:
+                self.set_sort_func(sort_func)
+
+        def set_sort_func(self, sort_func, *user_data):
+            compare_func = wrap_list_store_sort_func(sort_func)
+            return super(SortListModel, self).set_sort_func(compare_func, *user_data)
+
+    SortListModel = override(SortListModel)
+    __all__.append("SortListModel")
+
+
 if Gtk._version == '3.0':
     class Menu(Gtk.Menu):
         def popup(self, parent_menu_shell, parent_menu_item, func, data, button, activate_time):
diff --git a/gi/overrides/__init__.py b/gi/overrides/__init__.py
index 1572d251..37dfbbe5 100644
--- a/gi/overrides/__init__.py
+++ b/gi/overrides/__init__.py
@@ -6,7 +6,7 @@ import sys
 from pkgutil import get_loader
 
 from gi import PyGIDeprecationWarning
-from gi._gi import CallableInfo
+from gi._gi import CallableInfo, pygobject_new_full
 from gi._constants import \
     TYPE_NONE, \
     TYPE_INVALID
@@ -341,3 +341,13 @@ def strip_boolean_result(method, exc_type=None, exc_str=None, fail_ret=None):
                 raise exc_type(exc_str or 'call failed')
             return fail_ret
     return wrapped
+
+
+def wrap_list_store_sort_func(func):
+
+    def wrap(a, b, *user_data):
+        a = pygobject_new_full(a, False)
+        b = pygobject_new_full(b, False)
+        return func(a, b, *user_data)
+
+    return wrap
diff --git a/tests/test_overrides_gtk.py b/tests/test_overrides_gtk.py
index ff3acba9..44a72666 100644
--- a/tests/test_overrides_gtk.py
+++ b/tests/test_overrides_gtk.py
@@ -14,7 +14,7 @@ from .helper import ignore_gi_deprecation_warnings, capture_glib_warnings
 
 import gi.overrides
 import gi.types
-from gi.repository import GLib, GObject
+from gi.repository import Gio, GLib, GObject
 
 try:
     from gi.repository import Gtk, GdkPixbuf, Gdk
@@ -1190,6 +1190,70 @@ class TestTreeModelRow(unittest.TestCase):
         assert row.previous.previous is None
 
 
+@unittest.skipUnless(Gtk, "Gtk not available")
+@unittest.skipIf(Gtk_version != "4.0", "only in gtk4")
+class TestSortListModel(unittest.TestCase):
+    class Person(GObject.GObject):
+
+        name = GObject.Property(type=str, default="")
+
+        def __init__(self, name):
+            super().__init__()
+            self.props.name = name
+
+    def names_sort(self, name_a, name_b):
+        return name_b.props.name < name_a.props.name
+
+    def test_sort_list_model_init(self):
+        sort_list_model_empty = Gtk.SortListModel()
+        assert isinstance(sort_list_model_empty, Gtk.SortListModel)
+        assert sort_list_model_empty.props.model is None
+        assert sort_list_model_empty.props.has_sort is False
+
+        model = Gio.ListStore.new(self.Person)
+        sort_list_model_with_model = Gtk.SortListModel(model)
+        assert isinstance(sort_list_model_with_model, Gtk.SortListModel)
+        assert sort_list_model_with_model.props.model == model
+        assert sort_list_model_with_model.props.has_sort is False
+
+        sort_list_model_with_sort = Gtk.SortListModel(model, self.names_sort)
+        assert isinstance(sort_list_model_with_sort, Gtk.SortListModel)
+        assert sort_list_model_with_sort.props.model == model
+        assert sort_list_model_with_sort.props.has_sort is True
+
+        john = self.Person("john")
+        bob = self.Person("bob")
+        model.append(john)
+        model.append(bob)
+        assert sort_list_model_with_sort.get_item(0) == bob
+        assert sort_list_model_with_sort.get_item(1) == john
+
+        alice = self.Person("alice")
+        model.append(alice)
+        assert sort_list_model_with_sort.get_item(0) == alice
+        assert sort_list_model_with_sort.get_item(2) == john
+
+    def test_sort_list_model_sort_func(self):
+        model = Gio.ListStore.new(self.Person)
+        sort_model = Gtk.SortListModel(model)
+        sort_model.set_sort_func(self.names_sort)
+        assert isinstance(sort_model, Gtk.SortListModel)
+        assert sort_model.props.model == model
+        assert sort_model.props.has_sort is True
+
+        john = self.Person("john")
+        bob = self.Person("bob")
+        model.append(john)
+        model.append(bob)
+        assert sort_model.get_item(0) == bob
+        assert sort_model.get_item(1) == john
+
+        alice = self.Person("alice")
+        model.append(alice)
+        assert sort_model.get_item(0) == alice
+        assert sort_model.get_item(2) == john
+
+
 @ignore_gi_deprecation_warnings
 @unittest.skipUnless(Gtk, 'Gtk not available')
 class TestTreeModel(unittest.TestCase):


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