]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/toolbar-editor/egg-toolbars-model.c
Fix gcc 4.0 warnings. Second part
[evince.git] / cut-n-paste / toolbar-editor / egg-toolbars-model.c
1 /*
2  *  Copyright (C) 2002-2004 Marco Pesenti Gritti
3  *  Copyright (C) 2004 Christian Persch
4  *
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)
8  *  any later version.
9  *
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.
14  *
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.
18  *
19  *  $Id$
20  */
21
22 #include "config.h"
23
24 #include "egg-toolbars-model.h"
25 #include "eggmarshalers.h"
26
27 #include <unistd.h>
28 #include <string.h>
29 #include <libxml/tree.h>
30 #include <gdk/gdkproperty.h>
31
32 static void egg_toolbars_model_class_init (EggToolbarsModelClass *klass);
33 static void egg_toolbars_model_init       (EggToolbarsModel      *t);
34 static void egg_toolbars_model_finalize   (GObject               *object);
35
36 enum
37 {
38   ITEM_ADDED,
39   ITEM_REMOVED,
40   TOOLBAR_ADDED,
41   TOOLBAR_CHANGED,
42   TOOLBAR_REMOVED,
43   GET_ITEM_TYPE,
44   GET_ITEM_ID,
45   GET_ITEM_DATA,
46   LAST_SIGNAL
47 };
48
49 typedef struct
50 {
51   char *name;
52   EggTbModelFlags flags;
53 } EggToolbarsToolbar;
54
55 typedef struct
56 {
57   char *id;
58   char *type;
59   gboolean separator;
60 } EggToolbarsItem;
61
62 static guint signals[LAST_SIGNAL] = { 0 };
63
64 static GObjectClass *parent_class = NULL;
65
66 #define EGG_TOOLBARS_MODEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EGG_TYPE_TOOLBARS_MODEL, EggToolbarsModelPrivate))
67
68 struct EggToolbarsModelPrivate
69 {
70   GNode *toolbars;
71 };
72
73 GType
74 egg_toolbars_model_get_type (void)
75 {
76   static GType type = 0;
77
78   if (G_UNLIKELY (type == 0))
79     {
80       static const GTypeInfo our_info = {
81         sizeof (EggToolbarsModelClass),
82         NULL,                   /* base_init */
83         NULL,                   /* base_finalize */
84         (GClassInitFunc) egg_toolbars_model_class_init,
85         NULL,
86         NULL,                   /* class_data */
87         sizeof (EggToolbarsModel),
88         0,                      /* n_preallocs */
89         (GInstanceInitFunc) egg_toolbars_model_init
90       };
91
92       type = g_type_register_static (G_TYPE_OBJECT,
93                                      "EggToolbarsModel",
94                                      &our_info, 0);
95     }
96
97   return type;
98 }
99
100 static xmlDocPtr
101 egg_toolbars_model_to_xml (EggToolbarsModel *t)
102 {
103   GNode *l1, *l2, *tl;
104   xmlDocPtr doc;
105
106   g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (t), NULL);
107
108   tl = t->priv->toolbars;
109
110   xmlIndentTreeOutput = TRUE;
111   doc = xmlNewDoc ((const xmlChar*) "1.0");
112   doc->children = xmlNewDocNode (doc, NULL, (const xmlChar*) "toolbars", NULL);
113
114   for (l1 = tl->children; l1 != NULL; l1 = l1->next)
115     {
116       xmlNodePtr tnode;
117       EggToolbarsToolbar *toolbar = l1->data;
118
119       tnode = xmlNewChild (doc->children, NULL, (const xmlChar*) "toolbar", NULL);
120       xmlSetProp (tnode, (const xmlChar*) "name", (const xmlChar*) toolbar->name);
121
122       for (l2 = l1->children; l2 != NULL; l2 = l2->next)
123         {
124           xmlNodePtr node;
125           EggToolbarsItem *item = l2->data;
126
127           if (item->separator)
128             {
129               node = xmlNewChild (tnode, NULL, (const xmlChar*) "separator", NULL);
130             }
131           else
132             {
133               char *data;
134
135               node = xmlNewChild (tnode, NULL, (const xmlChar*) "toolitem", NULL);
136               data = egg_toolbars_model_get_item_data (t, item->type, item->id);
137               xmlSetProp (node, (const xmlChar*) "type", (const xmlChar*) item->type);
138               xmlSetProp (node, (const xmlChar*) "name", (const xmlChar*) data);
139               g_free (data);
140             }
141         }
142     }
143
144   return doc;
145 }
146
147 static gboolean
148 safe_save_xml (const char *xml_file, xmlDocPtr doc)
149 {
150         char *tmp_file;
151         char *old_file;
152         gboolean old_exist;
153         gboolean retval = TRUE;
154
155         tmp_file = g_strconcat (xml_file, ".tmp", NULL);
156         old_file = g_strconcat (xml_file, ".old", NULL);
157
158         if (xmlSaveFormatFile (tmp_file, doc, 1) <= 0)
159         {
160                 g_warning ("Failed to write XML data to %s", tmp_file);
161                 goto failed;
162         }
163
164         old_exist = g_file_test (xml_file, G_FILE_TEST_EXISTS);
165
166         if (old_exist)
167         {
168                 if (rename (xml_file, old_file) < 0)
169                 {
170                         g_warning ("Failed to rename %s to %s", xml_file, old_file);
171                         retval = FALSE;
172                         goto failed;
173                 }
174         }
175
176         if (rename (tmp_file, xml_file) < 0)
177         {
178                 g_warning ("Failed to rename %s to %s", tmp_file, xml_file);
179
180                 if (rename (old_file, xml_file) < 0)
181                 {
182                         g_warning ("Failed to restore %s from %s", xml_file, tmp_file);
183                 }
184                 retval = FALSE;
185                 goto failed;
186         }
187
188         if (old_exist)
189         {
190                 if (unlink (old_file) < 0)
191                 {
192                         g_warning ("Failed to delete old file %s", old_file);
193                 }
194         }
195
196         failed:
197         g_free (old_file);
198         g_free (tmp_file);
199
200         return retval;
201 }
202
203 void
204 egg_toolbars_model_save (EggToolbarsModel *t,
205                          const char *xml_file,
206                          const char *version)
207 {
208   xmlDocPtr doc;
209   xmlNodePtr root;
210
211   g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t));
212
213   doc = egg_toolbars_model_to_xml (t);
214   root = xmlDocGetRootElement (doc);
215   xmlSetProp (root, (const xmlChar*) "version", (const xmlChar*) version);
216   safe_save_xml (xml_file, doc);
217   xmlFreeDoc (doc);
218 }
219
220 static EggToolbarsToolbar *
221 toolbars_toolbar_new (const char *name)
222 {
223   EggToolbarsToolbar *toolbar;
224
225   toolbar = g_new (EggToolbarsToolbar, 1);
226   toolbar->name = g_strdup (name);
227   toolbar->flags = 0;
228
229   return toolbar;
230 }
231
232 static EggToolbarsItem *
233 toolbars_item_new (const char *id,
234                    const char *type,
235                    gboolean    separator)
236 {
237   EggToolbarsItem *item;
238
239   g_return_val_if_fail (id != NULL, NULL);
240   g_return_val_if_fail (type != NULL, NULL);
241
242   item = g_new (EggToolbarsItem, 1);
243   item->id = g_strdup (id);
244   item->type = g_strdup (type);
245   item->separator = separator;
246
247   return item;
248 }
249
250 static void
251 free_toolbar_node (GNode *toolbar_node)
252 {
253   EggToolbarsToolbar *toolbar = toolbar_node->data;
254
255   g_free (toolbar->name);
256   g_free (toolbar);
257
258   g_node_destroy (toolbar_node);
259 }
260
261 static void
262 free_item_node (GNode *item_node)
263 {
264   EggToolbarsItem *item = item_node->data;
265
266   g_free (item->id);
267   g_free (item->type);
268   g_free (item);
269
270   g_node_destroy (item_node);
271 }
272
273 EggTbModelFlags
274 egg_toolbars_model_get_flags (EggToolbarsModel *t,
275                               int               toolbar_position)
276 {
277   GNode *toolbar_node;
278   EggToolbarsToolbar *toolbar;
279
280   toolbar_node = g_node_nth_child (t->priv->toolbars, toolbar_position);
281   g_return_val_if_fail (toolbar_node != NULL, 0);
282
283   toolbar = toolbar_node->data;
284
285   return toolbar->flags;
286 }
287
288 void
289 egg_toolbars_model_set_flags (EggToolbarsModel *t,
290                               int               toolbar_position,
291                               EggTbModelFlags   flags)
292 {
293   GNode *toolbar_node;
294   EggToolbarsToolbar *toolbar;
295
296   toolbar_node = g_node_nth_child (t->priv->toolbars, toolbar_position);
297   g_return_if_fail (toolbar_node != NULL);
298
299   toolbar = toolbar_node->data;
300
301   toolbar->flags = flags;
302
303   g_signal_emit (G_OBJECT (t), signals[TOOLBAR_CHANGED],
304                  0, toolbar_position);
305 }
306
307 void
308 egg_toolbars_model_add_separator (EggToolbarsModel *t,
309                                   int               toolbar_position,
310                                   int               position)
311 {
312   GNode *parent_node;
313   GNode *node;
314   EggToolbarsItem *item;
315   int real_position;
316
317   g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t));
318
319   parent_node = g_node_nth_child (t->priv->toolbars, toolbar_position);
320   item = toolbars_item_new ("separator", EGG_TOOLBAR_ITEM_TYPE, TRUE);
321   node = g_node_new (item);
322   g_node_insert (parent_node, position, node);
323
324   real_position = g_node_child_position (parent_node, node);
325
326   g_signal_emit (G_OBJECT (t), signals[ITEM_ADDED], 0,
327                  toolbar_position, real_position);
328 }
329
330 static gboolean
331 impl_add_item (EggToolbarsModel    *t,
332                int                  toolbar_position,
333                int                  position,
334                const char          *id,
335                const char          *type)
336 {
337   GNode *parent_node;
338   GNode *node;
339   EggToolbarsItem *item;
340   int real_position;
341
342   g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (t), FALSE);
343   g_return_val_if_fail (id != NULL, FALSE);
344   g_return_val_if_fail (type != NULL, FALSE);
345
346   parent_node = g_node_nth_child (t->priv->toolbars, toolbar_position);
347   item = toolbars_item_new (id, type, FALSE);
348   node = g_node_new (item);
349   g_node_insert (parent_node, position, node);
350
351   real_position = g_node_child_position (parent_node, node);
352
353   g_signal_emit (G_OBJECT (t), signals[ITEM_ADDED], 0,
354                  toolbar_position, real_position);
355
356   return TRUE;
357 }
358
359 static void
360 parse_item_list (EggToolbarsModel *t,
361                  xmlNodePtr        child,
362                  int               position)
363 {
364   while (child)
365     {
366       if (xmlStrEqual (child->name, (const xmlChar*) "toolitem"))
367         {
368           xmlChar *name, *type;
369           char *id;
370
371           name = xmlGetProp (child, (const xmlChar*) "name");
372           type = xmlGetProp (child, (const xmlChar*) "type");
373           if (type == NULL)
374             {
375               type = xmlCharStrdup (EGG_TOOLBAR_ITEM_TYPE);
376             }
377
378           if (name != NULL && name[0] != '\0' && type != NULL)
379             {
380               id = egg_toolbars_model_get_item_id (t, (const char*)type, (const char*)name);
381               if (id != NULL)
382                 {
383                   egg_toolbars_model_add_item (t, position, -1, id, (const char*)type);
384                 }
385               g_free (id);
386             }
387           xmlFree (name);
388           xmlFree (type);
389         }
390       else if (xmlStrEqual (child->name, (const xmlChar*) "separator"))
391         {
392           egg_toolbars_model_add_separator (t, position, -1);
393         }
394
395       child = child->next;
396     }
397 }
398
399 int
400 egg_toolbars_model_add_toolbar (EggToolbarsModel *t,
401                                 int               position,
402                                 const char       *name)
403 {
404   GNode *node;
405   int real_position;
406
407   g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (t), -1);
408
409   node = g_node_new (toolbars_toolbar_new (name));
410   g_node_insert (t->priv->toolbars, position, node);
411
412   real_position = g_node_child_position (t->priv->toolbars, node);
413
414   g_signal_emit (G_OBJECT (t), signals[TOOLBAR_ADDED],
415                  0, real_position);
416
417   return g_node_child_position (t->priv->toolbars, node);
418 }
419
420 static void
421 parse_toolbars (EggToolbarsModel *t,
422                 xmlNodePtr        child)
423 {
424   while (child)
425     {
426       if (xmlStrEqual (child->name, (const xmlChar*) "toolbar"))
427         {
428           xmlChar *name;
429           xmlChar *style;
430           int position;
431
432           name = xmlGetProp (child, (const xmlChar*) "name");
433           position = egg_toolbars_model_add_toolbar (t, -1, (const char*) name);
434           xmlFree (name);
435
436           style = xmlGetProp (child, (const xmlChar*) "style");
437           if (style && xmlStrEqual (style, (const xmlChar*) "icons-only"))
438             {
439               /* FIXME: use toolbar position instead of 0 */
440               egg_toolbars_model_set_flags (t, 0, EGG_TB_MODEL_ICONS);
441             }
442           xmlFree (style);
443
444           parse_item_list (t, child->children, position);
445         }
446
447       child = child->next;
448     }
449 }
450
451 gboolean
452 egg_toolbars_model_load (EggToolbarsModel *t,
453                          const char *xml_file)
454 {
455   xmlDocPtr doc;
456   xmlNodePtr root;
457
458   g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (t), FALSE);
459
460   if (!xml_file || !g_file_test (xml_file, G_FILE_TEST_EXISTS)) return FALSE;
461
462   doc = xmlParseFile (xml_file);
463   if (doc == NULL)
464   {
465     g_warning ("Failed to load XML data from %s", xml_file);
466     return FALSE;
467   }
468   root = xmlDocGetRootElement (doc);
469
470   parse_toolbars (t, root->children);
471
472   xmlFreeDoc (doc);
473
474   return TRUE;
475 }
476
477 static char *
478 impl_get_item_id (EggToolbarsModel *t,
479                   const char       *type,
480                   const char       *data)
481 {
482   if (strcmp (type, EGG_TOOLBAR_ITEM_TYPE) == 0)
483     {
484       return g_strdup (data);
485     }
486
487   return NULL;
488 }
489
490 static char *
491 impl_get_item_data (EggToolbarsModel *t,
492                     const char       *type,
493                     const char       *id)
494 {
495   if (strcmp (type, EGG_TOOLBAR_ITEM_TYPE) == 0)
496     {
497       return g_strdup (id);
498     }
499
500   return NULL;
501 }
502
503 static char *
504 impl_get_item_type (EggToolbarsModel *t,
505                     GdkAtom type)
506 {
507   if (gdk_atom_intern (EGG_TOOLBAR_ITEM_TYPE, FALSE) == type)
508     {
509       return g_strdup (EGG_TOOLBAR_ITEM_TYPE);
510     }
511
512   return NULL;
513 }
514
515 static gboolean
516 _egg_accumulator_STRING (GSignalInvocationHint *ihint,
517                          GValue                *return_accu,
518                          const GValue          *handler_return,
519                          gpointer               dummy)
520 {
521   gboolean continue_emission;
522   const char *retval;
523
524   retval = g_value_get_string (handler_return);
525   g_value_set_string (return_accu, retval);
526   continue_emission = !retval || !retval[0];
527   
528   return continue_emission;
529 }
530
531
532 static void
533 egg_toolbars_model_class_init (EggToolbarsModelClass *klass)
534 {
535   GObjectClass *object_class = G_OBJECT_CLASS (klass);
536
537   parent_class = g_type_class_peek_parent (klass);
538
539   object_class->finalize = egg_toolbars_model_finalize;
540
541   klass->add_item = impl_add_item;
542   klass->get_item_id = impl_get_item_id;
543   klass->get_item_data = impl_get_item_data;
544   klass->get_item_type = impl_get_item_type;
545
546   signals[ITEM_ADDED] =
547     g_signal_new ("item_added",
548                   G_OBJECT_CLASS_TYPE (object_class),
549                   G_SIGNAL_RUN_LAST,
550                   G_STRUCT_OFFSET (EggToolbarsModelClass, item_added),
551                   NULL, NULL, _egg_marshal_VOID__INT_INT,
552                   G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
553   signals[TOOLBAR_ADDED] =
554     g_signal_new ("toolbar_added",
555                   G_OBJECT_CLASS_TYPE (object_class),
556                   G_SIGNAL_RUN_LAST,
557                   G_STRUCT_OFFSET (EggToolbarsModelClass, toolbar_added),
558                   NULL, NULL, g_cclosure_marshal_VOID__INT,
559                   G_TYPE_NONE, 1, G_TYPE_INT);
560   signals[ITEM_REMOVED] =
561     g_signal_new ("item_removed",
562                   G_OBJECT_CLASS_TYPE (object_class),
563                   G_SIGNAL_RUN_LAST,
564                   G_STRUCT_OFFSET (EggToolbarsModelClass, item_removed),
565                   NULL, NULL, _egg_marshal_VOID__INT_INT,
566                   G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
567   signals[TOOLBAR_REMOVED] =
568     g_signal_new ("toolbar_removed",
569                   G_OBJECT_CLASS_TYPE (object_class),
570                   G_SIGNAL_RUN_LAST,
571                   G_STRUCT_OFFSET (EggToolbarsModelClass, toolbar_removed),
572                   NULL, NULL, g_cclosure_marshal_VOID__INT,
573                   G_TYPE_NONE, 1, G_TYPE_INT);
574   signals[TOOLBAR_CHANGED] =
575     g_signal_new ("toolbar_changed",
576                   G_OBJECT_CLASS_TYPE (object_class),
577                   G_SIGNAL_RUN_LAST,
578                   G_STRUCT_OFFSET (EggToolbarsModelClass, toolbar_changed),
579                   NULL, NULL, g_cclosure_marshal_VOID__INT,
580                   G_TYPE_NONE, 1, G_TYPE_INT);
581   signals[GET_ITEM_TYPE] =
582     g_signal_new ("get_item_type",
583                   G_OBJECT_CLASS_TYPE (object_class),
584                   G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST,
585                   G_STRUCT_OFFSET (EggToolbarsModelClass, get_item_type),
586                   _egg_accumulator_STRING, NULL,
587                   _egg_marshal_STRING__POINTER,
588                   G_TYPE_STRING, 1, G_TYPE_POINTER);
589   signals[GET_ITEM_ID] =
590     g_signal_new ("get_item_id",
591                   G_OBJECT_CLASS_TYPE (object_class),
592                   G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST,
593                   G_STRUCT_OFFSET (EggToolbarsModelClass, get_item_id),
594                   _egg_accumulator_STRING, NULL,
595                   _egg_marshal_STRING__STRING_STRING,
596                   G_TYPE_STRING, 2, G_TYPE_STRING, G_TYPE_STRING);
597   signals[GET_ITEM_DATA] =
598     g_signal_new ("get_item_data",
599                   G_OBJECT_CLASS_TYPE (object_class),
600                   G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST,
601                   G_STRUCT_OFFSET (EggToolbarsModelClass, get_item_data),
602                   _egg_accumulator_STRING, NULL,
603                   _egg_marshal_STRING__STRING_STRING,
604                   G_TYPE_STRING, 2, G_TYPE_STRING, G_TYPE_STRING);
605
606   g_type_class_add_private (object_class, sizeof (EggToolbarsModelPrivate));
607 }
608
609 static void
610 egg_toolbars_model_init (EggToolbarsModel *t)
611 {
612   t->priv =EGG_TOOLBARS_MODEL_GET_PRIVATE (t);
613
614   t->priv->toolbars = g_node_new (NULL);
615 }
616
617 static void
618 free_toolbar (GNode *toolbar_node)
619 {
620   g_node_children_foreach (toolbar_node, G_TRAVERSE_ALL,
621                            (GNodeForeachFunc) free_item_node, NULL);
622   free_toolbar_node (toolbar_node);
623 }
624
625 static void
626 egg_toolbars_model_finalize (GObject *object)
627 {
628   EggToolbarsModel *t = EGG_TOOLBARS_MODEL (object);
629
630   g_node_children_foreach (t->priv->toolbars, G_TRAVERSE_ALL,
631                            (GNodeForeachFunc) free_toolbar, NULL);
632   g_node_destroy (t->priv->toolbars);
633
634   G_OBJECT_CLASS (parent_class)->finalize (object);
635 }
636
637 EggToolbarsModel *
638 egg_toolbars_model_new (void)
639 {
640   return EGG_TOOLBARS_MODEL (g_object_new (EGG_TYPE_TOOLBARS_MODEL, NULL));
641 }
642
643 void
644 egg_toolbars_model_remove_toolbar (EggToolbarsModel   *t,
645                                    int                 position)
646 {
647   GNode *node;
648   EggTbModelFlags flags;
649
650   g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t));
651
652   flags = egg_toolbars_model_get_flags (t, position);
653
654   if (!(flags & EGG_TB_MODEL_NOT_REMOVABLE))
655     {
656       node = g_node_nth_child (t->priv->toolbars, position);
657       g_return_if_fail (node != NULL);
658
659       free_toolbar_node (node);
660
661       g_signal_emit (G_OBJECT (t), signals[TOOLBAR_REMOVED],
662                      0, position);
663     }
664 }
665
666 void
667 egg_toolbars_model_remove_item (EggToolbarsModel *t,
668                                 int               toolbar_position,
669                                 int               position)
670 {
671   GNode *node, *toolbar;
672
673   g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t));
674
675   toolbar = g_node_nth_child (t->priv->toolbars, toolbar_position);
676   g_return_if_fail (toolbar != NULL);
677
678   node = g_node_nth_child (toolbar, position);
679   g_return_if_fail (node != NULL);
680
681   free_item_node (node);
682
683   g_signal_emit (G_OBJECT (t), signals[ITEM_REMOVED], 0,
684                  toolbar_position, position);
685 }
686
687 void
688 egg_toolbars_model_move_item (EggToolbarsModel *t,
689                               int               toolbar_position,
690                               int               position,
691                               int               new_toolbar_position,
692                               int               new_position)
693 {
694   GNode *node, *toolbar, *new_toolbar;
695
696   g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t));
697
698   toolbar = g_node_nth_child (t->priv->toolbars, toolbar_position);
699   g_return_if_fail (toolbar != NULL);
700
701   new_toolbar = g_node_nth_child (t->priv->toolbars, new_toolbar_position);
702   g_return_if_fail (new_toolbar != NULL);
703
704   node = g_node_nth_child (toolbar, position);
705   g_return_if_fail (node != NULL);
706
707   g_node_unlink (node);
708
709   g_signal_emit (G_OBJECT (t), signals[ITEM_REMOVED], 0,
710                  toolbar_position, position);
711
712   g_node_insert (new_toolbar, new_position, node);
713
714   g_signal_emit (G_OBJECT (t), signals[ITEM_ADDED], 0,
715                  new_toolbar_position, new_position);
716 }
717
718 int
719 egg_toolbars_model_n_items (EggToolbarsModel *t,
720                             int               toolbar_position)
721 {
722   GNode *toolbar;
723
724   toolbar = g_node_nth_child (t->priv->toolbars, toolbar_position);
725   g_return_val_if_fail (toolbar != NULL, -1);
726
727   return g_node_n_children (toolbar);
728 }
729
730 void
731 egg_toolbars_model_item_nth (EggToolbarsModel *t,
732                              int               toolbar_position,
733                              int               position,
734                              gboolean         *is_separator,
735                              const char      **id,
736                              const char      **type)
737 {
738   GNode *toolbar;
739   GNode *item;
740   EggToolbarsItem *idata;
741
742   toolbar = g_node_nth_child (t->priv->toolbars, toolbar_position);
743   g_return_if_fail (toolbar != NULL);
744
745   item = g_node_nth_child (toolbar, position);
746   g_return_if_fail (item != NULL);
747
748   idata = item->data;
749
750   *is_separator = idata->separator;
751
752   if (id)
753     {
754       *id = idata->id;
755     }
756
757   if (type)
758     {
759       *type = idata->type;
760     }
761 }
762
763 int
764 egg_toolbars_model_n_toolbars (EggToolbarsModel *t)
765 {
766   return g_node_n_children (t->priv->toolbars);
767 }
768
769 const char *
770 egg_toolbars_model_toolbar_nth (EggToolbarsModel *t,
771                                 int               position)
772 {
773   GNode *toolbar;
774   EggToolbarsToolbar *tdata;
775
776   toolbar = g_node_nth_child (t->priv->toolbars, position);
777   g_return_val_if_fail (toolbar != NULL, NULL);
778
779   tdata = toolbar->data;
780
781   return tdata->name;
782 }
783
784 gboolean
785 egg_toolbars_model_add_item (EggToolbarsModel *t,
786                              int               toolbar_position,
787                              int               position,
788                              const char       *id,
789                              const char       *type)
790 {
791   EggToolbarsModelClass *klass = EGG_TOOLBARS_MODEL_GET_CLASS (t);
792   return klass->add_item (t, toolbar_position, position, id, type);
793 }
794
795 char *
796 egg_toolbars_model_get_item_id (EggToolbarsModel *t,
797                                 const char       *type,
798                                 const char       *name)
799 {
800   char *retval;
801
802   g_signal_emit (t, signals[GET_ITEM_ID], 0, type, name, &retval);
803
804   return retval;
805 }
806
807 char *
808 egg_toolbars_model_get_item_data (EggToolbarsModel *t,
809                                   const char       *type,
810                                   const char       *id)
811 {
812   char *retval;
813
814   g_signal_emit (t, signals[GET_ITEM_DATA], 0, type, id, &retval);
815
816   return retval;
817 }
818
819 char *
820 egg_toolbars_model_get_item_type (EggToolbarsModel *t,
821                                   GdkAtom type)
822 {
823   char *retval;
824
825   g_signal_emit (t, signals[GET_ITEM_TYPE], 0, type, &retval);
826
827   return retval;
828 }