diff options
Diffstat (limited to 'mail/mail-component.c')
-rw-r--r-- | mail/mail-component.c | 1515 |
1 files changed, 105 insertions, 1410 deletions
diff --git a/mail/mail-component.c b/mail/mail-component.c index 12cc03ca78..f2e6a903c4 100644 --- a/mail/mail-component.c +++ b/mail/mail-component.c @@ -33,10 +33,8 @@ #include <fcntl.h> #include <errno.h> -#include "e-storage.h" -#include "e-storage-set.h" -#include "e-storage-browser.h" -#include "e-storage-set-view.h" +#include "em-folder-tree.h" +#include "em-folder-browser.h" #include "em-folder-selector.h" #include "em-folder-selection.h" @@ -72,164 +70,38 @@ #define d(x) x -#define MESSAGE_RFC822_TYPE "message/rfc822" -#define TEXT_URI_LIST_TYPE "text/uri-list" -#define UID_LIST_TYPE "x-uid-list" -#define FOLDER_TYPE "x-folder" - -/* Drag & Drop types */ -enum DndDragType { - DND_DRAG_TYPE_FOLDER, /* drag an evo folder */ - DND_DRAG_TYPE_TEXT_URI_LIST, /* drag to an mbox file */ -}; - -enum DndDropType { - DND_DROP_TYPE_UID_LIST, /* drop a list of message uids */ - DND_DROP_TYPE_FOLDER, /* drop an evo folder */ - DND_DROP_TYPE_MESSAGE_RFC822, /* drop a message/rfc822 stream */ - DND_DROP_TYPE_TEXT_URI_LIST, /* drop an mbox file */ -}; - -static GtkTargetEntry drag_types[] = { - { UID_LIST_TYPE, 0, DND_DRAG_TYPE_FOLDER }, - { TEXT_URI_LIST_TYPE, 0, DND_DRAG_TYPE_TEXT_URI_LIST }, -}; - -static const int num_drag_types = sizeof (drag_types) / sizeof (drag_types[0]); - -static GtkTargetEntry drop_types[] = { - { UID_LIST_TYPE, 0, DND_DROP_TYPE_UID_LIST }, - { FOLDER_TYPE, 0, DND_DROP_TYPE_FOLDER }, - { MESSAGE_RFC822_TYPE, 0, DND_DROP_TYPE_MESSAGE_RFC822 }, - { TEXT_URI_LIST_TYPE, 0, DND_DROP_TYPE_TEXT_URI_LIST }, -}; - -static const int num_drop_types = sizeof (drop_types) / sizeof (drop_types[0]); - #define PARENT_TYPE bonobo_object_get_type () static BonoboObjectClass *parent_class = NULL; struct _MailComponentPrivate { char *base_directory; - + + EMFolderTree *emft; + MailAsyncEvent *async_event; - GHashTable *storages_hash; /* storage by store */ - - EFolderTypeRegistry *folder_type_registry; - EStorageSet *storage_set; - + GHashTable *store_hash; /* display_name by store */ + RuleContext *search_context; - + char *context_path; /* current path for right-click menu */ - + CamelStore *local_store; }; -static int emc_tree_right_click(ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event, MailComponent *component); - /* Utility functions. */ -/* EPFIXME: Eeek, this totally sucks. See comment in e-storage.h, - async_open_folder() should NOT be a signal. */ - -struct _StorageConnectedData { - EStorage *storage; - char *path; - EStorageDiscoveryCallback callback; - void *callback_data; -}; -typedef struct _StorageConnectedData StorageConnectedData; - -static void -storage_connected_callback (CamelStore *store, - CamelFolderInfo *info, - StorageConnectedData *data) -{ - EStorageResult result; - - if (info != NULL) - result = E_STORAGE_OK; - else - result = E_STORAGE_GENERICERROR; - - (* data->callback) (data->storage, result, data->path, data->callback_data); - - g_object_unref (data->storage); - g_free (data->path); - g_free (data); -} - static void -storage_async_open_folder_callback (EStorage *storage, - const char *path, - EStorageDiscoveryCallback callback, - void *callback_data, - CamelStore *store) +add_storage (MailComponent *component, const char *name, CamelService *store, CamelException *ex) { - StorageConnectedData *storage_connected_data = g_new0 (StorageConnectedData, 1); - - g_object_ref (storage); - - storage_connected_data->storage = storage; - storage_connected_data->path = g_strdup (path); - storage_connected_data->callback = callback; - storage_connected_data->callback_data = callback_data; - - mail_note_store (store, NULL, storage, - (void *) storage_connected_callback, storage_connected_data); + camel_object_ref (store); + g_hash_table_insert (component->priv->store_hash, store, g_strdup (name)); + em_folder_tree_add_store (component->priv->emft, (CamelStore *) store, name); + mail_note_store ((CamelStore *) store, NULL, NULL, NULL); } static void -add_storage (MailComponent *component, - const char *name, - CamelService *store, - CamelException *ex) -{ - EStorage *storage; - EFolder *root_folder; - - root_folder = e_folder_new (name, "noselect", ""); - storage = e_storage_new (name, root_folder); - e_storage_declare_has_subfolders(storage, "/", _("Connecting...")); - - camel_object_ref(store); - - g_object_set_data((GObject *)storage, "em-store", store); - g_hash_table_insert (component->priv->storages_hash, store, storage); - - g_signal_connect(storage, "async_open_folder", - G_CALLBACK (storage_async_open_folder_callback), store); - -#if 0 /* Some private test code - zed */ - { - static void *model; - - if (model == NULL) { - model = em_store_model_new(); - em_store_model_view_new(model); - } - - em_store_model_add_store(model, store); - } -#endif - -#if 0 - /* EPFIXME these are not needed anymore. */ - g_signal_connect(storage, "create_folder", G_CALLBACK(storage_create_folder), store); - g_signal_connect(storage, "remove_folder", G_CALLBACK(storage_remove_folder), store); - g_signal_connect(storage, "xfer_folder", G_CALLBACK(storage_xfer_folder), store); -#endif - - e_storage_set_add_storage (component->priv->storage_set, storage); - - mail_note_store ((CamelStore *) store, NULL, storage, NULL, NULL); - - g_object_unref (storage); -} - -static void -load_accounts(MailComponent *component, EAccountList *accounts) +load_accounts (MailComponent *component, EAccountList *accounts) { EIterator *iter; @@ -247,7 +119,7 @@ load_accounts(MailComponent *component, EAccountList *accounts) account = (EAccount *) e_iterator_get (iter); service = account->source; name = account->name; - + if (account->enabled && service->url != NULL) mail_component_load_storage_by_uri (component, service->url, name); @@ -257,39 +129,21 @@ load_accounts(MailComponent *component, EAccountList *accounts) g_object_unref (iter); } -static inline gboolean -type_is_mail (const char *type) -{ - return !strcmp (type, "mail") || !strcmp (type, "mail/public"); -} - -static inline gboolean -type_is_vtrash (const char *type) -{ - return !strcmp (type, "vtrash"); -} - -static inline gboolean -type_is_vjunk (const char *type) -{ - return !strcmp (type, "vjunk"); -} - static void storage_go_online (gpointer key, gpointer value, gpointer data) { CamelStore *store = key; CamelService *service = CAMEL_SERVICE (store); - + if (! (service->provider->flags & CAMEL_PROVIDER_IS_REMOTE) || (service->provider->flags & CAMEL_PROVIDER_IS_EXTERNAL)) return; - + if ((CAMEL_IS_DISCO_STORE (service) && camel_disco_store_status (CAMEL_DISCO_STORE (service)) == CAMEL_DISCO_STORE_OFFLINE) || service->status != CAMEL_SERVICE_DISCONNECTED) { mail_store_set_offline (store, FALSE, NULL, NULL); - mail_note_store (store, NULL, NULL, NULL, NULL); + mail_note_store (store, NULL, NULL, NULL); } } @@ -369,7 +223,6 @@ setup_local_store(MailComponent *component) g_free(store_uri); } -/* EStorageBrowser callbacks. */ static BonoboControl * create_noselect_control (void) @@ -378,498 +231,51 @@ create_noselect_control (void) label = gtk_label_new (_("This folder cannot contain messages.")); gtk_widget_show (label); + return bonobo_control_new (label); } static GtkWidget * -create_view_callback (EStorageBrowser *browser, - const char *path, - void *unused_data) +create_view_widget (EMFolderTree *emft, const char *path, const char *uri) { BonoboControl *control; - EFolder *folder; - const char *folder_type; - const char *physical_uri; - - folder = e_storage_set_get_folder (e_storage_browser_peek_storage_set (browser), path); - if (folder == NULL) { - g_warning ("No folder at %s", path); - return gtk_label_new ("(You should not be seeing this label)"); - } - - folder_type = e_folder_get_type_string (folder); - physical_uri = e_folder_get_physical_uri (folder); - - if (type_is_mail (folder_type)) { - const char *noselect; - CamelURL *url; - - url = camel_url_new (physical_uri, NULL); - noselect = url ? camel_url_get_param (url, "noselect") : NULL; - if (noselect && !strcasecmp (noselect, "yes")) - control = create_noselect_control (); - else - control = folder_browser_factory_new_control (physical_uri); - camel_url_free (url); - } else if (type_is_vtrash (folder_type)) { - if (!strncasecmp (physical_uri, "file:", 5)) - control = folder_browser_factory_new_control ("vtrash:file:/"); - else - control = folder_browser_factory_new_control (physical_uri); - } else if (type_is_vjunk (folder_type)) { - if (!strncasecmp (physical_uri, "file:", 5)) - control = folder_browser_factory_new_control ("vjunk:file:/"); - else - control = folder_browser_factory_new_control (physical_uri); - } else - return NULL; + const char *noselect; + CamelURL *url; + + url = camel_url_new (uri, NULL); + noselect = url ? camel_url_get_param (url, "noselect") : NULL; + if (noselect && !strcasecmp (noselect, "yes")) + control = create_noselect_control (); + else + control = folder_browser_factory_new_control (uri); + camel_url_free (url); if (!control) return NULL; - - /* EPFIXME: This leaks the control. */ - return bonobo_widget_new_control_from_objref (BONOBO_OBJREF (control), CORBA_OBJECT_NIL); -} - -static void -browser_page_switched_callback (EStorageBrowser *browser, - GtkWidget *old_page, - GtkWidget *new_page, - BonoboControl *parent_control) -{ - if (BONOBO_IS_WIDGET (old_page)) { - BonoboControlFrame *control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (old_page)); - - bonobo_control_frame_control_deactivate (control_frame); - } - - if (BONOBO_IS_WIDGET (new_page)) { - BonoboControlFrame *control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (new_page)); - Bonobo_UIContainer ui_container = bonobo_control_get_remote_ui_container (parent_control, NULL); - - /* This is necessary because we are not embedding the folder browser control - directly; we are putting the folder browser control into a notebook which - is then exported to the shell as a control. So we need to forward the - notebook's UIContainer to the folder browser. */ - bonobo_control_frame_set_ui_container (control_frame, ui_container, NULL); - - bonobo_control_frame_control_activate (control_frame); - } -} - -static CamelFolder * -foo_get_folder (EStorageSetView *view, const char *path, CamelException *ex) -{ - /* <NotZed> either do - mail_tool_uri_to_folder(ess_get_folder(path).physicaluri), - or split the path into 'path' and 'storage name' and do get - ess_get_storage() -> store -> open_folder - */ - CamelFolder *folder; - EStorageSet *set; - EFolder *efolder; - const char *uri; - - set = e_storage_set_view_get_storage_set (view); - efolder = e_storage_set_get_folder (set, path); - uri = e_folder_get_physical_uri (efolder); - - folder = mail_tool_uri_to_folder (uri, 0, ex); - - return folder; -} - -static void -drag_text_uri_list (EStorageSetView *view, const char *path, GtkSelectionData *selection, gpointer user_data) -{ - CamelFolder *src, *dest; - const char *tmpdir; - CamelStore *store; - CamelException ex; - GtkWidget *dialog; - GPtrArray *uids; - char *uri; - - camel_exception_init (&ex); - - if (!(src = foo_get_folder (view, path, &ex))) { - dialog = gtk_message_dialog_new ((GtkWindow *) view, GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, - _("Could not open source folder: %s"), - camel_exception_get_description (&ex)); - - gtk_dialog_run ((GtkDialog *) dialog); - gtk_widget_destroy (dialog); - - camel_exception_clear (&ex); - - return; - } - if (!(tmpdir = e_mkdtemp ("drag-n-drop-XXXXXX"))) { - dialog = gtk_message_dialog_new ((GtkWindow *) view, GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, - _("Could not create temporary directory: %s"), - g_strerror (errno)); - - gtk_dialog_run ((GtkDialog *) dialog); - gtk_widget_destroy (dialog); - - camel_object_unref (src); - - return; - } - - uri = g_strdup_printf ("mbox:%s", tmpdir); - if (!(store = camel_session_get_store (session, uri, &ex))) { - dialog = gtk_message_dialog_new ((GtkWindow *) view, GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, - _("Could not create temporary mbox store: %s"), - camel_exception_get_description (&ex)); - - gtk_dialog_run ((GtkDialog *) dialog); - gtk_widget_destroy (dialog); - - camel_exception_clear (&ex); - camel_object_unref (src); - g_free (uri); - - return; - } - - if (!(dest = camel_store_get_folder (store, "mbox", CAMEL_STORE_FOLDER_CREATE, &ex))) { - dialog = gtk_message_dialog_new ((GtkWindow *) view, GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, - _("Could not create temporary mbox folder: %s"), - camel_exception_get_description (&ex)); - - gtk_dialog_run ((GtkDialog *) dialog); - gtk_widget_destroy (dialog); - - camel_exception_clear (&ex); - camel_object_unref (store); - camel_object_unref (src); - g_free (uri); - - return; - } - - camel_object_unref (store); - uids = camel_folder_get_uids (src); - - camel_folder_transfer_messages_to (src, uids, dest, NULL, FALSE, &ex); - if (camel_exception_is_set (&ex)) { - dialog = gtk_message_dialog_new ((GtkWindow *) view, GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, - _("Could not copy messages to temporary mbox folder: %s"), - camel_exception_get_description (&ex)); - - gtk_dialog_run ((GtkDialog *) dialog); - gtk_widget_destroy (dialog); - - camel_folder_free_uids (src, uids); - camel_exception_clear (&ex); - camel_object_unref (dest); - camel_object_unref (src); - g_free (uri); - - return; - } - - camel_folder_free_uids (src, uids); - camel_object_unref (dest); - camel_object_unref (src); - - memcpy (uri, "file", 4); - - gtk_selection_data_set (selection, selection->target, 8, - uri, strlen (uri)); - - g_free (uri); -} - -static void -folder_dragged_cb (EStorageSetView *view, const char *path, GdkDragContext *context, - GtkSelectionData *selection, guint info, guint time, gpointer user_data) -{ - printf ("dragging folder `%s'\n", path); - - switch (info) { - case DND_DRAG_TYPE_FOLDER: - /* dragging @path to a new location in the folder tree */ - gtk_selection_data_set (selection, selection->target, 8, path, strlen (path) + 1); - break; - case DND_DRAG_TYPE_TEXT_URI_LIST: - /* dragging @path to some place external to evolution */ - drag_text_uri_list (view, path, selection, user_data); - break; - default: - g_assert_not_reached (); - } -} - -static void -drop_uid_list (EStorageSetView *view, const char *path, gboolean move, GtkSelectionData *selection, gpointer user_data) -{ - CamelFolder *src, *dest; - CamelException ex; - GPtrArray *uids; - char *src_uri; - - em_utils_selection_get_uidlist (selection, &src_uri, &uids); - - camel_exception_init (&ex); - - if (!(src = mail_tool_uri_to_folder (src_uri, 0, &ex))) { - /* FIXME: report error to user? */ - camel_exception_clear (&ex); - em_utils_uids_free (uids); - g_free (src_uri); - return; - } - - g_free (src_uri); - - if (!(dest = foo_get_folder (view, path, &ex))) { - /* FIXME: report error to user? */ - camel_exception_clear (&ex); - em_utils_uids_free (uids); - camel_object_unref (src); - return; - } - - camel_folder_transfer_messages_to (src, uids, dest, NULL, move, &ex); - if (camel_exception_is_set (&ex)) { - /* FIXME: report error to user? */ - camel_exception_clear (&ex); - em_utils_uids_free (uids); - camel_object_unref (dest); - camel_object_unref (src); - return; - } - - em_utils_uids_free (uids); - camel_object_unref (dest); - camel_object_unref (src); -} - -static void -drop_folder (EStorageSetView *view, const char *path, gboolean move, GtkSelectionData *selection, gpointer user_data) -{ - CamelFolder *src, *dest; - CamelFolder *store; - CamelException ex; - - camel_exception_init (&ex); - - /* get the destination folder (where the user dropped). this - * will become the parent folder of the folder that got - * dragged */ - if (!(dest = foo_get_folder (view, path, &ex))) { - /* FIXME: report error to user? */ - camel_exception_clear (&ex); - return; - } - - /* get the folder being dragged */ - if (!(src = foo_get_folder (view, selection->data, &ex))) { - /* FIXME: report error to user? */ - camel_exception_clear (&ex); - camel_object_unref (dest); - return; - } - - if (src->parent_store == dest->parent_store && move) { - /* simple rename() action */ - char *old_name, *new_name; - - old_name = g_strdup (src->full_name); - new_name = g_strdup_printf ("%s/%s", dest->full_name, src->name); - camel_object_unref (src); - - camel_store_rename_folder (dest->parent_store, old_name, new_name, &ex); - if (camel_exception_is_set (&ex)) { - /* FIXME: report error to user? */ - camel_exception_clear (&ex); - camel_object_unref (dest); - g_free (old_name); - g_free (new_name); - return; - } - - camel_object_unref (dest); - g_free (old_name); - g_free (new_name); - } else { - /* copy the folder */ - camel_object_unref (dest); - camel_object_unref (src); - } -} - -static gboolean -import_message_rfc822 (CamelFolder *dest, CamelStream *stream, gboolean scan_from, CamelException *ex) -{ - CamelMimeParser *mp; - - mp = camel_mime_parser_new (); - camel_mime_parser_scan_from (mp, scan_from); - camel_mime_parser_init_with_stream (mp, stream); - - while (camel_mime_parser_step (mp, 0, 0) == CAMEL_MIME_PARSER_STATE_FROM) { - CamelMessageInfo *info; - CamelMimeMessage *msg; - - msg = camel_mime_message_new (); - if (camel_mime_part_construct_from_parser (CAMEL_MIME_PART (msg), mp) == -1) { - camel_object_unref (msg); - camel_object_unref (mp); - return FALSE; - } - - /* append the message to the folder... */ - info = g_new0 (CamelMessageInfo, 1); - camel_folder_append_message (dest, msg, info, NULL, ex); - camel_object_unref (msg); - - if (camel_exception_is_set (ex)) { - camel_object_unref (mp); - return FALSE; - } - - /* skip over the FROM_END state */ - camel_mime_parser_step (mp, 0, 0); - } - - camel_object_unref (mp); - - return TRUE; -} - -static void -drop_message_rfc822 (EStorageSetView *view, const char *path, GtkSelectionData *selection, gpointer user_data) -{ - CamelFolder *folder; - CamelStream *stream; - CamelException ex; - gboolean scan_from; - - camel_exception_init (&ex); - - if (!(folder = foo_get_folder (view, path, &ex))) { - /* FIXME: report error to user? */ - camel_exception_clear (&ex); - return; - } - - scan_from = selection->length > 5 && !strncmp (selection->data, "From ", 5); - stream = camel_stream_mem_new_with_buffer (selection->data, selection->length); - - if (!import_message_rfc822 (folder, stream, scan_from, &ex)) { - /* FIXME: report to user? */ - } - - camel_exception_clear (&ex); - - camel_object_unref (stream); - camel_object_unref (folder); + /* EPFIXME: This leaks the control. */ + return bonobo_widget_new_control_from_objref (BONOBO_OBJREF (control), CORBA_OBJECT_NIL); } static void -drop_text_uri_list (EStorageSetView *view, const char *path, GtkSelectionData *selection, gpointer user_data) +folder_selected_cb (EMFolderTree *emft, const char *path, const char *uri, GtkBox *vbox) { - CamelFolder *folder; - CamelStream *stream; - CamelException ex; - char **urls, *tmp; - int i; - - camel_exception_init (&ex); - - if (!(folder = foo_get_folder (view, path, &ex))) { - /* FIXME: report to user? */ - camel_exception_clear (&ex); - return; - } - - tmp = g_strndup (selection->data, selection->length); - urls = g_strsplit (tmp, "\n", 0); - g_free (tmp); + GtkWidget *view; + GList *l, *n; - for (i = 0; urls[i] != NULL; i++) { - CamelURL *uri; - char *url; - int fd; - - /* get the path component */ - url = g_strstrip (urls[i]); - uri = camel_url_new (url, NULL); - g_free (url); - - if (!uri || strcmp (uri->protocol, "file") != 0) { - camel_url_free (uri); - continue; - } - - url = uri->path; - uri->path = NULL; - camel_url_free (uri); - - if ((fd = open (url, O_RDONLY)) == -1) { - g_free (url); - continue; - } - - stream = camel_stream_fs_new_with_fd (fd); - if (!import_message_rfc822 (folder, stream, TRUE, &ex)) { - /* FIXME: report to user? */ - } - - camel_exception_clear (&ex); - camel_object_unref (stream); - g_free (url); + /* there should only ever be 1 child */ + l = gtk_container_get_children (GTK_CONTAINER (vbox)); + while (l != NULL) { + n = l->next; + gtk_widget_destroy (l->data); + g_list_free_1 (l); + l = n; } - camel_object_unref (folder); - g_free (urls); -} - -static void -folder_receive_drop_cb (EStorageSetView *view, const char *path, GdkDragContext *context, - GtkSelectionData *selection, guint info, guint time, gpointer user_data) -{ - gboolean move = context->action == GDK_ACTION_MOVE; - - /* this means we are receiving no data */ - if (!selection->data || selection->length == -1) - return; - - switch (info) { - case DND_DROP_TYPE_UID_LIST: - /* import a list of uids from another evo folder */ - drop_uid_list (view, path, move, selection, user_data); - printf ("* dropped a x-uid-list\n"); - break; - case DND_DROP_TYPE_FOLDER: - /* rename a folder */ - drop_folder (view, path, move, selection, user_data); - printf ("* dropped a x-folder\n"); - break; - case DND_DROP_TYPE_MESSAGE_RFC822: - /* import a message/rfc822 stream */ - drop_message_rfc822 (view, path, selection, user_data); - printf ("* dropped a message/rfc822\n"); - break; - case DND_DROP_TYPE_TEXT_URI_LIST: - /* import an mbox, maildir, or mh folder? */ - drop_text_uri_list (view, path, selection, user_data); - printf ("* dropped a text/uri-list\n"); - break; - default: - g_assert_not_reached (); - } + view = create_view_widget (emft, path, uri); + gtk_widget_show (view); - gtk_drag_finish (context, TRUE, TRUE, time); + gtk_box_pack_start_defaults (vbox, view); } @@ -879,49 +285,50 @@ static void impl_dispose (GObject *object) { MailComponentPrivate *priv = MAIL_COMPONENT (object)->priv; - - if (priv->storage_set != NULL) { - g_object_unref (priv->storage_set); - priv->storage_set = NULL; - } - - if (priv->folder_type_registry != NULL) { - g_object_unref (priv->folder_type_registry); - priv->folder_type_registry = NULL; - } - + if (priv->search_context != NULL) { g_object_unref (priv->search_context); priv->search_context = NULL; } - + if (priv->local_store != NULL) { camel_object_unref (CAMEL_OBJECT (priv->local_store)); priv->local_store = NULL; } - + (* G_OBJECT_CLASS (parent_class)->dispose) (object); } static void +store_hash_free (gpointer key, gpointer value, gpointer user_data) +{ + CamelStore *store = key; + char *name = value; + + g_free (name); + camel_object_unref (store); +} + +static void impl_finalize (GObject *object) { MailComponentPrivate *priv = MAIL_COMPONENT (object)->priv; - + g_free (priv->base_directory); - + mail_async_event_destroy (priv->async_event); - - g_hash_table_destroy (priv->storages_hash); /* EPFIXME free the data within? */ - + + g_hash_table_foreach (priv->store_hash, store_hash_free, NULL); + g_hash_table_destroy (priv->store_hash); + if (mail_async_event_destroy (priv->async_event) == -1) { g_warning("Cannot destroy async event: would deadlock"); g_warning(" system may be unstable at exit"); } - - g_free(priv->context_path); + + g_free (priv->context_path); g_free (priv); - + (* G_OBJECT_CLASS (parent_class)->finalize) (object); } @@ -930,45 +337,30 @@ impl_finalize (GObject *object) static void impl_createControls (PortableServer_Servant servant, - Bonobo_Control *corba_sidebar_control, + Bonobo_Control *corba_tree_control, Bonobo_Control *corba_view_control, CORBA_Environment *ev) { MailComponent *mail_component = MAIL_COMPONENT (bonobo_object_from_servant (servant)); MailComponentPrivate *priv = mail_component->priv; - EStorageBrowser *browser; + BonoboControl *tree_control; + BonoboControl *view_control; GtkWidget *tree_widget; - GtkWidget *tree_widget_scrolled; GtkWidget *view_widget; - BonoboControl *sidebar_control; - BonoboControl *view_control; - - browser = e_storage_browser_new (priv->storage_set, "/", create_view_callback, NULL); - - tree_widget = e_storage_browser_peek_tree_widget (browser); - tree_widget_scrolled = e_storage_browser_peek_tree_widget_scrolled (browser); - view_widget = e_storage_browser_peek_view_widget (browser); - - e_storage_set_view_set_drag_types ((EStorageSetView *) tree_widget, drag_types, num_drag_types); - e_storage_set_view_set_drop_types ((EStorageSetView *) tree_widget, drop_types, num_drop_types); - e_storage_set_view_set_allow_dnd ((EStorageSetView *) tree_widget, TRUE); - g_signal_connect (tree_widget, "folder_dragged", G_CALLBACK (folder_dragged_cb), browser); - g_signal_connect (tree_widget, "folder_receive_drop", G_CALLBACK (folder_receive_drop_cb), browser); + tree_widget = (GtkWidget *) priv->emft; + view_widget = gtk_vbox_new (0, TRUE); - gtk_widget_show (tree_widget_scrolled); + gtk_widget_show (tree_widget); gtk_widget_show (view_widget); - - sidebar_control = bonobo_control_new (tree_widget_scrolled); + + tree_control = bonobo_control_new (tree_widget); view_control = bonobo_control_new (view_widget); - - *corba_sidebar_control = CORBA_Object_duplicate (BONOBO_OBJREF (sidebar_control), ev); + + *corba_tree_control = CORBA_Object_duplicate (BONOBO_OBJREF (tree_control), ev); *corba_view_control = CORBA_Object_duplicate (BONOBO_OBJREF (view_control), ev); - - g_signal_connect_object (browser, "page_switched", - G_CALLBACK (browser_page_switched_callback), view_control, 0); - - g_signal_connect(tree_widget, "right_click", G_CALLBACK(emc_tree_right_click), mail_component); + + g_signal_connect (tree_widget, "folder-selected", G_CALLBACK (folder_selected_cb), view_widget); } @@ -1042,14 +434,13 @@ mail_component_init (MailComponent *component) if (camel_mkdir (priv->base_directory, 0777) == -1 && errno != EEXIST) abort (); + priv->emft = em_folder_tree_new (); + /* EPFIXME: Turn into an object? */ mail_session_init (priv->base_directory); priv->async_event = mail_async_event_new(); - priv->storages_hash = g_hash_table_new (NULL, NULL); - - priv->folder_type_registry = e_folder_type_registry_new (); - priv->storage_set = e_storage_set_new (priv->folder_type_registry); + priv->store_hash = g_hash_table_new (NULL, NULL); /* migrate evolution 1.x folders to 2.0's location/format */ mail_dir = g_strdup_printf ("%s/mail", priv->base_directory); @@ -1218,35 +609,34 @@ store_disconnect (CamelStore *store, void *data) { camel_service_disconnect (CAMEL_SERVICE (store), TRUE, NULL); - camel_object_unref (CAMEL_OBJECT (store)); + camel_object_unref (store); } void -mail_component_remove_storage (MailComponent *component, - CamelStore *store) +mail_component_remove_storage (MailComponent *component, CamelStore *store) { MailComponentPrivate *priv = component->priv; - EStorage *storage; + char *name; - /* Because the storages_hash holds a reference to each store + /* Because the store_hash holds a reference to each store * used as a key in it, none of them will ever be gc'ed, meaning * any call to camel_session_get_{service,store} with the same * URL will always return the same object. So this works. */ - storage = g_hash_table_lookup (priv->storages_hash, store); - if (!storage) + if (!(name = g_hash_table_lookup (priv->store_hash, store))) return; - g_hash_table_remove (priv->storages_hash, store); + g_hash_table_remove (priv->store_hash, store); + g_free (name); /* so i guess potentially we could have a race, add a store while one being removed. ?? */ mail_note_store_remove (store); - - e_storage_set_remove_storage (priv->storage_set, storage); - mail_async_event_emit(priv->async_event, MAIL_ASYNC_THREAD, (MailAsyncFunc) store_disconnect, store, NULL, NULL); + em_folder_tree_remove_store (priv->emft, store); + + mail_async_event_emit (priv->async_event, MAIL_ASYNC_THREAD, (MailAsyncFunc) store_disconnect, store, NULL, NULL); } @@ -1272,46 +662,29 @@ mail_component_remove_storage_by_uri (MailComponent *component, } -EStorage * -mail_component_lookup_storage (MailComponent *component, - CamelStore *store) -{ - EStorage *storage; - - /* Because the storages_hash holds a reference to each store - * used as a key in it, none of them will ever be gc'ed, meaning - * any call to camel_session_get_{service,store} with the same - * URL will always return the same object. So this works. - */ - - storage = g_hash_table_lookup (component->priv->storages_hash, store); - if (storage) - g_object_ref (storage); - - return storage; -} - - int mail_component_get_storage_count (MailComponent *component) { - return g_hash_table_size (component->priv->storages_hash); + return g_hash_table_size (component->priv->store_hash); } -EStorageSet * -mail_component_peek_storage_set (MailComponent *component) +void +mail_component_storages_foreach (MailComponent *component, GHFunc func, void *user_data) { - return component->priv->storage_set; + g_hash_table_foreach (component->priv->store_hash, func, user_data); } -void -mail_component_storages_foreach (MailComponent *component, - GHFunc func, - void *data) +EMFolderTreeModel * +mail_component_get_tree_model (MailComponent *component) { - g_hash_table_foreach (component->priv->storages_hash, func, data); + EMFolderTreeModel *model; + + model = (EMFolderTreeModel *) gtk_tree_view_get_model ((GtkTreeView *) component->priv->emft); + g_object_ref (model); + + return model; } extern struct _CamelSession *session; @@ -1502,681 +875,3 @@ mail_component_evomail_uri_from_folder (MailComponent *component, BONOBO_TYPE_FUNC_FULL (MailComponent, GNOME_Evolution_Component, PARENT_TYPE, mail_component) - - -/* ********************************************************************** */ -#if 0 -static void -emc_popup_view(GtkWidget *w, MailComponent *mc) -{ - -} - -static void -emc_popup_open_new(GtkWidget *w, MailComponent *mc) -{ -} -#endif - -/* FIXME: This must be done in another thread */ -static void -em_copy_folders(CamelStore *tostore, const char *tobase, CamelStore *fromstore, const char *frombase, int delete) -{ - GString *toname, *fromname; - CamelFolderInfo *fi; - GList *pending = NULL, *deleting = NULL, *l; - guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE; - CamelException *ex = camel_exception_new(); - int fromlen; - const char *tmp; - - if (camel_store_supports_subscriptions(fromstore)) - flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; - - fi = camel_store_get_folder_info(fromstore, frombase, flags, ex); - if (camel_exception_is_set(ex)) - goto done; - - pending = g_list_append(pending, fi); - - toname = g_string_new(""); - fromname = g_string_new(""); - - tmp = strrchr(frombase, '/'); - if (tmp == NULL) - fromlen = 0; - else - fromlen = tmp-frombase+1; - - 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; - - if (info->child) - pending = g_list_append(pending, info->child); - if (tobase[0]) - g_string_printf(toname, "%s/%s", tobase, info->full_name + fromlen); - else - g_string_printf(toname, "%s", info->full_name + fromlen); - - 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) { - printf("this folder is selectable\n"); - fromfolder = camel_store_get_folder(fromstore, info->full_name, 0, ex); - if (fromfolder == NULL) - goto exception; - - tofolder = camel_store_get_folder(tostore, toname->str, CAMEL_STORE_FOLDER_CREATE, ex); - if (tofolder == NULL) { - camel_object_unref(fromfolder); - goto exception; - } - - if (camel_store_supports_subscriptions(tostore) - && !camel_store_folder_subscribed(tostore, toname->str)) - camel_store_subscribe_folder(tostore, toname->str, NULL); - - uids = camel_folder_get_uids(fromfolder); - camel_folder_transfer_messages_to(fromfolder, uids, tofolder, NULL, delete, ex); - camel_folder_free_uids(fromfolder, uids); - - camel_object_unref(fromfolder); - camel_object_unref(tofolder); - } - - if (camel_exception_is_set(ex)) - goto exception; - else if (delete) - deleting = g_list_prepend(deleting, info); - - info = info->sibling; - } - } - - /* delete the folders in reverse order from how we copyied them, if we are deleting any */ - l = deleting; - while (l) { - CamelFolderInfo *info = l->data; - - printf("deleting folder '%s'\n", info->full_name); - - if (camel_store_supports_subscriptions(fromstore)) - camel_store_unsubscribe_folder(fromstore, info->full_name, NULL); - - camel_store_delete_folder(fromstore, info->full_name, NULL); - l = l->next; - } - -exception: - camel_store_free_folder_info(fromstore, fi); - g_list_free(deleting); - - g_string_free(toname, TRUE); - g_string_free(fromname, TRUE); -done: - printf("exception: %s\n", ex->desc?ex->desc:"<none>"); - camel_exception_free(ex); -} - -struct _copy_folder_data { - MailComponent *mc; - int delete; -}; - -static void -emc_popup_copy_folder_selected(const char *uri, void *data) -{ - struct _copy_folder_data *d = data; - - if (uri == NULL) { - g_free(d); - return; - } - - if (uri) { - EFolder *folder = e_storage_set_get_folder(d->mc->priv->storage_set, d->mc->priv->context_path); - CamelException *ex = camel_exception_new(); - CamelStore *fromstore, *tostore; - char *tobase, *frombase; - CamelURL *url; - - printf("copying folder '%s' to '%s'\n", d->mc->priv->context_path, uri); - - fromstore = camel_session_get_store(session, e_folder_get_physical_uri(folder), ex); - frombase = strchr(d->mc->priv->context_path+1, '/')+1; - - tostore = camel_session_get_store(session, uri, ex); - url = camel_url_new(uri, NULL); - if (url->fragment) - tobase = url->fragment; - else if (url->path && url->path[0]) - tobase = url->path+1; - else - tobase = ""; - - em_copy_folders(tostore, tobase, fromstore, frombase, d->delete); - - camel_url_free(url); - camel_exception_free(ex); - } - g_free(d); -} - -static void -emc_popup_copy(GtkWidget *w, MailComponent *mc) -{ - struct _copy_folder_data *d; - - d = g_malloc(sizeof(*d)); - d->mc = mc; - d->delete = 0; - em_select_folder(NULL, _("Select folder"), _("Select destination to copy folder into"), NULL, emc_popup_copy_folder_selected, d); -} - -static void -emc_popup_move(GtkWidget *w, MailComponent *mc) -{ - struct _copy_folder_data *d; - - d = g_malloc(sizeof(*d)); - d->mc = mc; - d->delete = 1; - em_select_folder(NULL, _("Select folder"), _("Select destination to move folder into"), NULL, emc_popup_copy_folder_selected, d); -} -static void -emc_popup_new_folder_create(EStorageSet *ess, EStorageResult result, void *data) -{ - printf("folder created %s\n", result == E_STORAGE_OK?"ok":"failed"); -} - -static void -emc_popup_new_folder_response(EMFolderSelector *emfs, guint response, MailComponent *mc) -{ - if (response == GTK_RESPONSE_OK) { - char *path, *tmp, *name, *full; - EStorage *storage; - CamelStore *store; - CamelException *ex; - - printf("Creating folder: %s (%s)\n", em_folder_selector_get_selected(emfs), - em_folder_selector_get_selected_uri(emfs)); - - path = g_strdup(em_folder_selector_get_selected(emfs)); - tmp = strchr(path+1, '/'); - *tmp++ = 0; - /* FIXME: camel_store_create_folder should just take full path names */ - full = g_strdup(tmp); - name = strrchr(tmp, '/'); - if (name == NULL) { - name = tmp; - tmp = ""; - } else - *name++ = 0; - - storage = e_storage_set_get_storage(mc->priv->storage_set, path+1); - store = g_object_get_data((GObject *)storage, "em-store"); - - printf("creating folder '%s' / '%s' on '%s'\n", tmp, name, path+1); - - ex = camel_exception_new(); - camel_store_create_folder(store, tmp, name, ex); - if (camel_exception_is_set(ex)) { - printf("Create failed: %s\n", ex->desc); - } else if (camel_store_supports_subscriptions(store)) { - camel_store_subscribe_folder(store, full, ex); - if (camel_exception_is_set(ex)) { - printf("Subscribe failed: %s\n", ex->desc); - } - } - - camel_exception_free(ex); - - g_free(full); - g_free(path); - - /* Blah, this should just use camel, we get better error reporting if we do too */ - /*e_storage_set_async_create_folder(mc->priv->storage_set, path, "mail", "", emc_popup_new_folder_create, mc);*/ - } - gtk_widget_destroy((GtkWidget *)emfs); -} - -static void -emc_popup_new_folder (GtkWidget *w, MailComponent *mc) -{ - GtkWidget *dialog; - - dialog = em_folder_selector_create_new(mc->priv->storage_set, 0, _("Create folder"), _("Specify where to create the folder:")); - em_folder_selector_set_selected((EMFolderSelector *)dialog, mc->priv->context_path); - g_signal_connect(dialog, "response", G_CALLBACK(emc_popup_new_folder_response), mc); - gtk_widget_show(dialog); -} - -static void -em_delete_rec(CamelStore *store, CamelFolderInfo *fi, CamelException *ex) -{ - while (fi) { - CamelFolder *folder; - - if (fi->child) - em_delete_rec(store, fi->child, ex); - if (camel_exception_is_set(ex)) - return; - - 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); - - folder = camel_store_get_folder(store, fi->full_name, 0, NULL); - if (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_sync(folder, TRUE, NULL); - camel_folder_thaw(folder); - camel_folder_free_uids(folder, uids); - } - - camel_store_delete_folder(store, fi->full_name, ex); - if (camel_exception_is_set(ex)) - return; - fi = fi->sibling; - } -} - -static void -em_delete_folders(CamelStore *store, const char *base, CamelException *ex) -{ - CamelFolderInfo *fi; - guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE; - - if (camel_store_supports_subscriptions(store)) - flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; - - fi = camel_store_get_folder_info(store, base, flags, ex); - if (camel_exception_is_set(ex)) - return; - - em_delete_rec(store, fi, ex); - camel_store_free_folder_info(store, fi); -} - -static void -emc_popup_delete_response(GtkWidget *w, guint response, MailComponent *mc) -{ - gtk_widget_destroy(w); - - if (response == GTK_RESPONSE_OK) { - const char *path = strchr(mc->priv->context_path+1, '/')+1; - EFolder *folder = e_storage_set_get_folder(mc->priv->storage_set, mc->priv->context_path); - CamelException *ex = camel_exception_new(); - CamelStore *store; - - /* FIXME: need to hook onto store changed event and delete view as well, somewhere else tho */ - store = camel_session_get_store(session, e_folder_get_physical_uri(folder), ex); - if (camel_exception_is_set(ex)) - goto exception; - - em_delete_folders(store, path, ex); - if (!camel_exception_is_set(ex)) - goto noexception; - exception: - e_notice(NULL, GTK_MESSAGE_ERROR, - _("Could not delete folder: %s"), ex->desc); - noexception: - camel_exception_free(ex); - if (store) - camel_object_unref(store); - } -} - -static void -emc_popup_delete_folder(GtkWidget *w, MailComponent *mc) -{ - GtkWidget *dialog; - char *title; - const char *path = strchr(mc->priv->context_path+1, '/')+1; - EFolder *folder; - - folder = e_storage_set_get_folder(mc->priv->storage_set, mc->priv->context_path); - if (folder == NULL) - return; - - dialog = gtk_message_dialog_new(NULL, - GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_NONE, - _("Really delete folder \"%s\" and all of its subfolders?"), path); - - gtk_dialog_add_button((GtkDialog *)dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); - gtk_dialog_add_button((GtkDialog *)dialog, GTK_STOCK_DELETE, GTK_RESPONSE_OK); - - gtk_dialog_set_default_response((GtkDialog *)dialog, GTK_RESPONSE_OK); - gtk_container_set_border_width((GtkContainer *)dialog, 6); - gtk_box_set_spacing((GtkBox *)((GtkDialog *)dialog)->vbox, 6); - - title = g_strdup_printf(_("Delete \"%s\""), path); - gtk_window_set_title((GtkWindow *)dialog, title); - g_free(title); - - g_signal_connect(dialog, "response", G_CALLBACK(emc_popup_delete_response), mc); - gtk_widget_show(dialog); -} - -static void -emc_popup_rename_folder(GtkWidget *w, MailComponent *mc) -{ - char *prompt, *new; - EFolder *folder; - const char *old, *why; - int done = 0; - - folder = e_storage_set_get_folder(mc->priv->storage_set, mc->priv->context_path); - if (folder == NULL) - return; - - old = e_folder_get_name(folder); - prompt = g_strdup_printf (_("Rename the \"%s\" folder to:"), e_folder_get_name(folder)); - while (!done) { - new = e_request_string(NULL, _("Rename Folder"), prompt, old); - if (new == NULL || strcmp(old, new) == 0) - done = 1; -#if 0 - else if (!e_shell_folder_name_is_valid(new, &why)) - e_notice(NULL, GTK_MESSAGE_ERROR, _("The specified folder name is not valid: %s"), why); -#endif - else { - char *base, *path; - - /* FIXME: we can't use the os independent path crap here, since we want to control the format */ - base = g_path_get_dirname(mc->priv->context_path); - path = g_build_filename(base, new, NULL); - - if (e_storage_set_get_folder(mc->priv->storage_set, path) != NULL) { - e_notice(NULL, GTK_MESSAGE_ERROR, - _("A folder named \"%s\" already exists. Please use a different name."), new); - } else { - CamelStore *store; - CamelException *ex = camel_exception_new(); - const char *oldpath, *newpath; - - oldpath = strchr(mc->priv->context_path+1, '/'); - g_assert(oldpath); - newpath = strchr(path+1, '/'); - g_assert(newpath); - oldpath++; - newpath++; - - printf("renaming %s to %s\n", oldpath, newpath); - - store = camel_session_get_store(session, e_folder_get_physical_uri(folder), ex); - if (camel_exception_is_set(ex)) - goto exception; - - camel_store_rename_folder(store, oldpath, newpath, ex); - if (!camel_exception_is_set(ex)) - goto noexception; - - exception: - e_notice(NULL, GTK_MESSAGE_ERROR, - _("Could not rename folder: %s"), ex->desc); - noexception: - if (store) - camel_object_unref(store); - camel_exception_free(ex); - - done = 1; - } - g_free(path); - g_free(base); - } - g_free(new); - } -} - -struct _prop_data { - void *object; - CamelArgV *argv; - GtkWidget **widgets; -}; - -static void -emc_popup_properties_response(GtkWidget *dialog, int response, struct _prop_data *prop_data) -{ - int i; - CamelArgV *argv = prop_data->argv; - - if (response != GTK_RESPONSE_OK) { - gtk_widget_destroy(dialog); - return; - } - - for (i=0;i<argv->argc;i++) { - CamelArg *arg = &argv->argv[i]; - - switch (arg->tag & CAMEL_ARG_TYPE) { - case CAMEL_ARG_BOO: - arg->ca_int = gtk_toggle_button_get_active ((GtkToggleButton *) prop_data->widgets[i]); - break; - case CAMEL_ARG_STR: - g_free(arg->ca_str); - arg->ca_str = gtk_entry_get_text ((GtkEntry *) prop_data->widgets[i]); - break; - default: - printf("unknown property type set\n"); - } - } - - camel_object_setv(prop_data->object, NULL, argv); - gtk_widget_destroy(dialog); -} - -static void -emc_popup_properties_free(void *data) -{ - struct _prop_data *prop_data = data; - int i; - - for (i=0; i<prop_data->argv->argc; i++) { - if ((prop_data->argv->argv[i].tag & CAMEL_ARG_TYPE) == CAMEL_ARG_STR) - g_free(prop_data->argv->argv[i].ca_str); - } - camel_object_unref(prop_data->object); - g_free(prop_data->argv); - g_free(prop_data); -} - -static void -emc_popup_properties_got_folder (char *uri, CamelFolder *folder, void *data) -{ - if (folder) { - GtkWidget *dialog, *w, *table, *label; - GSList *list, *l; - char *name; - int row = 1; - gint32 count, i; - struct _prop_data *prop_data; - CamelArgV *argv; - CamelArgGetV *arggetv; - - camel_object_get(folder, NULL, CAMEL_FOLDER_PROPERTIES, &list, CAMEL_FOLDER_NAME, &name, NULL); - - dialog = gtk_dialog_new_with_buttons(_("Folder properties"), - NULL, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_OK, - GTK_RESPONSE_OK, - NULL); - - /* TODO: maybe we want some basic properties here, like message counts/approximate size/etc */ - w = gtk_frame_new(_("Properties")); - gtk_box_pack_start ((GtkBox *) ((GtkDialog *)dialog)->vbox, w, TRUE, TRUE, 6); - table = gtk_table_new(g_slist_length(list)+1, 2, FALSE); - gtk_container_add((GtkContainer *)w, table); - label = gtk_label_new(_("Folder Name")); - gtk_misc_set_alignment ((GtkMisc *) label, 1.0, 0.5); - gtk_table_attach ((GtkTable *) table, label, 0, 1, 0, 1, GTK_FILL|GTK_EXPAND, 0, 3, 0); - label = gtk_label_new(name); - gtk_misc_set_alignment ((GtkMisc *) label, 0.0, 0.5); - gtk_table_attach ((GtkTable *) table, label, 1, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0, 3, 0); - - /* build an arggetv/argv to retrieve/store the results */ - count = g_slist_length(list); - arggetv = g_malloc0(sizeof(*arggetv) + (count - CAMEL_ARGV_MAX) * sizeof(arggetv->argv[0])); - arggetv->argc = count; - argv = g_malloc0(sizeof(*argv) + (count - CAMEL_ARGV_MAX) * sizeof(argv->argv[0])); - argv->argc = count; - i = 0; - l = list; - while (l) { - CamelProperty *prop = l->data; - - argv->argv[i].tag = prop->tag; - arggetv->argv[i].tag = prop->tag; - arggetv->argv[i].ca_ptr = &argv->argv[i].ca_ptr; - - l = l->next; - i++; - } - camel_object_getv(folder, NULL, arggetv); - g_free(arggetv); - - prop_data = g_malloc0(sizeof(*prop_data)); - prop_data->widgets = g_malloc0(sizeof(prop_data->widgets[0]) * count); - prop_data->argv = argv; - - /* setup the ui with the values retrieved */ - l = list; - i = 0; - while (l) { - CamelProperty *prop = l->data; - - switch (prop->tag & CAMEL_ARG_TYPE) { - case CAMEL_ARG_BOO: - w = gtk_check_button_new_with_label(prop->description); - gtk_toggle_button_set_active((GtkToggleButton *)w, argv->argv[i].ca_int != 0); - gtk_table_attach ((GtkTable *) table, w, 0, 2, row, row+1, 0, 0, 3, 3); - prop_data->widgets[i] = w; - break; - case CAMEL_ARG_STR: - label = gtk_label_new(prop->description); - gtk_misc_set_alignment ((GtkMisc *) label, 1.0, 0.5); - gtk_table_attach ((GtkTable *) table, label, 0, 1, row, row+1, GTK_FILL|GTK_EXPAND, 0, 3, 3); - - w = gtk_entry_new(); - if (argv->argv[i].ca_str) { - gtk_entry_set_text((GtkEntry *)w, argv->argv[i].ca_str); - camel_object_free(folder, argv->argv[i].tag, argv->argv[i].ca_str); - argv->argv[i].ca_str = NULL; - } - gtk_table_attach ((GtkTable *) table, w, 1, 2, row, row+1, GTK_FILL, 0, 3, 3); - prop_data->widgets[i] = w; - break; - default: - w = gtk_label_new("CamelFolder error: unsupported propery type"); - gtk_table_attach ((GtkTable *) table, w, 0, 2, row, row+1, 0, 0, 3, 3); - break; - } - - row++; - l = l->next; - } - - prop_data->object = folder; - camel_object_ref(folder); - - camel_object_free(folder, CAMEL_FOLDER_PROPERTIES, list); - camel_object_free(folder, CAMEL_FOLDER_NAME, name); - - /* we do 'apply on ok' ... since instant apply may apply some very long running tasks */ - - g_signal_connect(dialog, "response", G_CALLBACK(emc_popup_properties_response), prop_data); - g_object_set_data_full((GObject *)dialog, "e-prop-data", prop_data, emc_popup_properties_free); - gtk_widget_show_all(dialog); - } -} - -static void -emc_popup_properties(GtkWidget *w, MailComponent *mc) -{ - EFolder *efolder; - - /* TODO: Make sure we only have one dialog open for any given folder */ - - efolder = e_storage_set_get_folder(mc->priv->storage_set, mc->priv->context_path); - if (efolder == NULL) - return; - - mail_get_folder(e_folder_get_physical_uri(efolder), 0, emc_popup_properties_got_folder, mc, mail_thread_new); -} - -static EMPopupItem emc_popup_menu[] = { -#if 0 - { EM_POPUP_ITEM, "00.emc.00", N_("_View"), G_CALLBACK(emc_popup_view), NULL, NULL, 0 }, - { EM_POPUP_ITEM, "00.emc.01", N_("Open in _New Window"), G_CALLBACK(emc_popup_open_new), NULL, NULL, 0 }, - - { EM_POPUP_BAR, "10.emc" }, -#endif - { EM_POPUP_ITEM, "10.emc.00", N_("_Copy"), G_CALLBACK(emc_popup_copy), NULL, "folder-copy-16.png", 0 }, - { EM_POPUP_ITEM, "10.emc.01", N_("_Move"), G_CALLBACK(emc_popup_move), NULL, "folder-move-16.png", 0 }, - - { EM_POPUP_BAR, "20.emc" }, - { EM_POPUP_ITEM, "20.emc.00", N_("_New Folder..."), G_CALLBACK(emc_popup_new_folder), NULL, "folder-mini.png", 0 }, - { EM_POPUP_ITEM, "20.emc.01", N_("_Delete"), G_CALLBACK(emc_popup_delete_folder), NULL, "evolution-trash-mini.png", 0 }, - { EM_POPUP_ITEM, "20.emc.01", N_("_Rename"), G_CALLBACK(emc_popup_rename_folder), NULL, NULL, 0 }, - - { EM_POPUP_BAR, "80.emc" }, - { EM_POPUP_ITEM, "80.emc.00", N_("_Properties..."), G_CALLBACK(emc_popup_properties), NULL, "configure_16_folder.xpm", 0 }, -}; - - -static int -emc_tree_right_click(ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event, MailComponent *component) -{ - char *name; - ETreeModel *model = e_tree_get_model(tree); - EMPopup *emp; - int i; - GSList *menus = NULL; - struct _GtkMenu *menu; - - name = e_tree_memory_node_get_data((ETreeMemory *)model, path); - g_free(component->priv->context_path); - component->priv->context_path = g_strdup(name); - printf("right click, path = '%s'\n", name); - - emp = em_popup_new("com.ximian.mail.storageset.popup.select"); - - for (i=0;i<sizeof(emc_popup_menu)/sizeof(emc_popup_menu[0]);i++) { - EMPopupItem *item = &emc_popup_menu[i]; - - item->activate_data = component; - menus = g_slist_prepend(menus, item); - } - - em_popup_add_items(emp, menus, (GDestroyNotify)g_slist_free); - - menu = em_popup_create_menu_once(emp, NULL, 0, 0); - - if (event == NULL || event->type == GDK_KEY_PRESS) { - /* FIXME: menu pos function */ - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, event->key.time); - } else { - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button.button, event->button.time); - } - - return TRUE; -} |