summaryrefslogtreecommitdiff
path: root/gtk/gtkwidget.c
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2022-05-16 14:10:20 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2022-07-11 18:24:37 +0100
commit7857c1a66bd8f026d72d661751471de8f2b2e508 (patch)
tree1ad44c26ff410d220703df85afced460d0066bca /gtk/gtkwidget.c
parent636827800525770715bba96671edb2fc0234ccc2 (diff)
downloadgtk+-7857c1a66bd8f026d72d661751471de8f2b2e508.tar.gz
Add gtk_widget_clear_template()
The dual of gtk_widget_init_template(), which should be used to clear the template data associated with a specific GtkWidget type.
Diffstat (limited to 'gtk/gtkwidget.c')
-rw-r--r--gtk/gtkwidget.c83
1 files changed, 73 insertions, 10 deletions
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 3d1a46897d..432e10301b 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -7437,16 +7437,7 @@ gtk_widget_real_destroy (GtkWidget *object)
GObject *child_object = gtk_widget_get_template_child (widget,
class_type,
child_class->name);
-
- g_assert (child_object);
-
- if (!G_IS_OBJECT (child_object))
- {
- g_critical ("Automated component '%s' of class '%s' seems to"
- " have been prematurely finalized",
- child_class->name, g_type_name (class_type));
- }
- else
+ if (G_IS_OBJECT (child_object))
{
FinalizeAssertion *assertion = g_slice_new0 (FinalizeAssertion);
assertion->child_class = child_class;
@@ -10979,6 +10970,78 @@ out:
}
/**
+ * gtk_widget_clear_template:
+ * @widget: the widget with a template
+ * @widget_type: the type of the widget to finalize the template for
+ *
+ * Clears the template data for the given widget.
+ *
+ * This function is the opposite of [method@Gtk.Widget.init_template], and
+ * it is used to clear all the template data from a widget instance.
+ *
+ * You should call this function inside the `GObjectClass.dispose()`
+ * implementation of any widget that called `gtk_widget_init_template()`.
+ * Typically, you will want to call this function last, right before
+ * chaining up to the parent type's dispose implementation, e.g.
+ *
+ * ```c
+ * static void
+ * some_widget_dispose (GObject *gobject)
+ * {
+ * SomeWidget *self = SOME_WIDGET (gobject);
+ *
+ * // Clear the template data for SomeWidget
+ * gtk_widget_clear_template (GTK_WIDGET (self), SOME_TYPE_WIDGET);
+ *
+ * G_OBJECT_CLASS (some_widget_parent_class)->dispose (gobject);
+ * }
+ * ```
+ *
+ * Since: 4.8
+ */
+void
+gtk_widget_clear_template (GtkWidget *widget,
+ GType widget_type)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (g_type_name (widget_type) != NULL);
+
+ GtkWidgetTemplate *template = GTK_WIDGET_GET_CLASS (widget)->priv->template;
+ g_return_if_fail (template != NULL);
+
+ /* Tear down the automatic child data */
+ GHashTable *auto_child_hash = get_auto_child_hash (widget, widget_type, FALSE);
+
+ for (GSList *l = template->children; l != NULL; l = l->next)
+ {
+ AutomaticChildClass *child_class = l->data;
+
+ /* This will drop the reference on the template children */
+ if (auto_child_hash != NULL)
+ {
+ gpointer child = g_hash_table_lookup (auto_child_hash, child_class->name);
+
+ g_assert (child != NULL);
+
+ /* We have to explicitly unparent direct children of this widget */
+ if (GTK_IS_WIDGET (child) && _gtk_widget_get_parent (child) == widget)
+ gtk_widget_unparent (child);
+
+ g_hash_table_remove (auto_child_hash, child_class->name);
+ }
+
+ /* Nullify the field last, to avoid re-entrancy issues */
+ if (child_class->offset != 0)
+ {
+ gpointer field_p;
+
+ field_p = G_STRUCT_MEMBER_P (widget, child_class->offset);
+ (* (gpointer *) field_p) = NULL;
+ }
+ }
+}
+
+/**
* gtk_widget_class_set_template:
* @widget_class: A `GtkWidgetClass`
* @template_bytes: A `GBytes` holding the `GtkBuilder` XML