diff options
Diffstat (limited to 'mail')
-rw-r--r-- | mail/ChangeLog | 29 | ||||
-rw-r--r-- | mail/Makefile.am | 2 | ||||
-rw-r--r-- | mail/em-folder-browser.c | 125 | ||||
-rw-r--r-- | mail/em-folder-selector.c | 32 | ||||
-rw-r--r-- | mail/em-folder-tree.c | 800 | ||||
-rw-r--r-- | mail/em-folder-tree.h | 3 | ||||
-rw-r--r-- | mail/em-folder-utils.c | 744 | ||||
-rw-r--r-- | mail/em-folder-utils.h | 32 | ||||
-rw-r--r-- | mail/em-folder-view.c | 117 | ||||
-rw-r--r-- | mail/mail-component.c | 27 |
10 files changed, 1093 insertions, 818 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog index e477b2797e..b247d8cdde 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,32 @@ +2005-05-13 Rodney Dawes <dobey@novell.com> + + * Makefile.am: Add new em-folder-utils.[ch] abstraction + + * em-folder-browser.c: Update for new menu layout + Add new methods to handle the actions that were previously only + available from the context menu when right-clicking on a folder + + * em-folder-selector.c (emfs_response): Just call emfu_folder_create + if the user wants to create a new folder in the selector dialog + (em_folder_selector_get_selected_path): Clean up the code to fix a + couple potential crashes + + * em-folder-tree.[ch]: Add methods to get pointers to a CamelFolder or + CamelFolderInfo object for the selected item in the tree + Add a method to get a pointer to an EMFolderTreeModelStoreInfo object + for the selected store in the tree + Move folder operations out into em-folder-utils.[ch] so that they + are abstracted from the tree and can be used by methods other than + the internal context menu + + * em-folder-utils.[ch]: Move the folder operations code to here + + * em-folder-view.c: Update for the new menu layout + Fix Mark as Read/Unread in the context menu to only show up in the list + + * mail-component.c (create_item): Just call emfu_folder_create here + when the user requests to create a new folder from the New toolbar item + 2005-05-13 Shreyas Srinivasan <sshreyas@novell.com> * Fixes bug #273868, #300113, #302831. diff --git a/mail/Makefile.am b/mail/Makefile.am index 567e2256b9..b32973ad58 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -93,6 +93,8 @@ libevolution_mail_la_SOURCES = \ em-folder-tree-model.h \ em-folder-tree.c \ em-folder-tree.h \ + em-folder-utils.c \ + em-folder-utils.h \ em-folder-view.c \ em-folder-view.h \ em-format-hook.c \ diff --git a/mail/em-folder-browser.c b/mail/em-folder-browser.c index 582546facb..257ac8ad38 100644 --- a/mail/em-folder-browser.c +++ b/mail/em-folder-browser.c @@ -73,6 +73,7 @@ #include "em-format-html-print.h" #include "em-folder-browser.h" #include "em-folder-properties.h" +#include "em-folder-utils.h" #include "em-subscribe-editor.h" #include "em-menu.h" #include "message-list.h" @@ -569,6 +570,91 @@ emfb_folder_properties(BonoboUIComponent *uid, void *data, const char *path) } static void +emfb_folder_copy(BonoboUIComponent *uid, void *data, const char *path) +{ + EMFolderBrowser *emfb = data; + CamelFolderInfo *fi = NULL; + CamelException ex; + + camel_exception_init (&ex); + + if ((fi = camel_store_get_folder_info (emfb->view.folder->parent_store, + emfb->view.folder->full_name, + CAMEL_STORE_FOLDER_INFO_FAST, + &ex)) != NULL) + emfu_copy_folder (fi); + + camel_exception_clear (&ex); + + return; +} + +static void +emfb_folder_move(BonoboUIComponent *uid, void *data, const char *path) +{ + EMFolderBrowser *emfb = data; + CamelFolderInfo *fi = NULL; + CamelException ex; + + camel_exception_init (&ex); + + if ((fi = camel_store_get_folder_info (emfb->view.folder->parent_store, + emfb->view.folder->full_name, + CAMEL_STORE_FOLDER_INFO_FAST, + &ex)) != NULL) + emfu_move_folder (fi); + + camel_exception_clear (&ex); + + return; +} + +static void +emfb_folder_delete(BonoboUIComponent *uid, void *data, const char *path) +{ + EMFolderBrowser *emfb = data; + + emfu_delete_folder (emfb->view.folder); + + return; +} + +static void +emfb_folder_rename(BonoboUIComponent *uid, void *data, const char *path) +{ + EMFolderBrowser *emfb = data; + + emfu_rename_folder (emfb->view.folder); + + return; +} + +static void +emfb_folder_create(BonoboUIComponent *uid, void *data, const char *path) +{ + EMFolderBrowser *emfb = data; + CamelFolderInfo *fi = NULL; + CamelException ex; + + camel_exception_init (&ex); + + if (emfb->view.folder) { + if ((fi = camel_store_get_folder_info (emfb->view.folder->parent_store, + emfb->view.folder->full_name, + CAMEL_STORE_FOLDER_INFO_FAST, + &ex)) != NULL) + emfu_folder_create (fi); + } else { + emfu_folder_create (NULL); + } + + + camel_exception_clear (&ex); + + return; +} + +static void emfb_folder_expunge(BonoboUIComponent *uid, void *data, const char *path) { EMFolderBrowser *emfb = data; @@ -628,25 +714,6 @@ emfb_view_show_all(BonoboUIComponent *uid, void *data, const char *path) /* ********************************************************************** */ static void -emfb_empty_trash(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - em_utils_empty_trash (gtk_widget_get_toplevel ((GtkWidget *) emfv)); -} - -static void -emfb_mail_compose(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - if (!em_utils_check_user_can_send_mail((GtkWidget *)emfv)) - return; - - em_utils_compose_new_message(emfv->folder_uri); -} - -static void emfb_mail_stop(BonoboUIComponent *uid, void *data, const char *path) { mail_cancel_all(); @@ -712,8 +779,12 @@ static BonoboUIVerb emfb_verbs[] = { BONOBO_UI_UNSAFE_VERB ("ViewShowAll", emfb_view_show_all), /* ViewThreaded is a toggle */ - BONOBO_UI_UNSAFE_VERB ("EmptyTrash", emfb_empty_trash), - BONOBO_UI_UNSAFE_VERB ("MailCompose", emfb_mail_compose), + BONOBO_UI_UNSAFE_VERB ("FolderCopy", emfb_folder_copy), + BONOBO_UI_UNSAFE_VERB ("FolderMove", emfb_folder_move), + BONOBO_UI_UNSAFE_VERB ("FolderDelete", emfb_folder_delete), + BONOBO_UI_UNSAFE_VERB ("FolderRename", emfb_folder_rename), + BONOBO_UI_UNSAFE_VERB ("FolderCreate", emfb_folder_create), + BONOBO_UI_UNSAFE_VERB ("MailPost", emfb_mail_post), BONOBO_UI_UNSAFE_VERB ("MailStop", emfb_mail_stop), BONOBO_UI_UNSAFE_VERB ("ToolsFilters", emfb_tools_filters), @@ -726,11 +797,8 @@ static BonoboUIVerb emfb_verbs[] = { static EPixmap emfb_pixmaps[] = { E_PIXMAP ("/commands/ChangeFolderProperties", "stock_folder-properties", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ViewHideRead", "stock_mail-hide-read", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ViewHideSelected", "stock_mail-hide-selected", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ViewShowAll", "stock_show-all", E_ICON_SIZE_MENU), - - E_PIXMAP ("/commands/MailCompose", "stock_mail-compose", E_ICON_SIZE_MENU), + E_PIXMAP ("/commands/FolderCopy", "stock_folder-copy", E_ICON_SIZE_MENU), + E_PIXMAP ("/commands/FolderMove", "stock_folder-move", E_ICON_SIZE_MENU), E_PIXMAP_END }; @@ -740,10 +808,13 @@ static const EMFolderViewEnable emfb_enable_map[] = { { "EditSelectAll", EM_POPUP_SELECT_FOLDER }, { "EditSelectThread", EM_FOLDER_VIEW_SELECT_THREADED }, { "FolderExpunge", EM_POPUP_SELECT_FOLDER }, + { "FolderCopy", EM_POPUP_SELECT_FOLDER }, + { "FolderMove", EM_POPUP_SELECT_FOLDER }, + { "FolderDelete", EM_POPUP_SELECT_FOLDER }, + { "FolderRename", EM_POPUP_SELECT_FOLDER }, { "MailPost", EM_POPUP_SELECT_FOLDER }, { "MessageMarkAllAsRead", EM_POPUP_SELECT_FOLDER }, { "ViewHideSelected", EM_POPUP_SELECT_MANY }, - { "ViewShowAll", EM_FOLDER_VIEW_SELECT_HIDDEN }, { NULL }, }; diff --git a/mail/em-folder-selector.c b/mail/em-folder-selector.c index 69f4662d79..4a88e29ad9 100644 --- a/mail/em-folder-selector.c +++ b/mail/em-folder-selector.c @@ -161,28 +161,7 @@ emfs_response (GtkWidget *dialog, int response, EMFolderSelector *emfs) if (response != EM_FOLDER_SELECTOR_RESPONSE_NEW) return; - model = em_folder_tree_get_model (emfs->emft); - emft = (EMFolderTree *) em_folder_tree_new_with_model (model); - dialog = em_folder_selector_create_new (emft, 0, _("Create New Folder"), _("Specify where to create the folder:")); - gtk_window_set_transient_for ((GtkWindow *) dialog, (GtkWindow *) emfs); - uri = em_folder_selector_get_selected_uri (emfs); - if (uri) - em_folder_tree_set_selected (emft, uri); - - if (gtk_dialog_run ((GtkDialog *) dialog) == GTK_RESPONSE_OK) { - uri = em_folder_selector_get_selected_uri ((EMFolderSelector *) dialog); - path = em_folder_selector_get_selected_path ((EMFolderSelector *) dialog); - - g_free (emfs->created_uri); - emfs->created_uri = g_strdup (uri); - - if (emfs->created_id == 0) - emfs->created_id = g_signal_connect (model, "folder-added", G_CALLBACK (folder_created_cb), emfs); - - em_folder_tree_create_folder (emfs->emft, path, uri); - } - - gtk_widget_destroy (dialog); + emfu_folder_create (NULL); g_signal_stop_emission_by_name (emfs, "response"); } @@ -421,13 +400,10 @@ em_folder_selector_get_selected_path (EMFolderSelector *emfs) char *newpath; name = gtk_entry_get_text (emfs->name_entry); - if (strcmp (path, "") != 0) - newpath = g_strdup_printf ("%s/%s", path?path:"", name); - else - newpath = g_strdup (name); - + newpath = g_strdup_printf ("%s/%s", path?path:"", name); + g_free(path); - emfs->selected_path = newpath; + emfs->selected_path = g_strdup (newpath); } else { g_free(emfs->selected_path); emfs->selected_path = path?path:g_strdup(""); diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c index d0e34e9e83..c584f1f138 100644 --- a/mail/em-folder-tree.c +++ b/mail/em-folder-tree.c @@ -67,6 +67,7 @@ #include "em-popup.h" #include "em-marshal.h" #include "em-folder-tree.h" +#include "em-folder-utils.h" #include "em-folder-selector.h" #include "em-folder-selection.h" #include "em-folder-properties.h" @@ -2003,597 +2004,40 @@ emft_popup_open_new (GtkWidget *item, EMFolderTree *emft) #endif -struct _EMCopyFolders { - struct _mail_msg msg; - - /* input data */ - CamelStore *fromstore; - CamelStore *tostore; - - char *frombase; - char *tobase; - - int delete; -}; - -static char * -emft_copy_folders__desc (struct _mail_msg *mm, int complete) -{ - struct _EMCopyFolders *m = (struct _EMCopyFolders *) mm; - - return g_strdup_printf (_("Copying `%s' to `%s'"), m->frombase, m->tobase); -} - -static void -emft_copy_folders__copy (struct _mail_msg *mm) -{ - struct _EMCopyFolders *m = (struct _EMCopyFolders *) mm; - guint32 flags = CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_RECURSIVE; - GList *pending = NULL, *deleting = NULL, *l; - GString *fromname, *toname; - CamelFolderInfo *fi; - const char *tmp; - int fromlen; - - if (camel_store_supports_subscriptions (m->fromstore)) - flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; - - if (!(fi = camel_store_get_folder_info (m->fromstore, m->frombase, flags, &mm->ex))) - return; - - pending = g_list_append (pending, fi); - - toname = g_string_new (""); - fromname = g_string_new (""); - - tmp = strrchr (m->frombase, '/'); - if (tmp == NULL) - fromlen = 0; - else - fromlen = tmp - m->frombase + 1; - - d(printf ("top name is '%s'\n", fi->full_name)); - - while (pending) { - CamelFolderInfo *info = pending->data; - - pending = g_list_remove_link (pending, pending); - while (info) { - CamelFolder *fromfolder, *tofolder; - GPtrArray *uids; - int deleted = 0; - - if (info->child) - pending = g_list_append (pending, info->child); - - if (m->tobase[0]) - g_string_printf (toname, "%s/%s", m->tobase, info->full_name + fromlen); - else - g_string_printf (toname, "%s", info->full_name + fromlen); - - d(printf ("Copying from '%s' to '%s'\n", info->full_name, toname->str)); - - /* This makes sure we create the same tree, e.g. from a nonselectable source */ - /* Not sure if this is really the 'right thing', e.g. for spool stores, but it makes the ui work */ - if ((info->flags & CAMEL_FOLDER_NOSELECT) == 0) { - d(printf ("this folder is selectable\n")); - if (m->tostore == m->fromstore && m->delete) { - camel_store_rename_folder (m->fromstore, info->full_name, toname->str, &mm->ex); - if (camel_exception_is_set (&mm->ex)) - goto exception; - - /* this folder no longer exists, unsubscribe it */ - if (camel_store_supports_subscriptions (m->fromstore)) - camel_store_unsubscribe_folder (m->fromstore, info->full_name, NULL); - - deleted = 1; - } else { - if (!(fromfolder = camel_store_get_folder (m->fromstore, info->full_name, 0, &mm->ex))) - goto exception; - - if (!(tofolder = camel_store_get_folder (m->tostore, toname->str, CAMEL_STORE_FOLDER_CREATE, &mm->ex))) { - camel_object_unref (fromfolder); - goto exception; - } - - uids = camel_folder_get_uids (fromfolder); - camel_folder_transfer_messages_to (fromfolder, uids, tofolder, NULL, m->delete, &mm->ex); - camel_folder_free_uids (fromfolder, uids); - - if (m->delete) - camel_folder_sync(fromfolder, TRUE, NULL); - - camel_object_unref (fromfolder); - camel_object_unref (tofolder); - } - } - - if (camel_exception_is_set (&mm->ex)) - goto exception; - else if (m->delete && !deleted) - deleting = g_list_prepend (deleting, info); - - /* subscribe to the new folder if appropriate */ - if (camel_store_supports_subscriptions (m->tostore) - && !camel_store_folder_subscribed (m->tostore, toname->str)) - camel_store_subscribe_folder (m->tostore, toname->str, NULL); - - info = info->next; - } - } - - /* delete the folders in reverse order from how we copyied them, if we are deleting any */ - l = deleting; - while (l) { - CamelFolderInfo *info = l->data; - - d(printf ("deleting folder '%s'\n", info->full_name)); - - /* FIXME: we need to do something with the exception - since otherwise the users sees a failed operation - with no error message or even any warnings */ - if (camel_store_supports_subscriptions (m->fromstore)) - camel_store_unsubscribe_folder (m->fromstore, info->full_name, NULL); - - camel_store_delete_folder (m->fromstore, info->full_name, NULL); - l = l->next; - } - - exception: - - camel_store_free_folder_info (m->fromstore, fi); - g_list_free (deleting); - - g_string_free (toname, TRUE); - g_string_free (fromname, TRUE); -} - -static void -emft_copy_folders__free (struct _mail_msg *mm) -{ - struct _EMCopyFolders *m = (struct _EMCopyFolders *) mm; - - camel_object_unref (m->fromstore); - camel_object_unref (m->tostore); - - g_free (m->frombase); - g_free (m->tobase); -} - -static struct _mail_msg_op copy_folders_op = { - emft_copy_folders__desc, - emft_copy_folders__copy, - NULL, - emft_copy_folders__free, -}; - -static void -emft_copy_folders (CamelStore *tostore, const char *tobase, CamelStore *fromstore, const char *frombase, int delete) -{ - struct _EMCopyFolders *m; - - m = mail_msg_new (©_folders_op, NULL, sizeof (struct _EMCopyFolders)); - camel_object_ref (fromstore); - m->fromstore = fromstore; - camel_object_ref (tostore); - m->tostore = tostore; - m->frombase = g_strdup (frombase); - m->tobase = g_strdup (tobase); - m->delete = delete; - - e_thread_put (mail_thread_new, (EMsg *) m); -} - -struct _copy_folder_data { - EMFolderTree *emft; - gboolean delete; -}; - -static void -emft_popup_copy_folder_selected (const char *uri, void *data) -{ - struct _copy_folder_data *cfd = data; - struct _EMFolderTreePrivate *priv; - CamelStore *fromstore = NULL, *tostore = NULL; - char *tobase = NULL, *frombase = NULL, *fromuri = NULL; - CamelException ex; - CamelURL *url; - - if (uri == NULL) { - g_free (cfd); - return; - } - - priv = cfd->emft->priv; - - camel_exception_init (&ex); - - fromuri = em_folder_tree_get_selected_uri(cfd->emft); - g_return_if_fail(fromuri != NULL); - frombase = em_folder_tree_get_selected_path(cfd->emft); - g_return_if_fail(frombase != NULL); - - if (!(fromstore = camel_session_get_store (session, fromuri, &ex))) { - e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *) cfd->emft), - cfd->delete?"mail:no-move-folder-notexist":"mail:no-copy-folder-notexist", frombase, uri, ex.desc, NULL); - goto fail; - } - - if (cfd->delete && fromstore == mail_component_peek_local_store (NULL) && is_special_local_folder (frombase)) { - e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *) cfd->emft), - "mail:no-rename-special-folder", frombase, NULL); - goto fail; - } - - if (!(tostore = camel_session_get_store (session, uri, &ex))) { - e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *) cfd->emft), - cfd->delete?"mail:no-move-folder-to-notexist":"mail:no-copy-folder-to-notexist", frombase, uri, ex.desc, NULL); - goto fail; - } - - url = camel_url_new (uri, NULL); - if (((CamelService *)tostore)->provider->url_flags & CAMEL_URL_FRAGMENT_IS_PATH) - tobase = url->fragment; - else if (url->path && url->path[0]) - tobase = url->path+1; - if (tobase == NULL) - tobase = ""; - - emft_copy_folders (tostore, tobase, fromstore, frombase, cfd->delete); - - camel_url_free (url); -fail: - if (fromstore) - camel_object_unref(fromstore); - if (tostore) - camel_object_unref(tostore); - g_free(frombase); - g_free(fromuri); - camel_exception_clear (&ex); - g_free (cfd); -} - -/* tree here is the 'destination' selector, not 'self' */ -static gboolean -emft_popup_copy_folder_exclude(EMFolderTree *tree, GtkTreeModel *model, GtkTreeIter *iter, void *data) -{ - struct _copy_folder_data *cfd = data; - int fromvfolder, tovfolder; - char *fromuri, *touri; - guint flags; - gboolean is_store; - - /* handles moving to/from vfolders */ - - fromuri = em_folder_tree_get_selected_uri(cfd->emft); - fromvfolder = strncmp(fromuri, "vfolder:", 8) == 0; - gtk_tree_model_get(model, iter, COL_STRING_URI, &touri, COL_UINT_FLAGS, &flags, COL_BOOL_IS_STORE, &is_store, -1); - tovfolder = strncmp(touri, "vfolder:", 8) == 0; - g_free(fromuri); - g_free(touri); - - /* moving from vfolder to normal- not allowed */ - if (fromvfolder && !tovfolder && cfd->delete) - return FALSE; - /* copy/move from normal folder to vfolder - not allowed */ - if (!fromvfolder && tovfolder) - return FALSE; - /* copying to vfolder - not allowed */ - if (tovfolder && !cfd->delete) - return FALSE; - - return (flags & EMFT_EXCLUDE_NOINFERIORS) == 0; -} - static void emft_popup_copy(EPopup *ep, EPopupItem *item, void *data) { EMFolderTree *emft = data; - struct _copy_folder_data *cfd; - - cfd = g_malloc (sizeof (*cfd)); - cfd->emft = emft; - cfd->delete = FALSE; - - em_select_folder (NULL, _("Select folder"), _("C_opy"), - NULL, emft_popup_copy_folder_exclude, emft_popup_copy_folder_selected, cfd); -} + CamelFolderInfo *fi = NULL; -static void -emft_popup_move(EPopup *ep, EPopupItem *item, void *data) -{ - EMFolderTree *emft = data; - struct _copy_folder_data *cfd; - - cfd = g_malloc (sizeof (*cfd)); - cfd->emft = emft; - cfd->delete = TRUE; - - em_select_folder (NULL, _("Select folder"), _("_Move"), - NULL, emft_popup_copy_folder_exclude, emft_popup_copy_folder_selected, cfd); -} - - -struct _EMCreateFolder { - struct _mail_msg msg; - - /* input data */ - CamelStore *store; - char *full_name; - char *parent; - char *name; - - /* output data */ - CamelFolderInfo *fi; - - /* callback data */ - void (* done) (CamelFolderInfo *fi, void *user_data); - void *user_data; -}; - -static char * -emft_create_folder__desc (struct _mail_msg *mm, int done) -{ - struct _EMCreateFolder *m = (struct _EMCreateFolder *) mm; - - return g_strdup_printf (_("Creating folder `%s'"), m->full_name); -} - -static void -emft_create_folder__create (struct _mail_msg *mm) -{ - struct _EMCreateFolder *m = (struct _EMCreateFolder *) mm; - - d(printf ("creating folder parent='%s' name='%s' full_name='%s'\n", m->parent, m->name, m->full_name)); - - if ((m->fi = camel_store_create_folder (m->store, m->parent, m->name, &mm->ex))) { - if (camel_store_supports_subscriptions (m->store)) - camel_store_subscribe_folder (m->store, m->full_name, &mm->ex); + if ((fi = em_folder_tree_get_selected_folder_info (emft)) != NULL) { + emfu_copy_folder (fi); } } static void -emft_create_folder__created (struct _mail_msg *mm) -{ - struct _EMCreateFolder *m = (struct _EMCreateFolder *) mm; - - if (m->done) - m->done (m->fi, m->user_data); -} - -static void -emft_create_folder__free (struct _mail_msg *mm) -{ - struct _EMCreateFolder *m = (struct _EMCreateFolder *) mm; - - camel_store_free_folder_info (m->store, m->fi); - camel_object_unref (m->store); - g_free (m->full_name); - g_free (m->parent); - g_free (m->name); -} - -static struct _mail_msg_op create_folder_op = { - emft_create_folder__desc, - emft_create_folder__create, - emft_create_folder__created, - emft_create_folder__free, -}; - - -static int -emft_create_folder (CamelStore *store, const char *full_name, void (* done) (CamelFolderInfo *fi, void *user_data), void *user_data) -{ - char *name, *namebuf = NULL; - struct _EMCreateFolder *m; - const char *parent; - int id; - - namebuf = g_strdup (full_name); - if (!(name = strrchr (namebuf, '/'))) { - name = namebuf; - parent = ""; - } else { - *name++ = '\0'; - parent = namebuf; - } - - m = mail_msg_new (&create_folder_op, NULL, sizeof (struct _EMCreateFolder)); - camel_object_ref (store); - m->store = store; - m->full_name = g_strdup (full_name); - m->parent = g_strdup (parent); - m->name = g_strdup (name); - m->user_data = user_data; - m->done = done; - - g_free (namebuf); - - id = m->msg.seq; - e_thread_put (mail_thread_new, (EMsg *) m); - - return id; -} - -static void -created_cb (CamelFolderInfo *fi, void *user_data) -{ - gboolean *created = user_data; - - *created = fi ? TRUE : FALSE; -} - -gboolean -em_folder_tree_create_folder (EMFolderTree *emft, const char *full_name, const char *uri) -{ - struct _EMFolderTreePrivate *priv = emft->priv; - struct _EMFolderTreeModelStoreInfo *si; - gboolean created = FALSE; - CamelStore *store; - CamelException ex; - - d(printf ("Creating folder: %s (%s)\n", full_name, uri)); - - camel_exception_init (&ex); - if (!(store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex))) { - e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)emft), - "mail:no-create-folder-nostore", full_name, ex.desc, NULL); - goto fail; - } - - if (!(si = g_hash_table_lookup (priv->model->store_hash, store))) { - abort(); - camel_object_unref (store); - goto fail; - } - - camel_object_unref (store); - - mail_msg_wait (emft_create_folder (si->store, full_name, created_cb, &created)); -fail: - camel_exception_clear(&ex); - - return created; -} - -static void -new_folder_created_cb (CamelFolderInfo *fi, void *user_data) -{ - EMFolderSelector *emfs = user_data; - - if (fi) - gtk_widget_destroy ((GtkWidget *) emfs); - - g_object_unref (emfs); -} - -static void -emft_popup_new_folder_response (EMFolderSelector *emfs, int response, EMFolderTree *emft) +emft_popup_move(EPopup *ep, EPopupItem *item, void *data) { - struct _EMFolderTreePrivate *priv = emft->priv; - struct _EMFolderTreeModelStoreInfo *si; - const char *uri, *path; - CamelException ex; - CamelStore *store; - - if (response != GTK_RESPONSE_OK) { - gtk_widget_destroy ((GtkWidget *) emfs); - return; - } - - uri = em_folder_selector_get_selected_uri (emfs); - path = em_folder_selector_get_selected_path (emfs); - - d(printf ("Creating new folder: %s (%s)\n", path, uri)); - - camel_exception_init (&ex); - if (!(store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex))) { - camel_exception_clear (&ex); - return; - } - - if (!(si = g_hash_table_lookup (priv->model->store_hash, store))) { - g_assert_not_reached (); - camel_object_unref (store); - return; - } - - /* HACK: we need to create vfolders using the vfolder editor */ - if (CAMEL_IS_VEE_STORE(store)) { - EMVFolderRule *rule; + EMFolderTree *emft = data; + CamelFolderInfo *fi = NULL; - rule = em_vfolder_rule_new(); - filter_rule_set_name((FilterRule *)rule, path); - vfolder_gui_add_rule(rule); - gtk_widget_destroy((GtkWidget *)emfs); - } else { - g_object_ref (emfs); - emft_create_folder (si->store, path, new_folder_created_cb, emfs); + if ((fi = em_folder_tree_get_selected_folder_info (emft)) != NULL) { + emfu_copy_folder (fi); } - - camel_object_unref (store); } static void emft_popup_new_folder (EPopup *ep, EPopupItem *pitem, void *data) { EMFolderTree *emft = data; + CamelFolderInfo *fi; - EMFolderTree *folder_tree; - GtkWidget *dialog; - char *uri; - - folder_tree = (EMFolderTree *) em_folder_tree_new_with_model (emft->priv->model); - - dialog = em_folder_selector_create_new (folder_tree, 0, _("Create folder"), _("Specify where to create the folder:")); - uri = em_folder_tree_get_selected_uri(emft); - em_folder_selector_set_selected ((EMFolderSelector *) dialog, uri); - g_free(uri); - g_signal_connect (dialog, "response", G_CALLBACK (emft_popup_new_folder_response), emft); - gtk_widget_show (dialog); -} - -static void -emft_popup_delete_rec (CamelStore *store, CamelFolderInfo *fi, CamelException *ex) -{ - while (fi) { - CamelFolder *folder; - - if (fi->child) { - emft_popup_delete_rec (store, fi->child, ex); - if (camel_exception_is_set (ex)) - return; - } - - d(printf ("deleting folder '%s'\n", fi->full_name)); - - /* shouldn't camel do this itself? */ - if (camel_store_supports_subscriptions (store)) - camel_store_unsubscribe_folder (store, fi->full_name, NULL); - - if (!(folder = camel_store_get_folder (store, fi->full_name, 0, ex))) - return; - - if (!CAMEL_IS_VEE_FOLDER (folder)) { - GPtrArray *uids = camel_folder_get_uids (folder); - int i; - - camel_folder_freeze (folder); - for (i = 0; i < uids->len; i++) - camel_folder_delete_message (folder, uids->pdata[i]); - - camel_folder_free_uids (folder, uids); - - camel_folder_sync (folder, TRUE, NULL); - camel_folder_thaw (folder); - } - - camel_store_delete_folder (store, fi->full_name, ex); - if (camel_exception_is_set (ex)) - return; - - fi = fi->next; + if ((fi = em_folder_tree_get_selected_folder_info (emft)) != NULL) { + emfu_folder_create (fi); } } static void -emft_popup_delete_folders (CamelStore *store, const char *full_name, CamelException *ex) -{ - guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_FAST; - CamelFolderInfo *fi; - - if (camel_store_supports_subscriptions (store)) - flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; - - fi = camel_store_get_folder_info (store, full_name, flags, ex); - if (camel_exception_is_set (ex)) - return; - - emft_popup_delete_rec (store, fi, ex); - camel_store_free_folder_info (store, fi); -} - -static void selfunc (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { struct _emft_selection_data *dat = (struct _emft_selection_data *) data; @@ -2620,163 +2064,25 @@ emft_selection_get_selected (GtkTreeSelection *selection, GtkTreeModel **model, } static void -emft_popup_delete_response (GtkWidget *dialog, int response, EMFolderTree *emft) -{ - CamelStore *store; - CamelException ex; - char *full_name; - - full_name = g_object_get_data ((GObject *) dialog, "full_name"); - store = g_object_get_data ((GObject *) dialog, "store"); - - if (response == GTK_RESPONSE_OK) { - camel_exception_init (&ex); - emft_popup_delete_folders (store, full_name, &ex); - if (camel_exception_is_set (&ex)) { - e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)emft), - "mail:no-delete-folder", full_name, ex.desc, NULL); - camel_exception_clear (&ex); - } - } - - gtk_widget_destroy (dialog); -} - -static void emft_popup_delete_folder (EPopup *ep, EPopupItem *pitem, void *data) { EMFolderTree *emft = data; - struct _EMFolderTreePrivate *priv = emft->priv; - GtkTreeSelection *selection; - CamelStore *local, *store; - GtkTreeModel *model; - GtkTreeIter iter; - GtkWidget *dialog; - char *full_name; - - selection = gtk_tree_view_get_selection (priv->treeview); - if (!emft_selection_get_selected (selection, &model, &iter)) - return; - - gtk_tree_model_get (model, &iter, COL_POINTER_CAMEL_STORE, &store, - COL_STRING_FULL_NAME, &full_name, -1); - - local = mail_component_peek_local_store (NULL); - - if (store == local && is_special_local_folder (full_name)) { - e_error_run(NULL, "mail:no-delete-special-folder", full_name, NULL); - return; - } - - camel_object_ref (store); + CamelFolder *folder; - dialog = e_error_new((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)emft), - (store && CAMEL_IS_VEE_STORE(store))?"mail:ask-delete-vfolder":"mail:ask-delete-folder", - full_name, NULL); - g_object_set_data_full ((GObject *) dialog, "full_name", full_name, g_free); - g_object_set_data_full ((GObject *) dialog, "store", store, camel_object_unref); - g_signal_connect (dialog, "response", G_CALLBACK (emft_popup_delete_response), emft); - gtk_widget_show (dialog); + if ((folder = em_folder_tree_get_selected_folder (emft)) != NULL) { + emfu_delete_folder (folder); + } } static void emft_popup_rename_folder (EPopup *ep, EPopupItem *pitem, void *data) { EMFolderTree *emft = data; - struct _EMFolderTreePrivate *priv = emft->priv; - char *prompt, *full_name, *name, *new_name, *uri; - GtkTreeSelection *selection; - const char *p; - CamelStore *local, *store; - gboolean done = FALSE; - GtkTreeModel *model; - GtkTreeIter iter; - size_t base_len; - - local = mail_component_peek_local_store (NULL); - - selection = gtk_tree_view_get_selection (priv->treeview); - if (!emft_selection_get_selected (selection, &model, &iter)) - return; - - gtk_tree_model_get (model, &iter, COL_STRING_FULL_NAME, &full_name, - COL_STRING_DISPLAY_NAME, &name, - COL_POINTER_CAMEL_STORE, &store, - COL_STRING_URI, &uri, -1); - - /* don't allow user to rename one of the special local folders */ - if (store == local && is_special_local_folder (full_name)) { - e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)emft), - "mail:no-rename-special-folder", full_name, NULL); - g_free (full_name); - g_free (name); - g_free (uri); - return; - } - - if ((p = strrchr (full_name, '/'))) - base_len = (size_t) (p - full_name); - else - base_len = 0; - - prompt = g_strdup_printf (_("Rename the \"%s\" folder to:"), name); - while (!done) { - new_name = e_request_string (NULL, _("Rename Folder"), prompt, name); - if (new_name == NULL || !strcmp (name, new_name)) { - /* old name == new name */ - done = TRUE; - } else if (strchr(new_name, '/') != NULL) { - e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)emft), - "mail:no-rename-folder", name, new_name, _("Folder names cannot contain '/'"), NULL); - done = TRUE; - } else { - CamelFolderInfo *fi; - CamelException ex; - char *path, *p; - - if (base_len > 0) { - path = g_malloc (base_len + strlen (new_name) + 2); - memcpy (path, full_name, base_len); - p = path + base_len; - *p++ = '/'; - strcpy (p, new_name); - } else { - path = g_strdup (new_name); - } - - camel_exception_init (&ex); - if ((fi = camel_store_get_folder_info (store, path, CAMEL_STORE_FOLDER_INFO_FAST, &ex)) != NULL) { - camel_store_free_folder_info (store, fi); - e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)emft), - "mail:no-rename-folder-exists", name, new_name, NULL); - } else { - const char *oldpath, *newpath; - - oldpath = full_name; - newpath = path; - - d(printf ("renaming %s to %s\n", oldpath, newpath)); - - camel_exception_clear (&ex); - camel_store_rename_folder (store, oldpath, newpath, &ex); - if (camel_exception_is_set (&ex)) { - e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)emft), - "mail:no-rename-folder", oldpath, newpath, ex.desc, NULL); - camel_exception_clear (&ex); - } - - done = TRUE; - } - - g_free (path); - } - - g_free (new_name); + CamelFolder *folder; + + if ((folder = em_folder_tree_get_selected_folder (emft)) != NULL) { + emfu_rename_folder (folder); } - - g_free (full_name); - g_free (name); - g_free (uri); } @@ -3030,6 +2336,60 @@ em_folder_tree_get_selected_path (EMFolderTree *emft) return name; } +CamelFolder * +em_folder_tree_get_selected_folder (EMFolderTree *emft) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + char *full_name = NULL; + CamelException ex; + CamelStore *store = NULL; + CamelFolder *folder = NULL; + + g_return_val_if_fail (EM_IS_FOLDER_TREE (emft), NULL); + + camel_exception_init (&ex); + + selection = gtk_tree_view_get_selection(emft->priv->treeview); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + gtk_tree_model_get (model, &iter, COL_POINTER_CAMEL_STORE, &store, + COL_STRING_FULL_NAME, &full_name, -1); + + folder = camel_store_get_folder (store, full_name, CAMEL_STORE_FOLDER_INFO_FAST, &ex); + + camel_exception_clear (&ex); + + return folder; +} + +CamelFolderInfo * +em_folder_tree_get_selected_folder_info (EMFolderTree *emft) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + char *full_name = NULL; + CamelException ex; + CamelStore *store = NULL; + CamelFolderInfo *fi = NULL; + + g_return_val_if_fail (EM_IS_FOLDER_TREE (emft), NULL); + + camel_exception_init (&ex); + + selection = gtk_tree_view_get_selection(emft->priv->treeview); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + gtk_tree_model_get (model, &iter, COL_POINTER_CAMEL_STORE, &store, + COL_STRING_FULL_NAME, &full_name, -1); + + fi = camel_store_get_folder_info (store, full_name, CAMEL_STORE_FOLDER_INFO_FAST, &ex); + + camel_exception_clear (&ex); + + return fi; +} + EMFolderTreeModel * em_folder_tree_get_model (EMFolderTree *emft) { @@ -3038,6 +2398,18 @@ em_folder_tree_get_model (EMFolderTree *emft) return emft->priv->model; } +EMFolderTreeModelStoreInfo * +em_folder_tree_get_model_storeinfo (EMFolderTree *emft, CamelStore *store) +{ + struct _EMFolderTreePrivate *priv = emft->priv; + struct _EMFolderTreeModelStoreInfo *si; + + if (!(si = g_hash_table_lookup (priv->model->store_hash, store))) { + g_assert_not_reached (); + return NULL; + } + return si; +} static gboolean emft_save_state (EMFolderTree *emft) diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h index e7c465998b..35381dbfa3 100644 --- a/mail/em-folder-tree.h +++ b/mail/em-folder-tree.h @@ -85,8 +85,11 @@ GList *em_folder_tree_get_selected_paths (EMFolderTree *emft); void em_folder_tree_set_selected (EMFolderTree *emft, const char *uri); char *em_folder_tree_get_selected_uri (EMFolderTree *emft); char *em_folder_tree_get_selected_path (EMFolderTree *emft); +CamelFolder *em_folder_tree_get_selected_folder (EMFolderTree *emft); +CamelFolderInfo *em_folder_tree_get_selected_folder_info (EMFolderTree *emft); EMFolderTreeModel *em_folder_tree_get_model (EMFolderTree *emft); +EMFolderTreeModelStoreInfo *em_folder_tree_get_model_storeinfo (EMFolderTree *emft, CamelStore *store); gboolean em_folder_tree_create_folder (EMFolderTree *emft, const char *full_name, const char *uri); diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c new file mode 100644 index 0000000000..1e836fa661 --- /dev/null +++ b/mail/em-folder-utils.c @@ -0,0 +1,744 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2003 Ximian, Inc. (www.ximian.com) + * + * 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 Street #330, Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#include <libxml/tree.h> + +#include <gtk/gtk.h> +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <libgnome/gnome-i18n.h> + +#include <camel/camel-session.h> +#include <camel/camel-store.h> +#include <camel/camel-folder.h> +#include <camel/camel-vee-store.h> +#include <camel/camel-vtrash-folder.h> +#include <camel/camel-stream-mem.h> +#include <camel/camel-file-utils.h> +#include <camel/camel-stream-fs.h> + +#include "e-util/e-mktemp.h" +#include "e-util/e-request.h" +#include "e-util/e-icon-factory.h" + +#include "widgets/misc/e-error.h" + +#include "em-vfolder-rule.h" + +#include "mail-mt.h" +#include "mail-ops.h" +#include "mail-tools.h" +#include "mail-config.h" +#include "mail-component.h" +#include "mail-vfolder.h" + +#include "em-utils.h" +#include "em-popup.h" +#include "em-marshal.h" +#include "em-folder-tree.h" +#include "em-folder-tree-model.h" +#include "em-folder-utils.h" +#include "em-folder-selector.h" +#include "em-folder-selection.h" +#include "em-folder-properties.h" + +#define d(x) + +extern CamelSession *session; + +static gboolean +emfu_is_special_local_folder (const char *name) +{ + return (!strcmp (name, "Drafts") || !strcmp (name, "Inbox") || !strcmp (name, "Outbox") || !strcmp (name, "Sent")); +} + +struct _EMCopyFolders { + struct _mail_msg msg; + + /* input data */ + CamelStore *fromstore; + CamelStore *tostore; + + char *frombase; + char *tobase; + + int delete; +}; + +static char * +emft_copy_folders__desc (struct _mail_msg *mm, int complete) +{ + struct _EMCopyFolders *m = (struct _EMCopyFolders *) mm; + + return g_strdup_printf (_("Copying `%s' to `%s'"), m->frombase, m->tobase); +} + +static void +emft_copy_folders__copy (struct _mail_msg *mm) +{ + struct _EMCopyFolders *m = (struct _EMCopyFolders *) mm; + guint32 flags = CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_RECURSIVE; + GList *pending = NULL, *deleting = NULL, *l; + GString *fromname, *toname; + CamelFolderInfo *fi; + const char *tmp; + int fromlen; + + if (camel_store_supports_subscriptions (m->fromstore)) + flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; + + if (!(fi = camel_store_get_folder_info (m->fromstore, m->frombase, flags, &mm->ex))) + return; + + pending = g_list_append (pending, fi); + + toname = g_string_new (""); + fromname = g_string_new (""); + + tmp = strrchr (m->frombase, '/'); + if (tmp == NULL) + fromlen = 0; + else + fromlen = tmp - m->frombase + 1; + + d(printf ("top name is '%s'\n", fi->full_name)); + + while (pending) { + CamelFolderInfo *info = pending->data; + + pending = g_list_remove_link (pending, pending); + while (info) { + CamelFolder *fromfolder, *tofolder; + GPtrArray *uids; + int deleted = 0; + + if (info->child) + pending = g_list_append (pending, info->child); + + if (m->tobase[0]) + g_string_printf (toname, "%s/%s", m->tobase, info->full_name + fromlen); + else + g_string_printf (toname, "%s", info->full_name + fromlen); + + d(printf ("Copying from '%s' to '%s'\n", info->full_name, toname->str)); + + /* This makes sure we create the same tree, e.g. from a nonselectable source */ + /* Not sure if this is really the 'right thing', e.g. for spool stores, but it makes the ui work */ + if ((info->flags & CAMEL_FOLDER_NOSELECT) == 0) { + d(printf ("this folder is selectable\n")); + if (m->tostore == m->fromstore && m->delete) { + camel_store_rename_folder (m->fromstore, info->full_name, toname->str, &mm->ex); + if (camel_exception_is_set (&mm->ex)) + goto exception; + + /* this folder no longer exists, unsubscribe it */ + if (camel_store_supports_subscriptions (m->fromstore)) + camel_store_unsubscribe_folder (m->fromstore, info->full_name, NULL); + + deleted = 1; + } else { + if (!(fromfolder = camel_store_get_folder (m->fromstore, info->full_name, 0, &mm->ex))) + goto exception; + + if (!(tofolder = camel_store_get_folder (m->tostore, toname->str, CAMEL_STORE_FOLDER_CREATE, &mm->ex))) { + camel_object_unref (fromfolder); + goto exception; + } + + uids = camel_folder_get_uids (fromfolder); + camel_folder_transfer_messages_to (fromfolder, uids, tofolder, NULL, m->delete, &mm->ex); + camel_folder_free_uids (fromfolder, uids); + + if (m->delete) + camel_folder_sync(fromfolder, TRUE, NULL); + + camel_object_unref (fromfolder); + camel_object_unref (tofolder); + } + } + + if (camel_exception_is_set (&mm->ex)) + goto exception; + else if (m->delete && !deleted) + deleting = g_list_prepend (deleting, info); + + /* subscribe to the new folder if appropriate */ + if (camel_store_supports_subscriptions (m->tostore) + && !camel_store_folder_subscribed (m->tostore, toname->str)) + camel_store_subscribe_folder (m->tostore, toname->str, NULL); + + info = info->next; + } + } + + /* delete the folders in reverse order from how we copyied them, if we are deleting any */ + l = deleting; + while (l) { + CamelFolderInfo *info = l->data; + + d(printf ("deleting folder '%s'\n", info->full_name)); + + /* FIXME: we need to do something with the exception + since otherwise the users sees a failed operation + with no error message or even any warnings */ + if (camel_store_supports_subscriptions (m->fromstore)) + camel_store_unsubscribe_folder (m->fromstore, info->full_name, NULL); + + camel_store_delete_folder (m->fromstore, info->full_name, NULL); + l = l->next; + } + + exception: + + camel_store_free_folder_info (m->fromstore, fi); + g_list_free (deleting); + + g_string_free (toname, TRUE); + g_string_free (fromname, TRUE); +} + +static void +emft_copy_folders__free (struct _mail_msg *mm) +{ + struct _EMCopyFolders *m = (struct _EMCopyFolders *) mm; + + camel_object_unref (m->fromstore); + camel_object_unref (m->tostore); + + g_free (m->frombase); + g_free (m->tobase); +} + +static struct _mail_msg_op copy_folders_op = { + emft_copy_folders__desc, + emft_copy_folders__copy, + NULL, + emft_copy_folders__free, +}; + +static void +emfu_copy_folders (CamelStore *tostore, const char *tobase, CamelStore *fromstore, const char *frombase, int delete) +{ + struct _EMCopyFolders *m; + + m = mail_msg_new (©_folders_op, NULL, sizeof (struct _EMCopyFolders)); + camel_object_ref (fromstore); + m->fromstore = fromstore; + camel_object_ref (tostore); + m->tostore = tostore; + m->frombase = g_strdup (frombase); + m->tobase = g_strdup (tobase); + m->delete = delete; + + e_thread_put (mail_thread_new, (EMsg *) m); +} + +struct _copy_folder_data { + CamelFolderInfo *fi; + gboolean delete; +}; + +static void +emfu_copy_folder_selected (const char *uri, void *data) +{ + struct _copy_folder_data *cfd = data; + CamelStore *fromstore = NULL, *tostore = NULL; + char *tobase = NULL; + CamelException ex; + CamelURL *url; + + if (uri == NULL) { + g_free (cfd); + return; + } + + camel_exception_init (&ex); + + if (!(fromstore = camel_session_get_store (session, cfd->fi->uri, &ex))) { + e_error_run(NULL, + cfd->delete?"mail:no-move-folder-notexist":"mail:no-copy-folder-notexist", cfd->fi->full_name, uri, ex.desc, NULL); + goto fail; + } + + if (cfd->delete && fromstore == mail_component_peek_local_store (NULL) && emfu_is_special_local_folder (cfd->fi->full_name)) { + e_error_run(NULL, + "mail:no-rename-special-folder", cfd->fi->full_name, NULL); + goto fail; + } + + if (!(tostore = camel_session_get_store (session, uri, &ex))) { + e_error_run(NULL, + cfd->delete?"mail:no-move-folder-to-notexist":"mail:no-copy-folder-to-notexist", cfd->fi->full_name, uri, ex.desc, NULL); + goto fail; + } + + url = camel_url_new (uri, NULL); + if (((CamelService *)tostore)->provider->url_flags & CAMEL_URL_FRAGMENT_IS_PATH) + tobase = url->fragment; + else if (url->path && url->path[0]) + tobase = url->path+1; + if (tobase == NULL) + tobase = ""; + + emfu_copy_folders (tostore, tobase, fromstore, cfd->fi->full_name, cfd->delete); + + camel_url_free (url); +fail: + if (fromstore) + camel_object_unref(fromstore); + if (tostore) + camel_object_unref(tostore); + camel_exception_clear (&ex); + g_free (cfd); +} + +/* tree here is the 'destination' selector, not 'self' */ +static gboolean +emfu_copy_folder_exclude(EMFolderTree *tree, GtkTreeModel *model, GtkTreeIter *iter, void *data) +{ + struct _copy_folder_data *cfd = data; + int fromvfolder, tovfolder; + char *touri; + guint flags; + gboolean is_store; + + /* handles moving to/from vfolders */ + + fromvfolder = strncmp(cfd->fi->uri, "vfolder:", 8) == 0; + gtk_tree_model_get(model, iter, COL_STRING_URI, &touri, COL_UINT_FLAGS, &flags, COL_BOOL_IS_STORE, &is_store, -1); + tovfolder = strncmp(touri, "vfolder:", 8) == 0; + g_free(touri); + + /* moving from vfolder to normal- not allowed */ + if (fromvfolder && !tovfolder && cfd->delete) + return FALSE; + /* copy/move from normal folder to vfolder - not allowed */ + if (!fromvfolder && tovfolder) + return FALSE; + /* copying to vfolder - not allowed */ + if (tovfolder && !cfd->delete) + return FALSE; + + return (flags & EMFT_EXCLUDE_NOINFERIORS) == 0; +} + +void +emfu_copy_folder (CamelFolderInfo *folderinfo) +{ + struct _copy_folder_data *cfd; + + cfd = g_malloc (sizeof (*cfd)); + cfd->fi = folderinfo; + cfd->delete = FALSE; + + em_select_folder (NULL, _("Select folder"), _("C_opy"), + NULL, emfu_copy_folder_exclude, + emfu_copy_folder_selected, cfd);} + +void +emfu_move_folder (CamelFolderInfo *folderinfo) +{ + struct _copy_folder_data *cfd; + + cfd = g_malloc (sizeof (*cfd)); + cfd->fi = folderinfo; + cfd->delete = TRUE; + + em_select_folder (NULL, _("Select folder"), _("_Move"), + NULL, emfu_copy_folder_exclude, + emfu_copy_folder_selected, cfd); +} + +static void +emfu_delete_rec (CamelStore *store, CamelFolderInfo *fi, CamelException *ex) +{ + while (fi) { + CamelFolder *folder; + + if (fi->child) { + emfu_delete_rec (store, fi->child, ex); + if (camel_exception_is_set (ex)) + return; + } + + d(printf ("deleting folder '%s'\n", fi->full_name)); + + /* shouldn't camel do this itself? */ + if (camel_store_supports_subscriptions (store)) + camel_store_unsubscribe_folder (store, fi->full_name, NULL); + + if (!(folder = camel_store_get_folder (store, fi->full_name, 0, ex))) + return; + + if (!CAMEL_IS_VEE_FOLDER (folder)) { + GPtrArray *uids = camel_folder_get_uids (folder); + int i; + + camel_folder_freeze (folder); + for (i = 0; i < uids->len; i++) + camel_folder_delete_message (folder, uids->pdata[i]); + + camel_folder_free_uids (folder, uids); + + camel_folder_sync (folder, TRUE, NULL); + camel_folder_thaw (folder); + } + + camel_store_delete_folder (store, fi->full_name, ex); + if (camel_exception_is_set (ex)) + return; + + fi = fi->next; + } +} + +static void +emfu_delete_folders (CamelStore *store, const char *full_name, CamelException *ex) +{ + guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_FAST; + CamelFolderInfo *fi; + + if (camel_store_supports_subscriptions (store)) + flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; + + fi = camel_store_get_folder_info (store, full_name, flags, ex); + if (camel_exception_is_set (ex)) + return; + + emfu_delete_rec (store, fi, ex); + camel_store_free_folder_info (store, fi); +} + +static void +emfu_delete_response (GtkWidget *dialog, int response, gpointer data) +{ + CamelStore *store; + CamelException ex; + char *full_name; + + full_name = g_object_get_data ((GObject *) dialog, "full_name"); + store = g_object_get_data ((GObject *) dialog, "store"); + + if (response == GTK_RESPONSE_OK) { + camel_exception_init (&ex); + emfu_delete_folders (store, full_name, &ex); + if (camel_exception_is_set (&ex)) { + e_error_run(NULL, + "mail:no-delete-folder", full_name, ex.desc, NULL); + camel_exception_clear (&ex); + } + } + + gtk_widget_destroy (dialog); +} + +void +emfu_delete_folder (CamelFolder *folder) +{ + CamelStore *local; + GtkWidget *dialog; + + local = mail_component_peek_local_store (NULL); + + if (folder->parent_store == local && emfu_is_special_local_folder (folder->full_name)) { + e_error_run(NULL, "mail:no-delete-special-folder", folder->full_name, NULL); + return; + } + + camel_object_ref (folder->parent_store); + + dialog = e_error_new(NULL, + (folder->parent_store && CAMEL_IS_VEE_STORE(folder->parent_store))?"mail:ask-delete-vfolder":"mail:ask-delete-folder", + folder->full_name, NULL); + g_object_set_data_full ((GObject *) dialog, "full_name", folder->full_name, g_free); + g_object_set_data_full ((GObject *) dialog, "store", folder->parent_store, camel_object_unref); + g_signal_connect (dialog, "response", G_CALLBACK (emfu_delete_response), NULL); + gtk_widget_show (dialog); +} + +void +emfu_rename_folder (CamelFolder *folder) +{ + char *prompt, *new_name; + const char *p; + CamelStore *local; + gboolean done = FALSE; + size_t base_len; + + local = mail_component_peek_local_store (NULL); + + /* don't allow user to rename one of the special local folders */ + if (folder->parent_store == local && emfu_is_special_local_folder (folder->full_name)) { + e_error_run(NULL, + "mail:no-rename-special-folder", folder->full_name, NULL); + return; + } + + if ((p = strrchr (folder->full_name, '/'))) + base_len = (size_t) (p - folder->full_name); + else + base_len = 0; + + prompt = g_strdup_printf (_("Rename the \"%s\" folder to:"), folder->name); + while (!done) { + new_name = e_request_string (NULL, _("Rename Folder"), prompt, folder->name); + if (new_name == NULL || !strcmp (folder->name, new_name)) { + /* old name == new name */ + done = TRUE; + } else if (strchr(new_name, '/') != NULL) { + e_error_run(NULL, + "mail:no-rename-folder", folder->name, new_name, _("Folder names cannot contain '/'"), NULL); + done = TRUE; + } else { + CamelFolderInfo *fi; + CamelException ex; + char *path, *p; + + if (base_len > 0) { + path = g_malloc (base_len + strlen (new_name) + 2); + memcpy (path, folder->full_name, base_len); + p = path + base_len; + *p++ = '/'; + strcpy (p, new_name); + } else { + path = g_strdup (new_name); + } + + camel_exception_init (&ex); + if ((fi = camel_store_get_folder_info (folder->parent_store, path, CAMEL_STORE_FOLDER_INFO_FAST, &ex)) != NULL) { + camel_store_free_folder_info (folder->parent_store, fi); + e_error_run(NULL, + "mail:no-rename-folder-exists", folder->name, new_name, NULL); + } else { + const char *oldpath, *newpath; + + oldpath = folder->full_name; + newpath = path; + + d(printf ("renaming %s to %s\n", oldpath, newpath)); + + camel_exception_clear (&ex); + camel_store_rename_folder (folder->parent_store, oldpath, newpath, &ex); + if (camel_exception_is_set (&ex)) { + e_error_run(NULL, + "mail:no-rename-folder", oldpath, newpath, ex.desc, NULL); + camel_exception_clear (&ex); + } + + done = TRUE; + } + + g_free (path); + } + + g_free (new_name); + } +} + +struct _EMCreateFolder { + struct _mail_msg msg; + + /* input data */ + CamelStore *store; + char *full_name; + char *parent; + char *name; + + /* output data */ + CamelFolderInfo *fi; + + /* callback data */ + void (* done) (CamelFolderInfo *fi, void *user_data); + void *user_data; +}; + +static char * +emfu_create_folder__desc (struct _mail_msg *mm, int done) +{ + struct _EMCreateFolder *m = (struct _EMCreateFolder *) mm; + + return g_strdup_printf (_("Creating folder `%s'"), m->full_name); +} + +static void +emfu_create_folder__create (struct _mail_msg *mm) +{ + struct _EMCreateFolder *m = (struct _EMCreateFolder *) mm; + + d(printf ("creating folder parent='%s' name='%s' full_name='%s'\n", m->parent, m->name, m->full_name)); + + if ((m->fi = camel_store_create_folder (m->store, m->parent, m->name, &mm->ex))) { + if (camel_store_supports_subscriptions (m->store)) + camel_store_subscribe_folder (m->store, m->full_name, &mm->ex); + } +} + +static void +emfu_create_folder__created (struct _mail_msg *mm) +{ + struct _EMCreateFolder *m = (struct _EMCreateFolder *) mm; + + if (m->done) + m->done (m->fi, m->user_data); +} + +static void +emfu_create_folder__free (struct _mail_msg *mm) +{ + struct _EMCreateFolder *m = (struct _EMCreateFolder *) mm; + + camel_store_free_folder_info (m->store, m->fi); + camel_object_unref (m->store); + g_free (m->full_name); + g_free (m->parent); + g_free (m->name); +} + +static struct _mail_msg_op create_folder_op = { + emfu_create_folder__desc, + emfu_create_folder__create, + emfu_create_folder__created, + emfu_create_folder__free, +}; + + +static int +emfu_create_folder_real (CamelStore *store, const char *full_name, void (* done) (CamelFolderInfo *fi, void *user_data), void *user_data) +{ + char *name, *namebuf = NULL; + struct _EMCreateFolder *m; + const char *parent; + int id; + + namebuf = g_strdup (full_name); + if (!(name = strrchr (namebuf, '/'))) { + name = namebuf; + parent = ""; + } else { + *name++ = '\0'; + parent = namebuf; + } + + m = mail_msg_new (&create_folder_op, NULL, sizeof (struct _EMCreateFolder)); + camel_object_ref (store); + m->store = store; + m->full_name = g_strdup (full_name); + m->parent = g_strdup (parent); + m->name = g_strdup (name); + m->user_data = user_data; + m->done = done; + + g_free (namebuf); + + id = m->msg.seq; + e_thread_put (mail_thread_new, (EMsg *) m); + + return id; +} + +static void +new_folder_created_cb (CamelFolderInfo *fi, void *user_data) +{ + EMFolderSelector *emfs = user_data; + + if (fi) + gtk_widget_destroy ((GtkWidget *) emfs); + + g_object_unref (emfs); +} + +static void +emfu_popup_new_folder_response (EMFolderSelector *emfs, int response, gpointer data) +{ + EMFolderTreeModelStoreInfo *si; + const char *uri, *path; + CamelException ex; + CamelStore *store; + + if (response != GTK_RESPONSE_OK) { + gtk_widget_destroy ((GtkWidget *) emfs); + return; + } + + uri = em_folder_selector_get_selected_uri (emfs); + path = em_folder_selector_get_selected_path (emfs); + + d(printf ("Creating new folder: %s (%s)\n", path, uri)); + + g_print ("DEBUG: %s (%s)\n", path, uri); + + camel_exception_init (&ex); + if (!(store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex))) { + camel_exception_clear (&ex); + return; + } + + if (!(si = em_folder_tree_get_model_storeinfo (emfs->emft, store))) { + g_assert_not_reached (); + camel_object_unref (store); + return; + } + + /* HACK: we need to create vfolders using the vfolder editor */ + if (CAMEL_IS_VEE_STORE(store)) { + EMVFolderRule *rule; + + rule = em_vfolder_rule_new(); + filter_rule_set_name((FilterRule *)rule, path); + vfolder_gui_add_rule(rule); + gtk_widget_destroy((GtkWidget *)emfs); + } else { + g_object_ref (emfs); + emfu_create_folder_real (si->store, path, new_folder_created_cb, emfs); + } + + camel_object_unref (store); + camel_exception_clear (&ex); +} + +void +emfu_folder_create (CamelFolderInfo *folderinfo) { + EMFolderTree *folder_tree; + EMFolderTreeModel *model; + GtkWidget *dialog; + + model = mail_component_peek_tree_model (mail_component_peek ()); + folder_tree = (EMFolderTree *) em_folder_tree_new_with_model (model); + + dialog = em_folder_selector_create_new (folder_tree, 0, _("Create folder"), _("Specify where to create the folder:")); + if (folderinfo != NULL) + em_folder_selector_set_selected ((EMFolderSelector *) dialog, folderinfo->uri); + g_signal_connect (dialog, "response", G_CALLBACK (emfu_popup_new_folder_response), folder_tree); + gtk_widget_show (dialog); +} diff --git a/mail/em-folder-utils.h b/mail/em-folder-utils.h new file mode 100644 index 0000000000..ceec49ced1 --- /dev/null +++ b/mail/em-folder-utils.h @@ -0,0 +1,32 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * Rodney Dawes <dobey@novell.com> + * + * Copyright 2003-2005 Novell, Inc. (www.novell.com) + * + * 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 Street #330, Boston, MA 02111-1307, USA. + * + */ + +#include <camel/camel-store.h> + +void emfu_copy_folder (CamelFolderInfo *folderinfo); +void emfu_move_folder (CamelFolderInfo *folderinfo); + +void emfu_delete_folder (CamelFolder *folder); +void emfu_rename_folder (CamelFolder *folder); + +void emfu_folder_create (CamelFolderInfo *folderinfo); diff --git a/mail/em-folder-view.c b/mail/em-folder-view.c index f4c5b737f2..2ba14951a4 100644 --- a/mail/em-folder-view.c +++ b/mail/em-folder-view.c @@ -694,6 +694,22 @@ emfv_popup_saveas(EPopup *ep, EPopupItem *pitem, void *data) } static void +emfv_view_load_images(BonoboUIComponent *uic, void *data, const char *path) +{ + EMFolderView *emfv = data; + + if (emfv->preview) + em_format_html_load_http((EMFormatHTML *)emfv->preview); +} + +static void +emfv_popup_load_images(EPopup *ep, EPopupItem *pitem, void *data) +{ + EMFolderView *emfv = data; + emfv_view_load_images(NULL, data, NULL); +} + +static void emfv_popup_print(EPopup *ep, EPopupItem *pitem, void *data) { EMFolderView *emfv = data; @@ -708,6 +724,44 @@ emfv_popup_copy_text(EPopup *ep, EPopupItem *pitem, void *data) } static void +emfv_popup_source(EPopup *ep, EPopupItem *pitem, void *data) +{ + EMFolderView *emfv = data; + EMMessageBrowser *emmb; + GPtrArray *uids; + + uids = message_list_get_selected(emfv->list); + + emmb = (EMMessageBrowser *)em_message_browser_window_new(); + em_format_set_session((EMFormat *)((EMFolderView *)emmb)->preview, ((EMFormat *)emfv->preview)->session); + em_folder_view_set_folder((EMFolderView *)emmb, emfv->folder, emfv->folder_uri); + em_format_set_mode((EMFormat *)((EMFolderView *)emmb)->preview, EM_FORMAT_SOURCE); + em_folder_view_set_message((EMFolderView *)emmb, uids->pdata[0], FALSE); + gtk_widget_show(emmb->window); + + message_list_free_uids(emfv->list, uids); +} + +static void +emfv_mail_compose(BonoboUIComponent *uid, void *data, const char *path) +{ + EMFolderView *emfv = data; + + if (!em_utils_check_user_can_send_mail((GtkWidget *)emfv)) + return; + + em_utils_compose_new_message(emfv->folder_uri); +} + +static void +emfv_popup_selectall(EPopup *ep, EPopupItem *pitem, void *data) +{ + EMFolderView *emfv = data; + gtk_html_select_all (((EMFormatHTML *)emfv->preview)->html); + +} + +static void emfv_popup_reply_sender(EPopup *ep, EPopupItem *pitem, void *data) { EMFolderView *emfv = data; @@ -1009,8 +1063,8 @@ static EPopupItem emfv_popup_items[] = { { E_POPUP_ITEM, "40.emfv.03", N_("_Copy to Folder..."), emfv_popup_copy, NULL, "stock_mail-copy", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY }, { E_POPUP_BAR, "50.emfv", NULL, NULL, NULL, NULL }, - { E_POPUP_ITEM, "50.emfv.00", N_("Mar_k as Read"), emfv_popup_mark_read, NULL, "stock_mail-open", EM_POPUP_SELECT_MARK_READ }, - { E_POPUP_ITEM, "50.emfv.01", N_("Mark as U_nread"), emfv_popup_mark_unread, NULL, "stock_mail-unread", EM_POPUP_SELECT_MARK_UNREAD }, + { E_POPUP_ITEM, "50.emfv.00", N_("Mar_k as Read"), emfv_popup_mark_read, NULL, "stock_mail-open", EM_POPUP_SELECT_MARK_READ|EM_FOLDER_VIEW_SELECT_LISTONLY }, + { E_POPUP_ITEM, "50.emfv.01", N_("Mark as U_nread"), emfv_popup_mark_unread, NULL, "stock_mail-unread", EM_POPUP_SELECT_MARK_UNREAD|EM_FOLDER_VIEW_SELECT_LISTONLY }, { E_POPUP_ITEM, "50.emfv.02", N_("Mark as _Important"), emfv_popup_mark_important, NULL, "stock_mail-priority-high", EM_POPUP_SELECT_MARK_IMPORTANT|EM_FOLDER_VIEW_SELECT_LISTONLY }, { E_POPUP_ITEM, "50.emfv.03", N_("_Mark as Unimportant"), emfv_popup_mark_unimportant, NULL, NULL, EM_POPUP_SELECT_MARK_UNIMPORTANT|EM_FOLDER_VIEW_SELECT_LISTONLY }, { E_POPUP_ITEM, "50.emfv.04", N_("Mark as _Junk"), emfv_popup_mark_junk, NULL, "stock_spam", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY }, @@ -1169,6 +1223,16 @@ EMFV_MAP_CALLBACK(emfv_message_open, emfv_popup_open) EMFV_MAP_CALLBACK(emfv_message_edit, emfv_popup_edit) EMFV_MAP_CALLBACK(emfv_message_saveas, emfv_popup_saveas) EMFV_MAP_CALLBACK(emfv_print_message, emfv_popup_print) +EMFV_MAP_CALLBACK(emfv_message_source, emfv_popup_source) + +static void +emfv_empty_trash(BonoboUIComponent *uid, void *data, const char *path) +{ + EMFolderView *emfv = data; + + em_utils_empty_trash (gtk_widget_get_toplevel ((GtkWidget *) emfv)); +} + static void emfv_edit_cut(BonoboUIComponent *uid, void *data, const char *path) @@ -1201,6 +1265,14 @@ emfv_edit_paste(BonoboUIComponent *uid, void *data, const char *path) } static void +emfv_select_all_text(BonoboUIComponent *uid, void *data, const char *path) +{ + EMFolderView *emfv = data; + + html_engine_select_all (((EMFormatHTML *)emfv->preview)->html->engine); +} + +static void emfv_mail_next(BonoboUIComponent *uid, void *data, const char *path) { EMFolderView *emfv = data; @@ -1561,20 +1633,15 @@ EMFV_MAP_CALLBACK(emfv_tools_vfolder_mlist, emfv_popup_vfolder_mlist) /* ********************************************************************** */ -static void -emfv_view_load_images(BonoboUIComponent *uic, void *data, const char *path) -{ - EMFolderView *emfv = data; - - if (emfv->preview) - em_format_html_load_http((EMFormatHTML *)emfv->preview); -} - static BonoboUIVerb emfv_message_verbs[] = { + BONOBO_UI_UNSAFE_VERB ("EmptyTrash", emfv_empty_trash), + BONOBO_UI_UNSAFE_VERB ("EditCut", emfv_edit_cut), BONOBO_UI_UNSAFE_VERB ("EditCopy", emfv_edit_copy), BONOBO_UI_UNSAFE_VERB ("EditPaste", emfv_edit_paste), + BONOBO_UI_UNSAFE_VERB ("SelectAllText", emfv_select_all_text), + BONOBO_UI_UNSAFE_VERB ("MailNext", emfv_mail_next), BONOBO_UI_UNSAFE_VERB ("MailNextFlagged", emfv_mail_next_flagged), BONOBO_UI_UNSAFE_VERB ("MailNextUnread", emfv_mail_next_unread), @@ -1619,6 +1686,10 @@ static BonoboUIVerb emfv_message_verbs[] = { BONOBO_UI_UNSAFE_VERB ("TextZoomOut", emfv_text_zoom_out), BONOBO_UI_UNSAFE_VERB ("TextZoomReset", emfv_text_zoom_reset), + BONOBO_UI_UNSAFE_VERB ("ViewSource", emfv_message_source), + + BONOBO_UI_UNSAFE_VERB ("MailCompose", emfv_mail_compose), + /* TODO: This stuff should just be 1 item that runs a wizard */ BONOBO_UI_UNSAFE_VERB ("ToolsFilterMailingList", emfv_tools_filter_mlist), BONOBO_UI_UNSAFE_VERB ("ToolsFilterRecipient", emfv_tools_filter_recipient), @@ -1659,6 +1730,8 @@ static EPixmap emfv_message_pixmaps[] = { E_PIXMAP ("/commands/MessageMarkAsJunk", "stock_spam", E_ICON_SIZE_MENU), E_PIXMAP ("/commands/MessageMarkAsNotJunk", "stock_not-spam", E_ICON_SIZE_MENU), E_PIXMAP ("/commands/MessageFollowUpFlag", "stock_mail-flag-for-followup", E_ICON_SIZE_MENU), + E_PIXMAP ("/commands/ViewLoadImages", "stock_insert_image", E_ICON_SIZE_MENU), + E_PIXMAP ("/commands/MailCompose", "stock_mail-compose", E_ICON_SIZE_MENU), E_PIXMAP ("/Toolbar/MailMessageToolbar/MessageReplySender", "stock_mail-reply", E_ICON_SIZE_LARGE_TOOLBAR), E_PIXMAP ("/Toolbar/MailMessageToolbar/MessageReplyAll", "stock_mail-reply-to-all", E_ICON_SIZE_LARGE_TOOLBAR), @@ -1679,8 +1752,9 @@ static EPixmap emfv_message_pixmaps[] = { /* this is added to emfv->enable_map in :init() */ static const EMFolderViewEnable emfv_enable_map[] = { { "EditCut", EM_POPUP_SELECT_MANY }, - { "EditCopy", EM_POPUP_SELECT_MANY }, + { "EditCopy", EM_FOLDER_VIEW_SELECT_SELECTION }, { "EditPaste", EM_POPUP_SELECT_FOLDER }, + { "SelectAllText", EM_POPUP_SELECT_ONE }, /* FIXME: should these be single-selection? */ { "MailNext", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_NEXT_MSG }, @@ -1736,6 +1810,7 @@ static const EMFolderViewEnable emfv_enable_map[] = { { "ToolsVFolderSubject", EM_POPUP_SELECT_ONE }, { "ViewLoadImages", EM_POPUP_SELECT_ONE }, + { "ViewSource", EM_POPUP_SELECT_ONE }, /* always enabled */ { "MailStop", 0 }, @@ -1814,16 +1889,15 @@ emfv_view_mode(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_Even EMFolderView *emfv = data; int i; - if (type != Bonobo_UIComponent_STATE_CHANGED - || state[0] == '0') + if (type != Bonobo_UIComponent_STATE_CHANGED) return; /* TODO: I don't like this stuff much, is there any way we can move listening for such events elsehwere? Probably not I guess, unless there's a EMFolderViewContainer for bonobo usage of a folder view */ - for (i=0;i<= EM_FORMAT_SOURCE;i++) { - if (strcmp(emfv_display_styles[i]+strlen("/commands/"), path) == 0) { + i = state[0] != '0'; + em_format_set_mode((EMFormat *)emfv->preview, i); if (EM_FOLDER_VIEW_GET_CLASS (emfv)->update_message_style) { @@ -1831,9 +1905,6 @@ emfv_view_mode(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_Even gconf_client_set_int (gconf, "/apps/evolution/mail/display/message_style", i, NULL); } - break; - } - } } static void @@ -1894,11 +1965,11 @@ emfv_activate(EMFolderView *emfv, BonoboUIComponent *uic, int act) bonobo_ui_component_set_prop(uic, "/commands/CaretMode", "state", state?"1":"0", NULL); bonobo_ui_component_add_listener(uic, "CaretMode", emfv_caret_mode, emfv); - style = ((EMFormat *)emfv->preview)->mode; - bonobo_ui_component_set_prop(uic, emfv_display_styles[style], "state", "1", NULL); - bonobo_ui_component_add_listener(uic, "ViewNormal", emfv_view_mode, emfv); + style = ((EMFormat *)emfv->preview)->mode?EM_FORMAT_ALLHEADERS:EM_FORMAT_NORMAL; + bonobo_ui_component_set_prop(uic, emfv_display_styles[style], "state", style?"1":"0", NULL); + /* bonobo_ui_component_add_listener(uic, "ViewNormal", emfv_view_mode, emfv); */ bonobo_ui_component_add_listener(uic, "ViewFullHeaders", emfv_view_mode, emfv); - bonobo_ui_component_add_listener(uic, "ViewSource", emfv_view_mode, emfv); + /* bonobo_ui_component_add_listener(uic, "ViewSource", emfv_view_mode, emfv); */ em_format_set_mode((EMFormat *)emfv->preview, style); if (emfv->folder && !em_utils_folder_is_sent(emfv->folder, emfv->folder_uri)) diff --git a/mail/mail-component.c b/mail/mail-component.c index e831978235..34713baeab 100644 --- a/mail/mail-component.c +++ b/mail/mail-component.c @@ -737,23 +737,6 @@ impl__get_userCreatableItems (PortableServer_Servant servant, CORBA_Environment return list; } -static void -emc_new_folder_response(EMFolderSelector *emfs, int response, void *dummy) -{ - const char *uri, *path; - - if (response != GTK_RESPONSE_OK) { - gtk_widget_destroy((GtkWidget *)emfs); - return; - } - - uri = em_folder_selector_get_selected_uri(emfs); - path = em_folder_selector_get_selected_path(emfs); - - if (em_folder_tree_create_folder(emfs->emft, path, uri)) - gtk_widget_destroy((GtkWidget *)emfs); -} - static int create_item(const char *type, EMFolderTreeModel *model, const char *uri) { @@ -763,15 +746,7 @@ create_item(const char *type, EMFolderTreeModel *model, const char *uri) em_utils_compose_new_message(uri); } else if (strcmp(type, "folder") == 0) { - EMFolderTree *folder_tree; - GtkWidget *dialog; - - folder_tree = (EMFolderTree *)em_folder_tree_new_with_model(model); - dialog = em_folder_selector_create_new (folder_tree, 0, _("Create folder"), _("Specify where to create the folder:")); - if (uri) - em_folder_selector_set_selected ((EMFolderSelector *) dialog, uri); - g_signal_connect (dialog, "response", G_CALLBACK(emc_new_folder_response), NULL); - gtk_widget_show(dialog); + emfu_folder_create (NULL); } else return -1; |