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