From dbc4e091133eee525a8b7c0fd449dcca6a5c719f Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 6 Nov 2000 22:03:24 +0000 Subject: First draft of folder tree unread message indication for /local mail folders. * mail-local.c: Add a new CamelStore subclass, MailLocalStore, which attaches to an Evolution_LocalStorage on one side and CamelSession on the other, and keeps track of local folders. Some of this code was previously in mail-local-storage.c, which no longer exists. (local_reconfigure_folder, etc): Various mail_op-related cleanups, and wrap d() around a bunch of printfs. * mail-tools.c (mail_tool_get_local_inbox_url, mail_tool_get_local_movemail_url): Removed (mail_tool_get_local_inbox): Simplified. (mail_tool_do_movemail): Remove unused dest_url variable. (mail_tool_uri_to_folder): Simplify. Now down to two cases (vfolder, and everything else). * component-factory.c (owner_set_cb): Pass evolution_dir to mail_local_storage_startup. * Makefile.am (evolution_mail_SOURCES): Remove mail-local-storage.[ch] svn path=/trunk/; revision=6456 --- mail/ChangeLog | 26 +++ mail/Makefile.am | 2 - mail/component-factory.c | 4 +- mail/mail-local-storage.c | 188 ---------------- mail/mail-local-storage.h | 34 --- mail/mail-local.c | 542 +++++++++++++++++++++++++++++++++++++--------- mail/mail-local.h | 13 +- mail/mail-tools.c | 60 ++--- 8 files changed, 491 insertions(+), 378 deletions(-) delete mode 100644 mail/mail-local-storage.c delete mode 100644 mail/mail-local-storage.h diff --git a/mail/ChangeLog b/mail/ChangeLog index 6340d44bfa..9ba6aa360d 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,29 @@ +2000-11-06 Dan Winship + + First draft of folder tree unread message indication for /local + mail folders. + + * mail-local.c: Add a new CamelStore subclass, MailLocalStore, + which attaches to an Evolution_LocalStorage on one side and + CamelSession on the other, and keeps track of local folders. Some + of this code was previously in mail-local-storage.c, which no + longer exists. + (local_reconfigure_folder, etc): Various mail_op-related cleanups, + and wrap d() around a bunch of printfs. + + * mail-tools.c (mail_tool_get_local_inbox_url, + mail_tool_get_local_movemail_url): Removed + (mail_tool_get_local_inbox): Simplified. + (mail_tool_do_movemail): Remove unused dest_url variable. + (mail_tool_uri_to_folder): Simplify. Now down to two cases + (vfolder, and everything else). + + * component-factory.c (owner_set_cb): Pass evolution_dir to + mail_local_storage_startup. + + * Makefile.am (evolution_mail_SOURCES): Remove + mail-local-storage.[ch] + 2000-11-06 Kjartan Maraas * mail-autofilter.c: Fix up #include diff --git a/mail/Makefile.am b/mail/Makefile.am index 4f8a9e3dfa..a3ce6e27e8 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -63,8 +63,6 @@ evolution_mail_SOURCES = \ mail-identify.c \ mail-local.c \ mail-local.h \ - mail-local-storage.c \ - mail-local-storage.h \ mail-mlist-magic.c \ mail-mlist-magic.h \ mail-ops.c \ diff --git a/mail/component-factory.c b/mail/component-factory.c index acd635e5c6..014c4b8e3b 100644 --- a/mail/component-factory.c +++ b/mail/component-factory.c @@ -38,9 +38,9 @@ #include "mail.h" /* YUCK FIXME */ #include "mail-tools.h" #include "mail-ops.h" +#include "mail-local.h" #include "mail-session.h" #include -#include "mail-local-storage.h" #include "component-factory.h" @@ -141,7 +141,7 @@ owner_set_cb (EvolutionShellComponent *shell_component, sources = mail_config_get_news (); mail_load_storages (corba_shell, sources); - mail_local_storage_startup (shell_client); + mail_local_storage_startup (shell_client, evolution_dir); } static void diff --git a/mail/mail-local-storage.c b/mail/mail-local-storage.c deleted file mode 100644 index ea343c41b0..0000000000 --- a/mail/mail-local-storage.c +++ /dev/null @@ -1,188 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* mail-local-storage.h - * - * Copyright (C) 2000 Helix Code, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Ettore Perazzoli - */ - -/* This handles the interfacing with the shell's local storage. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "e-folder-tree.h" -#include "evolution-storage-listener.h" - -#include "mail-local-storage.h" - - -/* Static stuff. Sigh, it sucks, but it fits in the way the whole mail - compnent is written. */ - -/* The interface to the local storage. */ -static Evolution_LocalStorage corba_local_storage = CORBA_OBJECT_NIL; - -/* The listener on our side. We get notified of things happening in the local - storage through this. */ -static EvolutionStorageListener *local_storage_listener = NULL; - -/* The folder set. The folder data is an Evolution_Folder, allocated through - CORBA normally. */ -static EFolderTree *folder_tree = NULL; - - -/* Folder destroy notification function for the `folder_tree'. */ - -static void -folder_tree_folder_notify_cb (EFolderTree *tree, - const char *path, - void *data, - void *closure) -{ - Evolution_Folder *corba_folder; - - corba_folder = (Evolution_Folder *) data; - CORBA_free (corba_folder); -} - - -/* Callbacks for the EvolutionStorageListner signals. */ - -static void -local_storage_destroyed_cb (EvolutionStorageListener *storage_listener, - void *data) -{ - /* FIXME: Dunno how to handle this yet. */ - g_warning ("%s -- The LocalStorage has gone?!", __FILE__); -} - -static void -local_storage_new_folder_cb (EvolutionStorageListener *storage_listener, - const char *path, - const Evolution_Folder *folder, - void *data) -{ - Evolution_Folder *copy_of_folder; - CORBA_Environment ev; - - if (strcmp (folder->type, "mail") != 0) - return; - - CORBA_exception_init (&ev); - -#if 0 - /* This is how we could do to display extra information about the - folder. */ - display_name = g_strconcat (folder->display_name, _(" (XXX unread)"), NULL); - Evolution_LocalStorage_set_display_name (corba_local_storage, path, display_name, &ev); -#endif - - copy_of_folder = Evolution_Folder__alloc (); - copy_of_folder->type = CORBA_string_dup (folder->type); - copy_of_folder->description = CORBA_string_dup (folder->description); - copy_of_folder->display_name = CORBA_string_dup (folder->display_name); - copy_of_folder->physical_uri = CORBA_string_dup (folder->physical_uri); - - e_folder_tree_add (folder_tree, path, copy_of_folder); - - CORBA_exception_free (&ev); -} - -static void -local_storage_removed_folder_cb (EvolutionStorageListener *storage_listener, - const char *path, - void *data) -{ - /* Prevent a warning from `e_folder_tree_remove()'. */ - if (e_folder_tree_get_folder (folder_tree, path) == NULL) - return; - - e_folder_tree_remove (folder_tree, path); -} - - -gboolean -mail_local_storage_startup (EvolutionShellClient *shell_client) -{ - Evolution_StorageListener corba_local_storage_listener; - - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - corba_local_storage = evolution_shell_client_get_local_storage (shell_client); - if (corba_local_storage == CORBA_OBJECT_NIL) { - CORBA_exception_free (&ev); - return FALSE; - } - - local_storage_listener = evolution_storage_listener_new (); - corba_local_storage_listener = evolution_storage_listener_corba_objref (local_storage_listener); - - gtk_signal_connect (GTK_OBJECT (local_storage_listener), "destroyed", - GTK_SIGNAL_FUNC (local_storage_destroyed_cb), NULL); - gtk_signal_connect (GTK_OBJECT (local_storage_listener), "new_folder", - GTK_SIGNAL_FUNC (local_storage_new_folder_cb), NULL); - gtk_signal_connect (GTK_OBJECT (local_storage_listener), "removed_folder", - GTK_SIGNAL_FUNC (local_storage_removed_folder_cb), NULL); - - folder_tree = e_folder_tree_new (folder_tree_folder_notify_cb, NULL); - - Evolution_Storage_add_listener (corba_local_storage, corba_local_storage_listener, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("%s -- Cannot add a listener to the Local Storage.", __FILE__); - - gtk_object_unref (GTK_OBJECT (local_storage_listener)); - - Bonobo_Unknown_unref (corba_local_storage, &ev); - CORBA_Object_release (corba_local_storage, &ev); - - CORBA_exception_free (&ev); - return FALSE; - } - - CORBA_exception_free (&ev); - - return TRUE; -} - -void -mail_local_storage_shutdown (void) -{ - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - Bonobo_Unknown_unref (corba_local_storage, &ev); - CORBA_Object_release (corba_local_storage, &ev); - corba_local_storage = CORBA_OBJECT_NIL; - - gtk_object_unref (GTK_OBJECT (local_storage_listener)); - local_storage_listener = NULL; - - gtk_object_unref (GTK_OBJECT (folder_tree)); - folder_tree = NULL; - - CORBA_exception_free (&ev); -} diff --git a/mail/mail-local-storage.h b/mail/mail-local-storage.h deleted file mode 100644 index 251897681c..0000000000 --- a/mail/mail-local-storage.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* mail-local-storage.h - * - * Copyright (C) 2000 Helix Code, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Ettore Perazzoli - */ - -#ifndef _MAIL_LOCAL_STORAGE_H_ -#define _MAIL_LOCAL_STORAGE_H_ - -#include - -#include "evolution-shell-client.h" - -gboolean mail_local_storage_startup (EvolutionShellClient *shell_client); -void mail_local_storage_shutdown (void); - -#endif diff --git a/mail/mail-local.c b/mail/mail-local.c index 82f0ef3e18..ab2c4eba09 100644 --- a/mail/mail-local.c +++ b/mail/mail-local.c @@ -2,9 +2,11 @@ /* mail-local.c: Local mailbox support. */ /* - * Author: + * Authors: * Michael Zucchi * Peter Williams + * Ettore Perazzoli + * Dan Winship * * Copyright 2000 Helix Code, Inc. (http://www.helixcode.com) * @@ -24,14 +26,10 @@ * USA */ - -/* - code for handling local mail boxes -*/ - #ifdef HAVE_CONFIG_H #include #endif + #include #include #include @@ -39,9 +37,8 @@ #include "Evolution.h" #include "evolution-storage.h" - #include "evolution-shell-component.h" -#include "folder-browser.h" +#include "evolution-storage-listener.h" #include "camel/camel.h" @@ -53,9 +50,13 @@ #include "mail-local.h" #include "mail-tools.h" #include "mail-threads.h" +#include "folder-browser.h" #define d(x) + +/* Local folder metainfo */ + struct _local_meta { char *path; /* path of metainfo file */ @@ -74,7 +75,7 @@ load_metainfo(const char *path) meta = g_malloc0(sizeof(*meta)); meta->path = g_strdup(path); - printf("Loading folder metainfo from : %s\n", meta->path); + d(printf("Loading folder metainfo from : %s\n", meta->path)); doc = xmlParseFile(meta->path); if (doc == NULL) { @@ -128,7 +129,7 @@ save_metainfo(struct _local_meta *meta) xmlNodePtr root, node; int ret; - printf("Saving folder metainfo to : %s\n", meta->path); + d(printf("Saving folder metainfo to : %s\n", meta->path)); doc = xmlNewDoc("1.0"); root = xmlNewDocNode(doc, NULL, "folderinfo", NULL); @@ -144,89 +145,8 @@ save_metainfo(struct _local_meta *meta) return ret; } -/* maps a local uri to the real type */ -char * -mail_local_map_uri(const char *uri, int *index) -{ - CamelURL *url; - char *metapath; - char *storename; - struct _local_meta *meta; - CamelException *ex; - - if (index) - *index = TRUE; - - if (strncmp(uri, "file:", 5)) { - g_warning("Trying to map non-local uri: %s", uri); - return g_strdup(uri); - } - - ex = camel_exception_new(); - url = camel_url_new(uri, ex); - if (camel_exception_is_set(ex)) { - camel_exception_free(ex); - return g_strdup(uri); - } - camel_exception_free(ex); - - metapath = g_strdup_printf("%s/local-metadata.xml", url->path); - meta = load_metainfo(metapath); - g_free(metapath); - - if (index) - *index = meta->indexed; - - /* change file: to format: */ - camel_url_set_protocol(url, meta->format); - storename = camel_url_to_string (url, FALSE); - camel_url_free(url); - return storename; -} - -CamelFolder * -mail_tool_local_uri_to_folder(const char *uri, CamelException *ex) -{ - CamelURL *url; - char *metapath; - char *storename; - CamelFolder *folder = NULL; - struct _local_meta *meta; - int flags; - - if (strncmp(uri, "file:", 5)) { - return NULL; - } - - printf("opening local folder %s\n", uri); - - /* get the actual location of the mailbox */ - url = camel_url_new(uri, ex); - if (camel_exception_is_set(ex)) { - return NULL; - } - - metapath = g_strdup_printf("%s/local-metadata.xml", url->path); - meta = load_metainfo(metapath); - g_free(metapath); - - /* change file: to format: */ - camel_url_set_protocol(url, meta->format); - storename = camel_url_to_string (url, FALSE); - - printf("store name is %s\n", storename); - flags = 0; - if (meta->indexed) - flags |= CAMEL_STORE_FOLDER_BODY_INDEX; - - folder = mail_tool_get_folder_from_urlname (storename, meta->name, flags, ex); - camel_url_free(url); - g_free (storename); - free_metainfo(meta); - - return folder; -} +/* Local folder reconfiguration stuff */ /* open new @@ -265,11 +185,6 @@ typedef struct reconfigure_folder_input_s { GtkOptionMenu *optionlist; } reconfigure_folder_input_t; -static gchar *describe_reconfigure_folder (gpointer in_data, gboolean gerund); -static void setup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex); -static void do_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex); -static void cleanup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex); - static gchar * describe_reconfigure_folder (gpointer in_data, gboolean gerund) { @@ -290,6 +205,18 @@ setup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex { reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; + if (!IS_FOLDER_BROWSER (input->fb)) { + camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM, + "Input has a bad FolderBrowser in reconfigure_folder"); + return; + } + + if (!input->newtype) { + camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM, + "No new folder type in reconfigure_folder"); + return; + } + gtk_object_ref (GTK_OBJECT (input->fb)); } @@ -309,7 +236,7 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) struct _local_meta *meta; guint32 flags; - printf("reconfiguring folder: %s to type %s\n", input->fb->uri, input->newtype); + d(printf("reconfiguring folder: %s to type %s\n", input->fb->uri, input->newtype)); /* get the actual location of the mailbox */ url = camel_url_new(input->fb->uri, ex); @@ -338,7 +265,7 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) camel_url_set_protocol (url, input->newtype); tourl = camel_url_to_string (url, FALSE); - printf("opening stores %s and %s\n", fromurl, tourl); + d(printf("opening stores %s and %s\n", fromurl, tourl)); mail_tool_camel_lock_up (); fromstore = camel_session_get_store(session, fromurl, ex); @@ -355,7 +282,7 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) /* rename the old mbox and open it again, without indexing */ tmpname = g_strdup_printf("%s_reconfig", meta->name); - printf("renaming %s to %s, and opening it\n", meta->name, tmpname); + d(printf("renaming %s to %s, and opening it\n", meta->name, tmpname)); update_progress(_("Renaming old folder and opening"), 0.0); mail_tool_camel_lock_up (); @@ -376,7 +303,7 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) } /* create a new mbox */ - printf("Creating the destination mbox\n"); + d(printf("Creating the destination mbox\n")); update_progress(_("Creating new folder"), 0.0); flags = CAMEL_STORE_FOLDER_CREATE; @@ -384,7 +311,7 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) flags |= CAMEL_STORE_FOLDER_BODY_INDEX; tofolder = camel_store_get_folder(tostore, meta->name, flags, ex); if (tofolder == NULL || camel_exception_is_set(ex)) { - printf("cannot open destination folder\n"); + d(printf("cannot open destination folder\n")); /* try and recover ... */ camel_exception_clear (ex); camel_store_rename_folder(fromstore, tmpname, meta->name, ex); @@ -395,7 +322,7 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) update_progress(_("Copying messages"), 0.0); mail_tool_move_folder_contents (fromfolder, tofolder, FALSE, ex); - printf("delete old mbox ...\n"); + d(printf("delete old mbox ...\n")); camel_store_delete_folder(fromstore, tmpname, ex); mail_tool_camel_lock_down (); @@ -412,7 +339,7 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) free_metainfo(meta); /* force a reload of the newly formatted folder */ - printf("opening new source\n"); + d(printf("opening new source\n")); uri = g_strdup(input->fb->uri); folder_browser_set_uri(input->fb, uri); g_free(uri); @@ -517,3 +444,410 @@ local_reconfigure_folder(FolderBrowser *fb) gnome_dialog_run_and_close (GNOME_DIALOG (gd)); } + + + +/* MailLocalStore implementation */ + +#define MAIL_LOCAL_STORE_TYPE (mail_local_store_get_type ()) +#define MAIL_LOCAL_STORE(obj) (CAMEL_CHECK_CAST((obj), MAIL_LOCAL_STORE_TYPE, MailLocalStore)) +#define MAIL_LOCAL_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), MAIL_LOCAL_STORE_TYPE, MailLocalStoreClass)) +#define MAIL_IS_LOCAL_STORE(o) (CAMEL_CHECK_TYPE((o), MAIL_LOCAL_STORE_TYPE)) + +typedef struct { + CamelStore parent_object; + + Evolution_LocalStorage corba_local_storage; + EvolutionStorageListener *local_storage_listener; + + char *local_path; + int local_pathlen; + GHashTable *folders, *unread; +} MailLocalStore; + +typedef struct { + CamelStoreClass parent_class; +} MailLocalStoreClass; + +typedef struct { + CamelFolder *folder; + MailLocalStore *local_store; + char *path, *name; + int last_unread; +} MailLocalFolder; + +CamelType mail_local_store_get_type (void); + +static char *get_name (CamelService *service, gboolean brief); +static CamelFolder *get_folder (CamelStore *store, const char *folder_name, + guint32 flags, CamelException *ex); +static void delete_folder (CamelStore *store, const char *folder_name, + CamelException *ex); +static void rename_folder (CamelStore *store, const char *old_name, + const char *new_name, CamelException *ex); +static char *get_folder_name (CamelStore *store, const char *folder_name, + CamelException *ex); + +static void +mail_local_store_class_init (MailLocalStoreClass *mail_local_store_class) +{ + CamelStoreClass *camel_store_class = + CAMEL_STORE_CLASS (mail_local_store_class); + CamelServiceClass *camel_service_class = + CAMEL_SERVICE_CLASS (mail_local_store_class); + + /* virtual method overload */ + camel_service_class->get_name = get_name; + + camel_store_class->get_folder = get_folder; + camel_store_class->delete_folder = delete_folder; + camel_store_class->rename_folder = rename_folder; + camel_store_class->get_folder_name = get_folder_name; +} + +static void +mail_local_store_init (gpointer object, gpointer klass) +{ + MailLocalStore *local_store = MAIL_LOCAL_STORE (object); + + local_store->corba_local_storage = CORBA_OBJECT_NIL; +} + +static void +free_folder (gpointer key, gpointer data, gpointer user_data) +{ + MailLocalFolder *lf = data; + + g_free (key); + camel_object_unref (CAMEL_OBJECT (lf->folder)); + g_free (lf->path); +} + +static void +mail_local_store_finalize (gpointer object) +{ + MailLocalStore *local_store = MAIL_LOCAL_STORE (object); + CORBA_Environment ev; + + CORBA_exception_init (&ev); + if (!CORBA_Object_is_nil (local_store->corba_local_storage, &ev)) { + Bonobo_Unknown_unref (local_store->corba_local_storage, &ev); + CORBA_Object_release (local_store->corba_local_storage, &ev); + } + CORBA_exception_free (&ev); + + if (local_store->local_storage_listener) + gtk_object_unref (GTK_OBJECT (local_store->local_storage_listener)); + + g_hash_table_foreach (local_store->folders, free_folder, NULL); + g_hash_table_destroy (local_store->folders); + + g_free (local_store->local_path); +} + +CamelType +mail_local_store_get_type (void) +{ + static CamelType mail_local_store_type = CAMEL_INVALID_TYPE; + + if (mail_local_store_type == CAMEL_INVALID_TYPE) { + mail_local_store_type = camel_type_register ( + CAMEL_STORE_TYPE, "MailLocalStore", + sizeof (MailLocalStore), + sizeof (MailLocalStoreClass), + (CamelObjectClassInitFunc) mail_local_store_class_init, + NULL, + (CamelObjectInitFunc) mail_local_store_init, + (CamelObjectFinalizeFunc) mail_local_store_finalize); + } + + return mail_local_store_type; +} + +static CamelFolder * +get_folder (CamelStore *store, const char *folder_name, + guint32 flags, CamelException *ex) +{ + MailLocalStore *local_store = (MailLocalStore *)store; + CamelFolder *folder; + + folder = g_hash_table_lookup (local_store->folders, folder_name); + if (folder) + camel_object_ref (CAMEL_OBJECT (folder)); + else { + camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, + "No such folder %s", folder_name); + } + return folder; +} + +static void +delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) +{ + /* No-op. The shell local storage deals with this. */ +} + +static void +rename_folder (CamelStore *store, const char *old, const char *new, + CamelException *ex) +{ + /* Probable no-op... */ +} + +static char * +get_folder_name (CamelStore *store, const char *folder_name, + CamelException *ex) +{ + return g_strdup (folder_name); +} + +static char * +get_name (CamelService *service, gboolean brief) +{ + return g_strdup ("Local mail folders"); +} + + +/* Callbacks for the EvolutionStorageListner signals. */ + +static void +local_storage_destroyed_cb (EvolutionStorageListener *storage_listener, + void *data) +{ + /* FIXME: Dunno how to handle this yet. */ + g_warning ("%s -- The LocalStorage has gone?!", __FILE__); +} + + +static void +local_folder_changed (CamelObject *object, gpointer event_data, + gpointer user_data) +{ + CamelFolder *folder = CAMEL_FOLDER (object); + MailLocalFolder *local_folder = user_data; + int unread; + char *display; + + unread = camel_folder_get_unread_message_count (folder); + if (unread != local_folder->last_unread) { + CORBA_Environment ev; + + CORBA_exception_init (&ev); + if (unread > 0) { + display = g_strdup_printf ("%s (%d)", + local_folder->name, unread); + Evolution_LocalStorage_update_folder ( + local_folder->local_store->corba_local_storage, + local_folder->path, display, TRUE, &ev); + g_free (display); + } else { + Evolution_LocalStorage_update_folder ( + local_folder->local_store->corba_local_storage, + local_folder->path, local_folder->name, + FALSE, &ev); + } + CORBA_exception_free (&ev); + + local_folder->last_unread = unread; + } +} + +static char * +describe_register_folder (gpointer in_data, gboolean gerund) +{ + if (gerund) + return g_strdup (_("Registering local folder")); + else + return g_strdup (_("Register local folder")); +} + +static void +do_register_folder (gpointer in_data, gpointer op_data, CamelException *ex) +{ + MailLocalFolder *local_folder = in_data; + char *name; + struct _local_meta *meta; + CamelStore *store; + guint32 flags; + + name = g_strdup_printf ("%s/local-metadata.xml", local_folder->path); + meta = load_metainfo (name); + g_free (name); + + name = g_strdup_printf ("%s:%s", meta->format, local_folder->path); + store = camel_session_get_store (session, name, ex); + g_free (name); + if (!store) { + free_metainfo (meta); + return; + } + + flags = CAMEL_STORE_FOLDER_CREATE; + if (meta->indexed) + flags |= CAMEL_STORE_FOLDER_BODY_INDEX; + local_folder->folder = camel_store_get_folder (store, meta->name, flags, ex); + camel_object_unref (CAMEL_OBJECT (store)); + free_metainfo (meta); +} + +static const mail_operation_spec op_register_folder = +{ + describe_register_folder, + 0, + NULL, + do_register_folder, + NULL +}; + +static void +local_storage_new_folder_cb (EvolutionStorageListener *storage_listener, + const char *path, + const Evolution_Folder *folder, + void *data) +{ + MailLocalStore *local_store = data; + MailLocalFolder *local_folder; + + if (strcmp (folder->type, "mail") != 0 || + strncmp (folder->physical_uri, "file://", 7) != 0 || + strncmp (folder->physical_uri + 7, local_store->local_path, + local_store->local_pathlen) != 0) + return; + + /* We don't need to deal with locking/reffing/copying + * issues because we don't return from the function + * until this is finished. + */ + local_folder = g_new0 (MailLocalFolder, 1); + local_folder->path = folder->physical_uri + 7; + local_folder->local_store = local_store; + mail_operation_queue (&op_register_folder, local_folder, FALSE); + mail_operation_wait_for_finish (); + + if (!local_folder->folder) { + g_free (local_folder); + return; + } + + local_folder->path = g_strdup (path); + local_folder->name = strrchr (local_folder->path, '/') + 1; + local_folder->last_unread = 0; + + g_hash_table_insert (local_store->folders, + g_strdup (folder->physical_uri + 8), + local_folder->folder); + camel_object_hook_event (CAMEL_OBJECT (local_folder->folder), + "folder_changed", local_folder_changed, + local_folder); + local_folder_changed (CAMEL_OBJECT (local_folder->folder), + NULL, local_folder); +} + +static void +local_storage_removed_folder_cb (EvolutionStorageListener *storage_listener, + const char *path, + void *data) +{ + MailLocalStore *local_store = data; + CamelFolder *folder; + + if (strncmp (path, "file://", 7) != 0 || + strncmp (path + 7, local_store->local_path, + local_store->local_pathlen) != 0) + return; + + path += 7 + local_store->local_pathlen; + + folder = g_hash_table_lookup (local_store->folders, path); + if (folder) { + camel_object_unref (CAMEL_OBJECT (folder)); + g_hash_table_remove (local_store->folders, path); + } +} + +static CamelProvider local_provider = { + "file", "Local mail", NULL, "mail", + CAMEL_PROVIDER_IS_STORAGE, CAMEL_URL_NEED_PATH, + { 0, 0 }, NULL +}; + +/* There's only one "file:" store. */ +static guint +non_hash (gconstpointer key) +{ + return 0; +} + +static gint +non_equal (gconstpointer a, gconstpointer b) +{ + return TRUE; +} + +void +mail_local_storage_startup (EvolutionShellClient *shellclient, + const char *evolution_path) +{ + MailLocalStore *local_store; + Evolution_StorageListener corba_local_storage_listener; + CORBA_Environment ev; + + /* Register with Camel to handle file: URLs */ + local_provider.object_types[CAMEL_PROVIDER_STORE] = + mail_local_store_get_type(); + + local_provider.service_cache = g_hash_table_new (non_hash, non_equal); + camel_session_register_provider (session, &local_provider); + + + /* Now build the storage. */ + local_store = (MailLocalStore *)camel_session_get_service ( + session, "file:/", CAMEL_PROVIDER_STORE, NULL); + if (!local_store) { + g_warning ("No local store!"); + return; + } + local_store->corba_local_storage = + evolution_shell_client_get_local_storage (shellclient); + if (local_store->corba_local_storage == CORBA_OBJECT_NIL) { + g_warning ("No local storage!"); + camel_object_unref (CAMEL_OBJECT (local_store)); + return; + } + + local_store->local_storage_listener = + evolution_storage_listener_new (); + corba_local_storage_listener = + evolution_storage_listener_corba_objref ( + local_store->local_storage_listener); + + gtk_signal_connect (GTK_OBJECT (local_store->local_storage_listener), + "destroyed", + GTK_SIGNAL_FUNC (local_storage_destroyed_cb), + local_store); + gtk_signal_connect (GTK_OBJECT (local_store->local_storage_listener), + "new_folder", + GTK_SIGNAL_FUNC (local_storage_new_folder_cb), + local_store); + gtk_signal_connect (GTK_OBJECT (local_store->local_storage_listener), + "removed_folder", + GTK_SIGNAL_FUNC (local_storage_removed_folder_cb), + local_store); + + local_store->local_path = g_strdup_printf ("%s/local", + evolution_path); + local_store->local_pathlen = strlen (local_store->local_path); + + local_store->folders = g_hash_table_new (g_str_hash, g_str_equal); + + CORBA_exception_init (&ev); + Evolution_Storage_add_listener (local_store->corba_local_storage, + corba_local_storage_listener, &ev); + if (ev._major != CORBA_NO_EXCEPTION) { + g_warning ("Cannot add a listener to the Local Storage."); + camel_object_unref (CAMEL_OBJECT (local_store)); + CORBA_exception_free (&ev); + return; + } + CORBA_exception_free (&ev); +} diff --git a/mail/mail-local.h b/mail/mail-local.h index 7c0b619de4..254fcbe4f6 100644 --- a/mail/mail-local.h +++ b/mail/mail-local.h @@ -2,8 +2,9 @@ /* mail-local.h: Local mailbox support. */ /* - * Author: + * Authors: * Michael Zucchi + * Dan Winship * * Copyright 2000 Helix Code, Inc. (http://www.helixcode.com) * @@ -26,12 +27,12 @@ #ifndef _MAIL_LOCAL_H #define _MAIL_LOCAL_H -#include "camel/camel-folder.h" +#include "evolution-shell-client.h" #include "folder-browser.h" -/* mail-local.c */ -CamelFolder *mail_tool_local_uri_to_folder(const char *uri, CamelException *ex); -void local_reconfigure_folder(FolderBrowser *fb); -char *mail_local_map_uri(const char *uri, int *index); +void mail_local_storage_startup (EvolutionShellClient *shellclient, + const char *evolution_path); + +void mail_local_reconfigure_folder (FolderBrowser *fb); #endif diff --git a/mail/mail-tools.c b/mail/mail-tools.c index e12331819d..0ab7862200 100644 --- a/mail/mail-tools.c +++ b/mail/mail-tools.c @@ -135,23 +135,6 @@ mail_tool_get_folder_name (CamelFolder *folder) return path; } -gchar * -mail_tool_get_local_inbox_url (int *index) -{ - char *uri, *new; - - uri = g_strdup_printf("file://%s/local/Inbox", evolution_dir); - new = mail_local_map_uri(uri, index); - g_free(uri); - return new; -} - -gchar * -mail_tool_get_local_movemail_url (void) -{ - return g_strdup_printf ("mbox://%s/local/Inbox", evolution_dir); -} - gchar * mail_tool_get_local_movemail_path (void) { @@ -163,13 +146,9 @@ mail_tool_get_local_inbox (CamelException *ex) { gchar *url; CamelFolder *folder; - int index; - guint32 flags = CAMEL_STORE_FOLDER_CREATE; - url = mail_tool_get_local_inbox_url(&index); - if (index) - flags |= CAMEL_STORE_FOLDER_BODY_INDEX; - folder = mail_tool_get_folder_from_urlname (url, "mbox", flags, ex); + url = g_strdup_printf("file://%s/local/Inbox", evolution_dir); + folder = mail_tool_uri_to_folder (url, ex); g_free (url); return folder; } @@ -186,7 +165,6 @@ mail_tool_get_inbox (const gchar *url, CamelException *ex) char * mail_tool_do_movemail (const gchar *source_url, CamelException *ex) { - gchar *dest_url; gchar *dest_path; const gchar *source; struct stat sb; @@ -197,7 +175,6 @@ mail_tool_do_movemail (const gchar *source_url, CamelException *ex) /* Set up our destination. */ - dest_url = mail_tool_get_local_movemail_url(); dest_path = mail_tool_get_local_movemail_path(); /* Create a new movemail mailbox file of 0 size */ @@ -210,7 +187,6 @@ mail_tool_do_movemail (const gchar *source_url, CamelException *ex) _("Couldn't create temporary " "mbox `%s': %s"), dest_path, g_strerror (errno)); g_free (dest_path); - g_free (dest_url); return NULL; } @@ -232,17 +208,14 @@ mail_tool_do_movemail (const gchar *source_url, CamelException *ex) if (stat (dest_path, &sb) < 0 || sb.st_size == 0) { g_free (dest_path); - g_free (dest_url); return NULL; } if (camel_exception_is_set (ex)) { - g_free (dest_url); g_free (dest_path); return NULL; } - g_free (dest_url); return dest_path; } @@ -487,27 +460,30 @@ mail_tool_get_root_of_store (const char *source_uri, CamelException *ex) CamelFolder * mail_tool_uri_to_folder (const char *uri, CamelException *ex) { + CamelURL *url; CamelStore *store = NULL; CamelFolder *folder = NULL; - if (!strncmp (uri, "vfolder:", 8)) { + url = camel_url_new (uri, ex); + if (!url) + return NULL; + + if (!strcmp (url->protocol, "vfolder")) { folder = vfolder_uri_to_folder (uri, ex); - } else if (!strncmp (uri, "imap:", 5) || !strncmp (uri, "nntp:", 5)) { + } else { mail_tool_camel_lock_up (); store = camel_session_get_store (session, uri, ex); if (store) { - char *ptr; - - for (ptr = (char *)(uri + 7); *ptr && *ptr != '/'; ptr++); - if (*ptr == '/') - folder = camel_store_get_folder (store, ptr + 1, CAMEL_STORE_FOLDER_CREATE, ex); + char *name; + + if (url->path && *url->path) + name = url->path + 1; + else + name = ""; + folder = camel_store_get_folder ( + store, name, CAMEL_STORE_FOLDER_CREATE, ex); } mail_tool_camel_lock_down (); - } else if (!strncmp (uri, "file:", 5)) { - folder = mail_tool_local_uri_to_folder (uri, ex); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Don't know protocol to open URI `%s'"), uri); } if (camel_exception_is_set (ex)) { @@ -516,9 +492,9 @@ mail_tool_uri_to_folder (const char *uri, CamelException *ex) folder = NULL; } } - if (store) camel_object_unref (CAMEL_OBJECT (store)); + camel_url_free (url); return folder; } -- cgit v1.2.3