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



commit 8024b7570468bbbb5c7f2a8fd0f41faaaa5607b6
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 is inside a template it is created through a
    g_object_new and does not have a python wrapper when
    pygobject__g_instance_init is called. In that case, a wrapper is
    created and the "__init__" method is called to instantiate it. Then,
    "init_template" is called to init its own template (if it exists).
    
    However, "init_template" before the object constructor in order to
    create and instantiate all its children, signal and properties.
    
    This issue is fixed by calling init_template before the contructor if
    the python object has created through g_object_new.
    
    A new test for the template hierarchy is added (based on an example
    from Marinus Schraal).
    
    Closes: #257

 gi/gimodule.c              | 18 +++++++++---
 tests/test_gtk_template.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 84 insertions(+), 4 deletions(-)
---
diff --git a/gi/gimodule.c b/gi/gimodule.c
index 1b997617..b931c197 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -1096,15 +1096,25 @@ pygobject__g_instance_init(GTypeInstance   *instance,
          * will take the ref */
         pygobject_ref_float ((PyGObject *) wrapper);
 
+       /* XXX: used for Gtk.Template */
+        /* if the object is inside a Gtk.Template, it has been created through
+          g_object_new. Its own template needs to be initialized before the
+          constructor call.
+        */
+        if (PyObject_HasAttrString ((PyObject*) Py_TYPE (wrapper), "__dontuse_ginstance_init__")) {
+            result = PyObject_CallMethod (wrapper, "__dontuse_ginstance_init__", NULL);
+            if (result == NULL)
+                PyErr_Print ();
+            else
+                Py_DECREF (result);
+        }
+
         result = PyObject_CallMethod (wrapper, "__init__", NULL);
         if (result == NULL)
             PyErr_Print ();
         else
             Py_DECREF (result);
-    }
-
-    /* XXX: used for Gtk.Template */
-    if (PyObject_HasAttrString ((PyObject*) Py_TYPE (wrapper), "__dontuse_ginstance_init__")) {
+    } else if (PyObject_HasAttrString ((PyObject*) Py_TYPE (wrapper), "__dontuse_ginstance_init__")) {
         result = PyObject_CallMethod (wrapper, "__dontuse_ginstance_init__", NULL);
         if (result == NULL)
             PyErr_Print ();
diff --git a/tests/test_gtk_template.py b/tests/test_gtk_template.py
index 3a1c1f02..b11e0be9 100644
--- a/tests/test_gtk_template.py
+++ b/tests/test_gtk_template.py
@@ -590,3 +590,73 @@ 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)
+            assert len(self._testbox.get_children()) == 2
+
+    win = MyWindow()
+    assert isinstance(win, MyWindow)


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