Put subcategories and symbols in different lists.

Removes some ugliness from the code.
This commit is contained in:
Přemysl Eric Janouch 2012-08-11 07:37:40 +02:00
parent b0ecd81212
commit f55afb6542
5 changed files with 175 additions and 94 deletions

View File

@ -391,7 +391,7 @@ reload_library (LdLibraryToolbar *self)
{ {
GSList *categories; GSList *categories;
categories = (GSList *) ld_library_get_children (self->priv->library); categories = (GSList *) ld_library_get_categories (self->priv->library);
g_slist_foreach (categories, load_category_cb, self); g_slist_foreach (categories, load_category_cb, self);
} }
} }
@ -560,7 +560,7 @@ on_category_toggle (GtkToggleButton *toggle_button, gpointer user_data)
} }
else else
{ {
const GSList *children, *symbol_iter; const GSList *symbols, *symbol_iter;
SymbolMenuItem *item; SymbolMenuItem *item;
gint x, y, menu_width; gint x, y, menu_width;
@ -576,15 +576,15 @@ on_category_toggle (GtkToggleButton *toggle_button, gpointer user_data)
g_object_ref (data->active_button); g_object_ref (data->active_button);
category_name = ld_symbol_category_get_name (cat); category_name = ld_symbol_category_get_name (cat);
children = ld_symbol_category_get_children (cat); symbols = ld_symbol_category_get_symbols (cat);
data->n_items = g_slist_length ((GSList *) children); data->n_items = g_slist_length ((GSList *) symbols);
data->items = g_new (SymbolMenuItem, data->n_items); data->items = g_new (SymbolMenuItem, data->n_items);
data->active_item = -1; data->active_item = -1;
item = data->items; item = data->items;
menu_width = 0; menu_width = 0;
for (symbol_iter = children; symbol_iter; for (symbol_iter = symbols; symbol_iter;
symbol_iter = symbol_iter->next) symbol_iter = symbol_iter->next)
{ {
LdRectangle area; LdRectangle area;

View File

@ -2,7 +2,7 @@
* ld-library.c * ld-library.c
* *
* This file is a part of logdiag. * This file is a part of logdiag.
* Copyright Přemysl Janouch 2010 - 2011. All rights reserved. * Copyright Přemysl Janouch 2010, 2011, 2012. All rights reserved.
* *
* See the file LICENSE for licensing information. * See the file LICENSE for licensing information.
* *
@ -19,13 +19,15 @@
* @short_description: A symbol library * @short_description: A symbol library
* @see_also: #LdSymbol, #LdSymbolCategory * @see_also: #LdSymbol, #LdSymbolCategory
* *
* #LdLibrary is used for loading symbols from their files. * #LdLibrary is used for loading symbols from their files. The library object
* itself is a container for categories, which in turn contain other
* subcategories and the actual symbols.
*/ */
/* /*
* LdLibraryPrivate: * LdLibraryPrivate:
* @lua: state of the scripting language. * @lua: state of the scripting language.
* @children: child objects of the library. * @children: categories in the library.
*/ */
struct _LdLibraryPrivate struct _LdLibraryPrivate
{ {
@ -238,7 +240,7 @@ load_category_symbol_cb (LdSymbol *symbol, gpointer user_data)
{ {
const gchar *name; const gchar *name;
LdSymbolCategory *cat; LdSymbolCategory *cat;
const GSList *children, *iter; const GSList *symbols, *iter;
g_return_if_fail (LD_IS_SYMBOL (symbol)); g_return_if_fail (LD_IS_SYMBOL (symbol));
g_return_if_fail (LD_IS_SYMBOL_CATEGORY (user_data)); g_return_if_fail (LD_IS_SYMBOL_CATEGORY (user_data));
@ -247,11 +249,11 @@ load_category_symbol_cb (LdSymbol *symbol, gpointer user_data)
name = ld_symbol_get_name (symbol); name = ld_symbol_get_name (symbol);
/* Check for name collisions with other symbols. */ /* Check for name collisions with other symbols. */
children = ld_symbol_category_get_children (cat); /* XXX: This check should probably be in _insert_symbol() and _category().
for (iter = children; iter; iter = iter->next) * And the warning should show the full path. */
symbols = ld_symbol_category_get_symbols (cat);
for (iter = symbols; iter; iter = iter->next)
{ {
if (!LD_IS_SYMBOL (iter->data))
continue;
if (!strcmp (name, ld_symbol_get_name (LD_SYMBOL (iter->data)))) if (!strcmp (name, ld_symbol_get_name (LD_SYMBOL (iter->data))))
{ {
g_warning ("attempted to insert multiple `%s' symbols into" g_warning ("attempted to insert multiple `%s' symbols into"
@ -259,7 +261,7 @@ load_category_symbol_cb (LdSymbol *symbol, gpointer user_data)
return; return;
} }
} }
ld_symbol_category_insert_child (cat, G_OBJECT (symbol), -1); ld_symbol_category_insert_symbol (cat, symbol, -1);
} }
/* /*
@ -376,7 +378,7 @@ ld_library_load_cb (const gchar *base, const gchar *filename, gpointer userdata)
cat = load_category (data->self, filename, base); cat = load_category (data->self, filename, base);
if (cat) if (cat)
ld_library_insert_child (data->self, G_OBJECT (cat), -1); ld_library_insert_category (data->self, cat, -1);
data->changed = TRUE; data->changed = TRUE;
return TRUE; return TRUE;
@ -391,7 +393,6 @@ ld_library_load_cb (const gchar *base, const gchar *filename, gpointer userdata)
* *
* Return value: a symbol object if found, %NULL otherwise. * Return value: a symbol object if found, %NULL otherwise.
*/ */
/* XXX: With this level of indentation, this function is really ugly. */
LdSymbol * LdSymbol *
ld_library_find_symbol (LdLibrary *self, const gchar *identifier) ld_library_find_symbol (LdLibrary *self, const gchar *identifier)
{ {
@ -405,45 +406,55 @@ ld_library_find_symbol (LdLibrary *self, const gchar *identifier)
if (!id_el_start) if (!id_el_start)
return NULL; return NULL;
list = ld_library_get_children (self); id_el = id_el_start;
for (id_el = id_el_start; id_el[0]; id_el++) list = self->priv->children;
/* We need at least one category name plus the symbol name. */
if (!id_el[0] || !id_el[1])
goto ld_library_find_symbol_error;
/* Find the category where the symbol is in. */
while (1)
{ {
LdSymbolCategory *cat;
LdSymbol *symbol;
gboolean found = FALSE; gboolean found = FALSE;
LdSymbolCategory *cat;
for (list_el = list; list_el; list_el = g_slist_next (list_el)) for (list_el = list; list_el; list_el = g_slist_next (list_el))
{
/* If the current identifier element is a category (not last)
* and this list element is a category.
*/
if (id_el[1] && LD_IS_SYMBOL_CATEGORY (list_el->data))
{ {
cat = LD_SYMBOL_CATEGORY (list_el->data); cat = LD_SYMBOL_CATEGORY (list_el->data);
if (strcmp (id_el[0], ld_symbol_category_get_name (cat))) if (!strcmp (*id_el, ld_symbol_category_get_name (cat)))
continue; {
list = ld_symbol_category_get_children (cat);
found = TRUE; found = TRUE;
break; break;
} }
/* If the current identifier element is a symbol (last) }
* and this list element is a symbol.
*/
else if (!id_el[1] && LD_IS_SYMBOL (list_el->data))
{
symbol = LD_SYMBOL (list_el->data);
if (strcmp (id_el[0], ld_symbol_get_name (symbol)))
continue;
if (!found)
goto ld_library_find_symbol_error;
if (!(id_el++)[2])
{
list = ld_symbol_category_get_symbols (cat);
break;
}
list = ld_symbol_category_get_subcategories (cat);
}
/* And then the actual symbol. */
for (list_el = list; list_el; list_el = g_slist_next (list_el))
{
LdSymbol *symbol;
symbol = LD_SYMBOL (list_el->data);
if (!strcmp (*id_el, ld_symbol_get_name (symbol)))
{
g_strfreev (id_el_start); g_strfreev (id_el_start);
return symbol; return symbol;
} }
} }
if (!found) ld_library_find_symbol_error:
break;
}
g_strfreev (id_el_start); g_strfreev (id_el_start);
return NULL; return NULL;
} }
@ -468,52 +479,54 @@ ld_library_clear (LdLibrary *self)
} }
/** /**
* ld_library_insert_child: * ld_library_insert_category:
* @self: an #LdLibrary object. * @self: an #LdLibrary object.
* @child: the child to be inserted. * @category: the category to be inserted.
* @pos: the position at which the child will be inserted. * @pos: the position at which the category will be inserted.
* Negative values will append to the end of list. * Negative values will append to the end of list.
* *
* Insert a child into the library. * Insert a child category into the library.
*/ */
void void
ld_library_insert_child (LdLibrary *self, GObject *child, gint pos) ld_library_insert_category (LdLibrary *self,
LdSymbolCategory *category, gint pos)
{ {
g_return_if_fail (LD_IS_LIBRARY (self)); g_return_if_fail (LD_IS_LIBRARY (self));
g_return_if_fail (G_IS_OBJECT (child)); g_return_if_fail (LD_IS_SYMBOL_CATEGORY (category));
g_object_ref (child); g_object_ref (category);
self->priv->children = g_slist_insert (self->priv->children, child, pos); self->priv->children = g_slist_insert (self->priv->children, category, pos);
} }
/** /**
* ld_library_remove_child: * ld_library_remove_category:
* @self: an #LdLibrary object. * @self: an #LdLibrary object.
* @child: the child to be removed. * @category: the category to be removed.
* *
* Remove a child from the library. * Remove a child category from the library.
*/ */
void void
ld_library_remove_child (LdLibrary *self, GObject *child) ld_library_remove_category (LdLibrary *self, LdSymbolCategory *category)
{ {
g_return_if_fail (LD_IS_LIBRARY (self)); g_return_if_fail (LD_IS_LIBRARY (self));
g_return_if_fail (G_IS_OBJECT (child)); g_return_if_fail (LD_IS_SYMBOL_CATEGORY (category));
if (g_slist_find (self->priv->children, child)) if (g_slist_find (self->priv->children, category))
{ {
g_object_unref (child); g_object_unref (category);
self->priv->children = g_slist_remove (self->priv->children, child); self->priv->children = g_slist_remove (self->priv->children, category);
} }
} }
/** /**
* ld_library_get_children: * ld_library_get_categories:
* @self: an #LdLibrary object. * @self: an #LdLibrary object.
* *
* Return value: (element-type GObject): a list of children. Do not modify. * Return value: (element-type LdSymbolCategory *):
* a list of child categories. Do not modify.
*/ */
const GSList * const GSList *
ld_library_get_children (LdLibrary *self) ld_library_get_categories (LdLibrary *self)
{ {
g_return_val_if_fail (LD_IS_LIBRARY (self), NULL); g_return_val_if_fail (LD_IS_LIBRARY (self), NULL);
return self->priv->children; return self->priv->children;

View File

@ -2,7 +2,7 @@
* ld-library.h * ld-library.h
* *
* This file is a part of logdiag. * This file is a part of logdiag.
* Copyright Přemysl Janouch 2010. All rights reserved. * Copyright Přemysl Janouch 2010, 2012. All rights reserved.
* *
* See the file LICENSE for licensing information. * See the file LICENSE for licensing information.
* *
@ -62,9 +62,11 @@ gboolean ld_library_load (LdLibrary *self, const gchar *directory);
LdSymbol *ld_library_find_symbol (LdLibrary *self, const gchar *identifier); LdSymbol *ld_library_find_symbol (LdLibrary *self, const gchar *identifier);
void ld_library_clear (LdLibrary *self); void ld_library_clear (LdLibrary *self);
void ld_library_insert_child (LdLibrary *self, GObject *child, gint pos); void ld_library_insert_category (LdLibrary *self,
void ld_library_remove_child (LdLibrary *self, GObject *child); LdSymbolCategory *category, gint pos);
const GSList *ld_library_get_children (LdLibrary *self); void ld_library_remove_category (LdLibrary *self,
LdSymbolCategory *category);
const GSList *ld_library_get_categories (LdLibrary *self);
G_END_DECLS G_END_DECLS

View File

@ -24,14 +24,16 @@
* LdSymbolCategoryPrivate: * LdSymbolCategoryPrivate:
* @name: the name of this category. * @name: the name of this category.
* @image_path: path to the image for this category. * @image_path: path to the image for this category.
* @children: children of this category. * @symbols: (element-type LdSymbol *): symbols in this category.
* @subcategories: (element-type LdSymbolCategory *) children of this category.
*/ */
struct _LdSymbolCategoryPrivate struct _LdSymbolCategoryPrivate
{ {
gchar *name; gchar *name;
gchar *human_name; gchar *human_name;
gchar *image_path; gchar *image_path;
GSList *children; GSList *symbols;
GSList *subcategories;
}; };
enum enum
@ -162,8 +164,11 @@ ld_symbol_category_finalize (GObject *gobject)
if (self->priv->image_path) if (self->priv->image_path)
g_free (self->priv->image_path); g_free (self->priv->image_path);
g_slist_foreach (self->priv->children, (GFunc) g_object_unref, NULL); g_slist_foreach (self->priv->symbols, (GFunc) g_object_unref, NULL);
g_slist_free (self->priv->children); g_slist_free (self->priv->symbols);
g_slist_foreach (self->priv->subcategories, (GFunc) g_object_unref, NULL);
g_slist_free (self->priv->subcategories);
/* Chain up to the parent class. */ /* Chain up to the parent class. */
G_OBJECT_CLASS (ld_symbol_category_parent_class)->finalize (gobject); G_OBJECT_CLASS (ld_symbol_category_parent_class)->finalize (gobject);
@ -287,53 +292,108 @@ ld_symbol_category_get_image_path (LdSymbolCategory *self)
} }
/** /**
* ld_symbol_category_insert_child: * ld_symbol_category_insert_symbol:
* @self: an #LdSymbolCategory object. * @self: an #LdSymbolCategory object.
* @child: the child to be inserted. * @symbol: the symbol to be inserted.
* @pos: the position at which the child will be inserted. * @pos: the position at which the symbol will be inserted.
* Negative values will append to the end of list. * Negative values will append to the end of list.
* *
* Insert a child into the category. * Insert a symbol into the category. Doesn't check for duplicates.
*/ */
void void
ld_symbol_category_insert_child (LdSymbolCategory *self, ld_symbol_category_insert_symbol (LdSymbolCategory *self,
GObject *child, gint pos) LdSymbol *symbol, gint pos)
{ {
g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self)); g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
g_return_if_fail (G_IS_OBJECT (child)); g_return_if_fail (LD_IS_SYMBOL (symbol));
g_object_ref (child); g_object_ref (symbol);
self->priv->children = g_slist_insert (self->priv->children, child, pos); self->priv->symbols = g_slist_insert (self->priv->symbols, symbol, pos);
} }
/** /**
* ld_symbol_category_remove_child: * ld_symbol_category_remove_symbol:
* @self: an #LdSymbolCategory object. * @self: an #LdSymbolCategory object.
* @child: the child to be removed. * @symbol: the symbol to be removed.
* *
* Removes a child from the category. * Removes a symbol from the category.
*/ */
void void
ld_symbol_category_remove_child (LdSymbolCategory *self, ld_symbol_category_remove_symbol (LdSymbolCategory *self,
GObject *child) LdSymbol *symbol)
{ {
g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self)); g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
g_return_if_fail (G_IS_OBJECT (child)); g_return_if_fail (LD_IS_SYMBOL (symbol));
g_object_unref (child); g_object_unref (symbol);
self->priv->children = g_slist_remove (self->priv->children, child); self->priv->symbols = g_slist_remove (self->priv->symbols, symbol);
} }
/** /**
* ld_symbol_category_get_children: * ld_symbol_category_get_symbols:
* @self: an #LdSymbolCategory object. * @self: an #LdSymbolCategory object.
* *
* Return value: (element-type GObject): a list of children. Do not modify. * Return value: (element-type LdSymbol *): a list of symbols. Do not modify.
*/ */
const GSList * const GSList *
ld_symbol_category_get_children (LdSymbolCategory *self) ld_symbol_category_get_symbols (LdSymbolCategory *self)
{ {
g_return_val_if_fail (LD_IS_SYMBOL_CATEGORY (self), NULL); g_return_val_if_fail (LD_IS_SYMBOL_CATEGORY (self), NULL);
return self->priv->children; return self->priv->symbols;
}
/**
* ld_symbol_category_insert_subcategory:
* @self: an #LdSymbolCategory object.
* @category: the category to be inserted.
* @pos: the position at which the category will be inserted.
* Negative values will append to the end of list.
*
* Insert a subcategory into the category. Doesn't check for duplicates.
*/
void
ld_symbol_category_insert_subcategory (LdSymbolCategory *self,
LdSymbolCategory *category, gint pos)
{
g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
g_return_if_fail (LD_IS_SYMBOL_CATEGORY (category));
g_object_ref (category);
self->priv->subcategories
= g_slist_insert (self->priv->subcategories, category, pos);
}
/**
* ld_symbol_category_remove_subcategory:
* @self: an #LdSymbolCategory object.
* @category: the category to be removed.
*
* Removes a subcategory from the category.
*/
void
ld_symbol_category_remove_subcategory (LdSymbolCategory *self,
LdSymbolCategory *category)
{
g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
g_return_if_fail (LD_IS_SYMBOL_CATEGORY (category));
g_object_unref (category);
self->priv->subcategories
= g_slist_remove (self->priv->subcategories, category);
}
/**
* ld_symbol_category_get_subcategories:
* @self: an #LdSymbolCategory object.
*
* Return value: (element-type LdSymbolCategory *):
* a list of subcategories. Do not modify.
*/
const GSList *
ld_symbol_category_get_subcategories (LdSymbolCategory *self)
{
g_return_val_if_fail (LD_IS_SYMBOL_CATEGORY (self), NULL);
return self->priv->subcategories;
} }

View File

@ -66,11 +66,17 @@ void ld_symbol_category_set_image_path (LdSymbolCategory *self,
const gchar *image_path); const gchar *image_path);
const gchar *ld_symbol_category_get_image_path (LdSymbolCategory *self); const gchar *ld_symbol_category_get_image_path (LdSymbolCategory *self);
void ld_symbol_category_insert_child (LdSymbolCategory *self, void ld_symbol_category_insert_symbol (LdSymbolCategory *self,
GObject *child, gint pos); LdSymbol *symbol, gint pos);
void ld_symbol_category_remove_child (LdSymbolCategory *self, void ld_symbol_category_remove_symbol (LdSymbolCategory *self,
GObject *child); LdSymbol *symbol);
const GSList *ld_symbol_category_get_children (LdSymbolCategory *self); const GSList *ld_symbol_category_get_symbols (LdSymbolCategory *self);
void ld_symbol_category_insert_subcategory (LdSymbolCategory *self,
LdSymbolCategory *category, gint pos);
void ld_symbol_category_remove_subcategory (LdSymbolCategory *self,
LdSymbolCategory *category);
const GSList *ld_symbol_category_get_subcategories (LdSymbolCategory *self);
G_END_DECLS G_END_DECLS