X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;ds=sidebyside;f=cut-n-paste%2Ftoolbar-editor%2Fegg-toolbars-model.c;h=17c6e414bd5aa7c853f59dd414e6de94f6614486;hb=f51872613abaaa42c716e2fe6a2e4695c529dc4b;hp=10208cbbc998e410c9f68d3a64f01bd6fa3927b1;hpb=2d7d2bb4d1430ee3f94daa53a55ed6ee5b4c2ba0;p=evince.git diff --git a/cut-n-paste/toolbar-editor/egg-toolbars-model.c b/cut-n-paste/toolbar-editor/egg-toolbars-model.c index 10208cbb..17c6e414 100644 --- a/cut-n-paste/toolbar-editor/egg-toolbars-model.c +++ b/cut-n-paste/toolbar-editor/egg-toolbars-model.c @@ -19,11 +19,10 @@ * $Id$ */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif #include "egg-toolbars-model.h" +#include "eggtypebuiltins.h" #include "eggmarshalers.h" #include @@ -31,8 +30,6 @@ #include #include -static void egg_toolbars_model_class_init (EggToolbarsModelClass *klass); -static void egg_toolbars_model_init (EggToolbarsModel *t); static void egg_toolbars_model_finalize (GObject *object); enum @@ -42,9 +39,6 @@ enum TOOLBAR_ADDED, TOOLBAR_CHANGED, TOOLBAR_REMOVED, - GET_ITEM_TYPE, - GET_ITEM_ID, - GET_ITEM_DATA, LAST_SIGNAL }; @@ -56,89 +50,84 @@ typedef struct typedef struct { - char *id; - char *type; - gboolean separator; + char *name; } EggToolbarsItem; static guint signals[LAST_SIGNAL] = { 0 }; -static GObjectClass *parent_class = NULL; - #define EGG_TOOLBARS_MODEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EGG_TYPE_TOOLBARS_MODEL, EggToolbarsModelPrivate)) struct EggToolbarsModelPrivate { GNode *toolbars; + GList *types; + GHashTable *flags; }; -GType -egg_toolbars_model_get_type (void) -{ - static GType type = 0; - - if (type == 0) - { - static const GTypeInfo our_info = { - sizeof (EggToolbarsModelClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) egg_toolbars_model_class_init, - NULL, - NULL, /* class_data */ - sizeof (EggToolbarsModel), - 0, /* n_preallocs */ - (GInstanceInitFunc) egg_toolbars_model_init - }; - - type = g_type_register_static (G_TYPE_OBJECT, - "EggToolbarsModel", - &our_info, 0); - } - - return type; -} +G_DEFINE_TYPE (EggToolbarsModel, egg_toolbars_model, G_TYPE_OBJECT) static xmlDocPtr -egg_toolbars_model_to_xml (EggToolbarsModel *t) +egg_toolbars_model_to_xml (EggToolbarsModel *model) { GNode *l1, *l2, *tl; + GList *l3; xmlDocPtr doc; - g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (t), NULL); + g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), NULL); - tl = t->priv->toolbars; + tl = model->priv->toolbars; xmlIndentTreeOutput = TRUE; - doc = xmlNewDoc ((xmlChar *)"1.0"); - doc->children = xmlNewDocNode (doc, NULL, (xmlChar *)"toolbars", NULL); + doc = xmlNewDoc ((const xmlChar*) "1.0"); + doc->children = xmlNewDocNode (doc, NULL, (const xmlChar*) "toolbars", NULL); for (l1 = tl->children; l1 != NULL; l1 = l1->next) { xmlNodePtr tnode; EggToolbarsToolbar *toolbar = l1->data; - tnode = xmlNewChild (doc->children, NULL, (xmlChar *)"toolbar", NULL); - xmlSetProp (tnode, (xmlChar *)"name", (xmlChar *)toolbar->name); + tnode = xmlNewChild (doc->children, NULL, (const xmlChar*) "toolbar", NULL); + xmlSetProp (tnode, (const xmlChar*) "name", (const xmlChar*) toolbar->name); + xmlSetProp (tnode, (const xmlChar*) "hidden", + (toolbar->flags&EGG_TB_MODEL_HIDDEN) ? (const xmlChar*) "true" : (const xmlChar*) "false"); + xmlSetProp (tnode, (const xmlChar*) "editable", + (toolbar->flags&EGG_TB_MODEL_NOT_EDITABLE) ? (const xmlChar*) "false" : (const xmlChar*) "true"); for (l2 = l1->children; l2 != NULL; l2 = l2->next) { xmlNodePtr node; EggToolbarsItem *item = l2->data; - if (item->separator) - { - node = xmlNewChild (tnode, NULL, (xmlChar *)"separator", NULL); - } - else - { - char *data; + if (strcmp (item->name, "_separator") == 0) + { + node = xmlNewChild (tnode, NULL, (const xmlChar*) "separator", NULL); + continue; + } + + node = xmlNewChild (tnode, NULL, (const xmlChar*) "toolitem", NULL); + xmlSetProp (node, (const xmlChar*) "name", (const xmlChar*) item->name); - node = xmlNewChild (tnode, NULL, (xmlChar *)"toolitem", NULL); - data = egg_toolbars_model_get_item_data (t, item->type, item->id); - xmlSetProp (node, (xmlChar *)"type", (xmlChar *)item->type); - xmlSetProp (node, (xmlChar *)"name", (xmlChar *)data); - g_free (data); + /* Add 'data' nodes for each data type which can be written out for this + * item. Only write types which can be used to restore the data. */ + for (l3 = model->priv->types; l3 != NULL; l3 = l3->next) + { + EggToolbarsItemType *type = l3->data; + if (type->get_name != NULL && type->get_data != NULL) + { + xmlNodePtr dnode; + char *tmp; + + tmp = type->get_data (type, item->name); + if (tmp != NULL) + { + dnode = xmlNewTextChild (node, NULL, (const xmlChar*) "data", (const xmlChar*) tmp); + g_free (tmp); + + tmp = gdk_atom_name (type->type); + xmlSetProp (dnode, (const xmlChar*) "type", (const xmlChar*) tmp); + g_free (tmp); + } + } } } } @@ -203,24 +192,50 @@ safe_save_xml (const char *xml_file, xmlDocPtr doc) } void -egg_toolbars_model_save (EggToolbarsModel *t, - const char *xml_file, - const char *version) +egg_toolbars_model_save_toolbars (EggToolbarsModel *model, + const char *xml_file, + const char *version) { xmlDocPtr doc; xmlNodePtr root; - g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t)); + g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model)); - doc = egg_toolbars_model_to_xml (t); + doc = egg_toolbars_model_to_xml (model); root = xmlDocGetRootElement (doc); - xmlSetProp (root, (xmlChar *)"version", (xmlChar *)version); + xmlSetProp (root, (const xmlChar*) "version", (const xmlChar*) version); safe_save_xml (xml_file, doc); xmlFreeDoc (doc); } -static EggToolbarsToolbar * -toolbars_toolbar_new (const char *name) +static gboolean +is_unique (EggToolbarsModel *model, + EggToolbarsItem *idata) +{ + EggToolbarsItem *idata2; + GNode *toolbar, *item; + + + for(toolbar = g_node_first_child (model->priv->toolbars); + toolbar != NULL; toolbar = g_node_next_sibling (toolbar)) + { + for(item = g_node_first_child (toolbar); + item != NULL; item = g_node_next_sibling (item)) + { + idata2 = item->data; + + if (idata != idata2 && strcmp (idata->name, idata2->name) == 0) + { + return FALSE; + } + } + } + + return TRUE; +} + +static GNode * +toolbar_node_new (const char *name) { EggToolbarsToolbar *toolbar; @@ -228,58 +243,69 @@ toolbars_toolbar_new (const char *name) toolbar->name = g_strdup (name); toolbar->flags = 0; - return toolbar; + return g_node_new (toolbar); } -static EggToolbarsItem * -toolbars_item_new (const char *id, - const char *type, - gboolean separator) +static GNode * +item_node_new (const char *name, EggToolbarsModel *model) { EggToolbarsItem *item; + int flags; - g_return_val_if_fail (id != NULL, NULL); - g_return_val_if_fail (type != NULL, NULL); + g_return_val_if_fail (name != NULL, NULL); item = g_new (EggToolbarsItem, 1); - item->id = g_strdup (id); - item->type = g_strdup (type); - item->separator = separator; + item->name = g_strdup (name); + + flags = GPOINTER_TO_INT (g_hash_table_lookup (model->priv->flags, item->name)); + if ((flags & EGG_TB_MODEL_NAME_INFINITE) == 0) + g_hash_table_insert (model->priv->flags, + g_strdup (item->name), + GINT_TO_POINTER (flags | EGG_TB_MODEL_NAME_USED)); - return item; + return g_node_new (item); } static void -free_toolbar_node (GNode *toolbar_node) +item_node_free (GNode *item_node, EggToolbarsModel *model) { - EggToolbarsToolbar *toolbar = toolbar_node->data; + EggToolbarsItem *item = item_node->data; + int flags; - g_free (toolbar->name); - g_free (toolbar); + flags = GPOINTER_TO_INT (g_hash_table_lookup (model->priv->flags, item->name)); + if ((flags & EGG_TB_MODEL_NAME_INFINITE) == 0 && is_unique (model, item)) + g_hash_table_insert (model->priv->flags, + g_strdup (item->name), + GINT_TO_POINTER (flags & ~EGG_TB_MODEL_NAME_USED)); - g_node_destroy (toolbar_node); + g_free (item->name); + g_free (item); + + g_node_destroy (item_node); } static void -free_item_node (GNode *item_node) +toolbar_node_free (GNode *toolbar_node, EggToolbarsModel *model) { - EggToolbarsItem *item = item_node->data; + EggToolbarsToolbar *toolbar = toolbar_node->data; - g_free (item->id); - g_free (item->type); - g_free (item); + g_node_children_foreach (toolbar_node, G_TRAVERSE_ALL, + (GNodeForeachFunc) item_node_free, model); + + g_free (toolbar->name); + g_free (toolbar); - g_node_destroy (item_node); + g_node_destroy (toolbar_node); } EggTbModelFlags -egg_toolbars_model_get_flags (EggToolbarsModel *t, +egg_toolbars_model_get_flags (EggToolbarsModel *model, int toolbar_position) { GNode *toolbar_node; EggToolbarsToolbar *toolbar; - toolbar_node = g_node_nth_child (t->priv->toolbars, toolbar_position); + toolbar_node = g_node_nth_child (model->priv->toolbars, toolbar_position); g_return_val_if_fail (toolbar_node != NULL, 0); toolbar = toolbar_node->data; @@ -288,162 +314,267 @@ egg_toolbars_model_get_flags (EggToolbarsModel *t, } void -egg_toolbars_model_set_flags (EggToolbarsModel *t, +egg_toolbars_model_set_flags (EggToolbarsModel *model, int toolbar_position, EggTbModelFlags flags) { GNode *toolbar_node; EggToolbarsToolbar *toolbar; - toolbar_node = g_node_nth_child (t->priv->toolbars, toolbar_position); + toolbar_node = g_node_nth_child (model->priv->toolbars, toolbar_position); g_return_if_fail (toolbar_node != NULL); toolbar = toolbar_node->data; toolbar->flags = flags; - g_signal_emit (G_OBJECT (t), signals[TOOLBAR_CHANGED], + g_signal_emit (G_OBJECT (model), signals[TOOLBAR_CHANGED], 0, toolbar_position); } -void -egg_toolbars_model_add_separator (EggToolbarsModel *t, - int toolbar_position, - int position) + +char * +egg_toolbars_model_get_data (EggToolbarsModel *model, + GdkAtom type, + const char *name) +{ + EggToolbarsItemType *t; + char *data = NULL; + GList *l; + + if (type == GDK_NONE || type == gdk_atom_intern (EGG_TOOLBAR_ITEM_TYPE, FALSE)) + { + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (*name != 0, NULL); + return strdup (name); + } + + for (l = model->priv->types; l != NULL; l = l->next) + { + t = l->data; + if (t->type == type && t->get_data != NULL) + { + data = t->get_data (t, name); + if (data != NULL) break; + } + } + + return data; +} + +char * +egg_toolbars_model_get_name (EggToolbarsModel *model, + GdkAtom type, + const char *data, + gboolean create) +{ + EggToolbarsItemType *t; + char *name = NULL; + GList *l; + + if (type == GDK_NONE || type == gdk_atom_intern (EGG_TOOLBAR_ITEM_TYPE, FALSE)) + { + g_return_val_if_fail (data, NULL); + g_return_val_if_fail (*data, NULL); + return strdup (data); + } + + if (create) + { + for (l = model->priv->types; name == NULL && l != NULL; l = l->next) + { + t = l->data; + if (t->type == type && t->new_name != NULL) + name = t->new_name (t, data); + } + + return name; + } + else + { + for (l = model->priv->types; name == NULL && l != NULL; l = l->next) + { + t = l->data; + if (t->type == type && t->get_name != NULL) + name = t->get_name (t, data); + } + + return name; + } +} + +static gboolean +impl_add_item (EggToolbarsModel *model, + int toolbar_position, + int position, + const char *name) { GNode *parent_node; - GNode *node; - EggToolbarsItem *item; + GNode *child_node; int real_position; - g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t)); + g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), FALSE); + g_return_val_if_fail (name != NULL, FALSE); - parent_node = g_node_nth_child (t->priv->toolbars, toolbar_position); - item = toolbars_item_new ("separator", EGG_TOOLBAR_ITEM_TYPE, TRUE); - node = g_node_new (item); - g_node_insert (parent_node, position, node); + parent_node = g_node_nth_child (model->priv->toolbars, toolbar_position); + child_node = item_node_new (name, model); + g_node_insert (parent_node, position, child_node); - real_position = g_node_child_position (parent_node, node); + real_position = g_node_child_position (parent_node, child_node); - g_signal_emit (G_OBJECT (t), signals[ITEM_ADDED], 0, + g_signal_emit (G_OBJECT (model), signals[ITEM_ADDED], 0, toolbar_position, real_position); + + return TRUE; } -static gboolean -impl_add_item (EggToolbarsModel *t, - int toolbar_position, - int position, - const char *id, - const char *type) +gboolean +egg_toolbars_model_add_item (EggToolbarsModel *model, + int toolbar_position, + int position, + const char *name) +{ + EggToolbarsModelClass *klass = EGG_TOOLBARS_MODEL_GET_CLASS (model); + return klass->add_item (model, toolbar_position, position, name); +} + +int +egg_toolbars_model_add_toolbar (EggToolbarsModel *model, + int position, + const char *name) { - GNode *parent_node; GNode *node; - EggToolbarsItem *item; int real_position; - g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (t), FALSE); - g_return_val_if_fail (id != NULL, FALSE); - g_return_val_if_fail (type != NULL, FALSE); + g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), -1); - parent_node = g_node_nth_child (t->priv->toolbars, toolbar_position); - item = toolbars_item_new (id, type, FALSE); - node = g_node_new (item); - g_node_insert (parent_node, position, node); + node = toolbar_node_new (name); + g_node_insert (model->priv->toolbars, position, node); - real_position = g_node_child_position (parent_node, node); + real_position = g_node_child_position (model->priv->toolbars, node); - g_signal_emit (G_OBJECT (t), signals[ITEM_ADDED], 0, - toolbar_position, real_position); + g_signal_emit (G_OBJECT (model), signals[TOOLBAR_ADDED], + 0, real_position); - return TRUE; + return g_node_child_position (model->priv->toolbars, node); +} + +static char * +parse_data_list (EggToolbarsModel *model, + xmlNodePtr child, + gboolean create) +{ + char *name = NULL; + while (child && name == NULL) + { + if (xmlStrEqual (child->name, (const xmlChar*) "data")) + { + xmlChar *type = xmlGetProp (child, (const xmlChar*) "type"); + xmlChar *data = xmlNodeGetContent (child); + + if (type != NULL) + { + GdkAtom atom = gdk_atom_intern ((const char*) type, TRUE); + name = egg_toolbars_model_get_name (model, atom, (const char*) data, create); + } + + xmlFree (type); + xmlFree (data); + } + + child = child->next; + } + + return name; } static void -parse_item_list (EggToolbarsModel *t, +parse_item_list (EggToolbarsModel *model, xmlNodePtr child, int position) { while (child) { - if (xmlStrEqual (child->name, (xmlChar *)"toolitem")) + if (xmlStrEqual (child->name, (const xmlChar*) "toolitem")) { - xmlChar *name, *type; - char *id; + char *name; - name = xmlGetProp (child, (xmlChar *)"name"); - type = xmlGetProp (child, (xmlChar *)"type"); - if (type == NULL) + /* Try to get the name using the data elements first, + as they are more 'portable' or 'persistent'. */ + name = parse_data_list (model, child->children, FALSE); + if (name == NULL) { - type = xmlStrdup ((xmlChar *)EGG_TOOLBAR_ITEM_TYPE); + name = parse_data_list (model, child->children, TRUE); } - - if (name != NULL && name[0] != '\0' && type != NULL) - { - id = egg_toolbars_model_get_item_id (t, (char *)type, (char *)name); - if (id != NULL) - { - egg_toolbars_model_add_item (t, position, -1, id, (char *)type); + + /* If that fails, try to use the name. */ + if (name == NULL) + { + xmlChar *type = xmlGetProp (child, (const xmlChar*) "type"); + xmlChar *data = xmlGetProp (child, (const xmlChar*) "name"); + GdkAtom atom = type ? gdk_atom_intern ((const char*) type, TRUE) : GDK_NONE; + + /* If an old format, try to use it. */ + name = egg_toolbars_model_get_name (model, atom, (const char*) data, FALSE); + if (name == NULL) + { + name = egg_toolbars_model_get_name (model, atom, (const char*) data, TRUE); } - g_free (id); + + xmlFree (type); + xmlFree (data); + } + + if (name != NULL) + { + egg_toolbars_model_add_item (model, position, -1, name); + g_free (name); } - xmlFree (name); - xmlFree (type); } - else if (xmlStrEqual (child->name, (xmlChar *)"separator")) + else if (xmlStrEqual (child->name, (const xmlChar*) "separator")) { - egg_toolbars_model_add_separator (t, position, -1); + egg_toolbars_model_add_item (model, position, -1, "_separator"); } child = child->next; } } -int -egg_toolbars_model_add_toolbar (EggToolbarsModel *t, - int position, - const char *name) -{ - GNode *node; - int real_position; - - g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (t), -1); - - node = g_node_new (toolbars_toolbar_new (name)); - g_node_insert (t->priv->toolbars, position, node); - - real_position = g_node_child_position (t->priv->toolbars, node); - - g_signal_emit (G_OBJECT (t), signals[TOOLBAR_ADDED], - 0, real_position); - - return g_node_child_position (t->priv->toolbars, node); -} - static void -parse_toolbars (EggToolbarsModel *t, +parse_toolbars (EggToolbarsModel *model, xmlNodePtr child) { while (child) { - if (xmlStrEqual (child->name, (xmlChar *)"toolbar")) + if (xmlStrEqual (child->name, (const xmlChar*) "toolbar")) { - xmlChar *name; - xmlChar *style; + xmlChar *string; int position; - - name = xmlGetProp (child, (xmlChar *)"name"); - position = egg_toolbars_model_add_toolbar (t, -1, (char *)name); - xmlFree (name); - - style = xmlGetProp (child, (xmlChar *)"style"); - if (style && xmlStrEqual (style, (xmlChar *)"icons-only")) - { - /* FIXME: use toolbar position instead of 0 */ - egg_toolbars_model_set_flags (t, 0, EGG_TB_MODEL_ICONS_ONLY); - } - xmlFree (style); - - parse_item_list (t, child->children, position); + EggTbModelFlags flags; + + string = xmlGetProp (child, (const xmlChar*) "name"); + position = egg_toolbars_model_add_toolbar (model, -1, (const char*) string); + flags = egg_toolbars_model_get_flags (model, position); + xmlFree (string); + + string = xmlGetProp (child, (const xmlChar*) "editable"); + if (string && xmlStrEqual (string, (const xmlChar*) "false")) + flags |= EGG_TB_MODEL_NOT_EDITABLE; + xmlFree (string); + + string = xmlGetProp (child, (const xmlChar*) "hidden"); + if (string && xmlStrEqual (string, (const xmlChar*) "true")) + flags |= EGG_TB_MODEL_HIDDEN; + xmlFree (string); + + string = xmlGetProp (child, (const xmlChar*) "style"); + if (string && xmlStrEqual (string, (const xmlChar*) "icons-only")) + flags |= EGG_TB_MODEL_ICONS; + xmlFree (string); + + egg_toolbars_model_set_flags (model, position, flags); + + parse_item_list (model, child->children, position); } child = child->next; @@ -451,13 +582,13 @@ parse_toolbars (EggToolbarsModel *t, } gboolean -egg_toolbars_model_load (EggToolbarsModel *t, - const char *xml_file) +egg_toolbars_model_load_toolbars (EggToolbarsModel *model, + const char *xml_file) { xmlDocPtr doc; xmlNodePtr root; - g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (t), FALSE); + g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), FALSE); if (!xml_file || !g_file_test (xml_file, G_FILE_TEST_EXISTS)) return FALSE; @@ -469,81 +600,89 @@ egg_toolbars_model_load (EggToolbarsModel *t, } root = xmlDocGetRootElement (doc); - parse_toolbars (t, root->children); + parse_toolbars (model, root->children); xmlFreeDoc (doc); return TRUE; } -static char * -impl_get_item_id (EggToolbarsModel *t, - const char *type, - const char *data) +static void +parse_available_list (EggToolbarsModel *model, + xmlNodePtr child) { - if (strcmp (type, EGG_TOOLBAR_ITEM_TYPE) == 0) + gint flags; + + while (child) { - return g_strdup (data); - } + if (xmlStrEqual (child->name, (const xmlChar*) "toolitem")) + { + xmlChar *name; - return NULL; + name = xmlGetProp (child, (const xmlChar*) "name"); + flags = egg_toolbars_model_get_name_flags + (model, (const char*)name); + egg_toolbars_model_set_name_flags + (model, (const char*)name, flags | EGG_TB_MODEL_NAME_KNOWN); + xmlFree (name); + } + child = child->next; + } } -static char * -impl_get_item_data (EggToolbarsModel *t, - const char *type, - const char *id) +static void +parse_names (EggToolbarsModel *model, + xmlNodePtr child) { - if (strcmp (type, EGG_TOOLBAR_ITEM_TYPE) == 0) + while (child) { - return g_strdup (id); - } + if (xmlStrEqual (child->name, (const xmlChar*) "available")) + { + parse_available_list (model, child->children); + } - return NULL; + child = child->next; + } } -static char * -impl_get_item_type (EggToolbarsModel *t, - GdkAtom type) +gboolean +egg_toolbars_model_load_names (EggToolbarsModel *model, + const char *xml_file) { - if (gdk_atom_intern (EGG_TOOLBAR_ITEM_TYPE, FALSE) == type) - { - return g_strdup (EGG_TOOLBAR_ITEM_TYPE); - } + xmlDocPtr doc; + xmlNodePtr root; - return NULL; -} + g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), FALSE); -static gboolean -_egg_accumulator_STRING (GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, - gpointer dummy) -{ - gboolean continue_emission; - const char *retval; + if (!xml_file || !g_file_test (xml_file, G_FILE_TEST_EXISTS)) return FALSE; - retval = g_value_get_string (handler_return); - g_value_set_string (return_accu, retval); - continue_emission = !retval || !retval[0]; - - return continue_emission; -} + doc = xmlParseFile (xml_file); + if (doc == NULL) + { + g_warning ("Failed to load XML data from %s", xml_file); + return FALSE; + } + root = xmlDocGetRootElement (doc); + + parse_names (model, root->children); + xmlFreeDoc (doc); + + return TRUE; +} static void egg_toolbars_model_class_init (EggToolbarsModelClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + volatile GType flags_type; /* work around gcc's optimiser */ - parent_class = g_type_class_peek_parent (klass); + /* make sure the flags type is known */ + flags_type = EGG_TYPE_TB_MODEL_FLAGS; object_class->finalize = egg_toolbars_model_finalize; klass->add_item = impl_add_item; - klass->get_item_id = impl_get_item_id; - klass->get_item_data = impl_get_item_data; - klass->get_item_type = impl_get_item_type; signals[ITEM_ADDED] = g_signal_new ("item_added", @@ -580,60 +719,33 @@ egg_toolbars_model_class_init (EggToolbarsModelClass *klass) G_STRUCT_OFFSET (EggToolbarsModelClass, toolbar_changed), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); - signals[GET_ITEM_TYPE] = - g_signal_new ("get_item_type", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EggToolbarsModelClass, get_item_type), - _egg_accumulator_STRING, NULL, - _egg_marshal_STRING__POINTER, - G_TYPE_STRING, 1, G_TYPE_POINTER); - signals[GET_ITEM_ID] = - g_signal_new ("get_item_id", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EggToolbarsModelClass, get_item_id), - _egg_accumulator_STRING, NULL, - _egg_marshal_STRING__STRING_STRING, - G_TYPE_STRING, 2, G_TYPE_STRING, G_TYPE_STRING); - signals[GET_ITEM_DATA] = - g_signal_new ("get_item_data", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EggToolbarsModelClass, get_item_data), - _egg_accumulator_STRING, NULL, - _egg_marshal_STRING__STRING_STRING, - G_TYPE_STRING, 2, G_TYPE_STRING, G_TYPE_STRING); g_type_class_add_private (object_class, sizeof (EggToolbarsModelPrivate)); } static void -egg_toolbars_model_init (EggToolbarsModel *t) +egg_toolbars_model_init (EggToolbarsModel *model) { - t->priv =EGG_TOOLBARS_MODEL_GET_PRIVATE (t); + model->priv =EGG_TOOLBARS_MODEL_GET_PRIVATE (model); - t->priv->toolbars = g_node_new (NULL); -} - -static void -free_toolbar (GNode *toolbar_node) -{ - g_node_children_foreach (toolbar_node, G_TRAVERSE_ALL, - (GNodeForeachFunc) free_item_node, NULL); - free_toolbar_node (toolbar_node); + model->priv->toolbars = g_node_new (NULL); + model->priv->flags = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + egg_toolbars_model_set_name_flags (model, "_separator", + EGG_TB_MODEL_NAME_KNOWN | + EGG_TB_MODEL_NAME_INFINITE); } static void egg_toolbars_model_finalize (GObject *object) { - EggToolbarsModel *t = EGG_TOOLBARS_MODEL (object); + EggToolbarsModel *model = EGG_TOOLBARS_MODEL (object); - g_node_children_foreach (t->priv->toolbars, G_TRAVERSE_ALL, - (GNodeForeachFunc) free_toolbar, NULL); - g_node_destroy (t->priv->toolbars); + g_node_children_foreach (model->priv->toolbars, G_TRAVERSE_ALL, + (GNodeForeachFunc) toolbar_node_free, model); + g_node_destroy (model->priv->toolbars); + g_hash_table_destroy (model->priv->flags); - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (egg_toolbars_model_parent_class)->finalize (object); } EggToolbarsModel * @@ -643,51 +755,51 @@ egg_toolbars_model_new (void) } void -egg_toolbars_model_remove_toolbar (EggToolbarsModel *t, +egg_toolbars_model_remove_toolbar (EggToolbarsModel *model, int position) { GNode *node; EggTbModelFlags flags; - g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t)); + g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model)); - flags = egg_toolbars_model_get_flags (t, position); + flags = egg_toolbars_model_get_flags (model, position); if (!(flags & EGG_TB_MODEL_NOT_REMOVABLE)) { - node = g_node_nth_child (t->priv->toolbars, position); + node = g_node_nth_child (model->priv->toolbars, position); g_return_if_fail (node != NULL); - free_toolbar_node (node); + toolbar_node_free (node, model); - g_signal_emit (G_OBJECT (t), signals[TOOLBAR_REMOVED], + g_signal_emit (G_OBJECT (model), signals[TOOLBAR_REMOVED], 0, position); } } void -egg_toolbars_model_remove_item (EggToolbarsModel *t, +egg_toolbars_model_remove_item (EggToolbarsModel *model, int toolbar_position, int position) { GNode *node, *toolbar; - g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t)); + g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model)); - toolbar = g_node_nth_child (t->priv->toolbars, toolbar_position); + toolbar = g_node_nth_child (model->priv->toolbars, toolbar_position); g_return_if_fail (toolbar != NULL); node = g_node_nth_child (toolbar, position); g_return_if_fail (node != NULL); - free_item_node (node); + item_node_free (node, model); - g_signal_emit (G_OBJECT (t), signals[ITEM_REMOVED], 0, + g_signal_emit (G_OBJECT (model), signals[ITEM_REMOVED], 0, toolbar_position, position); } void -egg_toolbars_model_move_item (EggToolbarsModel *t, +egg_toolbars_model_move_item (EggToolbarsModel *model, int toolbar_position, int position, int new_toolbar_position, @@ -695,12 +807,12 @@ egg_toolbars_model_move_item (EggToolbarsModel *t, { GNode *node, *toolbar, *new_toolbar; - g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t)); + g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model)); - toolbar = g_node_nth_child (t->priv->toolbars, toolbar_position); + toolbar = g_node_nth_child (model->priv->toolbars, toolbar_position); g_return_if_fail (toolbar != NULL); - new_toolbar = g_node_nth_child (t->priv->toolbars, new_toolbar_position); + new_toolbar = g_node_nth_child (model->priv->toolbars, new_toolbar_position); g_return_if_fail (new_toolbar != NULL); node = g_node_nth_child (toolbar, position); @@ -708,74 +820,125 @@ egg_toolbars_model_move_item (EggToolbarsModel *t, g_node_unlink (node); - g_signal_emit (G_OBJECT (t), signals[ITEM_REMOVED], 0, + g_signal_emit (G_OBJECT (model), signals[ITEM_REMOVED], 0, toolbar_position, position); g_node_insert (new_toolbar, new_position, node); - g_signal_emit (G_OBJECT (t), signals[ITEM_ADDED], 0, + g_signal_emit (G_OBJECT (model), signals[ITEM_ADDED], 0, new_toolbar_position, new_position); } +void +egg_toolbars_model_delete_item (EggToolbarsModel *model, + const char *name) +{ + EggToolbarsItem *idata; + EggToolbarsToolbar *tdata; + GNode *toolbar, *item, *next; + int tpos, ipos; + + g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model)); + + toolbar = g_node_first_child (model->priv->toolbars); + tpos = 0; + + while (toolbar != NULL) + { + item = g_node_first_child (toolbar); + ipos = 0; + + /* Don't delete toolbars that were already empty */ + if (item == NULL) + { + toolbar = g_node_next_sibling (toolbar); + continue; + } + + while (item != NULL) + { + next = g_node_next_sibling (item); + idata = item->data; + if (strcmp (idata->name, name) == 0) + { + item_node_free (item, model); + g_signal_emit (G_OBJECT (model), + signals[ITEM_REMOVED], + 0, tpos, ipos); + } + else + { + ipos++; + } + + item = next; + } + + next = g_node_next_sibling (toolbar); + tdata = toolbar->data; + if (!(tdata->flags & EGG_TB_MODEL_NOT_REMOVABLE) && + g_node_first_child (toolbar) == NULL) + { + toolbar_node_free (toolbar, model); + + g_signal_emit (G_OBJECT (model), + signals[TOOLBAR_REMOVED], + 0, tpos); + } + else + { + tpos++; + } + + toolbar = next; + } +} + int -egg_toolbars_model_n_items (EggToolbarsModel *t, +egg_toolbars_model_n_items (EggToolbarsModel *model, int toolbar_position) { GNode *toolbar; - toolbar = g_node_nth_child (t->priv->toolbars, toolbar_position); + toolbar = g_node_nth_child (model->priv->toolbars, toolbar_position); g_return_val_if_fail (toolbar != NULL, -1); return g_node_n_children (toolbar); } -void -egg_toolbars_model_item_nth (EggToolbarsModel *t, +const char * +egg_toolbars_model_item_nth (EggToolbarsModel *model, int toolbar_position, - int position, - gboolean *is_separator, - const char **id, - const char **type) + int position) { GNode *toolbar; GNode *item; EggToolbarsItem *idata; - toolbar = g_node_nth_child (t->priv->toolbars, toolbar_position); - g_return_if_fail (toolbar != NULL); + toolbar = g_node_nth_child (model->priv->toolbars, toolbar_position); + g_return_val_if_fail (toolbar != NULL, NULL); item = g_node_nth_child (toolbar, position); - g_return_if_fail (item != NULL); + g_return_val_if_fail (item != NULL, NULL); idata = item->data; - - *is_separator = idata->separator; - - if (id) - { - *id = idata->id; - } - - if (type) - { - *type = idata->type; - } + return idata->name; } int -egg_toolbars_model_n_toolbars (EggToolbarsModel *t) +egg_toolbars_model_n_toolbars (EggToolbarsModel *model) { - return g_node_n_children (t->priv->toolbars); + return g_node_n_children (model->priv->toolbars); } const char * -egg_toolbars_model_toolbar_nth (EggToolbarsModel *t, +egg_toolbars_model_toolbar_nth (EggToolbarsModel *model, int position) { GNode *toolbar; EggToolbarsToolbar *tdata; - toolbar = g_node_nth_child (t->priv->toolbars, position); + toolbar = g_node_nth_child (model->priv->toolbars, position); g_return_val_if_fail (toolbar != NULL, NULL); tdata = toolbar->data; @@ -783,48 +946,42 @@ egg_toolbars_model_toolbar_nth (EggToolbarsModel *t, return tdata->name; } -gboolean -egg_toolbars_model_add_item (EggToolbarsModel *t, - int toolbar_position, - int position, - const char *id, - const char *type) +GList * +egg_toolbars_model_get_types (EggToolbarsModel *model) { - EggToolbarsModelClass *klass = EGG_TOOLBARS_MODEL_GET_CLASS (t); - return klass->add_item (t, toolbar_position, position, id, type); + return model->priv->types; } -char * -egg_toolbars_model_get_item_id (EggToolbarsModel *t, - const char *type, - const char *name) +void +egg_toolbars_model_set_types (EggToolbarsModel *model, GList *types) { - char *retval; - - g_signal_emit (t, signals[GET_ITEM_ID], 0, type, name, &retval); - - return retval; + model->priv->types = types; } -char * -egg_toolbars_model_get_item_data (EggToolbarsModel *t, - const char *type, - const char *id) +static void +fill_avail_array (gpointer key, gpointer value, GPtrArray *array) { - char *retval; - - g_signal_emit (t, signals[GET_ITEM_DATA], 0, type, id, &retval); - - return retval; + int flags = GPOINTER_TO_INT (value); + if ((flags & EGG_TB_MODEL_NAME_KNOWN) && !(flags & EGG_TB_MODEL_NAME_USED)) + g_ptr_array_add (array, key); } -char * -egg_toolbars_model_get_item_type (EggToolbarsModel *t, - GdkAtom type) +GPtrArray * +egg_toolbars_model_get_name_avail (EggToolbarsModel *model) { - char *retval; + GPtrArray *array = g_ptr_array_new (); + g_hash_table_foreach (model->priv->flags, (GHFunc) fill_avail_array, array); + return array; +} - g_signal_emit (t, signals[GET_ITEM_TYPE], 0, type, &retval); +gint +egg_toolbars_model_get_name_flags (EggToolbarsModel *model, const char *name) +{ + return GPOINTER_TO_INT (g_hash_table_lookup (model->priv->flags, name)); +} - return retval; +void +egg_toolbars_model_set_name_flags (EggToolbarsModel *model, const char *name, gint flags) +{ + g_hash_table_insert (model->priv->flags, g_strdup (name), GINT_TO_POINTER (flags)); }