diff options
author | Juan Pablo Ugarte <juanpablougarte@gmail.com> | 2013-12-04 21:00:14 -0300 |
---|---|---|
committer | Juan Pablo Ugarte <juanpablougarte@gmail.com> | 2013-12-11 18:07:15 -0300 |
commit | 44566c5f3d8c14d01408e8043bd946cac3d877ee (patch) | |
tree | b009081d7fe1b2a6485d702d42c569e76361b908 | |
parent | 56f47169dc09cfd6ed13a24cb9752050ecb66d6f (diff) | |
download | glade-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.c | 146 | ||||
-rw-r--r-- | gladeui/glade-private.h | 5 |
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 */ |