diff options
author | Dan Winship <danw@src.gnome.org> | 2001-02-10 00:45:09 +0800 |
---|---|---|
committer | Dan Winship <danw@src.gnome.org> | 2001-02-10 00:45:09 +0800 |
commit | fa2c19fdd1aee26d8bf5b622a3adf970004c3abf (patch) | |
tree | ffd18597510f602e430c08224748ab44761888ba /mail/mail-local.c | |
parent | ec981301f5489626ffbf9474db49f1fda4e41a99 (diff) | |
download | gsoc2013-evolution-fa2c19fdd1aee26d8bf5b622a3adf970004c3abf.tar gsoc2013-evolution-fa2c19fdd1aee26d8bf5b622a3adf970004c3abf.tar.gz gsoc2013-evolution-fa2c19fdd1aee26d8bf5b622a3adf970004c3abf.tar.bz2 gsoc2013-evolution-fa2c19fdd1aee26d8bf5b622a3adf970004c3abf.tar.lz gsoc2013-evolution-fa2c19fdd1aee26d8bf5b622a3adf970004c3abf.tar.xz gsoc2013-evolution-fa2c19fdd1aee26d8bf5b622a3adf970004c3abf.tar.zst gsoc2013-evolution-fa2c19fdd1aee26d8bf5b622a3adf970004c3abf.zip |
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
Diffstat (limited to 'mail/mail-local.c')
-rw-r--r-- | mail/mail-local.c | 774 |
1 files changed, 340 insertions, 434 deletions
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,315 +162,6 @@ save_metainfo(struct _local_meta *meta) } -/* 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 - -*/ - -static void -update_progress(char *fmt, float percent) -{ - if (fmt) - mail_status(fmt); - /*mail_op_set_percentage (percent);*/ -} - -/* ******************** */ - -typedef struct reconfigure_folder_input_s { - FolderBrowser *fb; - gchar *newtype; - GtkWidget *frame; - GtkWidget *apply; - GtkWidget *cancel; - GtkOptionMenu *optionlist; -} reconfigure_folder_input_t; - -static gchar * -describe_reconfigure_folder (gpointer in_data, gboolean gerund) -{ - reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; - - 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 -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)); -} - -static void -do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) -{ - reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; - - 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; - - d(printf("reconfiguring folder: %s to type %s\n", input->fb->uri, input->newtype)); - - mail_status_start(_("Reconfiguring folder")); - - /* 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; - } - - metapath = g_strdup_printf("%s/local-metadata.xml", url->path); - meta = load_metainfo(metapath); - g_free(metapath); - - /* first, 'close' the old folder */ - if (input->fb->folder != NULL) { - update_progress(_("Closing current folder"), 0.0); - - camel_folder_sync(input->fb->folder, FALSE, ex); - camel_object_unref (CAMEL_OBJECT (input->fb->folder)); - input->fb->folder = NULL; - } - - 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); - - d(printf("opening stores %s and %s\n", fromurl, tourl)); - - fromstore = camel_session_get_store(session, fromurl, ex); - - if (camel_exception_is_set(ex)) - goto cleanup; - - tostore = camel_session_get_store(session, tourl, ex); - if (camel_exception_is_set(ex)) - goto cleanup; - - /* 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); - - 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; - 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; - } - - update_progress(_("Copying messages"), 0.0); - uids = camel_folder_get_uids(fromfolder); - for (i=0;i<uids->len;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); - - d(printf("delete old mbox ...\n")); - camel_store_delete_folder(fromstore, tmpname, ex); - - /* 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); - } - 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) -{ - 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(); - - gtk_object_unref (GTK_OBJECT (input->fb)); - g_free (input->newtype); -} - -static const mail_operation_spec op_reconfigure_folder = -{ - describe_reconfigure_folder, - 0, - setup_reconfigure_folder, - do_reconfigure_folder, - cleanup_reconfigure_folder -}; - -static void -reconfigure_clicked(GnomeDialog *d, int button, reconfigure_folder_input_t *data) -{ - if (button == 0) { - GtkMenu *menu; - int type; - char *types[] = { "mbox", "maildir", "mh" }; - - 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; - - gtk_widget_set_sensitive(data->frame, FALSE); - gtk_widget_set_sensitive(data->apply, FALSE); - gtk_widget_set_sensitive(data->cancel, FALSE); - - data->newtype = g_strdup (types[type]); - mail_operation_queue (&op_reconfigure_folder, data, TRUE); - } - - if (button != -1) - gnome_dialog_close(d); -} - -void -mail_local_reconfigure_folder(FolderBrowser *fb) -{ - CamelStore *store; - GladeXML *gui; - GnomeDialog *gd; - reconfigure_folder_input_t *data; - - if (fb->folder == NULL) { - g_warning("Trying to reconfigure nonexistant folder"); - return; - } - - data = g_new (reconfigure_folder_input_t, 1); - - store = camel_folder_get_parent_store(fb->folder); - - gui = glade_xml_new(EVOLUTION_GLADEDIR "/local-config.glade", "dialog_format"); - gd = (GnomeDialog *)glade_xml_get_widget (gui, "dialog_format"); - - 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; - - 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)); -} - - - /* 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)) @@ -496,20 +187,20 @@ typedef struct { typedef struct { CamelFolder *folder; MailLocalStore *local_store; - char *path, *name; + char *path, *name, *uri; int last_unread; } MailLocalFolder; -static void local_folder_changed_proxy (CamelObject *folder, gpointer event_data, gpointer user_data); +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 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; @@ -524,11 +215,13 @@ mail_local_store_class_init (MailLocalStoreClass *mail_local_store_class) /* virtual method overload */ camel_service_class->get_name = get_name; + /* Don't cache folders */ + camel_store_class->hash_folder_name = NULL; + camel_store_class->compare_folder_name = NULL; + 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 ()); } @@ -555,6 +248,7 @@ free_local_folder(MailLocalFolder *lf) } g_free(lf->path); g_free(lf->name); + g_free(lf->uri); camel_object_unref((CamelObject *)lf->local_store); } @@ -608,88 +302,6 @@ mail_local_store_get_type (void) return mail_local_store_type; } -/* 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. - - 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) -{ - 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 (folder) - camel_object_ref((CamelObject *)folder); - - return folder; -} - static CamelFolder * get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) @@ -723,13 +335,6 @@ rename_folder (CamelStore *store, const char *old, const char *new, } 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"); @@ -800,16 +405,16 @@ static void do_register_folder (gpointer in_data, gpointer op_data, CamelException *ex) { MailLocalFolder *local_folder = in_data; - char *name; + char *name, *path = local_folder->uri + 7; struct _local_meta *meta; CamelStore *store; guint32 flags; - name = g_strdup_printf ("/%s/local-metadata.xml", local_folder->name); + name = g_strdup_printf ("%s/local-metadata.xml", path); meta = load_metainfo (name); g_free (name); - name = g_strdup_printf ("%s:/%s", meta->format, local_folder->name); + name = g_strdup_printf ("%s:%s", meta->format, path); store = camel_session_get_store (session, name, ex); g_free (name); if (!store) { @@ -821,7 +426,16 @@ do_register_folder (gpointer in_data, gpointer op_data, CamelException *ex) 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); + 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); + } + camel_object_unref (CAMEL_OBJECT (store)); free_metainfo (meta); } @@ -837,15 +451,8 @@ cleanup_register_folder (gpointer in_data, gpointer op_data, CamelException *ex) return; } - g_hash_table_insert (local_folder->local_store->folders, local_folder->name, local_folder); - local_folder->name = strrchr (local_folder->path, '/') + 1; + g_hash_table_insert (local_folder->local_store->folders, local_folder->uri + 8, local_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); unread = local_folder->last_unread; local_folder->last_unread = 0; local_folder_changed (CAMEL_OBJECT (local_folder->folder), GINT_TO_POINTER (unread), local_folder); @@ -876,8 +483,9 @@ local_storage_new_folder_cb (EvolutionStorageListener *storage_listener, return; local_folder = g_new0 (MailLocalFolder, 1); - local_folder->name = g_strdup (folder->physical_uri + 8); + 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); @@ -921,9 +529,7 @@ local_storage_removed_folder_cb (EvolutionStorageListener *storage_listener, local_store->local_pathlen) != 0) return; - path += 7 + local_store->local_pathlen; - - local_folder = g_hash_table_lookup (local_store->folders, path); + 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); @@ -949,24 +555,10 @@ non_equal (gconstpointer a, gconstpointer b) return TRUE; } -CamelFolder * -mail_local_lookup_folder (const char *name, - CamelException *ev) -{ - MailLocalStore *local_store; - - local_store = (MailLocalStore *)camel_session_get_service (session, - "file:/", - CAMEL_PROVIDER_STORE, NULL); - - return get_folder (CAMEL_STORE(local_store), name, 0, ev); -} - void mail_local_storage_startup (EvolutionShellClient *shellclient, const char *evolution_path) { - MailLocalStore *local_store; GNOME_Evolution_StorageListener corba_local_storage_listener; CORBA_Environment ev; @@ -1029,3 +621,317 @@ mail_local_storage_startup (EvolutionShellClient *shellclient, } CORBA_exception_free (&ev); } + + +/* 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 + +*/ + +static void +update_progress(char *fmt, float percent) +{ + if (fmt) + mail_status(fmt); + /*mail_op_set_percentage (percent);*/ +} + +/* ******************** */ + +typedef struct reconfigure_folder_input_s { + FolderBrowser *fb; + gchar *newtype; + GtkWidget *frame; + GtkWidget *apply; + GtkWidget *cancel; + GtkOptionMenu *optionlist; +} reconfigure_folder_input_t; + +static gchar * +describe_reconfigure_folder (gpointer in_data, gboolean gerund) +{ + reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; + + 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 +setup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex) +{ + reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; + + gtk_object_ref (GTK_OBJECT (input->fb)); +} + +static void +do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) +{ + 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; + + d(printf("reconfiguring folder: %s to type %s\n", input->fb->uri, input->newtype)); + + mail_status_start(_("Reconfiguring folder")); + + /* 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; + } + + 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; + } + + metapath = g_strdup_printf("%s/local-metadata.xml", url->path); + meta = load_metainfo(metapath); + g_free(metapath); + + /* 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; + + 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); + + d(printf("opening stores %s and %s\n", fromurl, tourl)); + + fromstore = camel_session_get_store(session, fromurl, ex); + + if (camel_exception_is_set(ex)) + goto cleanup; + + tostore = camel_session_get_store(session, tourl, ex); + if (camel_exception_is_set(ex)) + goto cleanup; + + /* 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); + + 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; + 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; + } + + update_progress(_("Copying messages"), 0.0); + uids = camel_folder_get_uids(fromfolder); + for (i=0;i<uids->len;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); + + d(printf("delete old mbox ...\n")); + camel_store_delete_folder(fromstore, tmpname, ex); + + /* 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); + } + + 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 +cleanup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex) +{ + reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; + char *uri; + + 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.")); + } + + /* 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(); + + gtk_object_unref (GTK_OBJECT (input->fb)); + g_free (input->newtype); +} + +static const mail_operation_spec op_reconfigure_folder = +{ + describe_reconfigure_folder, + 0, + setup_reconfigure_folder, + do_reconfigure_folder, + cleanup_reconfigure_folder +}; + +static void +reconfigure_clicked(GnomeDialog *d, int button, reconfigure_folder_input_t *data) +{ + if (button == 0) { + GtkMenu *menu; + int type; + char *types[] = { "mbox", "maildir", "mh" }; + + 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; + + gtk_widget_set_sensitive(data->frame, FALSE); + gtk_widget_set_sensitive(data->apply, FALSE); + gtk_widget_set_sensitive(data->cancel, FALSE); + + data->newtype = g_strdup (types[type]); + mail_operation_queue (&op_reconfigure_folder, data, TRUE); + } else + g_free (data); + + if (button != -1) + gnome_dialog_close(d); +} + +void +mail_local_reconfigure_folder(FolderBrowser *fb) +{ + CamelStore *store; + GladeXML *gui; + GnomeDialog *gd; + reconfigure_folder_input_t *data; + + if (fb->folder == NULL) { + g_warning("Trying to reconfigure nonexistant folder"); + return; + } + + data = g_new (reconfigure_folder_input_t, 1); + + store = camel_folder_get_parent_store(fb->folder); + + gui = glade_xml_new(EVOLUTION_GLADEDIR "/local-config.glade", "dialog_format"); + gd = (GnomeDialog *)glade_xml_get_widget (gui, "dialog_format"); + + 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; + + 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)); +} |