summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Pablo Ugarte <juanpablougarte@gmail.com>2013-11-15 22:45:17 -0300
committerJuan Pablo Ugarte <juanpablougarte@gmail.com>2013-11-15 23:44:47 -0300
commit2bc40ad87be072aac2759755df63707d43f8415c (patch)
treed2aef65c7f35a6fcfd1b7be4f77e29d7d785bb77
parentaf72b2dad1f4fa153a7449312841eec4d0a1e1dc (diff)
downloadglade-2bc40ad87be072aac2759755df63707d43f8415c.tar.gz
Sort object dependancy before saving using a topological
sorting algorithm _glade_tsort() instead of g_list_sort() with glade_widget_depends() which is not a transitive property. Closes Bug 709609 "[PATCH] Change way of sorting before writing XML output." Fixes Bug 711858 "editing glade project results in long CPU usage spikes after upgrading to 3.16 and GTK+3.10"
-rw-r--r--gladeui/Makefile.am5
-rw-r--r--gladeui/glade-project.c189
-rw-r--r--gladeui/glade-tsort.c177
-rw-r--r--gladeui/glade-tsort.h51
-rw-r--r--gladeui/glade-widget-adaptor.c26
-rw-r--r--gladeui/glade-widget-private.h36
-rw-r--r--gladeui/glade-widget.c66
-rw-r--r--plugins/gtk+/glade-gtk-entry.c11
-rw-r--r--plugins/gtk+/glade-gtk-size-group.c10
-rw-r--r--plugins/gtk+/glade-gtk-tree-view.c10
-rw-r--r--plugins/gtk+/glade-gtk-widget.c8
-rw-r--r--plugins/gtk+/gtk+.xml.in3
12 files changed, 474 insertions, 118 deletions
diff --git a/gladeui/Makefile.am b/gladeui/Makefile.am
index 7e78bcb4..87d610cc 100644
--- a/gladeui/Makefile.am
+++ b/gladeui/Makefile.am
@@ -119,6 +119,7 @@ libgladeui_2_la_SOURCES = \
glade-signal-class.c \
glade-signal-editor.c \
glade-signal-model.c \
+ glade-tsort.c \
glade-utils.c \
glade-widget.c \
glade-widget-action.c \
@@ -196,9 +197,11 @@ noinst_HEADERS = \
glade-preview-template.h \
glade-private.h \
glade-project-properties.h \
+ glade-tsort.h \
gladeui-resources.h \
glade-drag.h \
- glade-dnd.h
+ glade-dnd.h \
+ glade-widget-private.h
if PLATFORM_WIN32
libgladeui_2_la_LDFLAGS += -no-undefined
diff --git a/gladeui/glade-project.c b/gladeui/glade-project.c
index e1acd14d..b6570f17 100644
--- a/gladeui/glade-project.c
+++ b/gladeui/glade-project.c
@@ -56,6 +56,9 @@
#include "glade-dnd.h"
#include "glade-private.h"
+#include "glade-widget-private.h"
+#include "glade-tsort.h"
+
static void glade_project_target_version_for_adaptor
(GladeProject *project,
GladeWidgetAdaptor *adaptor,
@@ -2582,19 +2585,171 @@ glade_project_write_css_provider_path (GladeProject *project,
}
static gint
-sort_project_dependancies (GObject *a, GObject *b)
+glade_widgets_name_cmp (gconstpointer ga, gconstpointer gb)
{
- GladeWidget *ga, *gb;
+ return g_strcmp0 (glade_widget_get_name ((gpointer)ga), glade_widget_get_name ((gpointer)gb));
+}
- ga = glade_widget_get_from_gobject (a);
- gb = glade_widget_get_from_gobject (b);
+static inline gboolean
+glade_project_widget_hard_depends (GladeWidget *widget, GladeWidget *another)
+{
+ GList *l;
- if (glade_widget_depends (ga, gb))
- return 1;
- else if (glade_widget_depends (gb, ga))
- return -1;
- else
- return strcmp (glade_widget_get_name (ga), glade_widget_get_name (gb));
+ for (l = _glade_widget_peek_prop_refs (another); l; l = g_list_next (l))
+ {
+ GladePropertyClass *klass;
+
+ /* If one of the properties that reference @another is
+ * owned by @widget then @widget depends on @another
+ */
+ if (glade_property_get_widget (l->data) == widget &&
+ (klass = glade_property_get_class (l->data)) &&
+ glade_property_class_get_construct_only (klass))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static _NodeEdge *
+glade_project_get_graph_deps (GladeProject *project)
+{
+ GladeProjectPrivate *priv = project->priv;
+ GList *l, *objects = NULL;
+ _NodeEdge *edges = NULL;
+
+ /* Create list of GladeWidgets */
+ for (l = priv->objects; l; l = g_list_next (l))
+ objects = g_list_prepend (objects, glade_widget_get_from_gobject (l->data));
+
+ /* Sort objects alphabetically */
+ objects = g_list_sort (objects, glade_widgets_name_cmp);
+
+ /* Create edges of the directed graph */
+ for (l = objects; l; l = g_list_next (l))
+ {
+ GladeWidget *predecessor = l->data;
+ GladeWidget *predecessor_top;
+ GList *ll;
+
+ predecessor_top = glade_widget_get_toplevel (predecessor);
+
+ for (ll = objects; ll; ll = g_list_next (ll))
+ {
+ GladeWidget *successor = ll->data;
+ GladeWidget *successor_top;
+
+ successor_top = glade_widget_get_toplevel (successor);
+
+ /* Ignore object within the same toplevel */
+ if (predecessor_top == successor_top)
+ continue;
+
+ /* Check if succesor depends on predecessor and add a corresponding
+ * edge to the dependency graph.
+ * Note that we add the implicit dependency on their respective
+ * toplevels because that is what we care!
+ */
+ if (glade_widget_depends (successor, predecessor))
+ edges = _node_edge_prepend (edges, predecessor_top, successor_top);
+ }
+ }
+
+ g_list_free (objects);
+
+ return edges;
+}
+
+static GList *
+glade_project_get_nodes_from_edges (GladeProject *project, _NodeEdge *edges)
+{
+ _NodeEdge *edge, *hard_edges = NULL;
+ GList *cycles = NULL;
+
+ /* Collect widgets with circular dependencies */
+ for (edge = edges; edge; edge = edge->next)
+ {
+ if (glade_widget_get_parent (edge->successor) == edge->predecessor ||
+ glade_project_widget_hard_depends (edge->predecessor, edge->successor))
+ hard_edges = _node_edge_prepend (hard_edges, edge->predecessor, edge->successor);
+
+ /* Just toplevels */
+ if (glade_widget_get_parent (edge->successor))
+ continue;
+
+ if (!g_list_find (cycles, edge->successor))
+ cycles = g_list_prepend (cycles, edge->successor);
+ }
+
+ /* Sort them alphabetically */
+ cycles = g_list_sort (cycles, glade_widgets_name_cmp);
+
+ if (!hard_edges)
+ return cycles;
+
+ /* Sort them by hard deps */
+ cycles = _glade_tsort (&cycles, &hard_edges);
+
+ if (hard_edges)
+ {
+ GList *hard_cycles = NULL;
+
+ /* Collect widgets with hard circular dependencies */
+ for (edge = hard_edges; edge; edge = edge->next)
+ {
+ /* Just toplevels */
+ if (glade_widget_get_parent (edge->successor))
+ continue;
+
+ if (!g_list_find (hard_cycles, edge->successor))
+ hard_cycles = g_list_prepend (hard_cycles, edge->successor);
+ }
+
+ /* And append to the end of the cycles list */
+ cycles = g_list_concat (cycles, g_list_sort (hard_cycles, glade_widgets_name_cmp));
+
+ /* Opps! there is at least one hard circular dependency,
+ * GtkBuilder will fail to set one of the properties that create the cycle
+ */
+
+ _node_edge_free (hard_edges);
+ }
+
+ return cycles;
+}
+
+static GList *
+glade_project_get_ordered_toplevels (GladeProject *project)
+{
+ GladeProjectPrivate *priv = project->priv;
+ GList *l, *sorted_tree, *tree = NULL;
+ _NodeEdge *edges;
+
+ /* Create list of toplevels GladeWidgets */
+ for (l = priv->tree; l; l = g_list_next (l))
+ tree = g_list_prepend (tree, glade_widget_get_from_gobject (l->data));
+
+ /* Sort toplevels alphabetically */
+ tree = g_list_sort (tree, glade_widgets_name_cmp);
+
+ edges = glade_project_get_graph_deps (project);
+
+ /* Sort tree */
+ sorted_tree = _glade_tsort (&tree, &edges);
+
+ if (edges)
+ {
+ GList *cycles = glade_project_get_nodes_from_edges (project, edges);
+
+ /* And append to the end of the sorted list */
+ sorted_tree = g_list_concat (sorted_tree, cycles);
+
+ _node_edge_free (edges);
+ }
+
+ /* No need to free tree as tsort will consume the list */
+
+ return sorted_tree;
}
static inline void
@@ -2654,15 +2809,12 @@ glade_project_write (GladeProject *project)
glade_project_write_css_provider_path (project, context, root);
- /* Sort the toplevels */
- toplevels = g_list_copy (project->priv->tree);
- toplevels = g_list_sort (toplevels, (GCompareFunc)sort_project_dependancies);
+ /* Get sorted toplevels */
+ toplevels = glade_project_get_ordered_toplevels (project);
- for (list = toplevels; list; list = list->next)
+ for (list = toplevels; list; list = g_list_next (list))
{
- GladeWidget *widget;
-
- widget = glade_widget_get_from_gobject (list->data);
+ GladeWidget *widget = list->data;
/*
* Append toplevel widgets. Each widget then takes
@@ -2670,6 +2822,9 @@ glade_project_write (GladeProject *project)
*/
if (!glade_widget_get_parent (widget))
glade_widget_write (widget, context, root);
+ else
+ g_warning ("Tried to save a non toplevel object '%s' at xml root",
+ glade_widget_get_name (widget));
}
g_list_free (toplevels);
diff --git a/gladeui/glade-tsort.c b/gladeui/glade-tsort.c
new file mode 100644
index 00000000..439da33e
--- /dev/null
+++ b/gladeui/glade-tsort.c
@@ -0,0 +1,177 @@
+/*
+ * glade-tsort.c: a topological sorting algorithm implementation
+ *
+ * Copyright (C) 2013 Juan Pablo Ugarte.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Authors:
+ * Juan Pablo Ugarte <juanpablougarte@gmail.com>
+ */
+
+#include "glade-tsort.h"
+
+/**
+ * _node_edge_prepend:
+ * @node: a _NodeEdge pointer or NULL
+ * @predecessor:
+ * @successor:
+ *
+ * Adds a new node with the values @predecessor and @successor to the start of
+ * @node list.
+ *
+ * Returns: the new start of the node list.
+ */
+_NodeEdge *
+_node_edge_prepend (_NodeEdge *node,
+ gpointer predecessor,
+ gpointer successor)
+{
+ _NodeEdge *edge = g_slice_new (_NodeEdge);
+
+ edge->predecessor = predecessor;
+ edge->successor = successor;
+ edge->next = node;
+
+ return edge;
+}
+
+void
+_node_edge_free (_NodeEdge *node)
+{
+ g_slice_free_chain (_NodeEdge, node, next);
+}
+
+static inline void
+tsort_remove_non_start_nodes (GList **nodes, _NodeEdge *edges)
+{
+ _NodeEdge *edge;
+
+ for (edge = edges; edge; edge = edge->next)
+ *nodes = g_list_remove (*nodes, edge->successor);
+}
+
+
+static inline gboolean
+tsort_node_has_no_incoming_edge (gpointer node, _NodeEdge *edges)
+{
+ _NodeEdge *edge;
+
+ for (edge = edges; edge; edge = edge->next)
+ {
+ if (node == edge->successor)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * _glade_tsort:
+ * @nodes: list of pointers to sort
+ * @edges: pointer to the list of #_NodeEdge that conform the dependency
+ * graph of @nodes.
+ *
+ * Topological sorting implementation.
+ * After calling this funtion only graph cycles (circular dependencies) are left
+ * in @edges list. So if @edges is NULL it means the returned list has all the
+ * elements topologically sorted if not it means there are at least one
+ * circular dependency.
+ *
+ * L ← Empty list that will contain the sorted elements
+ * S ← Set of all nodes with no incoming edges
+ * while S is non-empty do
+ * remove a node n from S
+ * insert n into L
+ * for each node m with an edge e from n to m do
+ * remove edge e from the graph
+ * if m has no other incoming edges then
+ * insert m into S
+ * return L (a topologically sorted order if graph has no edges)
+ *
+ * see: http://en.wikipedia.org/wiki/Topological_sorting
+ *
+ * Returns: a new list sorted by dependency including nodes only present in @edges
+ */
+GList *
+_glade_tsort (GList **nodes, _NodeEdge **edges)
+{
+ GList *sorted_nodes;
+
+ /* L ← Empty list that will contain the sorted elements */
+ sorted_nodes = NULL;
+
+ /* S ← Set of all nodes with no incoming edges */
+ tsort_remove_non_start_nodes (nodes, *edges);
+
+ /* while S is non-empty do */
+ while (*nodes)
+ {
+ _NodeEdge *edge, *next, *prev = NULL;
+ gpointer n;
+
+ /* remove a node n from S */
+ n = (*nodes)->data;
+ *nodes = g_list_delete_link (*nodes, *nodes);
+
+ /* insert n into L */
+ /*if (!glade_widget_get_parent (n)) this would be a specific optimization */
+ sorted_nodes = g_list_prepend (sorted_nodes, n);
+
+ /* for each node m ... */
+ for (edge = *edges; edge; edge = next)
+ {
+ next = edge->next;
+
+ /* ... with an edge e from n to m do */
+ if (edge->predecessor == n)
+ {
+ /* remove edge e from the graph */
+ if (prev)
+ prev->next = (prev->next) ? prev->next->next : NULL;
+ else
+ /* edge is the first element in the list so we only need to
+ * change the start of the list */
+ *edges = next;
+
+ /* if m has no other incoming edges then */
+ if (tsort_node_has_no_incoming_edge (edge->successor, *edges))
+ /* insert m into S */
+ *nodes = g_list_prepend (*nodes, edge->successor);
+
+ g_slice_free (_NodeEdge, edge);
+ }
+ else
+ /* Keep a pointer to the previous node in the iteration to make
+ * things easier when removing a node
+ */
+ prev = edge;
+ }
+ }
+
+ /* if graph has edges then return error (graph has at least one cycle) */
+#if 0 /* We rather not return NULL, caller must check if edge */
+ if (*edges)
+ {
+ g_list_free (sorted_nodes);
+ g_slice_free_chain (_NodeEdge, *edges, next);
+ *edges = NULL;
+ return NULL;
+ }
+#endif
+
+ /* return L (a topologically sorted order if edge is NULL) */
+ return g_list_reverse (sorted_nodes);
+}
diff --git a/gladeui/glade-tsort.h b/gladeui/glade-tsort.h
new file mode 100644
index 00000000..3026e2d5
--- /dev/null
+++ b/gladeui/glade-tsort.h
@@ -0,0 +1,51 @@
+/*
+ * glade-tsort.h: a topological sorting algorithm implementation
+ *
+ * Copyright (C) 2013 Juan Pablo Ugarte.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Authors:
+ * Juan Pablo Ugarte <juanpablougarte@gmail.com>
+ */
+
+#ifndef __GLADE_TSORT_H__
+#define __GLADE_TSORT_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct __NodeEdge _NodeEdge;
+
+struct __NodeEdge
+{
+ gpointer predecessor;
+ gpointer successor;
+ _NodeEdge *next;
+};
+
+_NodeEdge *_node_edge_prepend (_NodeEdge *node,
+ gpointer predecessor,
+ gpointer successor);
+
+void _node_edge_free (_NodeEdge *node);
+
+GList *_glade_tsort (GList **nodes,
+ _NodeEdge **edges);
+
+G_END_DECLS
+
+#endif /* __GLADE_TSORT_H__ */
diff --git a/gladeui/glade-widget-adaptor.c b/gladeui/glade-widget-adaptor.c
index 1acc8d9d..c40e3c99 100644
--- a/gladeui/glade-widget-adaptor.c
+++ b/gladeui/glade-widget-adaptor.c
@@ -42,6 +42,7 @@
#include "glade-displayable-values.h"
#include "glade-editor-table.h"
#include "glade-cursor.h"
+#include "glade-widget-private.h"
/* For g_file_exists */
#include <sys/types.h>
@@ -978,33 +979,18 @@ glade_widget_adaptor_object_depends (GladeWidgetAdaptor *adaptor,
GladeWidget *widget,
GladeWidget *another)
{
- GList *prop_refs, *l;
- gboolean depends = FALSE;
-
- prop_refs = glade_widget_list_prop_refs (another);
+ GList *l;
- for (l = prop_refs; !depends && l; l = l->next)
+ for (l = _glade_widget_peek_prop_refs (another); l; l = g_list_next (l))
{
- GladeProperty *property = l->data;
- GladeWidget *prop_widget = glade_property_get_widget (property);
-
/* If one of the properties that reference @another is
* owned by @widget then @widget depends on @another
*/
- if (prop_widget == widget)
- depends = TRUE;
-
- /* Or if the widget that owns a property which references
- * @another is somewhere inside @widget... then @widget
- * also depends on @another.
- */
- else if (glade_widget_is_ancestor (prop_widget, widget))
- depends = TRUE;
+ if (glade_property_get_widget (l->data) == widget)
+ return TRUE;
}
- g_list_free (prop_refs);
-
- return depends;
+ return FALSE;
}
static void
diff --git a/gladeui/glade-widget-private.h b/gladeui/glade-widget-private.h
new file mode 100644
index 00000000..12869f47
--- /dev/null
+++ b/gladeui/glade-widget-private.h
@@ -0,0 +1,36 @@
+/*
+ * glade-widget-private.h
+ *
+ * Copyright (C) 2013 Juan Pablo Ugarte
+ *
+ * Authors:
+ * Juan Pablo Ugarte <juanpablougarte@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __GLADE_WIDGET_PRIVATE_H__
+#define __GLADE_WIDGET_PRIVATE_H__
+
+#include "glade-widget.h"
+
+G_BEGIN_DECLS
+
+GList *_glade_widget_peek_prop_refs (GladeWidget *widget);
+
+G_END_DECLS
+
+#endif /* __GLADE_WIDGET_PRIVATE_H__ */
diff --git a/gladeui/glade-widget.c b/gladeui/glade-widget.c
index 2ea24573..df3a965f 100644
--- a/gladeui/glade-widget.c
+++ b/gladeui/glade-widget.c
@@ -44,7 +44,7 @@
#include "glade-accumulators.h"
#include "glade-project.h"
#include "glade-widget-adaptor.h"
-#include "glade-widget.h"
+#include "glade-widget-private.h"
#include "glade-marshallers.h"
#include "glade-property.h"
#include "glade-property-class.h"
@@ -148,7 +148,9 @@ struct _GladeWidgetPrivate {
*/
GtkTreeModel *signal_model; /* Signal model (or NULL if not yet requested) */
-
+
+ GladeWidget *cached_toplevel; /* Used to speed up glade_widget_get_toplevel */
+
/* Construct parameters: */
GladeWidget *construct_template;
GladeCreateReason construct_reason;
@@ -2045,6 +2047,14 @@ glade_widget_create_packing_properties (GladeWidget * container,
return g_list_reverse (packing_props);
}
+/* Private API */
+
+GList *
+_glade_widget_peek_prop_refs (GladeWidget *widget)
+{
+ return widget->priv->prop_refs;
+}
+
/*******************************************************************************
API
*******************************************************************************/
@@ -3633,6 +3643,9 @@ glade_widget_set_parent (GladeWidget * widget, GladeWidget * parent)
old_parent = widget->priv->parent;
widget->priv->parent = parent;
+ /* unset toplevel cache used in glade_widget_get_toplevel() */
+ widget->priv->cached_toplevel = NULL;
+
/* Set packing props only if the object is actually parented by 'parent'
* (a subsequent call should come from glade_command after parenting).
*/
@@ -3744,9 +3757,14 @@ glade_widget_get_toplevel (GladeWidget * widget)
GladeWidget *toplevel = widget;
g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL);
+ if (widget->priv->cached_toplevel)
+ return widget->priv->cached_toplevel;
+
while (toplevel->priv->parent)
toplevel = toplevel->priv->parent;
+ widget->priv->cached_toplevel = toplevel;
+
return toplevel;
}
@@ -4343,11 +4361,8 @@ glade_widget_is_ancestor (GladeWidget * widget, GladeWidget * ancestor)
* Determines whether @widget is somehow dependent on @other, in
* which case it should be serialized after @other.
*
- * A widget is dependent on another widget if @widget or any
- * of @widget's children depends on @other or any of @other's children.
- *
- * <note><para>This is a very recursive operation, it is used once when
- * saving the project to ensure proper order at save time.</para></note>
+ * A widget is dependent on another widget.
+ * It does not take into account for children dependencies.
*
* Return value: %TRUE if @widget depends on @other.
**/
@@ -4358,42 +4373,7 @@ glade_widget_depends (GladeWidget *widget,
g_return_val_if_fail (GLADE_IS_WIDGET (widget), FALSE);
g_return_val_if_fail (GLADE_IS_WIDGET (other), FALSE);
- if (!glade_widget_adaptor_depends (widget->priv->adaptor, widget, other))
- {
- gboolean depends;
- GList *children, *l;
-
- /* Recurse into 'other' */
- children = glade_widget_get_children (other);
- for (depends = FALSE, l = children;
- depends == FALSE && l != NULL;
- l = l->next)
- {
- GladeWidget *child = glade_widget_get_from_gobject (l->data);
-
- depends = glade_widget_depends (widget, child);
- }
-
- g_list_free (children);
- if (depends)
- return TRUE;
-
- /* Recurse into 'widget' */
- children = glade_widget_get_children (widget);
- for (depends = FALSE, l = children;
- depends == FALSE && l != NULL;
- l = l->next)
- {
- GladeWidget *child = glade_widget_get_from_gobject (l->data);
-
- depends = glade_widget_depends (child, other);
- }
- g_list_free (children);
-
- return depends;
- }
-
- return TRUE;
+ return glade_widget_adaptor_depends (widget->priv->adaptor, widget, other);
}
/**
diff --git a/plugins/gtk+/glade-gtk-entry.c b/plugins/gtk+/glade-gtk-entry.c
index 2704afc2..cd8acfd8 100644
--- a/plugins/gtk+/glade-gtk-entry.c
+++ b/plugins/gtk+/glade-gtk-entry.c
@@ -28,17 +28,6 @@
#include "glade-image-editor.h" /* For the icon modes */
#include "glade-gtk.h"
-gboolean
-glade_gtk_entry_depends (GladeWidgetAdaptor * adaptor,
- GladeWidget * widget, GladeWidget * another)
-{
- if (GTK_IS_ENTRY_BUFFER (glade_widget_get_object (another)))
- return TRUE;
-
- return GWA_GET_CLASS (GTK_TYPE_WIDGET)->depends (adaptor, widget, another);
-}
-
-
static void
glade_gtk_entry_changed (GtkEditable * editable, GladeWidget * gentry)
{
diff --git a/plugins/gtk+/glade-gtk-size-group.c b/plugins/gtk+/glade-gtk-size-group.c
index 94d4725b..3ca480ae 100644
--- a/plugins/gtk+/glade-gtk-size-group.c
+++ b/plugins/gtk+/glade-gtk-size-group.c
@@ -28,16 +28,6 @@
#define GLADE_TAG_SIZEGROUP_WIDGETS "widgets"
#define GLADE_TAG_SIZEGROUP_WIDGET "widget"
-gboolean
-glade_gtk_size_group_depends (GladeWidgetAdaptor * adaptor,
- GladeWidget * widget, GladeWidget * another)
-{
- if (GTK_IS_WIDGET (glade_widget_get_object (another)))
- return TRUE;
-
- return GWA_GET_CLASS (G_TYPE_OBJECT)->depends (adaptor, widget, another);
-}
-
static void
glade_gtk_size_group_read_widgets (GladeWidget * widget, GladeXmlNode * node)
{
diff --git a/plugins/gtk+/glade-gtk-tree-view.c b/plugins/gtk+/glade-gtk-tree-view.c
index 704cabda..eb5bef5a 100644
--- a/plugins/gtk+/glade-gtk-tree-view.c
+++ b/plugins/gtk+/glade-gtk-tree-view.c
@@ -278,16 +278,6 @@ glade_gtk_treeview_replace_child (GladeWidgetAdaptor * adaptor,
glade_gtk_cell_layout_sync_attributes (G_OBJECT (column));
}
-gboolean
-glade_gtk_treeview_depends (GladeWidgetAdaptor * adaptor,
- GladeWidget * widget, GladeWidget * another)
-{
- if (GTK_IS_TREE_MODEL (glade_widget_get_object (another)))
- return TRUE;
-
- return GWA_GET_CLASS (GTK_TYPE_CONTAINER)->depends (adaptor, widget, another);
-}
-
void
glade_gtk_treeview_set_property (GladeWidgetAdaptor * adaptor,
GObject * object,
diff --git a/plugins/gtk+/glade-gtk-widget.c b/plugins/gtk+/glade-gtk-widget.c
index dba1d2b7..7806986c 100644
--- a/plugins/gtk+/glade-gtk-widget.c
+++ b/plugins/gtk+/glade-gtk-widget.c
@@ -87,9 +87,11 @@ gboolean
glade_gtk_widget_depends (GladeWidgetAdaptor * adaptor,
GladeWidget * widget, GladeWidget * another)
{
- if (GTK_IS_ICON_FACTORY (glade_widget_get_object (another)) ||
- GTK_IS_ACTION (glade_widget_get_object (another)) ||
- GTK_IS_ACTION_GROUP (glade_widget_get_object (another)))
+ /* We want GtkIconFactory to be before any toplevels, just in case one of
+ * the stock items defined in it are used.
+ */
+ if (!glade_widget_get_parent (widget) &&
+ GTK_IS_ICON_FACTORY (glade_widget_get_object (another)))
return TRUE;
return GWA_GET_CLASS (G_TYPE_OBJECT)->depends (adaptor, widget, another);
diff --git a/plugins/gtk+/gtk+.xml.in b/plugins/gtk+/gtk+.xml.in
index 4ec5ad81..2754302a 100644
--- a/plugins/gtk+/gtk+.xml.in
+++ b/plugins/gtk+/gtk+.xml.in
@@ -1359,7 +1359,6 @@
<create-editable-function>glade_gtk_entry_create_editable</create-editable-function>
<set-property-function>glade_gtk_entry_set_property</set-property-function>
<read-widget-function>glade_gtk_entry_read_widget</read-widget-function>
- <depends-function>glade_gtk_entry_depends</depends-function>
<signals>
<signal id="icon-press" since="2.16"/>
@@ -3139,7 +3138,6 @@
</glade-widget-class>
<glade-widget-class name="GtkSizeGroup" generic-name="sizegroup" _title="Size Group" toplevel="True">
- <depends-function>glade_gtk_size_group_depends</depends-function>
<read-widget-function>glade_gtk_size_group_read_widget</read-widget-function>
<write-widget-function>glade_gtk_size_group_write_widget</write-widget-function>
<set-property-function>glade_gtk_size_group_set_property</set-property-function>
@@ -3381,7 +3379,6 @@
<replace-child-function>glade_gtk_treeview_replace_child</replace-child-function>
<remove-child-function>glade_gtk_treeview_remove_child</remove-child-function>
<action-activate-function>glade_gtk_treeview_action_activate</action-activate-function>
- <depends-function>glade_gtk_treeview_depends</depends-function>
<actions>
<action id="launch_editor" _name="Edit&#8230;" stock="gtk-edit" important="True"/>