source: trunk/third/evolution/shell/e-shortcuts.c @ 18147

Revision 18147, 28.6 KB checked in by ghudson, 22 years ago (diff)
Merge with evolution 1.2.1.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/* e-shortcuts.c
3 *
4 * Copyright (C) 2000, 2001 Ximian, Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
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 GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Author: Ettore Perazzoli
21 */
22
23/* The shortcut list goes like this:
24
25   <?xml version="1.0"?>
26   <shortcuts>
27           <group title="Evolution shortcuts">
28                   <item name="Inbox" type="mail">evolution:/local/Inbox</item>
29                   <item name="Trash" type="vtrash">evolution:/local/Trash</item>
30                   <item name="Calendar" type="calendar">evolution:/local/Calendar</item>
31           </group>
32
33           <group title="Personal shortcuts">
34                   <item>evolution:/local/Personal</item>
35           </group>
36   </shortcuts>
37
38   FIXME: Do we want to use a namespace for this?
39 */
40
41#ifdef HAVE_CONFIG_H
42#include <config.h>
43#endif
44
45#include "e-shortcuts.h"
46
47#include <string.h>
48
49#include <glib.h>
50#include <gtk/gtkmain.h>
51#include <gtk/gtkobject.h>
52#include <gtk/gtksignal.h>
53#include <gtk/gtktypeutils.h>
54
55#include <gnome-xml/parser.h>
56#include <gnome-xml/xmlmemory.h>
57
58#include <libgnome/gnome-defs.h>
59#include <libgnome/gnome-i18n.h>
60#include <gal/util/e-util.h>
61#include <gal/util/e-xml-utils.h>
62#include <gal/widgets/e-unicode.h>
63#include <gal/shortcut-bar/e-shortcut-bar.h>
64
65#include "e-shortcuts-view.h"
66
67#include "e-shell-constants.h"
68
69
70#define PARENT_TYPE GTK_TYPE_OBJECT
71static GtkObjectClass *parent_class = NULL;
72
73struct _ShortcutGroup {
74        /* Title of the group.  */
75        char *title;
76
77        /* A list of shortcuts.  */
78        GSList *shortcuts;
79
80        /* Whether to use small icons for this group.  */
81        unsigned int use_small_icons : 1;
82};
83typedef struct _ShortcutGroup ShortcutGroup;
84
85struct _EShortcutsPrivate {
86        /* Name of the file associated with these shortcuts.  Changes in the shortcuts
87           will update this file automatically.  */
88        char *file_name;
89
90        /* ID of the idle function that will be called to save the shortcuts when they are
91           changed.  */
92        int save_idle_id;
93
94        /* Whether these shortcuts need to be saved to disk.  */
95        gboolean dirty;
96
97        /* The shell that is associated with these shortcuts.  */
98        EShell *shell;
99
100        /* Total number of groups.  */
101        int num_groups;
102
103        /* A list of ShortcutGroups.  */
104        GSList *groups;
105
106        /* A list of ShortcutViews.  */
107        GSList *views;
108};
109
110enum {
111        NEW_GROUP,
112        REMOVE_GROUP,
113        RENAME_GROUP,
114        GROUP_CHANGE_ICON_SIZE,
115        NEW_SHORTCUT,
116        REMOVE_SHORTCUT,
117        UPDATE_SHORTCUT,
118        LAST_SIGNAL
119};
120
121static guint signals[LAST_SIGNAL] = { 0 };
122
123
124static void make_dirty (EShortcuts *shortcuts);
125
126
127static EShortcutItem *
128shortcut_item_new (const char *uri,
129                   const char *name,
130                   int unread_count,
131                   const char *type,
132                   const char *custom_icon_name)
133{
134        EShortcutItem *new;
135
136        if (name == NULL)
137                name = g_basename (uri);
138
139        new = g_new (EShortcutItem, 1);
140        new->uri              = g_strdup (uri);
141        new->name             = g_strdup (name);
142        new->type             = g_strdup (type);
143        new->custom_icon_name = g_strdup (custom_icon_name);
144        new->unread_count     = unread_count;
145
146        return new;
147}
148
149static gboolean
150shortcut_item_update (EShortcutItem *shortcut_item,
151                      const char *uri,
152                      const char *name,
153                      int unread_count,
154                      const char *type,
155                      const char *custom_icon_name)
156{
157        gboolean changed = FALSE;
158
159        if (name == NULL)
160                name = g_basename (uri);
161
162        if (shortcut_item->unread_count != unread_count) {
163                shortcut_item->unread_count = unread_count;
164                changed = TRUE;
165        }
166
167#define UPDATE_STRING(member)                                   \
168        if (shortcut_item->member == NULL || member == NULL ||  \
169            strcmp (shortcut_item->member, member) != 0) {      \
170                g_free (shortcut_item->member);                 \
171                shortcut_item->member  = g_strdup (member);     \
172                changed = TRUE;                                 \
173        }
174
175        UPDATE_STRING (uri);
176        UPDATE_STRING (name);
177        UPDATE_STRING (type);
178        UPDATE_STRING (custom_icon_name);
179
180#undef UPDATE_STRING
181
182        return changed;
183}
184
185static void
186shortcut_item_free (EShortcutItem *shortcut_item)
187{
188        g_free (shortcut_item->uri);
189        g_free (shortcut_item->name);
190        g_free (shortcut_item->type);
191
192        g_free (shortcut_item);
193}
194
195static ShortcutGroup *
196shortcut_group_new (const char *title)
197{
198        ShortcutGroup *new;
199
200        new = g_new (ShortcutGroup, 1);
201        new->title           = g_strdup (title);
202        new->shortcuts       = NULL;
203        new->use_small_icons = FALSE;
204
205        return new;
206}
207
208static void
209shortcut_group_free (ShortcutGroup *group)
210{
211        GSList *p;
212
213        g_free (group->title);
214
215        for (p = group->shortcuts; p != NULL; p = p->next)
216                shortcut_item_free ((EShortcutItem *) p->data);
217        g_slist_free (group->shortcuts);
218
219        g_free (group);
220}
221
222
223/* Utility functions.  */
224
225static gboolean
226update_shortcut_and_emit_signal (EShortcuts *shortcuts,
227                                 EShortcutItem *shortcut_item,
228                                 int group_num,
229                                 int num,
230                                 const char *uri,
231                                 const char *name,
232                                 int unread_count,
233                                 const char *type,
234                                 const char *custom_icon_name)
235{
236        /* Only thing that changed was the unread count */
237        if (shortcut_item->unread_count != unread_count
238            && !shortcut_item_update (shortcut_item, uri, name, unread_count, type, custom_icon_name)) {
239                gtk_signal_emit (GTK_OBJECT (shortcuts), signals[UPDATE_SHORTCUT], group_num, num);
240                return FALSE;
241        }
242
243        /* Unread count is the same, but other stuff changed */
244        else if (shortcut_item_update (shortcut_item, uri, name, unread_count, type, custom_icon_name)) {
245                gtk_signal_emit (GTK_OBJECT (shortcuts), signals[UPDATE_SHORTCUT], group_num, num);
246                return TRUE;
247        }
248
249        /* Nothing at all changed, return false only */
250        else
251                return FALSE;
252}
253
254static void
255unload_shortcuts (EShortcuts *shortcuts)
256{
257        EShortcutsPrivate *priv;
258        GSList *orig_groups;
259        GSList *p;
260
261        priv = shortcuts->priv;
262        orig_groups = priv->groups;
263
264        for (p = priv->groups; p != NULL; p = p->next) {
265                ShortcutGroup *group;
266
267                gtk_signal_emit (GTK_OBJECT (shortcuts), signals[REMOVE_GROUP], 0);
268
269                group = (ShortcutGroup *) p->data;
270
271                shortcut_group_free (group);
272
273                priv->groups = priv->groups->next;
274        }
275
276        if (orig_groups != NULL)
277                g_slist_free (orig_groups);
278
279        priv->groups = NULL;
280}
281
282static gboolean
283load_shortcuts (EShortcuts *shortcuts,
284                const char *file_name)
285{
286        EShortcutsPrivate *priv;
287        xmlDoc *doc;
288        xmlNode *root;
289        xmlNode *p, *q;
290
291        /* FIXME: Update the views by emitting the appropriate signals.  */
292
293        priv = shortcuts->priv;
294
295        doc = xmlParseFile (file_name);
296        if (doc == NULL)
297                return FALSE;
298
299        root = xmlDocGetRootElement (doc);
300        if (root == NULL || strcmp (root->name, "shortcuts") != 0) {
301                xmlFreeDoc (doc);
302                return FALSE;
303        }
304
305        unload_shortcuts (shortcuts);
306
307        for (p = root->childs; p != NULL; p = p->next) {
308                ShortcutGroup *shortcut_group;
309                xmlChar *shortcut_group_title;
310                xmlChar *icon_size;
311
312                if (strcmp ((char *) p->name, "group") != 0)
313                        continue;
314
315                shortcut_group_title = xmlGetProp (p, "title");
316                if (shortcut_group_title == NULL)
317                        continue;
318
319                shortcut_group = shortcut_group_new (shortcut_group_title);
320                xmlFree (shortcut_group_title);
321
322                icon_size = xmlGetProp (p, "icon_size");
323                if (icon_size != NULL && strcmp (icon_size, "small") == 0)
324                        shortcut_group->use_small_icons = TRUE;
325                else
326                        shortcut_group->use_small_icons = FALSE;
327                xmlFree (icon_size);
328
329                for (q = p->childs; q != NULL; q = q->next) {
330                        EShortcutItem *shortcut_item;
331                        xmlChar *uri;
332                        xmlChar *name;
333                        xmlChar *type;
334                        xmlChar *icon;
335                        char *path;
336
337                        if (strcmp ((char *) q->name, "item") != 0)
338                                continue;
339
340                        uri  = xmlNodeListGetString (doc, q->childs, 1);
341                        if (uri == NULL)
342                                continue;
343
344                        if (e_shell_parse_uri (priv->shell, uri, &path, NULL)) {
345                                EFolder *folder;
346
347                                folder = e_storage_set_get_folder (e_shell_get_storage_set (priv->shell), path);
348                                if (folder != NULL) {
349                                        name = xmlMemStrdup (e_folder_get_name (folder));
350                                        type = xmlMemStrdup (e_folder_get_type_string (folder));
351
352                                        if (e_folder_get_custom_icon_name (folder) != NULL)
353                                                icon = xmlMemStrdup (e_folder_get_custom_icon_name (folder));
354                                        else
355                                                icon = NULL;
356                                } else {
357                                        name = xmlGetProp (q, "name");
358                                        type = xmlGetProp (q, "type");
359                                        icon = xmlGetProp (q, "icon");
360                                }
361
362                                shortcut_item = shortcut_item_new (uri, name, 0, type, icon);
363                                shortcut_group->shortcuts = g_slist_prepend (shortcut_group->shortcuts,
364                                                                             shortcut_item);
365
366                                if (name != NULL)
367                                        xmlFree (name);
368                                if (type != NULL)
369                                        xmlFree (type);
370                                if (icon != NULL)
371                                        xmlFree (icon);
372                        }
373
374                        xmlFree (uri);
375                }
376
377                shortcut_group->shortcuts = g_slist_reverse (shortcut_group->shortcuts);
378
379                priv->groups = g_slist_prepend (priv->groups, shortcut_group);
380                priv->num_groups ++;
381        }
382
383        priv->groups = g_slist_reverse (priv->groups);
384
385        xmlFreeDoc (doc);
386
387        /* After loading, we always have to re-save ourselves as we have merged
388           the information we have with the information we got from the
389           StorageSet.  */
390        /* FIXME: Obviously, this sucks.  */
391        make_dirty (shortcuts);
392
393        return TRUE;
394}
395
396static gboolean
397save_shortcuts (EShortcuts *shortcuts,
398                const char *file_name)
399{
400        EShortcutsPrivate *priv;
401        xmlDoc *doc;
402        xmlNode *root;
403        GSList *p, *q;
404
405        priv = shortcuts->priv;
406
407        doc = xmlNewDoc ((xmlChar *) "1.0");
408        root = xmlNewDocNode (doc, NULL, (xmlChar *) "shortcuts", NULL);
409        xmlDocSetRootElement (doc, root);
410
411        for (p = priv->groups; p != NULL; p = p->next) {
412                ShortcutGroup *group;
413                xmlNode *group_node;
414
415                group = (ShortcutGroup *) p->data;
416                group_node = xmlNewChild (root, NULL, (xmlChar *) "group", NULL);
417
418                xmlSetProp (group_node, (xmlChar *) "title", group->title);
419
420                if (group->use_small_icons)
421                        xmlSetProp (group_node, (xmlChar *) "icon_size", "small");
422                else
423                        xmlSetProp (group_node, (xmlChar *) "icon_size", "large");
424
425                for (q = group->shortcuts; q != NULL; q = q->next) {
426                        EShortcutItem *shortcut;
427                        xmlNode *shortcut_node;
428
429                        shortcut = (EShortcutItem *) q->data;
430                        shortcut_node = xmlNewTextChild (group_node, NULL, (xmlChar *) "item",
431                                                         (xmlChar *) shortcut->uri);
432
433                        if (shortcut->name != NULL)
434                                xmlSetProp (shortcut_node, (xmlChar *) "name", shortcut->name);
435
436                        if (shortcut->type != NULL)
437                                xmlSetProp (shortcut_node, (xmlChar *) "type", shortcut->type);
438
439                        if (shortcut->custom_icon_name != NULL)
440                                xmlSetProp (shortcut_node, (xmlChar *) "icon", shortcut->custom_icon_name);
441                }
442        }
443
444        if (xmlSaveFile (file_name, doc) < 0) {
445                xmlFreeDoc (doc);
446                return FALSE;
447        }
448
449        xmlFreeDoc (doc);
450        return TRUE;
451}
452
453
454/* Idle function to update the file on disk.  */
455
456static int
457idle_cb (void *data)
458{
459        EShortcuts *shortcuts;
460        EShortcutsPrivate *priv;
461
462        shortcuts = E_SHORTCUTS (data);
463        priv = shortcuts->priv;
464
465        if (priv->dirty) {
466                if (! e_shortcuts_save (shortcuts, NULL))
467                        g_warning ("Saving of shortcuts failed -- %s", priv->file_name);
468                else
469                        priv->dirty = FALSE;
470        }
471
472        priv->save_idle_id = 0;
473
474        return FALSE;
475}
476
477static void
478schedule_idle (EShortcuts *shortcuts)
479{
480        EShortcutsPrivate *priv;
481
482        priv = shortcuts->priv;
483
484        if (priv->save_idle_id != 0)
485                return;
486
487        priv->save_idle_id = gtk_idle_add (idle_cb, shortcuts);
488}
489
490static void
491make_dirty (EShortcuts *shortcuts)
492{
493        EShortcutsPrivate *priv;
494
495        priv = shortcuts->priv;
496
497        priv->dirty = TRUE;
498        schedule_idle (shortcuts);
499}
500
501static void
502update_shortcuts_by_path (EShortcuts *shortcuts,
503                          const char *path)
504{
505        EShortcutsPrivate *priv;
506        EFolder *folder;
507        const GSList *p, *q;
508        char *evolution_uri;
509        int group_num, num;
510        gboolean changed = FALSE;
511
512        priv = shortcuts->priv;
513        folder = e_storage_set_get_folder (e_shell_get_storage_set (priv->shell), path);
514
515        evolution_uri = g_strconcat (E_SHELL_URI_PREFIX, path, NULL);
516
517        group_num = 0;
518        for (p = priv->groups; p != NULL; p = p->next, group_num++) {
519                ShortcutGroup *group;
520
521                group = (ShortcutGroup *) p->data;
522                num = 0;
523                for (q = group->shortcuts; q != NULL; q = q->next, num++) {
524                        EShortcutItem *shortcut_item;
525
526                        shortcut_item = (EShortcutItem *) q->data;
527
528                        if (strcmp (shortcut_item->uri, evolution_uri) == 0) {
529                                changed = update_shortcut_and_emit_signal (shortcuts,
530                                                                           shortcut_item,
531                                                                           group_num,
532                                                                           num,
533                                                                           evolution_uri,
534                                                                           shortcut_item->name,
535                                                                           e_folder_get_unread_count (folder),
536                                                                           e_folder_get_type_string (folder),
537                                                                           e_folder_get_custom_icon_name (folder));
538                        }
539                }
540        }
541
542        g_free (evolution_uri);
543
544        if (changed)
545                make_dirty (shortcuts);
546}
547
548
549static EShortcutItem *
550get_item (EShortcuts *shortcuts,
551          int group_num,
552          int num)
553{
554        EShortcutsPrivate *priv;
555        ShortcutGroup *group;
556        GSList *group_element;
557        GSList *shortcut_element;
558
559        g_return_val_if_fail (shortcuts != NULL, NULL);
560        g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
561
562        priv = shortcuts->priv;
563
564        group_element = g_slist_nth (priv->groups, group_num);
565        if (group_element == NULL)
566                return NULL;
567
568        group = (ShortcutGroup *) group_element->data;
569
570        shortcut_element = g_slist_nth (group->shortcuts, num);
571        if (shortcut_element == NULL)
572                return NULL;
573
574        return (EShortcutItem *) shortcut_element->data;
575}
576
577
578/* Signal handlers for the views.  */
579
580static void
581view_destroyed_cb (GtkObject *object,
582                   gpointer data)
583{
584        EShortcuts *shortcuts;
585        EShortcutsPrivate *priv;
586
587        shortcuts = E_SHORTCUTS (data);
588        priv = shortcuts->priv;
589
590        priv->views = g_slist_remove (priv->views, object);
591}
592
593
594/* Signal handlers for the EStorageSet.  */
595
596static void
597storage_set_new_folder_callback (EStorageSet *storage_set,
598                                 const char *path,
599                                 void *data)
600{
601        EShortcuts *shortcuts;
602
603        shortcuts = E_SHORTCUTS (data);
604
605        update_shortcuts_by_path (shortcuts, path);
606}
607
608static void
609storage_set_updated_folder_callback (EStorageSet *storage_set,
610                                     const char *path,
611                                     void *data)
612{
613        EShortcuts *shortcuts;
614
615        shortcuts = E_SHORTCUTS (data);
616
617        update_shortcuts_by_path (shortcuts, path);
618}
619
620
621/* GtkObject methods.  */
622
623static void
624impl_destroy (GtkObject *object)
625{
626        EShortcuts *shortcuts;
627        EShortcutsPrivate *priv;
628
629        shortcuts = E_SHORTCUTS (object);
630        priv = shortcuts->priv;
631
632        g_free (priv->file_name);
633
634        unload_shortcuts (shortcuts);
635
636        if (priv->save_idle_id != 0)
637                gtk_idle_remove (priv->save_idle_id);
638
639        if (priv->dirty) {
640                if (! e_shortcuts_save (shortcuts, NULL))
641                        g_warning (_("Error saving shortcuts.")); /* FIXME */
642        }
643
644        (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
645}
646
647
648static void
649class_init (EShortcutsClass *klass)
650{
651        GtkObjectClass *object_class;
652
653        object_class = (GtkObjectClass*) klass;
654        object_class->destroy = impl_destroy;
655
656        parent_class = gtk_type_class (gtk_object_get_type ());
657
658        signals[NEW_GROUP]
659                = gtk_signal_new ("new_group",
660                                  GTK_RUN_FIRST,
661                                  object_class->type,
662                                  GTK_SIGNAL_OFFSET (EShortcutsClass, new_group),
663                                  gtk_marshal_NONE__INT,
664                                  GTK_TYPE_NONE, 1,
665                                  GTK_TYPE_INT);
666
667        signals[REMOVE_GROUP]
668                = gtk_signal_new ("remove_group",
669                                  GTK_RUN_FIRST,
670                                  object_class->type,
671                                  GTK_SIGNAL_OFFSET (EShortcutsClass, remove_group),
672                                  gtk_marshal_NONE__INT,
673                                  GTK_TYPE_NONE, 1,
674                                  GTK_TYPE_INT);
675
676        signals[RENAME_GROUP]
677                = gtk_signal_new ("rename_group",
678                                  GTK_RUN_FIRST,
679                                  object_class->type,
680                                  GTK_SIGNAL_OFFSET (EShortcutsClass, rename_group),
681                                  gtk_marshal_NONE__INT_POINTER,
682                                  GTK_TYPE_NONE, 2,
683                                  GTK_TYPE_INT,
684                                  GTK_TYPE_STRING);
685
686        signals[GROUP_CHANGE_ICON_SIZE]
687                = gtk_signal_new ("group_change_icon_size",
688                                  GTK_RUN_FIRST,
689                                  object_class->type,
690                                  GTK_SIGNAL_OFFSET (EShortcutsClass, group_change_icon_size),
691                                  gtk_marshal_NONE__INT_INT,
692                                  GTK_TYPE_NONE, 2,
693                                  GTK_TYPE_INT,
694                                  GTK_TYPE_INT);
695
696        signals[NEW_SHORTCUT]
697                = gtk_signal_new ("new_shortcut",
698                                  GTK_RUN_FIRST,
699                                  object_class->type,
700                                  GTK_SIGNAL_OFFSET (EShortcutsClass, new_shortcut),
701                                  gtk_marshal_NONE__INT_INT,
702                                  GTK_TYPE_NONE, 2,
703                                  GTK_TYPE_INT,
704                                  GTK_TYPE_INT);
705
706        signals[REMOVE_SHORTCUT]
707                = gtk_signal_new ("remove_shortcut",
708                                  GTK_RUN_FIRST,
709                                  object_class->type,
710                                  GTK_SIGNAL_OFFSET (EShortcutsClass, remove_shortcut),
711                                  gtk_marshal_NONE__INT_INT,
712                                  GTK_TYPE_NONE, 2,
713                                  GTK_TYPE_INT,
714                                  GTK_TYPE_INT);
715
716        signals[UPDATE_SHORTCUT]
717                = gtk_signal_new ("update_shortcut",
718                                  GTK_RUN_FIRST,
719                                  object_class->type,
720                                  GTK_SIGNAL_OFFSET (EShortcutsClass, update_shortcut),
721                                  gtk_marshal_NONE__INT_INT,
722                                  GTK_TYPE_NONE, 2,
723                                  GTK_TYPE_INT,
724                                  GTK_TYPE_INT);
725
726        gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
727}
728
729
730static void
731init (EShortcuts *shortcuts)
732{
733        EShortcutsPrivate *priv;
734
735        priv = g_new (EShortcutsPrivate, 1);
736
737        priv->file_name      = NULL;
738        priv->num_groups     = 0;
739        priv->groups         = NULL;
740        priv->views          = NULL;
741        priv->dirty          = 0;
742        priv->save_idle_id   = 0;
743        priv->shell          = NULL;
744
745        shortcuts->priv = priv;
746}
747
748
749void
750e_shortcuts_construct (EShortcuts *shortcuts,
751                       EShell *shell)
752{
753        EShortcutsPrivate *priv;
754        EStorageSet *storage_set;
755
756        g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
757        g_return_if_fail (E_IS_SHELL (shell));
758
759        GTK_OBJECT_UNSET_FLAGS (GTK_OBJECT (shortcuts), GTK_FLOATING);
760
761        priv = shortcuts->priv;
762
763        /* Don't ref it so we don't create a circular dependency.  */
764        priv->shell = shell;
765
766        storage_set = e_shell_get_storage_set (shell);
767
768        gtk_signal_connect_while_alive (GTK_OBJECT (storage_set), "new_folder",
769                                        GTK_SIGNAL_FUNC (storage_set_new_folder_callback),
770                                        shortcuts, GTK_OBJECT (shortcuts));
771        gtk_signal_connect_while_alive (GTK_OBJECT (storage_set), "updated_folder",
772                                        GTK_SIGNAL_FUNC (storage_set_updated_folder_callback),
773                                        shortcuts, GTK_OBJECT (shortcuts));
774}
775
776EShortcuts *
777e_shortcuts_new_from_file (EShell *shell,
778                           const char *file_name)
779{
780        EShortcuts *new;
781
782        g_return_val_if_fail (E_IS_SHELL (shell), NULL);
783        g_return_val_if_fail (file_name != NULL, NULL);
784
785        new = gtk_type_new (e_shortcuts_get_type ());
786        e_shortcuts_construct (new, shell);
787
788        if (! e_shortcuts_load (new, file_name))
789                new->priv->file_name = g_strdup (file_name);
790
791        return new;
792}
793
794
795int
796e_shortcuts_get_num_groups (EShortcuts *shortcuts)
797{
798        g_return_val_if_fail (shortcuts != NULL, 0);
799        g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), 0);
800
801        return shortcuts->priv->num_groups;
802}
803
804GSList *
805e_shortcuts_get_group_titles (EShortcuts *shortcuts)
806{
807        EShortcutsPrivate *priv;
808        ShortcutGroup *group;
809        GSList *list;
810        GSList *p;
811
812        g_return_val_if_fail (shortcuts != NULL, NULL);
813        g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
814
815        priv = shortcuts->priv;
816
817        list = NULL;
818
819        for (p = priv->groups; p != NULL; p = p->next) {
820                group = (ShortcutGroup *) p->data;
821                list = g_slist_prepend (list, g_strdup (group->title));
822        }
823
824        return g_slist_reverse (list);
825}
826
827const GSList *
828e_shortcuts_get_shortcuts_in_group (EShortcuts *shortcuts,
829                                    int group_num)
830{
831        EShortcutsPrivate *priv;
832        ShortcutGroup *shortcut_group;
833        GSList *shortcut_group_list_item;
834
835        priv = shortcuts->priv;
836
837        g_return_val_if_fail (shortcuts != NULL, NULL);
838        g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
839
840        shortcut_group_list_item = g_slist_nth (priv->groups, group_num);
841        if (shortcut_group_list_item == NULL)
842                return NULL;
843
844        shortcut_group = (ShortcutGroup *) shortcut_group_list_item->data;
845
846        return shortcut_group->shortcuts;
847}
848
849
850EShell *
851e_shortcuts_get_shell (EShortcuts *shortcuts)
852{
853        g_return_val_if_fail (shortcuts != NULL, NULL);
854        g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
855
856        return shortcuts->priv->shell;
857}
858
859
860GtkWidget *
861e_shortcuts_new_view (EShortcuts *shortcuts)
862{
863        EShortcutsPrivate *priv;
864        GtkWidget *new;
865
866        g_return_val_if_fail (shortcuts != NULL, NULL);
867        g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
868
869        priv = shortcuts->priv;
870
871        new = e_shortcuts_view_new (shortcuts);
872        priv->views = g_slist_prepend (priv->views, new);
873
874        gtk_signal_connect (GTK_OBJECT (new), "destroy", view_destroyed_cb, shortcuts);
875
876        return new;
877}
878
879
880gboolean
881e_shortcuts_load (EShortcuts *shortcuts,
882                  const char *file_name)
883{
884        EShortcutsPrivate *priv;
885        char *tmp;
886
887        g_return_val_if_fail (shortcuts != NULL, FALSE);
888        g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), FALSE);
889        g_return_val_if_fail (file_name == NULL || g_path_is_absolute (file_name), FALSE);
890
891        priv = shortcuts->priv;
892
893        if (file_name == NULL) {
894                if (priv->file_name == NULL)
895                        return FALSE;
896                file_name = priv->file_name;
897        }
898
899        if (! load_shortcuts (shortcuts, file_name))
900                return FALSE;
901
902        tmp = g_strdup (file_name);
903        g_free (priv->file_name);
904        priv->file_name = tmp;
905
906        return TRUE;
907}
908
909gboolean
910e_shortcuts_save (EShortcuts *shortcuts,
911                  const char *file_name)
912{
913        EShortcutsPrivate *priv;
914        char *tmp;
915
916        g_return_val_if_fail (shortcuts != NULL, FALSE);
917        g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), FALSE);
918        g_return_val_if_fail (file_name == NULL || g_path_is_absolute (file_name), FALSE);
919
920        priv = shortcuts->priv;
921
922        if (file_name == NULL) {
923                if (priv->file_name == NULL)
924                        return FALSE;
925                file_name = priv->file_name;
926        }
927
928        if (! save_shortcuts (shortcuts, file_name))
929                return FALSE;
930
931        tmp = g_strdup (file_name);
932        g_free (priv->file_name);
933        priv->file_name = tmp;
934
935        return TRUE;
936}
937
938
939const EShortcutItem *
940e_shortcuts_get_shortcut (EShortcuts *shortcuts,
941                          int group_num,
942                          int num)
943{
944        g_return_val_if_fail (shortcuts != NULL, NULL);
945        g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
946
947        return (const EShortcutItem *) get_item (shortcuts, group_num, num);
948}
949
950
951void
952e_shortcuts_remove_shortcut (EShortcuts *shortcuts,
953                             int group_num,
954                             int num)
955{
956        EShortcutsPrivate *priv;
957        ShortcutGroup *group;
958        GSList *p;
959        EShortcutItem *item;
960
961        g_return_if_fail (shortcuts != NULL);
962        g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
963
964        priv = shortcuts->priv;
965
966        p = g_slist_nth (priv->groups, group_num);
967        g_return_if_fail (p != NULL);
968
969        group = (ShortcutGroup *) p->data;
970
971        p = g_slist_nth (group->shortcuts, num);
972        g_return_if_fail (p != NULL);
973
974        gtk_signal_emit (GTK_OBJECT (shortcuts), signals[REMOVE_SHORTCUT], group_num, num);
975
976        item = (EShortcutItem *) p->data;
977        shortcut_item_free (item);
978
979        group->shortcuts = g_slist_remove_link (group->shortcuts, p);
980
981        make_dirty (shortcuts);
982}
983
984void
985e_shortcuts_add_shortcut (EShortcuts *shortcuts,
986                          int group_num,
987                          int num,
988                          const char *uri,
989                          const char *name,
990                          int unread_count,
991                          const char *type,
992                          const char *custom_icon_name)
993{
994        EShortcutsPrivate *priv;
995        ShortcutGroup *group;
996        EShortcutItem *item;
997        GSList *p;
998
999        g_return_if_fail (shortcuts != NULL);
1000        g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
1001
1002        priv = shortcuts->priv;
1003
1004        p = g_slist_nth (priv->groups, group_num);
1005        g_return_if_fail (p != NULL);
1006
1007        group = (ShortcutGroup *) p->data;
1008
1009        if (num == -1)
1010                num = g_slist_length (group->shortcuts);
1011
1012        item = shortcut_item_new (uri, name, unread_count, type, custom_icon_name);
1013
1014        group->shortcuts = g_slist_insert (group->shortcuts, item, num);
1015
1016        gtk_signal_emit (GTK_OBJECT (shortcuts), signals[NEW_SHORTCUT], group_num, num);
1017
1018        make_dirty (shortcuts);
1019}
1020
1021void
1022e_shortcuts_update_shortcut (EShortcuts *shortcuts,
1023                             int         group_num,
1024                             int         num,
1025                             const char *uri,
1026                             const char *name,
1027                             int unread_count,
1028                             const char *type,
1029                             const char *custom_icon_name)
1030{
1031        EShortcutItem *shortcut_item;
1032
1033        g_return_if_fail (shortcuts != NULL);
1034        g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
1035
1036        shortcut_item = get_item (shortcuts, group_num, num);
1037
1038        update_shortcut_and_emit_signal (shortcuts, shortcut_item, group_num, num,
1039                                         uri, name, unread_count, type, custom_icon_name);
1040
1041        make_dirty (shortcuts);
1042}
1043
1044
1045void
1046e_shortcuts_add_default_shortcuts (EShortcuts *shortcuts,
1047                                   int group_num)
1048{
1049        char *utf;
1050
1051        utf = e_utf8_from_locale_string (_("Summary"));
1052        e_shortcuts_add_shortcut (shortcuts, 0, -1, E_SUMMARY_URI, utf, 0, "summary", NULL);
1053        g_free (utf);
1054
1055        utf = e_utf8_from_locale_string (_("Inbox"));
1056        e_shortcuts_add_shortcut (shortcuts, 0, -1, "default:mail", utf, 0, "mail", "inbox");
1057        g_free (utf);
1058
1059        utf = e_utf8_from_locale_string (_("Calendar"));
1060        e_shortcuts_add_shortcut (shortcuts, 0, -1, "default:calendar", utf, 0, "calendar", NULL);
1061        g_free (utf);
1062
1063        utf = e_utf8_from_locale_string (_("Tasks"));
1064        e_shortcuts_add_shortcut (shortcuts, 0, -1, "default:tasks", utf, 0, "tasks", NULL);
1065        g_free (utf);
1066
1067        utf = e_utf8_from_locale_string (_("Contacts"));
1068        e_shortcuts_add_shortcut (shortcuts, 0, -1, "default:contacts", utf, 0, "contacts", NULL);
1069        g_free (utf);
1070}
1071
1072void
1073e_shortcuts_add_default_group (EShortcuts *shortcuts)
1074{
1075        char *utf;
1076
1077        g_return_if_fail (shortcuts != NULL);
1078        g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
1079
1080        utf = e_utf8_from_locale_string (_("Shortcuts"));
1081        e_shortcuts_add_group (shortcuts, -1, utf);
1082        g_free (utf);
1083
1084        e_shortcuts_add_default_shortcuts (shortcuts, -1);
1085}
1086
1087void
1088e_shortcuts_remove_group (EShortcuts *shortcuts,
1089                          int group_num)
1090{
1091        EShortcutsPrivate *priv;
1092        GSList *p;
1093
1094        g_return_if_fail (shortcuts != NULL);
1095        g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
1096
1097        priv = shortcuts->priv;
1098
1099        p = g_slist_nth (priv->groups, group_num);
1100        g_return_if_fail (p != NULL);
1101
1102        gtk_signal_emit (GTK_OBJECT (shortcuts), signals[REMOVE_GROUP], group_num);
1103
1104        shortcut_group_free ((ShortcutGroup *) p->data);
1105
1106        priv->groups = g_slist_remove_link (priv->groups, p);
1107        priv->num_groups --;
1108
1109        make_dirty (shortcuts);
1110}
1111
1112void
1113e_shortcuts_rename_group (EShortcuts *shortcuts,
1114                          int group_num,
1115                          const char *new_title)
1116{
1117        EShortcutsPrivate *priv;
1118        GSList *p;
1119        ShortcutGroup *group;
1120
1121        g_return_if_fail (shortcuts != NULL);
1122        g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
1123
1124        priv = shortcuts->priv;
1125
1126        p = g_slist_nth (priv->groups, group_num);
1127        g_return_if_fail (p != NULL);
1128
1129        group = (ShortcutGroup *) p->data;
1130        if (strcmp (group->title, new_title)) {
1131                g_free (group->title);
1132                group->title = g_strdup (new_title);
1133        } else
1134                return;
1135
1136        gtk_signal_emit (GTK_OBJECT (shortcuts), signals[RENAME_GROUP], group_num, new_title);
1137
1138        make_dirty (shortcuts);
1139}
1140
1141void
1142e_shortcuts_add_group (EShortcuts *shortcuts,
1143                       int group_num,
1144                       const char *group_name)
1145{
1146        EShortcutsPrivate *priv;
1147        ShortcutGroup *group;
1148
1149        g_return_if_fail (shortcuts != NULL);
1150        g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
1151
1152        priv = shortcuts->priv;
1153
1154        group = shortcut_group_new (group_name);
1155
1156        if (group_num == -1)
1157                group_num = g_slist_length (priv->groups);
1158
1159        priv->groups = g_slist_insert (priv->groups, group, group_num);
1160        priv->num_groups ++;
1161
1162        gtk_signal_emit (GTK_OBJECT (shortcuts), signals[NEW_GROUP], group_num);
1163
1164        make_dirty (shortcuts);
1165}
1166
1167
1168const char *
1169e_shortcuts_get_group_title (EShortcuts *shortcuts,
1170                             int group_num)
1171{
1172        EShortcutsPrivate *priv;
1173        GSList *group_element;
1174        const ShortcutGroup *group;
1175
1176        g_return_val_if_fail (shortcuts != NULL, NULL);
1177        g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL);
1178
1179        priv = shortcuts->priv;
1180
1181        group_element = g_slist_nth (priv->groups, group_num);
1182        if (group_element == NULL)
1183                return NULL;
1184
1185        group = (ShortcutGroup *) group_element->data;
1186
1187        return group->title;
1188}
1189
1190void
1191e_shortcuts_set_group_uses_small_icons  (EShortcuts *shortcuts,
1192                                         int group_num,
1193                                         gboolean use_small_icons)
1194{
1195        EShortcutsPrivate *priv;
1196        ShortcutGroup *group;
1197        GSList *group_element;
1198
1199        g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
1200
1201        priv = shortcuts->priv;
1202
1203        group_element = g_slist_nth (priv->groups, group_num);
1204        if (group_element == NULL)
1205                return;
1206
1207        group = (ShortcutGroup *) group_element->data;
1208
1209        use_small_icons = !! use_small_icons;
1210        if (group->use_small_icons != use_small_icons) {
1211                group->use_small_icons = use_small_icons;
1212                gtk_signal_emit (GTK_OBJECT (shortcuts), signals[GROUP_CHANGE_ICON_SIZE],
1213                                 group_num, use_small_icons);
1214
1215                make_dirty (shortcuts);
1216        }
1217}
1218
1219gboolean
1220e_shortcuts_get_group_uses_small_icons  (EShortcuts *shortcuts,
1221                                         int group_num)
1222{
1223        EShortcutsPrivate *priv;
1224        ShortcutGroup *group;
1225        GSList *group_element;
1226
1227        g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), FALSE);
1228
1229        priv = shortcuts->priv;
1230
1231        group_element = g_slist_nth (priv->groups, group_num);
1232        if (group_element == NULL)
1233                return FALSE;
1234
1235        group = (ShortcutGroup *) group_element->data;
1236        return group->use_small_icons;
1237}
1238
1239
1240void
1241e_shortcuts_update_shortcuts_for_changed_uri (EShortcuts *shortcuts,
1242                                              const char *old_uri,
1243                                              const char *new_uri)
1244{
1245        EShortcutsPrivate *priv;
1246        GSList *p;
1247
1248        g_return_if_fail (E_IS_SHORTCUTS (shortcuts));
1249        g_return_if_fail (old_uri != NULL);
1250        g_return_if_fail (new_uri != NULL);
1251
1252        priv = shortcuts->priv;
1253
1254        for (p = priv->groups; p != NULL; p = p->next) {
1255                ShortcutGroup *group;
1256                GSList *q;
1257
1258                group = (ShortcutGroup *) p->data;
1259                for (q = group->shortcuts; q != NULL; q = q->next) {
1260                        EShortcutItem *item;
1261
1262                        item = (EShortcutItem *) q->data;
1263
1264                        if (strcmp (item->uri, old_uri) == 0) {
1265                                g_free (item->uri);
1266                                item->uri = g_strdup (new_uri);
1267
1268                                make_dirty (shortcuts);
1269                        }
1270                }
1271        }
1272}
1273
1274
1275E_MAKE_TYPE (e_shortcuts, "EShortcuts", EShortcuts, class_init, init, PARENT_TYPE)
Note: See TracBrowser for help on using the repository browser.