[pygobject/wip/jfelder/template-hierarchy-fix: 1/2] gtk overrides: Fix template hierarchy issue
- From: Jean Felder <jfelder src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject/wip/jfelder/template-hierarchy-fix: 1/2] gtk overrides: Fix template hierarchy issue
- Date: Fri, 17 Apr 2020 00:17:42 +0000 (UTC)
commit b5013bf7e127a87cf9f1ab0aef048bf8ef9f46c5
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" needs to be called before the object
constructor in order to create and instantiate all its children,
signals and properties.
This issue is fixed by calling init_template before the contructor if
the python object has been created through g_object_new.
A new test for the template hierarchy is added (based on an example
from Marinus Schraal).
Closes: #257, #386
gi/gimodule.c | 13 ++++++---
tests/test_gtk_template.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+), 4 deletions(-)
---
diff --git a/gi/gimodule.c b/gi/gimodule.c
index f3404583..890a6bfa 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -1069,6 +1069,7 @@ pygobject__g_instance_init(GTypeInstance *instance,
GObject *object = (GObject *) instance;
PyObject *wrapper, *result;
PyGILState_STATE state;
+ gboolean needs_init = FALSE;
wrapper = g_object_get_qdata(object, pygobject_wrapper_key);
if (wrapper == NULL) {
@@ -1095,16 +1096,20 @@ pygobject__g_instance_init(GTypeInstance *instance,
* will take the ref */
pygobject_ref_float ((PyGObject *) wrapper);
- result = PyObject_CallMethod (wrapper, "__init__", NULL);
+ needs_init = TRUE;
+ }
+
+ /* XXX: used for Gtk.Template */
+ 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);
}
- /* XXX: used for Gtk.Template */
- if (PyObject_HasAttrString ((PyObject*) Py_TYPE (wrapper), "__dontuse_ginstance_init__")) {
- result = PyObject_CallMethod (wrapper, "__dontuse_ginstance_init__", NULL);
+ if (needs_init) {
+ result = PyObject_CallMethod (wrapper, "__init__", NULL);
if (result == NULL)
PyErr_Print ();
else
diff --git a/tests/test_gtk_template.py b/tests/test_gtk_template.py
index d3388b37..69911c81 100644
--- a/tests/test_gtk_template.py
+++ b/tests/test_gtk_template.py
@@ -586,3 +586,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]