[glade/glade-3-16] Sort object dependancy before saving using a topological sorting algorithm _glade_tsort() instead of



commit 47f6916e86b0d70d0fdbada47bc8ef1bf3afd9ff
Author: Juan Pablo Ugarte <juanpablougarte gmail com>
Date:   Fri Nov 15 22:45:17 2013 -0300

    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"

 gladeui/Makefile.am                 |    5 +-
 gladeui/glade-project.c             |  189 +++++++++++++++++++++++++++++++---
 gladeui/glade-tsort.c               |  177 ++++++++++++++++++++++++++++++++
 gladeui/glade-tsort.h               |   51 ++++++++++
 gladeui/glade-widget-adaptor.c      |   26 +----
 gladeui/glade-widget-private.h      |   36 +++++++
 gladeui/glade-widget.c              |   66 ++++--------
 plugins/gtk+/glade-gtk-entry.c      |   11 --
 plugins/gtk+/glade-gtk-size-group.c |   10 --
 plugins/gtk+/glade-gtk-tree-view.c  |   10 --
 plugins/gtk+/glade-gtk-widget.c     |    8 +-
 plugins/gtk+/gtk+.xml.in            |    3 -
 12 files changed, 474 insertions(+), 118 deletions(-)
---
diff --git a/gladeui/Makefile.am b/gladeui/Makefile.am
index 077da12..cc860d8 100644
--- a/gladeui/Makefile.am
+++ b/gladeui/Makefile.am
@@ -117,6 +117,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 \
@@ -192,9 +193,11 @@ noinst_HEADERS = \
        glade-preview-tokens.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 85d47f3..4a3290f 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,
@@ -2407,19 +2410,171 @@ glade_project_write_resource_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
@@ -2472,15 +2627,12 @@ glade_project_write (GladeProject *project)
 
   glade_project_write_resource_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
@@ -2488,6 +2640,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 0000000..439da33
--- /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 0000000..3026e2d
--- /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 b761de2..032dffa 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 0000000..12869f4
--- /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 2ea2457..df3a965 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 2704afc..cd8acfd 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 94d4725..3ca480a 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 704cabd..eb5bef5 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 9927f36..ce03ad1 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 1580308..273076b 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"/>


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