source: trunk/third/evolution/shell/e-storage.c @ 18142

Revision 18142, 20.2 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18141, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/* e-storage.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/* FIXME: The EFolderTree is kept both in the EStorage and the
24 * EvolutionStorage.  Bad design.
25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31#include "e-storage.h"
32
33#include "e-folder-tree.h"
34#include "e-shell-constants.h"
35
36#include <gtk/gtkobject.h>
37#include <gtk/gtksignal.h>
38
39#include <libgnome/gnome-defs.h>
40#include <libgnome/gnome-i18n.h>
41#include <gal/util/e-util.h>
42
43
44#define PARENT_TYPE GTK_TYPE_OBJECT
45static GtkObjectClass *parent_class = NULL;
46
47#define ES_CLASS(obj) \
48        E_STORAGE_CLASS (GTK_OBJECT (obj)->klass)
49
50struct _EStoragePrivate {
51        /* The set of folders we have in this storage.  */
52        EFolderTree *folder_tree;
53
54        /* The pseudofolders representing un-filled-in subtrees */
55        GHashTable *pseudofolders;
56
57        /* Internal name of the storage */
58        char *name;
59};
60
61enum {
62        NEW_FOLDER,
63        UPDATED_FOLDER,
64        REMOVED_FOLDER,
65        CLOSE_FOLDER,
66        LAST_SIGNAL
67};
68
69static guint signals[LAST_SIGNAL] = { 0 };
70
71
72/* Destroy notification function for the folders in the tree.  */
73
74static void
75folder_destroy_notify (EFolderTree *tree,
76                       const char *path,
77                       void *data,
78                       void *closure)
79{
80        EFolder *e_folder;
81
82        if (data == NULL) {
83                /* The root folder has no EFolder associated to it.  */
84                return;
85        }
86
87        e_folder = E_FOLDER (data);
88        gtk_object_unref (GTK_OBJECT (e_folder));
89}
90
91
92/* Signal callbacks for the EFolders.  */
93
94static void
95folder_changed_cb (EFolder *folder,
96                   void *data)
97{
98        EStorage *storage;
99        EStoragePrivate *priv;
100        const char *path, *p;
101        gboolean highlight;
102
103        g_assert (E_IS_STORAGE (data));
104
105        storage = E_STORAGE (data);
106        priv = storage->priv;
107
108        path = e_folder_tree_get_path_for_data (priv->folder_tree, folder);
109        g_assert (path != NULL);
110
111        gtk_signal_emit (GTK_OBJECT (storage), signals[UPDATED_FOLDER], path);
112
113        highlight = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (folder), "last_highlight"));
114        if (highlight != e_folder_get_highlighted (folder)) {
115                highlight = !highlight;
116                gtk_object_set_data (GTK_OBJECT (folder), "last_highlight",
117                                     GINT_TO_POINTER (highlight));
118                p = strrchr (path, '/');
119                if (p && p != path) {
120                        char *name;
121                       
122                        name = g_strndup (path, p - path);
123                        folder = e_folder_tree_get_folder (priv->folder_tree, name);
124                        g_free (name);
125                        if (folder)
126                                e_folder_set_child_highlight (folder, highlight);
127                }
128        }
129}
130
131
132/* GtkObject methods.  */
133
134static void
135free_folder (gpointer path, gpointer folder, gpointer user_data)
136{
137        g_free (path);
138        /* folders will have been freed by e_folder_tree_destroy */
139}
140
141static void
142destroy (GtkObject *object)
143{
144        EStorage *storage;
145        EStoragePrivate *priv;
146
147        storage = E_STORAGE (object);
148        priv = storage->priv;
149
150        if (priv->folder_tree != NULL)
151                e_folder_tree_destroy (priv->folder_tree);
152        if (priv->pseudofolders) {
153                g_hash_table_foreach (priv->pseudofolders, free_folder, NULL);
154                g_hash_table_destroy (priv->pseudofolders);
155        }
156
157        g_free (priv->name);
158
159        (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
160}
161
162
163/* EStorage methods.  */
164
165static GList *
166impl_get_subfolder_paths (EStorage *storage,
167                          const char *path)
168{
169        EStoragePrivate *priv;
170
171        priv = storage->priv;
172
173        return e_folder_tree_get_subfolders (priv->folder_tree, path);
174}
175
176static EFolder *
177impl_get_folder (EStorage *storage,
178                 const char *path)
179{
180        EStoragePrivate *priv;
181        EFolder *e_folder;
182
183        priv = storage->priv;
184
185        e_folder = (EFolder *) e_folder_tree_get_folder (priv->folder_tree, path);
186
187        return e_folder;
188}
189
190static const char *
191impl_get_name (EStorage *storage)
192{
193        return storage->priv->name;
194}
195
196static void
197impl_async_create_folder (EStorage *storage,
198                          const char *path,
199                          const char *type,
200                          const char *description,
201                          EStorageResultCallback callback,
202                          void *data)
203{
204        (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, data);
205}
206
207static void
208impl_async_remove_folder (EStorage *storage,
209                          const char *path,
210                          EStorageResultCallback callback,
211                          void *data)
212{
213        (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, data);
214}
215
216static void
217impl_async_xfer_folder (EStorage *storage,
218                        const char *source_path,
219                        const char *destination_path,
220                        gboolean remove_source,
221                        EStorageResultCallback callback,
222                        void *data)
223{
224        (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, data);
225}
226
227static void
228impl_async_open_folder (EStorage *storage,
229                        const char *path)
230{
231        ;
232}
233
234static gboolean
235impl_supports_shared_folders (EStorage *storage)
236{
237        return FALSE;
238}
239
240static void
241impl_async_discover_shared_folder (EStorage *storage,
242                                   const char *owner,
243                                   const char *folder_name,
244                                   EStorageDiscoveryCallback callback,
245                                   void *data)
246{
247        (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, NULL, data);
248}
249
250static void
251impl_async_remove_shared_folder (EStorage *storage,
252                                 const char *path,
253                                 EStorageResultCallback callback,
254                                 void *data)
255{
256        (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, data);
257}
258
259
260/* Initialization.  */
261
262static void
263class_init (EStorageClass *class)
264{
265        GtkObjectClass *object_class;
266
267        object_class = GTK_OBJECT_CLASS (class);
268        parent_class = gtk_type_class (gtk_object_get_type ());
269
270        object_class->destroy = destroy;
271
272        class->get_subfolder_paths = impl_get_subfolder_paths;
273        class->get_folder          = impl_get_folder;
274        class->get_name            = impl_get_name;
275        class->async_create_folder = impl_async_create_folder;
276        class->async_remove_folder = impl_async_remove_folder;
277        class->async_xfer_folder   = impl_async_xfer_folder;
278        class->async_open_folder   = impl_async_open_folder;
279
280        class->supports_shared_folders       = impl_supports_shared_folders;
281        class->async_discover_shared_folder  = impl_async_discover_shared_folder;
282        class->async_remove_shared_folder    = impl_async_remove_shared_folder;
283
284        signals[NEW_FOLDER] =
285                gtk_signal_new ("new_folder",
286                                GTK_RUN_FIRST,
287                                object_class->type,
288                                GTK_SIGNAL_OFFSET (EStorageClass, new_folder),
289                                gtk_marshal_NONE__STRING,
290                                GTK_TYPE_NONE, 1,
291                                GTK_TYPE_STRING);
292        signals[UPDATED_FOLDER] =
293                gtk_signal_new ("updated_folder",
294                                GTK_RUN_FIRST,
295                                object_class->type,
296                                GTK_SIGNAL_OFFSET (EStorageClass, updated_folder),
297                                gtk_marshal_NONE__STRING,
298                                GTK_TYPE_NONE, 1,
299                                GTK_TYPE_STRING);
300        signals[REMOVED_FOLDER] =
301                gtk_signal_new ("removed_folder",
302                                GTK_RUN_FIRST,
303                                object_class->type,
304                                GTK_SIGNAL_OFFSET (EStorageClass, removed_folder),
305                                gtk_marshal_NONE__STRING,
306                                GTK_TYPE_NONE, 1,
307                                GTK_TYPE_STRING);
308        signals[CLOSE_FOLDER] =
309                gtk_signal_new ("close_folder",
310                                GTK_RUN_FIRST,
311                                object_class->type,
312                                GTK_SIGNAL_OFFSET (EStorageClass, close_folder),
313                                gtk_marshal_NONE__STRING,
314                                GTK_TYPE_NONE, 1,
315                                GTK_TYPE_STRING);
316
317        gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
318}
319
320static void
321init (EStorage *storage)
322{
323        EStoragePrivate *priv;
324
325        priv = g_new (EStoragePrivate, 1);
326
327        priv->folder_tree   = e_folder_tree_new (folder_destroy_notify, NULL);
328        priv->pseudofolders = g_hash_table_new (g_str_hash, g_str_equal);
329        priv->name          = NULL;
330
331        storage->priv = priv;
332}
333
334
335/* Creation.  */
336
337void
338e_storage_construct (EStorage *storage,
339                     const char *name,
340                     EFolder *root_folder)
341{
342        EStoragePrivate *priv;
343
344        g_return_if_fail (storage != NULL);
345        g_return_if_fail (E_IS_STORAGE (storage));
346
347        priv = storage->priv;
348
349        priv->name               = g_strdup (name);
350
351        e_storage_new_folder (storage, "/", root_folder);
352
353        GTK_OBJECT_UNSET_FLAGS (GTK_OBJECT (storage), GTK_FLOATING);
354}
355
356EStorage *
357e_storage_new (const char *name,
358               EFolder *root_folder)
359{
360        EStorage *new;
361
362        new = gtk_type_new (e_storage_get_type ());
363
364        e_storage_construct (new, name, root_folder);
365
366        return new;
367}
368
369
370gboolean
371e_storage_path_is_absolute (const char *path)
372{
373        g_return_val_if_fail (path != NULL, FALSE);
374
375        return *path == E_PATH_SEPARATOR;
376}
377
378gboolean
379e_storage_path_is_relative (const char *path)
380{
381        g_return_val_if_fail (path != NULL, FALSE);
382
383        return *path != E_PATH_SEPARATOR;
384}
385
386
387GList *
388e_storage_get_subfolder_paths (EStorage *storage,
389                               const char *path)
390{
391        g_return_val_if_fail (storage != NULL, NULL);
392        g_return_val_if_fail (E_IS_STORAGE (storage), NULL);
393        g_return_val_if_fail (path != NULL, NULL);
394        g_return_val_if_fail (g_path_is_absolute (path), NULL);
395
396        return (* ES_CLASS (storage)->get_subfolder_paths) (storage, path);
397}
398
399EFolder *
400e_storage_get_folder (EStorage *storage,
401                      const char *path)
402{
403        g_return_val_if_fail (storage != NULL, NULL);
404        g_return_val_if_fail (E_IS_STORAGE (storage), NULL);
405        g_return_val_if_fail (path != NULL, NULL);
406        g_return_val_if_fail (e_storage_path_is_absolute (path), NULL);
407
408        return (* ES_CLASS (storage)->get_folder) (storage, path);
409}
410
411const char *
412e_storage_get_name (EStorage *storage)
413{
414        g_return_val_if_fail (storage != NULL, NULL);
415        g_return_val_if_fail (E_IS_STORAGE (storage), NULL);
416
417        return (* ES_CLASS (storage)->get_name) (storage);
418}
419
420
421/* Folder operations.  */
422
423void
424e_storage_async_create_folder (EStorage *storage,
425                               const char *path,
426                               const char *type,
427                               const char *description,
428                               EStorageResultCallback callback,
429                               void *data)
430{
431        g_return_if_fail (storage != NULL);
432        g_return_if_fail (E_IS_STORAGE (storage));
433        g_return_if_fail (path != NULL);
434        g_return_if_fail (g_path_is_absolute (path));
435        g_return_if_fail (type != NULL);
436        g_return_if_fail (callback != NULL);
437
438        (* ES_CLASS (storage)->async_create_folder) (storage, path, type, description, callback, data);
439}
440
441void
442e_storage_async_remove_folder (EStorage              *storage,
443                               const char            *path,
444                               EStorageResultCallback callback,
445                               void                  *data)
446{
447        g_return_if_fail (storage != NULL);
448        g_return_if_fail (E_IS_STORAGE (storage));
449        g_return_if_fail (path != NULL);
450        g_return_if_fail (g_path_is_absolute (path));
451        g_return_if_fail (callback != NULL);
452
453        (* ES_CLASS (storage)->async_remove_folder) (storage, path, callback, data);
454}
455
456void
457e_storage_async_xfer_folder (EStorage *storage,
458                             const char *source_path,
459                             const char *destination_path,
460                             const gboolean remove_source,
461                             EStorageResultCallback callback,
462                             void *data)
463{
464        g_return_if_fail (storage != NULL);
465        g_return_if_fail (E_IS_STORAGE (storage));
466        g_return_if_fail (source_path != NULL);
467        g_return_if_fail (g_path_is_absolute (source_path));
468        g_return_if_fail (destination_path != NULL);
469        g_return_if_fail (g_path_is_absolute (destination_path));
470
471        if (strcmp (source_path, destination_path) == 0) {
472                (* callback) (storage, E_STORAGE_OK, data);
473                return;
474        }
475
476        if (remove_source) {
477                int destination_len;
478                int source_len;
479
480                source_len = strlen (source_path);
481                destination_len = strlen (destination_path);
482
483                if (source_len < destination_len
484                    && destination_path[source_len] == E_PATH_SEPARATOR
485                    && strncmp (destination_path, source_path, source_len) == 0) {
486                        (* callback) (storage, E_STORAGE_CANTMOVETODESCENDANT, data);
487                        return;
488                }
489        }
490
491        (* ES_CLASS (storage)->async_xfer_folder) (storage, source_path, destination_path, remove_source, callback, data);
492}
493
494void
495e_storage_async_open_folder (EStorage *storage,
496                             const char *path)
497{
498        g_return_if_fail (storage != NULL);
499        g_return_if_fail (E_IS_STORAGE (storage));
500        g_return_if_fail (path != NULL);
501        g_return_if_fail (g_path_is_absolute (path));
502
503        if (g_hash_table_lookup (storage->priv->pseudofolders, path) == NULL)
504                return;
505
506        (* ES_CLASS (storage)->async_open_folder) (storage, path);
507}
508
509
510/* Shared folders.  */
511
512gboolean
513e_storage_supports_shared_folders (EStorage *storage)
514{
515        g_return_val_if_fail (storage != NULL, FALSE);
516        g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
517
518        return (* ES_CLASS (storage)->supports_shared_folders) (storage);
519}
520
521void
522e_storage_async_discover_shared_folder (EStorage *storage,
523                                        const char *owner,
524                                        const char *folder_name,
525                                        EStorageDiscoveryCallback callback,
526                                        void *data)
527{
528        g_return_if_fail (storage != NULL);
529        g_return_if_fail (E_IS_STORAGE (storage));
530        g_return_if_fail (owner != NULL);
531        g_return_if_fail (folder_name != NULL);
532
533        (* ES_CLASS (storage)->async_discover_shared_folder) (storage, owner, folder_name, callback, data);
534}
535
536void
537e_storage_cancel_discover_shared_folder (EStorage *storage,
538                                         const char *owner,
539                                         const char *folder_name)
540{
541        g_return_if_fail (E_IS_STORAGE (storage));
542        g_return_if_fail (owner != NULL);
543        g_return_if_fail (folder_name != NULL);
544        g_return_if_fail (ES_CLASS (storage)->cancel_discover_shared_folder != NULL);
545
546        (* ES_CLASS (storage)->cancel_discover_shared_folder) (storage, owner, folder_name);
547}
548
549void
550e_storage_async_remove_shared_folder (EStorage *storage,
551                                      const char *path,
552                                      EStorageResultCallback callback,
553                                      void *data)
554{
555        g_return_if_fail (storage != NULL);
556        g_return_if_fail (E_IS_STORAGE (storage));
557        g_return_if_fail (path != NULL);
558        g_return_if_fail (g_path_is_absolute (path));
559
560        (* ES_CLASS (storage)->async_remove_shared_folder) (storage, path, callback, data);
561}
562
563
564const char *
565e_storage_result_to_string (EStorageResult result)
566{
567        switch (result) {
568        case E_STORAGE_OK:
569                return _("No error");
570        case E_STORAGE_GENERICERROR:
571                return _("Generic error");
572        case E_STORAGE_EXISTS:
573                return _("A folder with the same name already exists");
574        case E_STORAGE_INVALIDTYPE:
575                return _("The specified folder type is not valid");
576        case E_STORAGE_IOERROR:
577                return _("I/O error");
578        case E_STORAGE_NOSPACE:
579                return _("Not enough space to create the folder");
580        case E_STORAGE_NOTEMPTY:
581                return _("The folder is not empty");
582        case E_STORAGE_NOTFOUND:
583                return _("The specified folder was not found");
584        case E_STORAGE_NOTIMPLEMENTED:
585                return _("Function not implemented in this storage");
586        case E_STORAGE_PERMISSIONDENIED:
587                return _("Permission denied");
588        case E_STORAGE_UNSUPPORTEDOPERATION:
589                return _("Operation not supported");
590        case E_STORAGE_UNSUPPORTEDTYPE:
591                return _("The specified type is not supported in this storage");
592        case E_STORAGE_CANTCHANGESTOCKFOLDER:
593                return _("The specified folder cannot be modified or removed");
594        case E_STORAGE_CANTMOVETODESCENDANT:
595                return _("Cannot make a folder a child of one of its descendants");
596        case E_STORAGE_INVALIDNAME:
597                return _("Cannot create a folder with that name");
598        case E_STORAGE_NOTONLINE:
599                return _("This operation cannot be performed in off-line mode");
600        default:
601                return _("Unknown error");
602        }
603}
604
605
606/* Public utility functions.  */
607
608struct _GetPathForPhysicalUriForeachData {
609        const char *physical_uri;
610        char *retval;
611};
612typedef struct _GetPathForPhysicalUriForeachData GetPathForPhysicalUriForeachData;
613
614static void
615get_path_for_physical_uri_foreach (EFolderTree *folder_tree,
616                                   const char *path,
617                                   void *path_data,
618                                   void *user_data)
619{
620        GetPathForPhysicalUriForeachData *foreach_data;
621        const char *physical_uri;
622        EFolder *e_folder;
623
624        foreach_data = (GetPathForPhysicalUriForeachData *) user_data;
625        if (foreach_data->retval != NULL)
626                return;
627
628        e_folder = (EFolder *) path_data;
629        if (e_folder == NULL)
630                return;
631
632        physical_uri = e_folder_get_physical_uri (e_folder);
633        if (physical_uri == NULL)
634                return;
635
636        if (strcmp (foreach_data->physical_uri, physical_uri) == 0)
637                foreach_data->retval = g_strdup (path);
638}
639
640/**
641 * e_storage_get_path_for_physical_uri:
642 * @storage: A storage
643 * @physical_uri: A physical URI
644 *
645 * Look for the folder having the specified @physical_uri.
646 *
647 * Return value: The path of the folder having the specified @physical_uri in
648 * @storage.  If such a folder does not exist, just return NULL.  The return
649 * value must be freed by the caller.
650 **/
651char *
652e_storage_get_path_for_physical_uri (EStorage *storage,
653                                     const char *physical_uri)
654{
655        GetPathForPhysicalUriForeachData foreach_data;
656        EStoragePrivate *priv;
657
658        g_return_val_if_fail (storage != NULL, NULL);
659        g_return_val_if_fail (E_IS_STORAGE (storage), NULL);
660        g_return_val_if_fail (physical_uri != NULL, NULL);
661
662        priv = storage->priv;
663
664        foreach_data.physical_uri = physical_uri;
665        foreach_data.retval       = NULL;
666
667        e_folder_tree_foreach (priv->folder_tree, get_path_for_physical_uri_foreach, &foreach_data);
668
669        return foreach_data.retval;
670}
671
672
673/* Protected functions.  */
674
675/* These functions are used by subclasses to add and remove folders from the
676   state stored in the storage object.  */
677
678gboolean
679e_storage_new_folder (EStorage *storage,
680                      const char *path,
681                      EFolder *e_folder)
682{
683        EStoragePrivate *priv;
684        char *parent_path, *p;
685        gpointer stored_path, pseudofolder;
686
687        g_return_val_if_fail (storage != NULL, FALSE);
688        g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
689        g_return_val_if_fail (path != NULL, FALSE);
690        g_return_val_if_fail (g_path_is_absolute (path), FALSE);
691        g_return_val_if_fail (e_folder != NULL, FALSE);
692        g_return_val_if_fail (E_IS_FOLDER (e_folder), FALSE);
693
694        priv = storage->priv;
695
696        if (! e_folder_tree_add (priv->folder_tree, path, e_folder))
697                return FALSE;
698
699        p = strrchr (path, '/');
700        if (p && p != path)
701                parent_path = g_strndup (path, p - path);
702        else
703                parent_path = g_strdup ("/");
704        if (g_hash_table_lookup_extended (priv->pseudofolders, parent_path,
705                                          &stored_path, &pseudofolder) &&
706            pseudofolder != e_folder) {
707                g_hash_table_remove (priv->pseudofolders, parent_path);
708                g_free (stored_path);           
709                e_storage_removed_folder (storage, e_folder_get_physical_uri (pseudofolder));
710        }
711        g_free (parent_path);
712
713        gtk_signal_connect_while_alive (GTK_OBJECT (e_folder), "changed", folder_changed_cb,
714                                        storage, GTK_OBJECT (storage));
715
716        gtk_signal_emit (GTK_OBJECT (storage), signals[NEW_FOLDER], path);
717
718        folder_changed_cb (e_folder, storage);
719
720        return TRUE;
721}
722
723gboolean
724e_storage_has_subfolders (EStorage *storage,
725                          const char *path,
726                          const char *message)
727{
728        EStoragePrivate *priv;
729        GList *subfolders, *f;
730        EFolder *pseudofolder;
731        char *pseudofolder_path;
732        gboolean retval;
733
734        g_return_val_if_fail (storage != NULL, FALSE);
735        g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
736        g_return_val_if_fail (path != NULL, FALSE);
737        g_return_val_if_fail (g_path_is_absolute (path), FALSE);
738        g_return_val_if_fail (message != NULL, FALSE);
739
740        priv = storage->priv;
741
742        gtk_signal_emit (GTK_OBJECT (storage), signals[CLOSE_FOLDER], path);
743
744        if (g_hash_table_lookup (priv->pseudofolders, path))
745                return TRUE;
746
747        subfolders = e_folder_tree_get_subfolders (priv->folder_tree, path);
748        if (subfolders != NULL) {
749                for (f = subfolders; f; f = f->next)
750                        e_storage_removed_folder (storage, f->data);
751                g_list_free (subfolders);
752                /* FIXME: close parent */
753        }
754
755        pseudofolder = e_folder_new (message, "working", "");
756        if (strcmp (path, "/") == 0)
757                pseudofolder_path = g_strdup_printf ("/%s", message);
758        else
759                pseudofolder_path = g_strdup_printf ("%s/%s", path, message);
760        e_folder_set_physical_uri (pseudofolder, pseudofolder_path);
761
762        g_hash_table_insert (priv->pseudofolders, g_strdup (path), pseudofolder);
763
764        retval = e_storage_new_folder (storage, pseudofolder_path, pseudofolder);
765        g_free (pseudofolder_path);
766
767        return retval;
768}
769
770gboolean
771e_storage_removed_folder (EStorage *storage,
772                          const char *path)
773{
774        EStoragePrivate *priv;
775        EFolder *folder;
776        const char *p;
777
778        g_return_val_if_fail (storage != NULL, FALSE);
779        g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
780        g_return_val_if_fail (path != NULL, FALSE);
781        g_return_val_if_fail (g_path_is_absolute (path), FALSE);
782
783        priv = storage->priv;
784
785        folder = e_folder_tree_get_folder (priv->folder_tree, path);
786        if (folder == NULL)
787                return FALSE;
788
789        p = strrchr (path, '/');
790        if (p != NULL && p != path) {
791                EFolder *parent_folder;
792                char *parent_path;
793
794                parent_path = g_strndup (path, p - path);
795                parent_folder = e_folder_tree_get_folder (priv->folder_tree, parent_path);
796
797                if (e_folder_get_highlighted (folder))
798                        e_folder_set_child_highlight (parent_folder, FALSE);
799
800                g_free (parent_path);
801        }
802
803        gtk_signal_emit (GTK_OBJECT (storage), signals[REMOVED_FOLDER], path);
804
805        e_folder_tree_remove (priv->folder_tree, path);
806
807        return TRUE;
808}
809
810
811E_MAKE_TYPE (e_storage, "EStorage", EStorage, class_init, init, PARENT_TYPE)
Note: See TracBrowser for help on using the repository browser.