From fa2c19fdd1aee26d8bf5b622a3adf970004c3abf Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 9 Feb 2001 16:45:09 +0000 Subject: Updates for CamelStore changes, small memory leak fixes. (lookup_folder): * mail-local.c: Updates for CamelStore changes, small memory leak fixes. (lookup_folder): Removed (and moved into the reconfigure code) since this method no longer exists in CamelStore. (do_reconfigure_folder, etc): Update the info in the MailLocalStore after reconfiguring. (mail_local_lookup_folder): Removed * local-config.glade: fix padding of the label_format * message-list.c (ml_tree_value_at): Don't keep message infos reffed across calls, since this can cause badness after a reconfigure. Instead, just strdup the needed values and free those on the next call. * mail-tools.c (mail_tool_get_root_of_store): Unused, remove. (mail_tool_get_inbox): use camel_store_get_inbox. * evolution-outlook-importer.c (load_file_fn): * evolution-mbox-importer.c (load_file_fn): Use mail_tool_get_local_inbox() instead of mail_importer_get_folder() * mail-importer.c (mail_importer_get_folder): Removed svn path=/trunk/; revision=8147 --- mail/ChangeLog | 26 + mail/evolution-mbox-importer.c | 3 +- mail/evolution-outlook-importer.c | 3 +- mail/local-config.glade | 2 +- mail/mail-importer.c | 36 -- mail/mail-importer.h | 2 - mail/mail-local.c | 1294 +++++++++++++++++-------------------- mail/mail-local.h | 2 - mail/mail-threads.c | 9 +- mail/mail-tools.c | 55 +- mail/mail-tools.h | 4 - mail/message-list.c | 93 +-- 12 files changed, 703 insertions(+), 826 deletions(-) (limited to 'mail') diff --git a/mail/ChangeLog b/mail/ChangeLog index ff8ee843e7..1d3e2c6640 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,29 @@ +2001-02-09 Dan Winship + + * mail-local.c: Updates for CamelStore changes, small memory leak + fixes. + (lookup_folder): Removed (and moved into the reconfigure code) + since this method no longer exists in CamelStore. + (do_reconfigure_folder, etc): Update the info in the + MailLocalStore after reconfiguring. + (mail_local_lookup_folder): Removed + + * local-config.glade: fix padding of the label_format + + * message-list.c (ml_tree_value_at): Don't keep message infos + reffed across calls, since this can cause badness after a + reconfigure. Instead, just strdup the needed values and free those + on the next call. + + * mail-tools.c (mail_tool_get_root_of_store): Unused, remove. + (mail_tool_get_inbox): use camel_store_get_inbox. + + * evolution-outlook-importer.c (load_file_fn): + * evolution-mbox-importer.c (load_file_fn): Use + mail_tool_get_local_inbox() instead of mail_importer_get_folder() + + * mail-importer.c (mail_importer_get_folder): Removed + 2001-02-08 Jeffrey Stedfast * mail-callbacks.c (mail_generate_reply): New location for this diff --git a/mail/evolution-mbox-importer.c b/mail/evolution-mbox-importer.c index 84837ccb9b..0e18fb6732 100644 --- a/mail/evolution-mbox-importer.c +++ b/mail/evolution-mbox-importer.c @@ -33,6 +33,7 @@ #include #include "mail-importer.h" +#include "mail-tools.h" #include @@ -183,7 +184,7 @@ load_file_fn (EvolutionImporter *eimporter, } importer->mstream = NULL; - importer->folder = mail_importer_get_folder ("Inbox", NULL); + importer->folder = mail_tool_get_local_inbox (NULL); if (importer->folder == NULL) { g_print ("Bad folder\n"); diff --git a/mail/evolution-outlook-importer.c b/mail/evolution-outlook-importer.c index 35fa2e7315..d78f2ad7f8 100644 --- a/mail/evolution-outlook-importer.c +++ b/mail/evolution-outlook-importer.c @@ -34,6 +34,7 @@ #include #include "mail-importer.h" +#include "mail-tools.h" #include @@ -253,7 +254,7 @@ load_file_fn (EvolutionImporter *eimporter, importer->mstream = NULL; - importer->folder = mail_importer_get_folder ("Inbox", NULL); + importer->folder = mail_tool_get_local_inbox (NULL); if (importer->folder == NULL){ g_warning ("Bad folder"); diff --git a/mail/local-config.glade b/mail/local-config.glade index 890f55144d..7a2dbc2862 100644 --- a/mail/local-config.glade +++ b/mail/local-config.glade @@ -152,7 +152,7 @@ False 7.45058e-09 0.5 - 0 + 8 0 1 diff --git a/mail/mail-importer.c b/mail/mail-importer.c index 3c02576599..b46c4ccc50 100644 --- a/mail/mail-importer.c +++ b/mail/mail-importer.c @@ -87,42 +87,6 @@ mail_importer_add_line (MailImporter *importer, g_free (info); } -/** - * mail_importer_get_folder: - * @name: The folder name. - * *opt_ex: A #CamelException, or NULL if you don't care about errors. - * - * Gets the local folder called @name. - * - * Returns: A CamelFolder (which needs to be unrefed when you are done with it) - * on success, or NULL on fail. A more detailed error is given in @opt_ex, if - * @opt_ex is not NULL. - */ -CamelFolder * -mail_importer_get_folder (const char *name, - CamelException *opt_ex) -{ - CamelFolder *folder; - CamelException *real_ex; - char *path, *tmp; - - if (opt_ex != NULL) - real_ex = opt_ex; - else - real_ex = camel_exception_new (); - - g_print ("Evolution_dir: %s\n", evolution_dir); - tmp = g_concat_dir_and_file (evolution_dir, "local"); - path = g_concat_dir_and_file (tmp, name); - g_free (tmp); - - folder = mail_local_lookup_folder (path + 1, real_ex); - if (opt_ex == NULL) - camel_exception_free (real_ex); - - return folder; -} - /** * mail_importer_init: * diff --git a/mail/mail-importer.h b/mail/mail-importer.h index 0c46c7c78c..cc9c189eef 100644 --- a/mail/mail-importer.h +++ b/mail/mail-importer.h @@ -40,6 +40,4 @@ void mail_importer_init (void); void mail_importer_add_line (MailImporter *importer, const char *str, gboolean finished); -CamelFolder *mail_importer_get_folder (const char *name, - CamelException *opt_ex); #endif diff --git a/mail/mail-local.c b/mail/mail-local.c index 1559418a83..7b5b744018 100644 --- a/mail/mail-local.c +++ b/mail/mail-local.c @@ -162,870 +162,776 @@ save_metainfo(struct _local_meta *meta) } -/* Local folder reconfiguration stuff */ +/* 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)) -/* - open new - copy old->new - close old - rename old oldsave - rename new old - open oldsave - delete oldsave +typedef struct { + CamelStore parent_object; - close old - rename oldtmp - open new - open oldtmp - copy oldtmp new - close oldtmp - close oldnew + GNOME_Evolution_LocalStorage corba_local_storage; + EvolutionStorageListener *local_storage_listener; -*/ + char *local_path; + int local_pathlen; + GHashTable *folders, /* points to MailLocalFolder */ + *unread; +} MailLocalStore; + +typedef struct { + CamelStoreClass parent_class; +} MailLocalStoreClass; + +typedef struct { + CamelFolder *folder; + MailLocalStore *local_store; + char *path, *name, *uri; + int last_unread; +} MailLocalFolder; + +static MailLocalStore *local_store; + +CamelType mail_local_store_get_type (void); + +static void local_folder_changed_proxy (CamelObject *folder, gpointer event_data, gpointer user_data); + +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 CamelStoreClass *local_parent_class; static void -update_progress(char *fmt, float percent) +mail_local_store_class_init (MailLocalStoreClass *mail_local_store_class) { - if (fmt) - mail_status(fmt); - /*mail_op_set_percentage (percent);*/ -} + 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; -typedef struct reconfigure_folder_input_s { - FolderBrowser *fb; - gchar *newtype; - GtkWidget *frame; - GtkWidget *apply; - GtkWidget *cancel; - GtkOptionMenu *optionlist; -} reconfigure_folder_input_t; + /* Don't cache folders */ + camel_store_class->hash_folder_name = NULL; + camel_store_class->compare_folder_name = NULL; -static gchar * -describe_reconfigure_folder (gpointer in_data, gboolean gerund) -{ - reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; + camel_store_class->get_folder = get_folder; + camel_store_class->delete_folder = delete_folder; + camel_store_class->rename_folder = rename_folder; - if (gerund) - return g_strdup_printf (_("Changing folder \"%s\" to \"%s\" format"), - input->fb->uri, - input->newtype); - else - return g_strdup_printf (_("Change folder \"%s\" to \"%s\" format"), - input->fb->uri, - input->newtype); + local_parent_class = (CamelStoreClass *)camel_type_get_global_classfuncs(camel_store_get_type ()); } static void -setup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex) +mail_local_store_init (gpointer object, gpointer klass) { - reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; + MailLocalStore *local_store = MAIL_LOCAL_STORE (object); - if (!IS_FOLDER_BROWSER (input->fb)) { - camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM, - "Input has a bad FolderBrowser in reconfigure_folder"); - return; - } + local_store->corba_local_storage = CORBA_OBJECT_NIL; +} - if (!input->newtype) { - camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM, - "No new folder type in reconfigure_folder"); - return; +static void +free_local_folder(MailLocalFolder *lf) +{ + if (lf->folder) { + camel_object_unhook_event((CamelObject *)lf->folder, + "folder_changed", local_folder_changed_proxy, + lf); + camel_object_unhook_event((CamelObject *)lf->folder, + "message_changed", local_folder_changed_proxy, + lf); + camel_object_unref((CamelObject *)lf->folder); } + g_free(lf->path); + g_free(lf->name); + g_free(lf->uri); + camel_object_unref((CamelObject *)lf->local_store); +} - gtk_object_ref (GTK_OBJECT (input->fb)); +static void +free_folder (gpointer key, gpointer data, gpointer user_data) +{ + MailLocalFolder *lf = data; + + g_free(key); + free_local_folder(lf); } static void -do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) +mail_local_store_finalize (gpointer object) { - reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; + MailLocalStore *local_store = MAIL_LOCAL_STORE (object); + CORBA_Environment ev; - CamelStore *fromstore = NULL, *tostore = NULL; - char *fromurl = NULL, *tourl = NULL; - CamelFolder *fromfolder = NULL, *tofolder = NULL; - GPtrArray *uids; - int i; - char *metapath; - char *tmpname; - CamelURL *url = NULL; - struct _local_meta *meta; - guint32 flags; + 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); - d(printf("reconfiguring folder: %s to type %s\n", input->fb->uri, input->newtype)); + if (local_store->local_storage_listener) + gtk_object_unref (GTK_OBJECT (local_store->local_storage_listener)); - mail_status_start(_("Reconfiguring folder")); + g_hash_table_foreach (local_store->folders, free_folder, NULL); + g_hash_table_destroy (local_store->folders); - /* NOTE: This var is cleared by the folder_browser via the set_uri method */ - input->fb->reconfigure = TRUE; + g_free (local_store->local_path); +} - /* get the actual location of the mailbox */ - url = camel_url_new(input->fb->uri, ex); - if (camel_exception_is_set(ex)) { - g_warning("%s is not a workable url!", input->fb->uri); - goto cleanup; +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); } - metapath = g_strdup_printf("%s/local-metadata.xml", url->path); - meta = load_metainfo(metapath); - g_free(metapath); + return mail_local_store_type; +} - /* first, 'close' the old folder */ - if (input->fb->folder != NULL) { - update_progress(_("Closing current folder"), 0.0); +static CamelFolder * +get_folder (CamelStore *store, const char *folder_name, + guint32 flags, CamelException *ex) +{ + MailLocalStore *local_store = (MailLocalStore *)store; + CamelFolder *folder; + MailLocalFolder *local_folder; - camel_folder_sync(input->fb->folder, FALSE, ex); - camel_object_unref (CAMEL_OBJECT (input->fb->folder)); - input->fb->folder = NULL; + local_folder = g_hash_table_lookup (local_store->folders, folder_name); + if (local_folder) { + folder = local_folder->folder; + camel_object_ref (CAMEL_OBJECT (folder)); + } else { + folder = NULL; + camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, "No such folder %s", folder_name); } + return folder; +} - camel_url_set_protocol (url, meta->format); - fromurl = camel_url_to_string (url, FALSE); - camel_url_set_protocol (url, input->newtype); - tourl = camel_url_to_string (url, FALSE); +static void +delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) +{ + /* No-op. The shell local storage deals with this. */ +} - d(printf("opening stores %s and %s\n", fromurl, tourl)); +static void +rename_folder (CamelStore *store, const char *old, const char *new, + CamelException *ex) +{ + /* Probable no-op... */ +} - fromstore = camel_session_get_store(session, fromurl, ex); +static char * +get_name (CamelService *service, gboolean brief) +{ + return g_strdup ("Local mail folders"); +} - if (camel_exception_is_set(ex)) - goto cleanup; - tostore = camel_session_get_store(session, tourl, ex); - if (camel_exception_is_set(ex)) - goto cleanup; +/* Callbacks for the EvolutionStorageListner signals. */ - /* rename the old mbox and open it again, without indexing */ - tmpname = g_strdup_printf("%s_reconfig", meta->name); - d(printf("renaming %s to %s, and opening it\n", meta->name, tmpname)); - update_progress(_("Renaming old folder and opening"), 0.0); +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__); +} - camel_store_rename_folder(fromstore, meta->name, tmpname, ex); - if (camel_exception_is_set(ex)) { - goto cleanup; - } - - /* we dont need to set the create flag ... or need an index if it has one */ - fromfolder = camel_store_get_folder(fromstore, tmpname, 0, ex); - if (fromfolder == NULL || camel_exception_is_set(ex)) { - /* try and recover ... */ - camel_exception_clear (ex); - camel_store_rename_folder(fromstore, tmpname, meta->name, ex); - goto cleanup; - } - /* create a new mbox */ - d(printf("Creating the destination mbox\n")); - update_progress(_("Creating new folder"), 0.0); +static void +local_folder_changed (CamelObject *object, gpointer event_data, + gpointer user_data) +{ + MailLocalFolder *local_folder = user_data; + int unread = GPOINTER_TO_INT (event_data); + char *display; - flags = CAMEL_STORE_FOLDER_CREATE; - if (meta->indexed) - flags |= CAMEL_STORE_FOLDER_BODY_INDEX; - tofolder = camel_store_get_folder(tostore, meta->name, flags, ex); - if (tofolder == NULL || camel_exception_is_set(ex)) { - d(printf("cannot open destination folder\n")); - /* try and recover ... */ - camel_exception_clear (ex); - camel_store_rename_folder(fromstore, tmpname, meta->name, ex); - goto cleanup; - } + if (unread != local_folder->last_unread) { + CORBA_Environment ev; - update_progress(_("Copying messages"), 0.0); - uids = camel_folder_get_uids(fromfolder); - for (i=0;ilen;i++) { - mail_statusf("Copying message %d of %d", i, uids->len); - camel_folder_move_message_to(fromfolder, uids->pdata[i], tofolder, ex); - if (camel_exception_is_set(ex)) { - camel_folder_free_uids(fromfolder, uids); - goto cleanup; + CORBA_exception_init (&ev); + if (unread > 0) { + display = g_strdup_printf ("%s (%d)", local_folder->name, unread); + GNOME_Evolution_LocalStorage_updateFolder ( + local_folder->local_store->corba_local_storage, + local_folder->path, display, TRUE, &ev); + g_free (display); + } else { + GNOME_Evolution_LocalStorage_updateFolder ( + local_folder->local_store->corba_local_storage, + local_folder->path, local_folder->name, + FALSE, &ev); } - } - camel_folder_free_uids(fromfolder, uids); - camel_folder_expunge(fromfolder, ex); - - d(printf("delete old mbox ...\n")); - camel_store_delete_folder(fromstore, tmpname, ex); + CORBA_exception_free (&ev); - /* switch format */ - g_free(meta->format); - meta->format = g_strdup(input->newtype); - if (save_metainfo(meta) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot save folder metainfo; " - "you'll probably find you can't\n" - "open this folder anymore: %s"), - tourl); + local_folder->last_unread = unread; } - free_metainfo(meta); - - /* and unref our copy of the new folder ... */ - cleanup: - if (tofolder) - camel_object_unref (CAMEL_OBJECT (tofolder)); - if (fromfolder) - camel_object_unref (CAMEL_OBJECT (fromfolder)); - if (fromstore) - camel_object_unref (CAMEL_OBJECT (fromstore)); - if (tostore) - camel_object_unref (CAMEL_OBJECT (tostore)); - g_free(fromurl); - g_free(tourl); - if (url) - camel_url_free (url); } static void -cleanup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex) +local_folder_changed_proxy (CamelObject *folder, gpointer event_data, gpointer user_data) { - reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; - char *uri; - - if (camel_exception_is_set(ex)) { - GtkWidget *win = gtk_widget_get_ancestor((GtkWidget *)input->frame, GTK_TYPE_WINDOW); - gnome_error_dialog_parented (_("If you can no longer open this mailbox, then\n" - "you may need to repair it manually."), GTK_WINDOW (win)); - } - - /* force a reload of the newly formatted folder */ - d(printf("opening new source\n")); - uri = g_strdup(input->fb->uri); - folder_browser_set_uri(input->fb, uri); - g_free(uri); - - mail_status_end(); + int unread; - gtk_object_unref (GTK_OBJECT (input->fb)); - g_free (input->newtype); + unread = camel_folder_get_unread_message_count (CAMEL_FOLDER (folder)); + mail_proxy_event (local_folder_changed, folder, + GINT_TO_POINTER (unread), user_data); } -static const mail_operation_spec op_reconfigure_folder = +static char * +describe_register_folder (gpointer in_data, gboolean gerund) { - describe_reconfigure_folder, - 0, - setup_reconfigure_folder, - do_reconfigure_folder, - cleanup_reconfigure_folder -}; + if (gerund) + return g_strdup (_("Registering local folder")); + else + return g_strdup (_("Register local folder")); +} static void -reconfigure_clicked(GnomeDialog *d, int button, reconfigure_folder_input_t *data) +do_register_folder (gpointer in_data, gpointer op_data, CamelException *ex) { - if (button == 0) { - GtkMenu *menu; - int type; - char *types[] = { "mbox", "maildir", "mh" }; + MailLocalFolder *local_folder = in_data; + char *name, *path = local_folder->uri + 7; + struct _local_meta *meta; + CamelStore *store; + guint32 flags; - menu = (GtkMenu *)gtk_option_menu_get_menu(data->optionlist); - type = g_list_index(GTK_MENU_SHELL(menu)->children, gtk_menu_get_active(menu)); - if (type < 0 || type > 2) - type = 0; + name = g_strdup_printf ("%s/local-metadata.xml", path); + meta = load_metainfo (name); + g_free (name); - gtk_widget_set_sensitive(data->frame, FALSE); - gtk_widget_set_sensitive(data->apply, FALSE); - gtk_widget_set_sensitive(data->cancel, FALSE); + name = g_strdup_printf ("%s:%s", meta->format, path); + store = camel_session_get_store (session, name, ex); + g_free (name); + if (!store) { + free_metainfo (meta); + return; + } - data->newtype = g_strdup (types[type]); - mail_operation_queue (&op_reconfigure_folder, data, TRUE); + 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); + if (local_folder->folder) { + camel_object_hook_event (CAMEL_OBJECT (local_folder->folder), + "folder_changed", local_folder_changed_proxy, + local_folder); + camel_object_hook_event (CAMEL_OBJECT (local_folder->folder), + "message_changed", local_folder_changed_proxy, + local_folder); + local_folder->last_unread = camel_folder_get_unread_message_count(local_folder->folder); } - if (button != -1) - gnome_dialog_close(d); + camel_object_unref (CAMEL_OBJECT (store)); + free_metainfo (meta); } -void -mail_local_reconfigure_folder(FolderBrowser *fb) +static void +cleanup_register_folder (gpointer in_data, gpointer op_data, CamelException *ex) { - CamelStore *store; - GladeXML *gui; - GnomeDialog *gd; - reconfigure_folder_input_t *data; + MailLocalFolder *local_folder = in_data; + int unread; - if (fb->folder == NULL) { - g_warning("Trying to reconfigure nonexistant folder"); + if (!local_folder->folder) { + free_local_folder(local_folder); return; } - data = g_new (reconfigure_folder_input_t, 1); + g_hash_table_insert (local_folder->local_store->folders, local_folder->uri + 8, local_folder); - store = camel_folder_get_parent_store(fb->folder); + unread = local_folder->last_unread; + local_folder->last_unread = 0; + local_folder_changed (CAMEL_OBJECT (local_folder->folder), GINT_TO_POINTER (unread), local_folder); +} - gui = glade_xml_new(EVOLUTION_GLADEDIR "/local-config.glade", "dialog_format"); - gd = (GnomeDialog *)glade_xml_get_widget (gui, "dialog_format"); +static const mail_operation_spec op_register_folder = +{ + describe_register_folder, + 0, + NULL, + do_register_folder, + cleanup_register_folder +}; - data->frame = glade_xml_get_widget (gui, "frame_format"); - data->apply = glade_xml_get_widget (gui, "apply_format"); - data->cancel = glade_xml_get_widget (gui, "cancel_format"); - data->optionlist = (GtkOptionMenu *)glade_xml_get_widget (gui, "option_format"); - data->newtype = NULL; - data->fb = fb; +static void +local_storage_new_folder_cb (EvolutionStorageListener *storage_listener, + const char *path, + const GNOME_Evolution_Folder *folder, + void *data) +{ + MailLocalStore *local_store = data; + MailLocalFolder *local_folder; - gtk_label_set_text((GtkLabel *)glade_xml_get_widget (gui, "label_format"), - ((CamelService *)store)->url->protocol); + 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; - gtk_signal_connect((GtkObject *)gd, "clicked", reconfigure_clicked, data); - gtk_object_unref((GtkObject *)gui); + local_folder = g_new0 (MailLocalFolder, 1); + local_folder->name = g_strdup (strrchr (path, '/') + 1); + local_folder->path = g_strdup (path); + local_folder->uri = g_strdup (folder->physical_uri); + local_folder->local_store = local_store; + camel_object_ref((CamelObject *)local_store); - gnome_dialog_run_and_close (GNOME_DIALOG (gd)); -} + /* Note: This needs to be synchronous, as that is what the shell + expects. Doesn't that suck. */ + /* This used to be made 'synchronous' by having us wait for + outstanding requests, which was BAD */ + /*mail_operation_queue (&op_register_folder, local_folder, FALSE);*/ + { + CamelException *ex = camel_exception_new(); + do_register_folder(local_folder, NULL, ex); + cleanup_register_folder(local_folder, NULL, ex); -/* 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)) +#if 0 + /* yay, so we can't do this, because we've probably got the bloody + splash screen up */ + if (camel_exception_is_set(ex)) { + char *msg = g_strdup_printf(_("Unable to register folder '%s':\n%s"), + path, camel_exception_get_description(ex)); + GnomeDialog *gd = (GnomeDialog *)gnome_error_dialog(msg); + gnome_dialog_run_and_close(gd); + g_free(msg); + } +#endif + camel_exception_free(ex); + } +} -typedef struct { - CamelStore parent_object; +static void +local_storage_removed_folder_cb (EvolutionStorageListener *storage_listener, + const char *path, + void *data) +{ + MailLocalStore *local_store = data; + MailLocalFolder *local_folder; - GNOME_Evolution_LocalStorage corba_local_storage; - EvolutionStorageListener *local_storage_listener; + if (strncmp (path, "file://", 7) != 0 || + strncmp (path + 7, local_store->local_path, + local_store->local_pathlen) != 0) + return; - char *local_path; - int local_pathlen; - GHashTable *folders, /* points to MailLocalFolder */ - *unread; -} MailLocalStore; + local_folder = g_hash_table_lookup (local_store->folders, path + 8); + if (local_folder) { + g_hash_table_remove (local_store->folders, path); + free_local_folder(local_folder); + } +} -typedef struct { - CamelStoreClass parent_class; -} MailLocalStoreClass; +static CamelProvider local_provider = { + "file", "Local mail", NULL, "mail", + CAMEL_PROVIDER_IS_STORAGE, CAMEL_URL_NEED_PATH, + { 0, 0 }, NULL +}; -typedef struct { - CamelFolder *folder; - MailLocalStore *local_store; - char *path, *name; - int last_unread; -} MailLocalFolder; - -static void local_folder_changed_proxy (CamelObject *folder, gpointer event_data, gpointer user_data); - -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 CamelFolder *lookup_folder(CamelStore *store, const char *folder_name); - -static CamelStoreClass *local_parent_class; - -static void -mail_local_store_class_init (MailLocalStoreClass *mail_local_store_class) +/* There's only one "file:" store. */ +static guint +non_hash (gconstpointer key) { - 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; - camel_store_class->lookup_folder = lookup_folder; - - local_parent_class = (CamelStoreClass *)camel_type_get_global_classfuncs(camel_store_get_type ()); + return 0; } -static void -mail_local_store_init (gpointer object, gpointer klass) +static gint +non_equal (gconstpointer a, gconstpointer b) { - MailLocalStore *local_store = MAIL_LOCAL_STORE (object); - - local_store->corba_local_storage = CORBA_OBJECT_NIL; + return TRUE; } -static void -free_local_folder(MailLocalFolder *lf) +void +mail_local_storage_startup (EvolutionShellClient *shellclient, + const char *evolution_path) { - if (lf->folder) { - camel_object_unhook_event((CamelObject *)lf->folder, - "folder_changed", local_folder_changed_proxy, - lf); - camel_object_unhook_event((CamelObject *)lf->folder, - "message_changed", local_folder_changed_proxy, - lf); - camel_object_unref((CamelObject *)lf->folder); - } - g_free(lf->path); - g_free(lf->name); - camel_object_unref((CamelObject *)lf->local_store); -} + GNOME_Evolution_StorageListener corba_local_storage_listener; + CORBA_Environment ev; -static void -free_folder (gpointer key, gpointer data, gpointer user_data) -{ - MailLocalFolder *lf = data; + /* Register with Camel to handle file: URLs */ + local_provider.object_types[CAMEL_PROVIDER_STORE] = + mail_local_store_get_type(); - g_free(key); - free_local_folder(lf); -} + local_provider.service_cache = g_hash_table_new (non_hash, non_equal); + camel_session_register_provider (session, &local_provider); -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); + /* 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; } - CORBA_exception_free (&ev); - if (local_store->local_storage_listener) - gtk_object_unref (GTK_OBJECT (local_store->local_storage_listener)); + local_store->local_storage_listener = + evolution_storage_listener_new (); + corba_local_storage_listener = + evolution_storage_listener_corba_objref ( + local_store->local_storage_listener); - g_hash_table_foreach (local_store->folders, free_folder, NULL); - g_hash_table_destroy (local_store->folders); + 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); - g_free (local_store->local_path); -} + local_store->local_path = g_strdup_printf ("%s/local", + evolution_path); + local_store->local_pathlen = strlen (local_store->local_path); -CamelType -mail_local_store_get_type (void) -{ - static CamelType mail_local_store_type = CAMEL_INVALID_TYPE; + local_store->folders = g_hash_table_new (g_str_hash, g_str_equal); - 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); + CORBA_exception_init (&ev); + GNOME_Evolution_Storage_addListener (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; } - - return mail_local_store_type; + CORBA_exception_free (&ev); } -/* sigh, - because of all this LocalStore nonsense, we have to snoop cache hits to find out - if our local folder type has changed under us (sort of the whole point of most - of this file, is the storage type of the folder), and then reload the new folder - to match. - The only other way would be to poke it even more directly, which seems worse. +/* Local folder reconfiguration stuff */ + +/* + open new + copy old->new + close old + rename old oldsave + rename new old + open oldsave + delete oldsave + + close old + rename oldtmp + open new + open oldtmp + copy oldtmp new + close oldtmp + close oldnew - Not sure if the ref stuff is 100%, but its probably no worse than it was. */ -static CamelFolder * -lookup_folder (CamelStore *store, const char *folder_name) + +static void +update_progress(char *fmt, float percent) { - char *name, *type; - struct _local_meta *meta; - MailLocalFolder *local_folder; - CamelStore *newstore; - MailLocalStore *local_store = (MailLocalStore *)store; - CamelFolder *folder; - CamelException *ex; - - folder = local_parent_class->lookup_folder(store, folder_name); - - d(printf("looking up local folder: %s = %p\n", folder_name, folder)); - - if (folder != NULL) { - type = ((CamelService *)folder->parent_store)->url->protocol; - name = g_strdup_printf("/%s/local-metadata.xml", folder_name); - meta = load_metainfo(name); - g_free(name); - d(printf("found folder, checking type '%s' against meta '%s'\n", type, meta->format)); - if (strcmp(meta->format, type) != 0) { - d(printf("ok, mismatch, checking ...\n")); - local_parent_class->uncache_folder(store, folder); - local_folder = g_hash_table_lookup(local_store->folders, folder_name); - if (local_folder) { - d(printf("we have to update the old folder ...\n")); - camel_object_unhook_event(CAMEL_OBJECT (local_folder->folder), - "folder_changed", local_folder_changed_proxy, - local_folder); - camel_object_unhook_event(CAMEL_OBJECT (local_folder->folder), - "message_changed", local_folder_changed_proxy, - local_folder); - camel_object_unref((CamelObject *)local_folder->folder); - folder = local_folder->folder = NULL; - - ex = camel_exception_new(); - name = g_strdup_printf ("%s:/%s", meta->format, folder_name); - newstore = camel_session_get_store (session, name, ex); - d(printf("getting new store %s = %p\n", name, newstore)); - g_free (name); - if (newstore) { - guint32 flags = CAMEL_STORE_FOLDER_CREATE; - if (meta->indexed) - flags |= CAMEL_STORE_FOLDER_BODY_INDEX; - folder = local_folder->folder = - camel_store_get_folder(newstore, meta->name, flags, ex); - camel_object_unref((CamelObject *)newstore); - - d(printf("we got the new folder: %s : %p\n", folder_name, folder)); - camel_object_hook_event (CAMEL_OBJECT (local_folder->folder), - "folder_changed", local_folder_changed_proxy, - local_folder); - camel_object_hook_event (CAMEL_OBJECT (local_folder->folder), - "message_changed", local_folder_changed_proxy, - local_folder); - } - if (folder) - local_parent_class->cache_folder(store, folder_name, folder); - - camel_exception_free(ex); - } - } - free_metainfo(meta); - } + if (fmt) + mail_status(fmt); + /*mail_op_set_percentage (percent);*/ +} - if (folder) - camel_object_ref((CamelObject *)folder); +/* ******************** */ - return folder; -} +typedef struct reconfigure_folder_input_s { + FolderBrowser *fb; + gchar *newtype; + GtkWidget *frame; + GtkWidget *apply; + GtkWidget *cancel; + GtkOptionMenu *optionlist; +} reconfigure_folder_input_t; -static CamelFolder * -get_folder (CamelStore *store, const char *folder_name, - guint32 flags, CamelException *ex) +static gchar * +describe_reconfigure_folder (gpointer in_data, gboolean gerund) { - MailLocalStore *local_store = (MailLocalStore *)store; - CamelFolder *folder; - MailLocalFolder *local_folder; + reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; - local_folder = g_hash_table_lookup (local_store->folders, folder_name); - if (local_folder) { - folder = local_folder->folder; - camel_object_ref (CAMEL_OBJECT (folder)); - } else { - folder = NULL; - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, "No such folder %s", folder_name); - } - return folder; + if (gerund) + return g_strdup_printf (_("Changing folder \"%s\" to \"%s\" format"), + input->fb->uri, + input->newtype); + else + return g_strdup_printf (_("Change folder \"%s\" to \"%s\" format"), + input->fb->uri, + input->newtype); } static void -delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) +setup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex) { - /* No-op. The shell local storage deals with this. */ -} + reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; -static void -rename_folder (CamelStore *store, const char *old, const char *new, - CamelException *ex) -{ - /* Probable no-op... */ + gtk_object_ref (GTK_OBJECT (input->fb)); } -static char * -get_folder_name (CamelStore *store, const char *folder_name, - CamelException *ex) +static void +do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) { - return g_strdup (folder_name); -} + reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; + MailLocalFolder *local_folder; + CamelStore *fromstore = NULL, *tostore = NULL; + char *fromurl = NULL, *tourl = NULL; + CamelFolder *fromfolder = NULL, *tofolder = NULL; + GPtrArray *uids; + int i; + char *metapath; + char *tmpname; + CamelURL *url = NULL; + struct _local_meta *meta; + guint32 flags; -static char * -get_name (CamelService *service, gboolean brief) -{ - return g_strdup ("Local mail folders"); -} + d(printf("reconfiguring folder: %s to type %s\n", input->fb->uri, input->newtype)); + mail_status_start(_("Reconfiguring 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__); -} + /* NOTE: This var is cleared by the folder_browser via the set_uri method */ + input->fb->reconfigure = TRUE; + /* get the actual location of the mailbox */ + url = camel_url_new(input->fb->uri, ex); + if (camel_exception_is_set(ex)) { + g_warning("%s is not a workable url!", input->fb->uri); + goto cleanup; + } -static void -local_folder_changed (CamelObject *object, gpointer event_data, - gpointer user_data) -{ - MailLocalFolder *local_folder = user_data; - int unread = GPOINTER_TO_INT (event_data); - char *display; + tmpname = strchr (input->fb->uri, '/'); + if (tmpname) { + while (*tmpname == '/') + tmpname++; + local_folder = g_hash_table_lookup (local_store->folders, tmpname); + } else + local_folder = NULL; + if (!local_folder) { + g_warning("%s is not a registered local folder!", input->fb->uri); + goto cleanup; + } - if (unread != local_folder->last_unread) { - CORBA_Environment ev; + metapath = g_strdup_printf("%s/local-metadata.xml", url->path); + meta = load_metainfo(metapath); + g_free(metapath); - CORBA_exception_init (&ev); - if (unread > 0) { - display = g_strdup_printf ("%s (%d)", local_folder->name, unread); - GNOME_Evolution_LocalStorage_updateFolder ( - local_folder->local_store->corba_local_storage, - local_folder->path, display, TRUE, &ev); - g_free (display); - } else { - GNOME_Evolution_LocalStorage_updateFolder ( - local_folder->local_store->corba_local_storage, - local_folder->path, local_folder->name, - FALSE, &ev); - } - CORBA_exception_free (&ev); + /* first, 'close' the old folder */ + update_progress(_("Closing current folder"), 0.0); + camel_folder_sync(local_folder->folder, FALSE, ex); + camel_object_unhook_event(CAMEL_OBJECT (local_folder->folder), + "folder_changed", local_folder_changed_proxy, + local_folder); + camel_object_unhook_event(CAMEL_OBJECT (local_folder->folder), + "message_changed", local_folder_changed_proxy, + local_folder); + /* Once for the FolderBrowser, once for the local store */ + camel_object_unref(CAMEL_OBJECT(local_folder->folder)); + camel_object_unref(CAMEL_OBJECT(local_folder->folder)); + local_folder->folder = input->fb->folder = NULL; - local_folder->last_unread = unread; - } -} + camel_url_set_protocol (url, meta->format); + fromurl = camel_url_to_string (url, FALSE); + camel_url_set_protocol (url, input->newtype); + tourl = camel_url_to_string (url, FALSE); -static void -local_folder_changed_proxy (CamelObject *folder, gpointer event_data, gpointer user_data) -{ - int unread; + d(printf("opening stores %s and %s\n", fromurl, tourl)); - unread = camel_folder_get_unread_message_count (CAMEL_FOLDER (folder)); - mail_proxy_event (local_folder_changed, folder, - GINT_TO_POINTER (unread), user_data); -} + fromstore = camel_session_get_store(session, fromurl, ex); -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")); -} + if (camel_exception_is_set(ex)) + goto cleanup; -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; + tostore = camel_session_get_store(session, tourl, ex); + if (camel_exception_is_set(ex)) + goto cleanup; - name = g_strdup_printf ("/%s/local-metadata.xml", local_folder->name); - meta = load_metainfo (name); - g_free (name); + /* rename the old mbox and open it again, without indexing */ + tmpname = g_strdup_printf("%s_reconfig", meta->name); + d(printf("renaming %s to %s, and opening it\n", meta->name, tmpname)); + update_progress(_("Renaming old folder and opening"), 0.0); - name = g_strdup_printf ("%s:/%s", meta->format, local_folder->name); - store = camel_session_get_store (session, name, ex); - g_free (name); - if (!store) { - free_metainfo (meta); - return; + camel_store_rename_folder(fromstore, meta->name, tmpname, ex); + if (camel_exception_is_set(ex)) { + goto cleanup; + } + + /* we dont need to set the create flag ... or need an index if it has one */ + fromfolder = camel_store_get_folder(fromstore, tmpname, 0, ex); + if (fromfolder == NULL || camel_exception_is_set(ex)) { + /* try and recover ... */ + camel_exception_clear (ex); + camel_store_rename_folder(fromstore, tmpname, meta->name, ex); + goto cleanup; } + /* create a new mbox */ + d(printf("Creating the destination mbox\n")); + update_progress(_("Creating new folder"), 0.0); + 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); - local_folder->last_unread = camel_folder_get_unread_message_count(local_folder->folder); - camel_object_unref (CAMEL_OBJECT (store)); - free_metainfo (meta); -} - -static void -cleanup_register_folder (gpointer in_data, gpointer op_data, CamelException *ex) -{ - MailLocalFolder *local_folder = in_data; - int unread; + tofolder = camel_store_get_folder(tostore, meta->name, flags, ex); + if (tofolder == NULL || camel_exception_is_set(ex)) { + d(printf("cannot open destination folder\n")); + /* try and recover ... */ + camel_exception_clear (ex); + camel_store_rename_folder(fromstore, tmpname, meta->name, ex); + goto cleanup; + } - if (!local_folder->folder) { - free_local_folder(local_folder); - return; + update_progress(_("Copying messages"), 0.0); + uids = camel_folder_get_uids(fromfolder); + for (i=0;ilen;i++) { + mail_statusf("Copying message %d of %d", i, uids->len); + camel_folder_move_message_to(fromfolder, uids->pdata[i], tofolder, ex); + if (camel_exception_is_set(ex)) { + camel_folder_free_uids(fromfolder, uids); + goto cleanup; + } } + camel_folder_free_uids(fromfolder, uids); + camel_folder_expunge(fromfolder, ex); - g_hash_table_insert (local_folder->local_store->folders, local_folder->name, local_folder); - local_folder->name = strrchr (local_folder->path, '/') + 1; + d(printf("delete old mbox ...\n")); + camel_store_delete_folder(fromstore, tmpname, ex); - camel_object_hook_event (CAMEL_OBJECT (local_folder->folder), - "folder_changed", local_folder_changed_proxy, - local_folder); - camel_object_hook_event (CAMEL_OBJECT (local_folder->folder), - "message_changed", local_folder_changed_proxy, - local_folder); - unread = local_folder->last_unread; - local_folder->last_unread = 0; - local_folder_changed (CAMEL_OBJECT (local_folder->folder), GINT_TO_POINTER (unread), local_folder); -} + /* switch format */ + g_free(meta->format); + meta->format = g_strdup(input->newtype); + if (save_metainfo(meta) == -1) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + _("Cannot save folder metainfo; " + "you'll probably find you can't\n" + "open this folder anymore: %s"), + tourl); + } -static const mail_operation_spec op_register_folder = -{ - describe_register_folder, - 0, - NULL, - do_register_folder, - cleanup_register_folder -}; + cleanup: + if (!local_folder->folder) + do_register_folder (local_folder, NULL, ex); + if (tofolder) + camel_object_unref (CAMEL_OBJECT (tofolder)); + if (fromfolder) + camel_object_unref (CAMEL_OBJECT (fromfolder)); + if (fromstore) + camel_object_unref (CAMEL_OBJECT (fromstore)); + if (tostore) + camel_object_unref (CAMEL_OBJECT (tostore)); + free_metainfo(meta); + g_free(fromurl); + g_free(tourl); + if (url) + camel_url_free (url); +} static void -local_storage_new_folder_cb (EvolutionStorageListener *storage_listener, - const char *path, - const GNOME_Evolution_Folder *folder, - void *data) +cleanup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex) { - 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; - - local_folder = g_new0 (MailLocalFolder, 1); - local_folder->name = g_strdup (folder->physical_uri + 8); - local_folder->path = g_strdup (path); - local_folder->local_store = local_store; - camel_object_ref((CamelObject *)local_store); - - /* Note: This needs to be synchronous, as that is what the shell - expects. Doesn't that suck. */ - /* This used to be made 'synchronous' by having us wait for - outstanding requests, which was BAD */ - - /*mail_operation_queue (&op_register_folder, local_folder, FALSE);*/ - { - CamelException *ex = camel_exception_new(); - - do_register_folder(local_folder, NULL, ex); - cleanup_register_folder(local_folder, NULL, ex); + reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; + char *uri; -#if 0 - /* yay, so we can't do this, because we've probably got the bloody - splash screen up */ - if (camel_exception_is_set(ex)) { - char *msg = g_strdup_printf(_("Unable to register folder '%s':\n%s"), - path, camel_exception_get_description(ex)); - GnomeDialog *gd = (GnomeDialog *)gnome_error_dialog(msg); - gnome_dialog_run_and_close(gd); - g_free(msg); - } -#endif - camel_exception_free(ex); + if (camel_exception_is_set(ex)) { + gnome_error_dialog (_("If you can no longer open this mailbox, then\n" + "you may need to repair it manually.")); } -} - -static void -local_storage_removed_folder_cb (EvolutionStorageListener *storage_listener, - const char *path, - void *data) -{ - MailLocalStore *local_store = data; - MailLocalFolder *local_folder; - if (strncmp (path, "file://", 7) != 0 || - strncmp (path + 7, local_store->local_path, - local_store->local_pathlen) != 0) - return; + /* force a reload of the newly formatted folder */ + d(printf("opening new source\n")); + uri = g_strdup(input->fb->uri); + folder_browser_set_uri(input->fb, uri); + g_free(uri); - path += 7 + local_store->local_pathlen; + mail_status_end(); - local_folder = g_hash_table_lookup (local_store->folders, path); - if (local_folder) { - g_hash_table_remove (local_store->folders, path); - free_local_folder(local_folder); - } + gtk_object_unref (GTK_OBJECT (input->fb)); + g_free (input->newtype); } -static CamelProvider local_provider = { - "file", "Local mail", NULL, "mail", - CAMEL_PROVIDER_IS_STORAGE, CAMEL_URL_NEED_PATH, - { 0, 0 }, NULL +static const mail_operation_spec op_reconfigure_folder = +{ + describe_reconfigure_folder, + 0, + setup_reconfigure_folder, + do_reconfigure_folder, + cleanup_reconfigure_folder }; -/* There's only one "file:" store. */ -static guint -non_hash (gconstpointer key) +static void +reconfigure_clicked(GnomeDialog *d, int button, reconfigure_folder_input_t *data) { - return 0; -} + if (button == 0) { + GtkMenu *menu; + int type; + char *types[] = { "mbox", "maildir", "mh" }; -static gint -non_equal (gconstpointer a, gconstpointer b) -{ - return TRUE; -} + menu = (GtkMenu *)gtk_option_menu_get_menu(data->optionlist); + type = g_list_index(GTK_MENU_SHELL(menu)->children, gtk_menu_get_active(menu)); + if (type < 0 || type > 2) + type = 0; -CamelFolder * -mail_local_lookup_folder (const char *name, - CamelException *ev) -{ - MailLocalStore *local_store; + gtk_widget_set_sensitive(data->frame, FALSE); + gtk_widget_set_sensitive(data->apply, FALSE); + gtk_widget_set_sensitive(data->cancel, FALSE); - local_store = (MailLocalStore *)camel_session_get_service (session, - "file:/", - CAMEL_PROVIDER_STORE, NULL); + data->newtype = g_strdup (types[type]); + mail_operation_queue (&op_reconfigure_folder, data, TRUE); + } else + g_free (data); - return get_folder (CAMEL_STORE(local_store), name, 0, ev); + if (button != -1) + gnome_dialog_close(d); } void -mail_local_storage_startup (EvolutionShellClient *shellclient, - const char *evolution_path) +mail_local_reconfigure_folder(FolderBrowser *fb) { - MailLocalStore *local_store; - GNOME_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); - + CamelStore *store; + GladeXML *gui; + GnomeDialog *gd; + reconfigure_folder_input_t *data; - /* 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)); + if (fb->folder == NULL) { + g_warning("Trying to reconfigure nonexistant folder"); return; } - local_store->local_storage_listener = - evolution_storage_listener_new (); - corba_local_storage_listener = - evolution_storage_listener_corba_objref ( - local_store->local_storage_listener); + data = g_new (reconfigure_folder_input_t, 1); - 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); + store = camel_folder_get_parent_store(fb->folder); - local_store->local_path = g_strdup_printf ("%s/local", - evolution_path); - local_store->local_pathlen = strlen (local_store->local_path); + gui = glade_xml_new(EVOLUTION_GLADEDIR "/local-config.glade", "dialog_format"); + gd = (GnomeDialog *)glade_xml_get_widget (gui, "dialog_format"); - local_store->folders = g_hash_table_new (g_str_hash, g_str_equal); + data->frame = glade_xml_get_widget (gui, "frame_format"); + data->apply = glade_xml_get_widget (gui, "apply_format"); + data->cancel = glade_xml_get_widget (gui, "cancel_format"); + data->optionlist = (GtkOptionMenu *)glade_xml_get_widget (gui, "option_format"); + data->newtype = NULL; + data->fb = fb; - CORBA_exception_init (&ev); - GNOME_Evolution_Storage_addListener (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); + gtk_label_set_text((GtkLabel *)glade_xml_get_widget (gui, "label_format"), + ((CamelService *)store)->url->protocol); + + gtk_signal_connect((GtkObject *)gd, "clicked", reconfigure_clicked, data); + gtk_object_unref((GtkObject *)gui); + + gnome_dialog_run_and_close (GNOME_DIALOG (gd)); } diff --git a/mail/mail-local.h b/mail/mail-local.h index 808c2cdf18..254fcbe4f6 100644 --- a/mail/mail-local.h +++ b/mail/mail-local.h @@ -35,6 +35,4 @@ void mail_local_storage_startup (EvolutionShellClient *shellclient, void mail_local_reconfigure_folder (FolderBrowser *fb); -CamelFolder *mail_local_lookup_folder (const char *name, - CamelException *ex); #endif diff --git a/mail/mail-threads.c b/mail/mail-threads.c index 4b989bb762..8f0e263765 100644 --- a/mail/mail-threads.c +++ b/mail/mail-threads.c @@ -557,9 +557,14 @@ mail_operations_terminate (void) memset (&clur, 0, sizeof (closure_t)); clur.spec = NULL; - pipe_write (DISPATCH_WRITER, &clur, sizeof (closure_t)); + /* DISPATCH_WRITER will only have been initialized if any + * calls have been made using the old thread system. + */ + if (DISPATCH_WRITER != -1) { + pipe_write (DISPATCH_WRITER, &clur, sizeof (closure_t)); - close (DISPATCH_WRITER); + close (DISPATCH_WRITER); + } close (MAIN_READER); } diff --git a/mail/mail-tools.c b/mail/mail-tools.c index 1dc13c5f2e..cb4325ca70 100644 --- a/mail/mail-tools.c +++ b/mail/mail-tools.c @@ -106,14 +106,6 @@ mail_tool_get_folder_from_urlname (const gchar *url, const gchar *name, return NULL; } - /*camel_service_connect (CAMEL_SERVICE (store), ex); - *if (camel_exception_is_set (ex)) { - * camel_object_unref (CAMEL_OBJECT (store)); - * mail_tool_camel_lock_down(); - * return NULL; - *} - */ - folder = camel_store_get_folder (store, name, flags, ex); camel_object_unref (CAMEL_OBJECT (store)); mail_tool_camel_lock_down(); @@ -161,8 +153,22 @@ mail_tool_get_local_inbox (CamelException *ex) CamelFolder * mail_tool_get_inbox (const gchar *url, CamelException *ex) { - /* FIXME: should be smarter? get_default_folder, etc */ - return mail_tool_get_folder_from_urlname (url, "inbox", 0, ex); + CamelStore *store; + CamelFolder *folder; + + mail_tool_camel_lock_up(); + + store = camel_session_get_store (session, url, ex); + if (!store) { + mail_tool_camel_lock_down(); + return NULL; + } + + folder = camel_store_get_inbox (store, ex); + camel_object_unref (CAMEL_OBJECT (store)); + mail_tool_camel_lock_down(); + + return folder; } @@ -295,35 +301,6 @@ mail_tool_filter_get_folder_func (CamelFilterDriver *d, const char *uri, void *d return mail_tool_uri_to_folder_noex (uri); } -CamelFolder * -mail_tool_get_root_of_store (const char *source_uri, CamelException *ex) -{ - CamelStore *store; - CamelFolder *folder; - - mail_tool_camel_lock_up(); - - store = camel_session_get_store (session, source_uri, ex); - if (!store) { - mail_tool_camel_lock_down (); - return NULL; - } - - /*camel_service_connect (CAMEL_SERVICE (store), ex); - *if (camel_exception_is_set (ex)) { - * camel_object_unref (CAMEL_OBJECT (store)); - * mail_tool_camel_lock_down(); - * return NULL; - *} - */ - - folder = camel_store_get_root_folder (store, ex); - camel_object_unref (CAMEL_OBJECT (store)); - mail_tool_camel_lock_down(); - - return folder; -} - CamelFolder * mail_tool_uri_to_folder (const char *uri, CamelException *ex) { diff --git a/mail/mail-tools.h b/mail/mail-tools.h index 4601b71dc1..87fd6a5f79 100644 --- a/mail/mail-tools.h +++ b/mail/mail-tools.h @@ -75,10 +75,6 @@ mail_tool_generate_forward_subject (CamelMimeMessage *msg); CamelMimePart * mail_tool_make_message_attachment (CamelMimeMessage *message); -/* Get the root folder of the store specified by @source_uri */ -CamelFolder * -mail_tool_get_root_of_store (const char *source_uri, CamelException *ex); - /* Parse the ui into a real CamelFolder any way we know how. */ CamelFolder * mail_tool_uri_to_folder (const char *uri, CamelException *ex); diff --git a/mail/message-list.c b/mail/message-list.c index f4cefc8788..1344fd381c 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -774,8 +774,8 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data) MessageList *message_list = model_data; char *uid; static char *saved; - CamelMessageInfo *info; - static CamelMessageInfo *msg_info; + CamelMessageInfo *msg_info; + void *value; /* simlated(tm) static dynamic memory (sigh) */ if (saved) { @@ -795,23 +795,8 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data) } uid = id_uid(uid); - /* we need ot keep the msg_info ref'd as we return the data, sigh. - - Well, since we have it around, also check to see if its the same - one each call, and save the folder lookup */ - if (msg_info == NULL || strcmp(camel_message_info_uid(msg_info), uid) != 0) { - /* FIXME: what if the folder changes? Nothing sets the folder - yet, but this probably means we need to cache this inside the ml itself */ - if (msg_info) - camel_folder_free_message_info(message_list->folder, msg_info); + msg_info = camel_folder_get_message_info (message_list->folder, uid); - msg_info = camel_folder_get_message_info (message_list->folder, uid); - if (msg_info == NULL) { - g_warning("UID for message-list not found in folder: %s", uid); - return NULL; - } - } - switch (col){ case COL_MESSAGE_STATUS: { ETreePath *child; @@ -826,15 +811,17 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data) } if (msg_info->flags & CAMEL_MESSAGE_ANSWERED) - return GINT_TO_POINTER (2); + value = GINT_TO_POINTER (2); else if (msg_info->flags & CAMEL_MESSAGE_SEEN) - return GINT_TO_POINTER (1); + value = GINT_TO_POINTER (1); else - return GINT_TO_POINTER (0); + value = GINT_TO_POINTER (0); + break; } case COL_FLAGGED: - return (void *)((msg_info->flags & CAMEL_MESSAGE_FLAGGED) != 0); + value = GINT_TO_POINTER ((msg_info->flags & CAMEL_MESSAGE_FLAGGED) != 0); + break; case COL_SCORE: { @@ -845,32 +832,44 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data) if (tag) score = atoi (tag); - return GINT_TO_POINTER (score); + value = GINT_TO_POINTER (score); + break; } case COL_ATTACHMENT: - return (void *)((msg_info->flags & CAMEL_MESSAGE_ATTACHMENTS) != 0); - + value = GINT_TO_POINTER ((msg_info->flags & CAMEL_MESSAGE_ATTACHMENTS) != 0); + break; + case COL_FROM: - return (char *)camel_message_info_from(msg_info); + saved = g_strdup (camel_message_info_from(msg_info)); + value = saved; + break; case COL_SUBJECT: - return (char *)camel_message_info_subject(msg_info); + saved = g_strdup (camel_message_info_subject(msg_info)); + value = saved; + break; case COL_SENT: - return GINT_TO_POINTER (msg_info->date_sent); + value = GINT_TO_POINTER (msg_info->date_sent); + break; case COL_RECEIVED: - return GINT_TO_POINTER (msg_info->date_received); + value = GINT_TO_POINTER (msg_info->date_received); + break; case COL_TO: - return (char *)camel_message_info_to(msg_info); + saved = g_strdup (camel_message_info_to(msg_info)); + value = saved; + break; case COL_SIZE: - return GINT_TO_POINTER (msg_info->size); + value = GINT_TO_POINTER (msg_info->size); + break; case COL_DELETED: - return (void *)((msg_info->flags & CAMEL_MESSAGE_DELETED) != 0); + value = GINT_TO_POINTER ((msg_info->flags & CAMEL_MESSAGE_DELETED) != 0); + break; case COL_UNREAD: { ETreePath *child; @@ -881,7 +880,8 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data) return (void *)subtree_unread(message_list, child); } - return GINT_TO_POINTER (!(msg_info->flags & CAMEL_MESSAGE_SEEN)); + value = GINT_TO_POINTER (!(msg_info->flags & CAMEL_MESSAGE_SEEN)); + break; } case COL_COLOUR: { @@ -889,16 +889,21 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data) colour = camel_tag_get ((CamelTag **) &msg_info->user_tags, "colour"); - if (colour) - return (void *)colour; - else if (msg_info->flags & CAMEL_MESSAGE_FLAGGED) + if (colour) { + saved = g_strdup (colour); + value = saved; + } else if (msg_info->flags & CAMEL_MESSAGE_FLAGGED) /* FIXME: extract from the xpm somehow. */ - return "#A7453E"; + value = "#A7453E"; else - return NULL; + value = NULL; + break; } } + camel_folder_free_message_info(message_list->folder, msg_info); + return value; + g_assert_not_reached (); fake: @@ -940,10 +945,10 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data) if ( (child = e_tree_model_node_get_first_child(etm, path)) && (uid = e_tree_model_node_get_data (etm, child)) && id_is_uid(uid) - && (info = camel_folder_get_message_info (message_list->folder, id_uid(uid))) ) { + && (msg_info = camel_folder_get_message_info (message_list->folder, id_uid(uid))) ) { /* well, we could scan more children, build up a (more accurate) list, but this should do ok */ - saved = g_strdup_printf(_("%s, et al."), camel_message_info_from(info)); - camel_folder_free_message_info(message_list->folder, info); + saved = g_strdup_printf(_("%s, et al."), camel_message_info_from(msg_info)); + camel_folder_free_message_info(message_list->folder, msg_info); } else { return _(""); } @@ -956,10 +961,10 @@ ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data) if ( (child = e_tree_model_node_get_first_child(etm, path)) && (uid = e_tree_model_node_get_data (etm, child)) && id_is_uid(uid) - && (info = camel_folder_get_message_info (message_list->folder, id_uid(uid))) ) { + && (msg_info = camel_folder_get_message_info (message_list->folder, id_uid(uid))) ) { /* well, we could scan more children, build up a (more accurate) list, but this should do ok */ - saved = g_strdup_printf(_("%s, et al."), camel_message_info_to(info)); - camel_folder_free_message_info(message_list->folder, info); + saved = g_strdup_printf(_("%s, et al."), camel_message_info_to(msg_info)); + camel_folder_free_message_info(message_list->folder, msg_info); } else { return _(""); } -- cgit v1.2.3