[pygobject/wip/jfelder/template-hierarchy-fix] gtk overrides: Fix template hierarchy issue



commit 3687d17ebad669127c53b996ef5c582606e363e4
Author: Jean Felder <jfelder src gnome org>
Date:   Thu Mar 19 22:20:37 2020 +0100

    gtk overrides: Fix template hierarchy issue
    
    When a widget inside a template has its own template, the children of
    this widget have been registered as Child (by the register_template
    function) but they are not Gtk.Widget yet. They will be constructed
    once the init_template method of the widget is called. It means that
    it's not possible to change a gobject property of a child inside the
    widget constructor for example.
    
    This issue is fixed by overriding GtkWidget constructor. It the
    widget has a template, the init_template method is called.
    
    A new test for the template hierarchy is added (based on an example
    from Marinus Schraal).

 gi/overrides/Gtk.py        |  9 ++++++
 tests/test_gtk_template.py | 69 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+)
---
diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py
index d1ed83da..177f045c 100644
--- a/gi/overrides/Gtk.py
+++ b/gi/overrides/Gtk.py
@@ -137,6 +137,15 @@ class Widget(Gtk.Widget):
 
     translate_coordinates = strip_boolean_result(Gtk.Widget.translate_coordinates)
 
+    def __init__(self, *args, **kwargs):
+        super(Widget, self).__init__(*args, **kwargs)
+
+        # if the widget has a template and is also part of an other
+        # widget, init the template to ensure that all its children
+        # are initialized
+        if hasattr(self, "__dontuse_ginstance_init__"):
+            self.__dontuse_ginstance_init__()
+
     if Gtk._version != "4.0":
         def freeze_child_notify(self):
             super(Widget, self).freeze_child_notify()
diff --git a/tests/test_gtk_template.py b/tests/test_gtk_template.py
index 3a1c1f02..c4ee8e2a 100644
--- a/tests/test_gtk_template.py
+++ b/tests/test_gtk_template.py
@@ -590,3 +590,72 @@ def test_internal_child():
     child = child.get_children()[0]
     assert isinstance(child, Gtk.Label)
     assert child.props.label == "foo"
+
+
+def test_template_hierarchy():
+    testlabel = """
+    <interface>
+      <template class="TestLabel" parent="GtkLabel">
+       </template>
+     </interface>
+    """
+    @Gtk.Template(string=testlabel)
+    class TestLabel(Gtk.Label):
+
+        __gtype_name__ = "TestLabel"
+
+        def __init__(self):
+            super().__init__()
+            self.props.label = "TestLabel"
+
+    testbox = """
+    <interface>
+      <template class="TestBox" parent="GtkBox">
+        <child>
+          <object class="TestLabel" id="_testlabel"/>
+        </child>
+      </template>
+    </interface>
+    """
+    @Gtk.Template(string=testbox)
+    class TestBox(Gtk.Box):
+
+        __gtype_name__ = "TestBox"
+
+        _testlabel = Gtk.Template.Child()
+
+    def __init__(self):
+        super().__init__()
+
+        assert isinstance(self._testlabel, TestLabel)
+
+    window = """
+    <interface>
+      <template class="MyWindow" parent="GtkWindow">
+        <property name="title">"Hellow World"</property>
+        <child>
+          <object class="TestBox" id="_testbox">
+            <child>
+              <object class="TestLabel" id="_testlabel"/>
+            </child>
+          </object>
+        </child>
+      </template>
+    </interface>
+    """
+    @Gtk.Template(string=window)
+    class MyWindow(Gtk.Window):
+
+        __gtype_name__ = "MyWindow"
+
+        _testbox = Gtk.Template.Child()
+        _testlabel = Gtk.Template.Child()
+
+        def __init__(self):
+            super().__init__()
+
+            assert isinstance(self._testbox, TestBox)
+            assert isinstance(self._testlabel, TestLabel)
+
+    win = MyWindow()
+    assert isinstance(win, MyWindow)


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