summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Pablo Ugarte <juanpablougarte@gmail.com>2013-12-04 21:00:14 -0300
committerJuan Pablo Ugarte <juanpablougarte@gmail.com>2013-12-11 18:07:15 -0300
commit44566c5f3d8c14d01408e8043bd946cac3d877ee (patch)
treeb009081d7fe1b2a6485d702d42c569e76361b908
parent56f47169dc09cfd6ed13a24cb9752050ecb66d6f (diff)
downloadglade-44566c5f3d8c14d01408e8043bd946cac3d877ee.tar.gz
GladeCatalog: implemented catalog dependency sorting using _glade_tsort()
Now we detect circular dependencies! Added private functions _glade_catalog_get_catalog() and _glade_catalog_tsort()
-rw-r--r--gladeui/glade-catalog.c146
-rw-r--r--gladeui/glade-private.h5
2 files changed, 93 insertions, 58 deletions
diff --git a/gladeui/glade-catalog.c b/gladeui/glade-catalog.c
index 0be542e5..39fa24af 100644
--- a/gladeui/glade-catalog.c
+++ b/gladeui/glade-catalog.c
@@ -25,6 +25,8 @@
#include "glade.h"
#include "glade-catalog.h"
#include "glade-widget-adaptor.h"
+#include "glade-private.h"
+#include "glade-tsort.h"
#include <string.h>
#include <sys/types.h>
@@ -171,6 +173,7 @@ catalog_open (const gchar *filename)
GladeXmlContext *context;
GladeXmlDoc *doc;
GladeXmlNode *root;
+ gchar *name;
/* get the context & root node of the catalog file */
context = glade_xml_context_new_from_path (filename,
@@ -192,17 +195,12 @@ catalog_open (const gchar *filename)
return NULL;
}
+ if (!(name = glade_xml_get_property_string_required (root, GLADE_TAG_NAME, NULL)))
+ return NULL;
+
catalog = catalog_allocate ();
catalog->context = context;
- catalog->name = glade_xml_get_property_string (root, GLADE_TAG_NAME);
-
- if (!catalog->name)
- {
- g_warning ("Couldn't find required property 'name' in catalog root node");
- catalog_destroy (catalog);
- return NULL;
- }
-
+ catalog->name = name;
glade_xml_get_property_version (root, GLADE_TAG_VERSION,
&catalog->major_version,
@@ -426,54 +424,80 @@ catalog_load (GladeCatalog *catalog)
return;
}
+static GladeCatalog *
+catalog_find_by_name (GList *catalogs, const gchar *name)
+{
+ if (name)
+ {
+ GList *l;
+ for (l = catalogs; l; l = g_list_next (l))
+ {
+ GladeCatalog *catalog = l->data;
+ if (g_strcmp0 (catalog->name, name) == 0)
+ return catalog;
+ }
+ }
+
+ return NULL;
+}
+
static gint
-catalog_find_by_name (GladeCatalog *catalog, const gchar *name)
+catalog_name_cmp (gconstpointer a, gconstpointer b)
{
- return strcmp (catalog->name, name);
+ return (a && b) ? g_strcmp0 (GLADE_CATALOG(a)->name, GLADE_CATALOG(b)->name) : 0;
}
static GList *
-catalog_sort (GList *catalogs)
+glade_catalog_tsort (GList *catalogs, gboolean loading)
{
- GList *l, *node, *sorted = NULL, *sort;
- GladeCatalog *catalog, *cat;
+ GList *l, *sorted = NULL;
+ GList *deps = NULL;
+
+ /* Sort alphabetically first */
+ catalogs = g_list_sort (catalogs, catalog_name_cmp);
- /* Add all dependant catalogs to the sorted list first */
- for (l = catalogs; l; l = l->next)
+ /* Generate dependency graph edges */
+ for (l = catalogs; l; l = g_list_next (l))
{
- catalog = l->data;
- sort = NULL;
+ GladeCatalog *catalog = l->data, *dep;
- /* itterate ascending through dependancy hierarchy */
- while (catalog->dep_catalog)
- {
- node = g_list_find_custom
- (catalogs, catalog->dep_catalog,
- (GCompareFunc) catalog_find_by_name);
+ if (!catalog->dep_catalog)
+ continue;
- if (!node || (cat = node->data) == NULL)
- {
- g_critical ("Catalog %s depends on catalog %s, not found",
- catalog->name, catalog->dep_catalog);
- break;
- }
+ if ((dep = catalog_find_by_name ((loading) ? catalogs : loaded_catalogs,
+ catalog->dep_catalog)))
+ deps = _node_edge_prepend (deps, dep, catalog);
+ else
+ g_critical ("Catalog %s depends on catalog %s, not found",
+ catalog->name, catalog->dep_catalog);
+ }
- /* Prepend to sort list */
- if (g_list_find (sort, cat) == NULL &&
- g_list_find (sorted, cat) == NULL)
- sort = g_list_prepend (sort, cat);
+ sorted = _glade_tsort (&catalogs, &deps);
- catalog = cat;
+ if (deps)
+ {
+ GList *l, *cycles = NULL;
+
+ g_warning ("Circular dependency detected loading catalogs, they will be ignored");
+
+ for (l = deps; l; l = g_list_next (l))
+ {
+ _NodeEdge *edge = l->data;
+
+ g_message ("\t%s depends on %s",
+ GLADE_CATALOG (edge->successor)->name,
+ GLADE_CATALOG (edge->successor)->dep_catalog);
+
+ if (loading && !g_list_find (cycles, edge->successor))
+ cycles = g_list_prepend (cycles, edge->successor);
}
- sorted = g_list_concat (sorted, sort);
- }
- /* Append all independant catalogs after */
- for (l = catalogs; l; l = l->next)
- if (g_list_find (sorted, l->data) == NULL)
- sorted = g_list_append (sorted, l->data);
+ if (cycles)
+ g_list_free_full (cycles, (GDestroyNotify) catalog_destroy);
+
+ _node_edge_list_free (deps);
+ }
- g_list_free (catalogs);
return sorted;
}
@@ -515,11 +539,10 @@ catalogs_from_path (GList *catalogs, const gchar *path)
{
/* Verify that we are not loading the same catalog twice !
*/
- if (!g_list_find_custom (catalogs, catalog->name,
- (GCompareFunc) catalog_find_by_name))
- catalogs = g_list_prepend (catalogs, catalog);
- else
+ if (catalog_find_by_name (catalogs, catalog->name))
catalog_destroy (catalog);
+ else
+ catalogs = g_list_prepend (catalogs, catalog);
}
else
g_warning ("Unable to open the catalog file %s.\n", filename);
@@ -622,7 +645,7 @@ glade_catalog_load_all (void)
* the gtk+ catalog, but some custom toolkits may depend
* on the gnome catalog for instance.
*/
- catalogs = catalog_sort (catalogs);
+ catalogs = glade_catalog_tsort (catalogs, TRUE);
/* After sorting, execute init function and then load */
for (l = catalogs; l; l = g_list_next (l))
@@ -809,19 +832,9 @@ glade_catalog_get_adaptors (GladeCatalog *catalog)
gboolean
glade_catalog_is_loaded (const gchar *name)
{
- GList *l;
-
g_return_val_if_fail (name != NULL, FALSE);
g_assert (loaded_catalogs != NULL);
-
- for (l = loaded_catalogs; l; l = l->next)
- {
- GladeCatalog *catalog = GLADE_CATALOG (l->data);
- if (strcmp (catalog->name, name) == 0)
- return TRUE;
- }
-
- return FALSE;
+ return catalog_find_by_name (loaded_catalogs, name) != NULL;
}
/**
@@ -905,3 +918,20 @@ glade_widget_group_get_adaptors (GladeWidgetGroup *group)
return group->adaptors;
}
+
+/* Private API */
+
+GladeCatalog *
+_glade_catalog_get_catalog (const gchar *name)
+{
+ g_return_val_if_fail (name != NULL, NULL);
+ g_assert (loaded_catalogs != NULL);
+
+ return catalog_find_by_name (loaded_catalogs, name);
+}
+
+GList *
+_glade_catalog_tsort (GList *catalogs)
+{
+ return glade_catalog_tsort (catalogs, FALSE);
+}
diff --git a/gladeui/glade-private.h b/gladeui/glade-private.h
index ea35011d..0de48b21 100644
--- a/gladeui/glade-private.h
+++ b/gladeui/glade-private.h
@@ -30,6 +30,11 @@
G_BEGIN_DECLS
+/* glade-catalog.c */
+
+GladeCatalog *_glade_catalog_get_catalog (const gchar *name);
+GList *_glade_catalog_tsort (GList *catalogs);
+
/* glade-xml-utils.c */
/* GladeXml Error handling */