2 * Copyright (C) 2002-2004 Marco Pesenti Gritti
3 * Copyright (C) 2004 Christian Persch
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "egg-toolbars-model.h"
25 #include "eggtypebuiltins.h"
26 #include "eggmarshalers.h"
30 #include <libxml/tree.h>
31 #include <gdk/gdkproperty.h>
33 static void egg_toolbars_model_class_init (EggToolbarsModelClass *klass);
34 static void egg_toolbars_model_init (EggToolbarsModel *model);
35 static void egg_toolbars_model_finalize (GObject *object);
50 EggTbModelFlags flags;
58 static guint signals[LAST_SIGNAL] = { 0 };
60 static GObjectClass *parent_class = NULL;
62 #define EGG_TOOLBARS_MODEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EGG_TYPE_TOOLBARS_MODEL, EggToolbarsModelPrivate))
64 struct EggToolbarsModelPrivate
72 egg_toolbars_model_get_type (void)
74 static GType type = 0;
76 if (G_UNLIKELY (type == 0))
78 static const GTypeInfo our_info = {
79 sizeof (EggToolbarsModelClass),
81 NULL, /* base_finalize */
82 (GClassInitFunc) egg_toolbars_model_class_init,
84 NULL, /* class_data */
85 sizeof (EggToolbarsModel),
87 (GInstanceInitFunc) egg_toolbars_model_init
89 volatile GType flags_type; /* work around gcc's optimiser */
91 /* make sure the flags type is known */
92 flags_type = EGG_TYPE_TB_MODEL_FLAGS;
94 type = g_type_register_static (G_TYPE_OBJECT,
103 egg_toolbars_model_to_xml (EggToolbarsModel *model)
109 g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), NULL);
111 tl = model->priv->toolbars;
113 xmlIndentTreeOutput = TRUE;
114 doc = xmlNewDoc ((const xmlChar*) "1.0");
115 doc->children = xmlNewDocNode (doc, NULL, (const xmlChar*) "toolbars", NULL);
117 for (l1 = tl->children; l1 != NULL; l1 = l1->next)
120 EggToolbarsToolbar *toolbar = l1->data;
122 tnode = xmlNewChild (doc->children, NULL, (const xmlChar*) "toolbar", NULL);
123 xmlSetProp (tnode, (const xmlChar*) "name", (const xmlChar*) toolbar->name);
124 xmlSetProp (tnode, (const xmlChar*) "hidden",
125 (toolbar->flags&EGG_TB_MODEL_HIDDEN) ? (const xmlChar*) "true" : (const xmlChar*) "false");
126 xmlSetProp (tnode, (const xmlChar*) "editable",
127 (toolbar->flags&EGG_TB_MODEL_NOT_EDITABLE) ? (const xmlChar*) "false" : (const xmlChar*) "true");
129 for (l2 = l1->children; l2 != NULL; l2 = l2->next)
132 EggToolbarsItem *item = l2->data;
134 if (strcmp (item->name, "_separator") == 0)
136 node = xmlNewChild (tnode, NULL, (const xmlChar*) "separator", NULL);
140 node = xmlNewChild (tnode, NULL, (const xmlChar*) "toolitem", NULL);
141 xmlSetProp (node, (const xmlChar*) "name", (const xmlChar*) item->name);
143 /* Add 'data' nodes for each data type which can be written out for this
144 * item. Only write types which can be used to restore the data. */
145 for (l3 = model->priv->types; l3 != NULL; l3 = l3->next)
147 EggToolbarsItemType *type = l3->data;
148 if (type->get_name != NULL && type->get_data != NULL)
153 tmp = type->get_data (type, item->name);
156 dnode = xmlNewTextChild (node, NULL, (const xmlChar*) "data", (const xmlChar*) tmp);
159 tmp = gdk_atom_name (type->type);
160 xmlSetProp (dnode, (const xmlChar*) "type", (const xmlChar*) tmp);
172 safe_save_xml (const char *xml_file, xmlDocPtr doc)
177 gboolean retval = TRUE;
179 tmp_file = g_strconcat (xml_file, ".tmp", NULL);
180 old_file = g_strconcat (xml_file, ".old", NULL);
182 if (xmlSaveFormatFile (tmp_file, doc, 1) <= 0)
184 g_warning ("Failed to write XML data to %s", tmp_file);
188 old_exist = g_file_test (xml_file, G_FILE_TEST_EXISTS);
192 if (rename (xml_file, old_file) < 0)
194 g_warning ("Failed to rename %s to %s", xml_file, old_file);
200 if (rename (tmp_file, xml_file) < 0)
202 g_warning ("Failed to rename %s to %s", tmp_file, xml_file);
204 if (rename (old_file, xml_file) < 0)
206 g_warning ("Failed to restore %s from %s", xml_file, tmp_file);
214 if (unlink (old_file) < 0)
216 g_warning ("Failed to delete old file %s", old_file);
228 egg_toolbars_model_save_toolbars (EggToolbarsModel *model,
229 const char *xml_file,
235 g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model));
237 doc = egg_toolbars_model_to_xml (model);
238 root = xmlDocGetRootElement (doc);
239 xmlSetProp (root, (const xmlChar*) "version", (const xmlChar*) version);
240 safe_save_xml (xml_file, doc);
245 is_unique (EggToolbarsModel *model,
246 EggToolbarsItem *idata)
248 EggToolbarsItem *idata2;
249 GNode *toolbar, *item;
252 for(toolbar = g_node_first_child (model->priv->toolbars);
253 toolbar != NULL; toolbar = g_node_next_sibling (toolbar))
255 for(item = g_node_first_child (toolbar);
256 item != NULL; item = g_node_next_sibling (item))
260 if (idata != idata2 && strcmp (idata->name, idata2->name) == 0)
271 toolbar_node_new (const char *name)
273 EggToolbarsToolbar *toolbar;
275 toolbar = g_new (EggToolbarsToolbar, 1);
276 toolbar->name = g_strdup (name);
279 return g_node_new (toolbar);
283 item_node_new (const char *name, EggToolbarsModel *model)
285 EggToolbarsItem *item;
288 g_return_val_if_fail (name != NULL, NULL);
290 item = g_new (EggToolbarsItem, 1);
291 item->name = g_strdup (name);
293 flags = GPOINTER_TO_INT (g_hash_table_lookup (model->priv->flags, item->name));
294 if ((flags & EGG_TB_MODEL_NAME_INFINITE) == 0)
295 g_hash_table_insert (model->priv->flags,
296 g_strdup (item->name),
297 GINT_TO_POINTER (flags | EGG_TB_MODEL_NAME_USED));
299 return g_node_new (item);
303 item_node_free (GNode *item_node, EggToolbarsModel *model)
305 EggToolbarsItem *item = item_node->data;
308 flags = GPOINTER_TO_INT (g_hash_table_lookup (model->priv->flags, item->name));
309 if ((flags & EGG_TB_MODEL_NAME_INFINITE) == 0 && is_unique (model, item))
310 g_hash_table_insert (model->priv->flags,
311 g_strdup (item->name),
312 GINT_TO_POINTER (flags & ~EGG_TB_MODEL_NAME_USED));
317 g_node_destroy (item_node);
321 toolbar_node_free (GNode *toolbar_node, EggToolbarsModel *model)
323 EggToolbarsToolbar *toolbar = toolbar_node->data;
325 g_node_children_foreach (toolbar_node, G_TRAVERSE_ALL,
326 (GNodeForeachFunc) item_node_free, model);
328 g_free (toolbar->name);
331 g_node_destroy (toolbar_node);
335 egg_toolbars_model_get_flags (EggToolbarsModel *model,
336 int toolbar_position)
339 EggToolbarsToolbar *toolbar;
341 toolbar_node = g_node_nth_child (model->priv->toolbars, toolbar_position);
342 g_return_val_if_fail (toolbar_node != NULL, 0);
344 toolbar = toolbar_node->data;
346 return toolbar->flags;
350 egg_toolbars_model_set_flags (EggToolbarsModel *model,
351 int toolbar_position,
352 EggTbModelFlags flags)
355 EggToolbarsToolbar *toolbar;
357 toolbar_node = g_node_nth_child (model->priv->toolbars, toolbar_position);
358 g_return_if_fail (toolbar_node != NULL);
360 toolbar = toolbar_node->data;
362 toolbar->flags = flags;
364 g_signal_emit (G_OBJECT (model), signals[TOOLBAR_CHANGED],
365 0, toolbar_position);
370 egg_toolbars_model_get_data (EggToolbarsModel *model,
374 EggToolbarsItemType *t;
378 if (type == GDK_NONE || type == gdk_atom_intern (EGG_TOOLBAR_ITEM_TYPE, FALSE))
380 g_return_val_if_fail (name != NULL, NULL);
381 g_return_val_if_fail (*name != 0, NULL);
382 return strdup (name);
385 for (l = model->priv->types; l != NULL; l = l->next)
388 if (t->type == type && t->get_data != NULL)
390 data = t->get_data (t, name);
391 if (data != NULL) break;
399 egg_toolbars_model_get_name (EggToolbarsModel *model,
404 EggToolbarsItemType *t;
408 if (type == GDK_NONE || type == gdk_atom_intern (EGG_TOOLBAR_ITEM_TYPE, FALSE))
410 g_return_val_if_fail (data, NULL);
411 g_return_val_if_fail (*data, NULL);
412 return strdup (data);
417 for (l = model->priv->types; name == NULL && l != NULL; l = l->next)
420 if (t->type == type && t->new_name != NULL)
421 name = t->new_name (t, data);
428 for (l = model->priv->types; name == NULL && l != NULL; l = l->next)
431 if (t->type == type && t->get_name != NULL)
432 name = t->get_name (t, data);
440 impl_add_item (EggToolbarsModel *model,
441 int toolbar_position,
449 g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), FALSE);
450 g_return_val_if_fail (name != NULL, FALSE);
452 parent_node = g_node_nth_child (model->priv->toolbars, toolbar_position);
453 child_node = item_node_new (name, model);
454 g_node_insert (parent_node, position, child_node);
456 real_position = g_node_child_position (parent_node, child_node);
458 g_signal_emit (G_OBJECT (model), signals[ITEM_ADDED], 0,
459 toolbar_position, real_position);
465 egg_toolbars_model_add_item (EggToolbarsModel *model,
466 int toolbar_position,
470 EggToolbarsModelClass *klass = EGG_TOOLBARS_MODEL_GET_CLASS (model);
471 return klass->add_item (model, toolbar_position, position, name);
475 egg_toolbars_model_add_toolbar (EggToolbarsModel *model,
482 g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), -1);
484 node = toolbar_node_new (name);
485 g_node_insert (model->priv->toolbars, position, node);
487 real_position = g_node_child_position (model->priv->toolbars, node);
489 g_signal_emit (G_OBJECT (model), signals[TOOLBAR_ADDED],
492 return g_node_child_position (model->priv->toolbars, node);
496 parse_data_list (EggToolbarsModel *model,
501 while (child && name == NULL)
503 if (xmlStrEqual (child->name, (const xmlChar*) "data"))
505 xmlChar *type = xmlGetProp (child, (const xmlChar*) "type");
506 xmlChar *data = xmlNodeGetContent (child);
510 GdkAtom atom = gdk_atom_intern ((const char*) type, TRUE);
511 name = egg_toolbars_model_get_name (model, atom, (const char*) data, create);
525 parse_item_list (EggToolbarsModel *model,
531 if (xmlStrEqual (child->name, (const xmlChar*) "toolitem"))
535 /* Try to get the name using the data elements first,
536 as they are more 'portable' or 'persistent'. */
537 name = parse_data_list (model, child->children, FALSE);
540 name = parse_data_list (model, child->children, TRUE);
543 /* If that fails, try to use the name. */
546 xmlChar *type = xmlGetProp (child, (const xmlChar*) "type");
547 xmlChar *data = xmlGetProp (child, (const xmlChar*) "name");
548 GdkAtom atom = type ? gdk_atom_intern ((const char*) type, TRUE) : GDK_NONE;
550 /* If an old format, try to use it. */
551 name = egg_toolbars_model_get_name (model, atom, (const char*) data, FALSE);
554 name = egg_toolbars_model_get_name (model, atom, (const char*) data, TRUE);
563 egg_toolbars_model_add_item (model, position, -1, name);
567 else if (xmlStrEqual (child->name, (const xmlChar*) "separator"))
569 egg_toolbars_model_add_item (model, position, -1, "_separator");
577 parse_toolbars (EggToolbarsModel *model,
582 if (xmlStrEqual (child->name, (const xmlChar*) "toolbar"))
586 EggTbModelFlags flags;
588 string = xmlGetProp (child, (const xmlChar*) "name");
589 position = egg_toolbars_model_add_toolbar (model, -1, (const char*) string);
590 flags = egg_toolbars_model_get_flags (model, position);
593 string = xmlGetProp (child, (const xmlChar*) "editable");
594 if (string && xmlStrEqual (string, (const xmlChar*) "false"))
595 flags |= EGG_TB_MODEL_NOT_EDITABLE;
598 string = xmlGetProp (child, (const xmlChar*) "hidden");
599 if (string && xmlStrEqual (string, (const xmlChar*) "true"))
600 flags |= EGG_TB_MODEL_HIDDEN;
603 string = xmlGetProp (child, (const xmlChar*) "style");
604 if (string && xmlStrEqual (string, (const xmlChar*) "icons-only"))
605 flags |= EGG_TB_MODEL_ICONS;
608 egg_toolbars_model_set_flags (model, position, flags);
610 parse_item_list (model, child->children, position);
618 egg_toolbars_model_load_toolbars (EggToolbarsModel *model,
619 const char *xml_file)
624 g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), FALSE);
626 if (!xml_file || !g_file_test (xml_file, G_FILE_TEST_EXISTS)) return FALSE;
628 doc = xmlParseFile (xml_file);
631 g_warning ("Failed to load XML data from %s", xml_file);
634 root = xmlDocGetRootElement (doc);
636 parse_toolbars (model, root->children);
644 parse_available_list (EggToolbarsModel *model,
651 if (xmlStrEqual (child->name, (const xmlChar*) "toolitem"))
655 name = xmlGetProp (child, (const xmlChar*) "name");
656 flags = egg_toolbars_model_get_name_flags
657 (model, (const char*)name);
658 egg_toolbars_model_set_name_flags
659 (model, (const char*)name, flags | EGG_TB_MODEL_NAME_KNOWN);
667 parse_names (EggToolbarsModel *model,
672 if (xmlStrEqual (child->name, (const xmlChar*) "available"))
674 parse_available_list (model, child->children);
682 egg_toolbars_model_load_names (EggToolbarsModel *model,
683 const char *xml_file)
688 g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), FALSE);
690 if (!xml_file || !g_file_test (xml_file, G_FILE_TEST_EXISTS)) return FALSE;
692 doc = xmlParseFile (xml_file);
695 g_warning ("Failed to load XML data from %s", xml_file);
698 root = xmlDocGetRootElement (doc);
700 parse_names (model, root->children);
708 egg_toolbars_model_class_init (EggToolbarsModelClass *klass)
710 GObjectClass *object_class = G_OBJECT_CLASS (klass);
712 parent_class = g_type_class_peek_parent (klass);
714 object_class->finalize = egg_toolbars_model_finalize;
716 klass->add_item = impl_add_item;
718 signals[ITEM_ADDED] =
719 g_signal_new ("item_added",
720 G_OBJECT_CLASS_TYPE (object_class),
722 G_STRUCT_OFFSET (EggToolbarsModelClass, item_added),
723 NULL, NULL, _egg_marshal_VOID__INT_INT,
724 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
725 signals[TOOLBAR_ADDED] =
726 g_signal_new ("toolbar_added",
727 G_OBJECT_CLASS_TYPE (object_class),
729 G_STRUCT_OFFSET (EggToolbarsModelClass, toolbar_added),
730 NULL, NULL, g_cclosure_marshal_VOID__INT,
731 G_TYPE_NONE, 1, G_TYPE_INT);
732 signals[ITEM_REMOVED] =
733 g_signal_new ("item_removed",
734 G_OBJECT_CLASS_TYPE (object_class),
736 G_STRUCT_OFFSET (EggToolbarsModelClass, item_removed),
737 NULL, NULL, _egg_marshal_VOID__INT_INT,
738 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
739 signals[TOOLBAR_REMOVED] =
740 g_signal_new ("toolbar_removed",
741 G_OBJECT_CLASS_TYPE (object_class),
743 G_STRUCT_OFFSET (EggToolbarsModelClass, toolbar_removed),
744 NULL, NULL, g_cclosure_marshal_VOID__INT,
745 G_TYPE_NONE, 1, G_TYPE_INT);
746 signals[TOOLBAR_CHANGED] =
747 g_signal_new ("toolbar_changed",
748 G_OBJECT_CLASS_TYPE (object_class),
750 G_STRUCT_OFFSET (EggToolbarsModelClass, toolbar_changed),
751 NULL, NULL, g_cclosure_marshal_VOID__INT,
752 G_TYPE_NONE, 1, G_TYPE_INT);
754 g_type_class_add_private (object_class, sizeof (EggToolbarsModelPrivate));
758 egg_toolbars_model_init (EggToolbarsModel *model)
760 model->priv =EGG_TOOLBARS_MODEL_GET_PRIVATE (model);
762 model->priv->toolbars = g_node_new (NULL);
763 model->priv->flags = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
764 egg_toolbars_model_set_name_flags (model, "_separator",
765 EGG_TB_MODEL_NAME_KNOWN |
766 EGG_TB_MODEL_NAME_INFINITE);
770 egg_toolbars_model_finalize (GObject *object)
772 EggToolbarsModel *model = EGG_TOOLBARS_MODEL (object);
774 g_node_children_foreach (model->priv->toolbars, G_TRAVERSE_ALL,
775 (GNodeForeachFunc) toolbar_node_free, model);
776 g_node_destroy (model->priv->toolbars);
777 g_hash_table_destroy (model->priv->flags);
779 G_OBJECT_CLASS (parent_class)->finalize (object);
783 egg_toolbars_model_new (void)
785 return EGG_TOOLBARS_MODEL (g_object_new (EGG_TYPE_TOOLBARS_MODEL, NULL));
789 egg_toolbars_model_remove_toolbar (EggToolbarsModel *model,
793 EggTbModelFlags flags;
795 g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model));
797 flags = egg_toolbars_model_get_flags (model, position);
799 if (!(flags & EGG_TB_MODEL_NOT_REMOVABLE))
801 node = g_node_nth_child (model->priv->toolbars, position);
802 g_return_if_fail (node != NULL);
804 toolbar_node_free (node, model);
806 g_signal_emit (G_OBJECT (model), signals[TOOLBAR_REMOVED],
812 egg_toolbars_model_remove_item (EggToolbarsModel *model,
813 int toolbar_position,
816 GNode *node, *toolbar;
818 g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model));
820 toolbar = g_node_nth_child (model->priv->toolbars, toolbar_position);
821 g_return_if_fail (toolbar != NULL);
823 node = g_node_nth_child (toolbar, position);
824 g_return_if_fail (node != NULL);
826 item_node_free (node, model);
828 g_signal_emit (G_OBJECT (model), signals[ITEM_REMOVED], 0,
829 toolbar_position, position);
833 egg_toolbars_model_move_item (EggToolbarsModel *model,
834 int toolbar_position,
836 int new_toolbar_position,
839 GNode *node, *toolbar, *new_toolbar;
841 g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model));
843 toolbar = g_node_nth_child (model->priv->toolbars, toolbar_position);
844 g_return_if_fail (toolbar != NULL);
846 new_toolbar = g_node_nth_child (model->priv->toolbars, new_toolbar_position);
847 g_return_if_fail (new_toolbar != NULL);
849 node = g_node_nth_child (toolbar, position);
850 g_return_if_fail (node != NULL);
852 g_node_unlink (node);
854 g_signal_emit (G_OBJECT (model), signals[ITEM_REMOVED], 0,
855 toolbar_position, position);
857 g_node_insert (new_toolbar, new_position, node);
859 g_signal_emit (G_OBJECT (model), signals[ITEM_ADDED], 0,
860 new_toolbar_position, new_position);
864 egg_toolbars_model_delete_item (EggToolbarsModel *model,
867 EggToolbarsItem *idata;
868 EggToolbarsToolbar *tdata;
869 GNode *toolbar, *item, *next;
872 g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model));
874 toolbar = g_node_first_child (model->priv->toolbars);
877 while (toolbar != NULL)
879 item = g_node_first_child (toolbar);
882 /* Don't delete toolbars that were already empty */
885 toolbar = g_node_next_sibling (toolbar);
891 next = g_node_next_sibling (item);
893 if (strcmp (idata->name, name) == 0)
895 item_node_free (item, model);
896 g_signal_emit (G_OBJECT (model),
897 signals[ITEM_REMOVED],
908 next = g_node_next_sibling (toolbar);
909 tdata = toolbar->data;
910 if (!(tdata->flags & EGG_TB_MODEL_NOT_REMOVABLE) &&
911 g_node_first_child (toolbar) == NULL)
913 toolbar_node_free (toolbar, model);
915 g_signal_emit (G_OBJECT (model),
916 signals[TOOLBAR_REMOVED],
929 egg_toolbars_model_n_items (EggToolbarsModel *model,
930 int toolbar_position)
934 toolbar = g_node_nth_child (model->priv->toolbars, toolbar_position);
935 g_return_val_if_fail (toolbar != NULL, -1);
937 return g_node_n_children (toolbar);
941 egg_toolbars_model_item_nth (EggToolbarsModel *model,
942 int toolbar_position,
947 EggToolbarsItem *idata;
949 toolbar = g_node_nth_child (model->priv->toolbars, toolbar_position);
950 g_return_val_if_fail (toolbar != NULL, NULL);
952 item = g_node_nth_child (toolbar, position);
953 g_return_val_if_fail (item != NULL, NULL);
960 egg_toolbars_model_n_toolbars (EggToolbarsModel *model)
962 return g_node_n_children (model->priv->toolbars);
966 egg_toolbars_model_toolbar_nth (EggToolbarsModel *model,
970 EggToolbarsToolbar *tdata;
972 toolbar = g_node_nth_child (model->priv->toolbars, position);
973 g_return_val_if_fail (toolbar != NULL, NULL);
975 tdata = toolbar->data;
981 egg_toolbars_model_get_types (EggToolbarsModel *model)
983 return model->priv->types;
987 egg_toolbars_model_set_types (EggToolbarsModel *model, GList *types)
989 model->priv->types = types;
993 fill_avail_array (gpointer key, gpointer value, GPtrArray *array)
995 int flags = GPOINTER_TO_INT (value);
996 if ((flags & EGG_TB_MODEL_NAME_KNOWN) && !(flags & EGG_TB_MODEL_NAME_USED))
997 g_ptr_array_add (array, key);
1001 egg_toolbars_model_get_name_avail (EggToolbarsModel *model)
1003 GPtrArray *array = g_ptr_array_new ();
1004 g_hash_table_foreach (model->priv->flags, (GHFunc) fill_avail_array, array);
1009 egg_toolbars_model_get_name_flags (EggToolbarsModel *model, const char *name)
1011 return GPOINTER_TO_INT (g_hash_table_lookup (model->priv->flags, name));
1015 egg_toolbars_model_set_name_flags (EggToolbarsModel *model, const char *name, gint flags)
1017 g_hash_table_insert (model->priv->flags, g_strdup (name), GINT_TO_POINTER (flags));