diff options
68 files changed, 3370 insertions, 1558 deletions
diff --git a/Makefile.am b/Makefile.am index 217bdf9e83..041a0dd2c5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -68,6 +68,7 @@ SUBDIRS = \ addressbook \ calendar \ art \ + composer \ plugins \ doc \ ui \ diff --git a/addressbook/gui/component/e-book-shell-view.c b/addressbook/gui/component/e-book-shell-view.c index 05b7f91f30..243fb908f0 100644 --- a/addressbook/gui/component/e-book-shell-view.c +++ b/addressbook/gui/component/e-book-shell-view.c @@ -270,7 +270,7 @@ book_shell_view_class_init (EBookShellViewClass *class, object_class->constructed = book_shell_view_constructed; shell_view_class = E_SHELL_VIEW_CLASS (class); - shell_view_class->label = N_("Contacts"); + shell_view_class->label = _("Contacts"); shell_view_class->icon_name = "x-office-address-book"; shell_view_class->ui_definition = "evolution-contacts.ui"; shell_view_class->search_options = "/contact-search-options"; diff --git a/calendar/modules/e-cal-shell-view.c b/calendar/modules/e-cal-shell-view.c index 353658474b..4e966024bd 100644 --- a/calendar/modules/e-cal-shell-view.c +++ b/calendar/modules/e-cal-shell-view.c @@ -185,8 +185,8 @@ cal_shell_view_class_init (ECalShellViewClass *class, object_class->constructed = cal_shell_view_constructed; shell_view_class = E_SHELL_VIEW_CLASS (class); - shell_view_class->label = N_("Cals"); - shell_view_class->icon_name = "evolution-cals"; + shell_view_class->label = _("Calendar"); + shell_view_class->icon_name = "evolution-calendar"; shell_view_class->ui_definition = "evolution-calendars.ui"; shell_view_class->search_options = "/calendar-search-options"; shell_view_class->search_rules = "caltypes.xml"; diff --git a/calendar/modules/e-memo-shell-view.c b/calendar/modules/e-memo-shell-view.c index 72427107d3..a618c307e9 100644 --- a/calendar/modules/e-memo-shell-view.c +++ b/calendar/modules/e-memo-shell-view.c @@ -195,7 +195,7 @@ memo_shell_view_class_init (EMemoShellViewClass *class, object_class->constructed = memo_shell_view_constructed; shell_view_class = E_SHELL_VIEW_CLASS (class); - shell_view_class->label = N_("Memos"); + shell_view_class->label = _("Memos"); shell_view_class->icon_name = "evolution-memos"; shell_view_class->ui_definition = "evolution-memos.ui"; shell_view_class->search_options = "/memo-search-options"; diff --git a/calendar/modules/e-task-shell-view.c b/calendar/modules/e-task-shell-view.c index 9fc0643a14..3183323901 100644 --- a/calendar/modules/e-task-shell-view.c +++ b/calendar/modules/e-task-shell-view.c @@ -230,7 +230,7 @@ task_shell_view_class_init (ETaskShellViewClass *class, object_class->constructed = task_shell_view_constructed; shell_view_class = E_SHELL_VIEW_CLASS (class); - shell_view_class->label = N_("Tasks"); + shell_view_class->label = _("Tasks"); shell_view_class->icon_name = "evolution-tasks"; shell_view_class->ui_definition = "evolution-tasks.ui"; shell_view_class->search_options = "/task-search-options"; diff --git a/composer/e-composer-header-table.c b/composer/e-composer-header-table.c index d659e5290f..1954e92f47 100644 --- a/composer/e-composer-header-table.c +++ b/composer/e-composer-header-table.c @@ -80,6 +80,7 @@ enum { PROP_DESTINATIONS_BCC, PROP_DESTINATIONS_CC, PROP_DESTINATIONS_TO, + PROP_MODEL, PROP_POST_TO, PROP_REPLY_TO, PROP_SIGNATURE, @@ -92,6 +93,7 @@ struct _EComposerHeaderTablePrivate { GtkWidget *signature_label; GtkWidget *signature_combo_box; ENameSelector *name_selector; + EMFolderTreeModel *model; }; static gpointer parent_class; @@ -346,6 +348,12 @@ composer_header_table_set_property (GObject *object, e_destination_freev (destinations); return; + case PROP_MODEL: + e_composer_header_table_set_folder_tree_model ( + E_COMPOSER_HEADER_TABLE (object), + g_value_get_object (value)); + return; + case PROP_POST_TO: list = g_value_dup_string_list (value); e_composer_header_table_set_post_to_list ( @@ -437,6 +445,13 @@ composer_header_table_get_property (GObject *object, e_destination_freev (destinations); return; + case PROP_MODEL: + g_value_set_object ( + value, + e_composer_header_table_get_folder_tree_model ( + E_COMPOSER_HEADER_TABLE (object))); + return; + case PROP_POST_TO: list = e_composer_header_table_get_post_to ( E_COMPOSER_HEADER_TABLE (object)); @@ -502,6 +517,11 @@ composer_header_table_dispose (GObject *object) priv->name_selector = NULL; } + if (priv->model != NULL) { + g_object_unref (priv->model); + priv->model = NULL; + } + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -591,6 +611,17 @@ composer_header_table_class_init (EComposerHeaderTableClass *class) g_object_class_install_property ( object_class, + PROP_MODEL, + g_param_spec_object ( + "model", + NULL, + NULL, + EM_TYPE_FOLDER_TREE_MODEL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + object_class, PROP_REPLY_TO, g_param_spec_string ( "reply-to", @@ -971,6 +1002,29 @@ e_composer_header_table_set_destinations_to (EComposerHeaderTable *table, e_composer_name_header_set_destinations (header, destinations); } +EMFolderTreeModel * +e_composer_header_table_get_folder_tree_model (EComposerHeaderTable *table) +{ + EComposerPostHeader *header; + + g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL); + + header = E_COMPOSER_HEADER_TABLE_GET_POST_TO_HEADER (table); + return e_composer_post_header_get_folder_tree_model (header); +} + +void +e_composer_header_table_set_folder_tree_model (EComposerHeaderTable *table, + EMFolderTreeModel *model) +{ + EComposerPostHeader *header; + + g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table)); + + header = E_COMPOSER_HEADER_TABLE_GET_POST_TO_HEADER (table); + e_composer_post_header_set_folder_tree_model (header, model); +} + GList * e_composer_header_table_get_post_to (EComposerHeaderTable *table) { diff --git a/composer/e-composer-header-table.h b/composer/e-composer-header-table.h index 0e03618dc9..5e1d3e1922 100644 --- a/composer/e-composer-header-table.h +++ b/composer/e-composer-header-table.h @@ -27,6 +27,7 @@ #include <libebook/e-destination.h> #include <e-util/e-signature.h> #include <e-util/e-signature-list.h> +#include <mail/em-folder-tree-model.h> #include "e-composer-header.h" @@ -127,6 +128,12 @@ EDestination ** e_composer_header_table_get_destinations_to void e_composer_header_table_set_destinations_to (EComposerHeaderTable *table, EDestination **destinations); +EMFolderTreeModel * + e_composer_header_table_get_folder_tree_model + (EComposerHeaderTable *table); +void e_composer_header_table_set_folder_tree_model + (EComposerHeaderTable *table, + EMFolderTreeModel *model); GList * e_composer_header_table_get_post_to (EComposerHeaderTable *table); void e_composer_header_table_set_post_to_base diff --git a/composer/e-composer-post-header.c b/composer/e-composer-post-header.c index bb971d53bf..2ff98d053b 100644 --- a/composer/e-composer-post-header.c +++ b/composer/e-composer-post-header.c @@ -32,10 +32,12 @@ enum { PROP_0, - PROP_ACCOUNT + PROP_ACCOUNT, + PROP_FOLDER_TREE_MODEL }; struct _EComposerPostHeaderPrivate { + EMFolderTreeModel *model; EAccount *account; gchar *base_url; /* derived from account */ gboolean custom; @@ -43,10 +45,6 @@ struct _EComposerPostHeaderPrivate { static gpointer parent_class; -/* Forward Declarations (to avoid pulling in Bonobo stuff) */ -struct _MailComponent *mail_component_peek (void); -struct _EMFolderTreeModel *mail_component_peek_tree_model (struct _MailComponent *component); - static gchar * composer_post_header_folder_name_to_string (EComposerPostHeader *header, const gchar *url) @@ -120,7 +118,9 @@ composer_post_header_clicked_cb (EComposerPostHeader *header) GtkWidget *dialog; GList *list; - model = mail_component_peek_tree_model (mail_component_peek ()); + g_return_if_fail (header->priv->model != NULL); + + model = header->priv->model; folder_tree = em_folder_tree_new_with_model (model); em_folder_tree_set_multiselect ( @@ -194,6 +194,12 @@ composer_post_header_set_property (GObject *object, E_COMPOSER_POST_HEADER (object), g_value_get_object (value)); return; + + case PROP_FOLDER_TREE_MODEL: + e_composer_post_header_set_folder_tree_model ( + E_COMPOSER_POST_HEADER (object), + g_value_get_object (value)); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -211,6 +217,13 @@ composer_post_header_get_property (GObject *object, value, e_composer_post_header_get_account ( E_COMPOSER_POST_HEADER (object))); return; + + case PROP_FOLDER_TREE_MODEL: + g_value_set_object ( + value, + e_composer_post_header_get_folder_tree_model ( + E_COMPOSER_POST_HEADER (object))); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -228,6 +241,11 @@ composer_post_header_dispose (GObject *object) priv->account = NULL; } + if (priv->model != NULL) { + g_object_unref (priv->model); + priv->model = NULL; + } + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -269,6 +287,16 @@ composer_post_header_class_init (EComposerPostHeaderClass *class) NULL, E_TYPE_ACCOUNT, G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FOLDER_TREE_MODEL, + g_param_spec_object ( + "folder-tree-model", + NULL, + NULL, + EM_TYPE_FOLDER_TREE_MODEL, + G_PARAM_READWRITE)); } static void @@ -352,6 +380,29 @@ e_composer_post_header_set_account (EComposerPostHeader *header, g_object_notify (G_OBJECT (header), "account"); } +EMFolderTreeModel * +e_composer_post_header_get_folder_tree_model (EComposerPostHeader *header) +{ + g_return_val_if_fail (E_IS_COMPOSER_POST_HEADER (header), NULL); + + return header->priv->model; +} + +void +e_composer_post_header_set_folder_tree_model (EComposerPostHeader *header, + EMFolderTreeModel *model) +{ + g_return_if_fail (E_IS_COMPOSER_POST_HEADER (header)); + g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model)); + + if (header->priv->model != NULL) + g_object_unref (header->priv->model); + + header->priv->model = g_object_ref (model); + + g_object_notify (G_OBJECT (header), "folder-tree-model"); +} + GList * e_composer_post_header_get_folders (EComposerPostHeader *header) { diff --git a/composer/e-composer-post-header.h b/composer/e-composer-post-header.h index 666d043df2..f2a1a5057c 100644 --- a/composer/e-composer-post-header.h +++ b/composer/e-composer-post-header.h @@ -22,6 +22,7 @@ #define E_COMPOSER_POST_HEADER_H #include <libedataserver/e-account.h> +#include <mail/em-folder-tree-model.h> #include "e-composer-text-header.h" @@ -46,6 +47,8 @@ G_BEGIN_DECLS +/* Avoid including files from the Mail module. */ + typedef struct _EComposerPostHeader EComposerPostHeader; typedef struct _EComposerPostHeaderClass EComposerPostHeaderClass; typedef struct _EComposerPostHeaderPrivate EComposerPostHeaderPrivate; @@ -60,12 +63,19 @@ struct _EComposerPostHeaderClass { }; GType e_composer_post_header_get_type (void); -EComposerHeader * e_composer_post_header_new (const gchar *label); +EComposerHeader * + e_composer_post_header_new (const gchar *label); EAccount * e_composer_post_header_get_account (EComposerPostHeader *header); void e_composer_post_header_set_account (EComposerPostHeader *header, EAccount *account); +EMFolderTreeModel * + e_composer_post_header_get_folder_tree_model + (EComposerPostHeader *header); +void e_composer_post_header_set_folder_tree_model + (EComposerPostHeader *header, + EMFolderTreeModel *model); GList * e_composer_post_header_get_folders (EComposerPostHeader *header); void e_composer_post_header_set_folders diff --git a/composer/e-composer-private.c b/composer/e-composer-private.c index 30cdbfab75..c1e463a98b 100644 --- a/composer/e-composer-private.c +++ b/composer/e-composer-private.c @@ -19,6 +19,8 @@ #include "e-composer-private.h" +#include "mail/e-mail-shell-module.h" + static void composer_setup_charset_menu (EMsgComposer *composer) { @@ -144,6 +146,14 @@ e_composer_private_init (EMsgComposer *composer) priv->header_table = g_object_ref (widget); gtk_widget_show (widget); + /* XXX We have to access the mail shell module directly for the + * benefit of other modules that spawn composer windows but + * don't link to the mail module. Need to work out a better + * inter-module messaging system, in lieu of Bonobo. D-Bus? */ + e_composer_header_table_set_folder_tree_model ( + E_COMPOSER_HEADER_TABLE (widget), + e_mail_shell_module_get_folder_tree_model (mail_shell_module)); + /* Construct attachment widgets. * XXX Move this stuff into a new custom widget. */ diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c index f2ef200219..4f4285215b 100644 --- a/composer/e-msg-composer.c +++ b/composer/e-msg-composer.c @@ -86,16 +86,16 @@ #include <camel/camel-smime-context.h> #endif -#include "mail/em-utils.h" #include "mail/em-composer-utils.h" +#include "mail/em-menu.h" +#include "mail/em-popup.h" +#include "mail/em-utils.h" #include "mail/mail-config.h" #include "mail/mail-crypto.h" -#include "mail/mail-tools.h" -#include "mail/mail-ops.h" #include "mail/mail-mt.h" +#include "mail/mail-ops.h" #include "mail/mail-session.h" -#include "mail/em-popup.h" -#include "mail/em-menu.h" +#include "mail/mail-tools.h" #include "e-msg-composer.h" #include "e-attachment.h" diff --git a/mail/Makefile.am b/mail/Makefile.am index e029968a0f..8eaf2ae5de 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -1,4 +1,4 @@ -#SUBDIRS = default importers +SUBDIRS = default importers mailincludedir = $(privincludedir)/mail @@ -48,10 +48,111 @@ libevolution_module_mail_la_SOURCES = \ e-mail-shell-view-actions.c \ e-mail-shell-view-actions.h \ e-mail-shell-view-private.c \ - e-mail-shell-view-private.h + e-mail-shell-view-private.h \ + e-searching-tokenizer.c \ + e-searching-tokenizer.h \ + em-account-editor.c \ + em-account-editor.h \ + em-composer-prefs.c \ + em-composer-prefs.h \ + em-composer-utils.c \ + em-composer-utils.h \ + em-config.c \ + em-config.h \ + em-event.c \ + em-event.h \ + em-filter-context.c \ + em-filter-context.h \ + em-filter-editor.c \ + em-filter-editor.h \ + em-filter-folder-element.c \ + em-filter-folder-element.h \ + em-filter-rule.c \ + em-filter-rule.h \ + em-filter-source-element.c \ + em-filter-source-element.h \ + em-folder-properties.c \ + em-folder-properties.h \ + em-folder-selection.c \ + em-folder-selection.h \ + em-folder-selector.c \ + em-folder-selector.h \ + em-folder-selection-button.c \ + em-folder-selection-button.h \ + em-folder-tree.c \ + em-folder-tree.h \ + em-folder-tree-model.c \ + em-folder-tree-model.h \ + em-folder-utils.c \ + em-folder-utils.h \ + em-format.c \ + em-format.h \ + em-format-hook.c \ + em-format-hook.h \ + em-format-html.c \ + em-format-html.h \ + em-format-html-display.c \ + em-format-html-display.h \ + em-format-html-print.c \ + em-format-html-print.h \ + em-format-quote.c \ + em-format-quote.h \ + em-html-stream.c \ + em-html-stream.h \ + em-icon-stream.c \ + em-icon-stream.h \ + em-inline-filter.c \ + em-inline-filter.h \ + em-junk-hook.c \ + em-junk-hook.h \ + em-popup.c \ + em-popup.h \ + em-search-context.c \ + em-search-context.h \ + em-stripsig-filter.c \ + em-stripsig-filter.h \ + em-sync-stream.c \ + em-sync-stream.h \ + em-utils.c \ + em-utils.h \ + em-vfolder-context.c \ + em-vfolder-context.h \ + em-vfolder-editor.c \ + em-vfolder-editor.h \ + em-vfolder-rule.c \ + em-vfolder-rule.h \ + mail-autofilter.c \ + mail-autofilter.h \ + mail-config.c \ + mail-config.h \ + mail-crypto.c \ + mail-crypto.h \ + mail-folder-cache.c \ + mail-folder-cache.h \ + mail-mt.c \ + mail-mt.h \ + mail-ops.c \ + mail-ops.h \ + mail-send-recv.c \ + mail-send-recv.h \ + mail-session.c \ + mail-session.h \ + mail-signature-editor.c \ + mail-signature-editor.h \ + mail-tools.c \ + mail-tools.h \ + mail-vfolder.c \ + mail-vfolder.h \ + message-tag-editor.c \ + message-tag-editor.h \ + message-tag-followup.c \ + message-tag-followup,h libevolution_module_mail_la_LIBADD = \ - $(top_builddir)/shell/libeshell.la + $(top_builddir)/composer/libcomposer.la \ + $(top_builddir)/mail/importers/libevolution-mail-importers.la \ + $(top_builddir)/shell/libeshell.la \ + $(top_builddir)/widgets/misc/libemiscwidgets.la # plugin mail api #mailinclude_HEADERS = \ diff --git a/mail/e-mail-shell-content.c b/mail/e-mail-shell-content.c index d0c773d470..84651d0b1c 100644 --- a/mail/e-mail-shell-content.c +++ b/mail/e-mail-shell-content.c @@ -25,12 +25,17 @@ #include "e-util/gconf-bridge.h" +#include "em-folder-browser.h" +#include "em-search-context.h" + #define E_MAIL_SHELL_CONTENT_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContentPrivate)) struct _EMailShellContentPrivate { GtkWidget *paned; + GtkWidget *msglist; + GtkWidget *preview; guint paned_binding_id; @@ -105,6 +110,16 @@ mail_shell_content_dispose (GObject *object) priv->paned = NULL; } + if (priv->msglist != NULL) { + g_object_unref (priv->msglist); + priv->msglist = NULL; + } + + if (priv->preview != NULL) { + g_object_unref (priv->preview); + priv->preview = NULL; + } + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -145,8 +160,10 @@ mail_shell_content_constructed (GObject *object) container = widget; + /*widget = em_folder_browser_new ();*/ widget = gtk_label_new ("Message List"); gtk_paned_add1 (GTK_PANED (container), widget); + priv->msglist = g_object_ref (widget); gtk_widget_show (widget); widget = gtk_scrolled_window_new (NULL, NULL); @@ -171,6 +188,7 @@ static void mail_shell_content_class_init (EMailShellContentClass *class) { GObjectClass *object_class; + EShellContentClass *shell_content_class; parent_class = g_type_class_peek_parent (class); g_type_class_add_private (class, sizeof (EMailShellContentPrivate)); @@ -182,6 +200,9 @@ mail_shell_content_class_init (EMailShellContentClass *class) object_class->finalize = mail_shell_content_finalize; object_class->constructed = mail_shell_content_constructed; + shell_content_class = E_SHELL_CONTENT_CLASS (class); + shell_content_class->new_search_context = em_search_context_new; + g_object_class_install_property ( object_class, PROP_PREVIEW_VISIBLE, diff --git a/mail/e-mail-shell-module-migrate.c b/mail/e-mail-shell-module-migrate.c index c41ec65e2e..a0ce1624cb 100644 --- a/mail/e-mail-shell-module-migrate.c +++ b/mail/e-mail-shell-module-migrate.c @@ -2953,7 +2953,8 @@ migrate_to_db (EShellModule *shell_module) CamelException ex; camel_exception_init (&ex); - e_mail_shell_module_load_store_by_uri (service->url, name); + e_mail_shell_module_load_store_by_uri ( + shell_module, service->url, name); store = (CamelStore *) camel_session_get_service (CAMEL_SESSION (session), service->url, CAMEL_PROVIDER_STORE, &ex); info = camel_store_get_folder_info (store, NULL, CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST|CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, &ex); diff --git a/mail/e-mail-shell-module.c b/mail/e-mail-shell-module.c index cd74a76cd9..7ee718a9de 100644 --- a/mail/e-mail-shell-module.c +++ b/mail/e-mail-shell-module.c @@ -20,23 +20,365 @@ */ #include <glib/gi18n.h> +#include <camel/camel-session.h> +#include <camel/camel-url.h> +#include "e-util/e-import.h" +#include "e-util/e-util.h" #include "shell/e-shell.h" -#include "shell/e-shell-module.h" #include "shell/e-shell-window.h" #include "e-mail-shell-view.h" #include "e-mail-shell-module.h" #include "e-mail-shell-module-migrate.h" +#include "em-config.h" +#include "em-event.h" +#include "em-folder-tree-model.h" +#include "em-format-hook.h" +#include "em-format-html-display.h" +#include "em-junk-hook.h" +#include "mail-config.h" +#include "mail-folder-cache.h" +#include "mail-mt.h" +#include "mail-session.h" +#include "importers/mail-importer.h" + #define MODULE_NAME "mail" #define MODULE_ALIASES "" #define MODULE_SCHEMES "mailto:email" #define MODULE_SORT_ORDER 200 +typedef struct _StoreInfo StoreInfo; + +/* XXX Temporary */ +CamelStore *vfolder_store; + +struct _StoreInfo { + CamelStore *store; + gint ref_count; + gchar *name; + + /* Keep a reference to these so they remain around for the session. */ + CamelFolder *vtrash; + CamelFolder *vjunk; + + /* Initialization callback. */ + void (*done) (CamelStore *store, + CamelFolderInfo *info, + gpointer user_data); + gpointer done_user_data; + + guint removed : 1; +}; + /* Module Entry Point */ void e_shell_module_init (GTypeModule *type_module); +/* The array elements correspond to EMailFolderType. */ +static struct { + gchar *name; + gchar *uri; + CamelFolder *folder; +} default_local_folders[] = { + { N_("Inbox") }, + { N_("Drafts") }, + { N_("Outbox") }, + { N_("Sent") }, + { N_("Templates") }, + { "Inbox" } /* "always local" inbox */ +}; + +/* XXX So many things need the shell module that it's + * just easier to make it globally available. */ +EShellModule *mail_shell_module = NULL; + +static GHashTable *store_hash; +static MailAsyncEvent *async_event; +static EMFolderTreeModel *folder_tree_model; +static CamelStore *local_store; + +G_LOCK_DEFINE_STATIC (local_store); + +static StoreInfo * +store_info_new (CamelStore *store, + const gchar *name) +{ + CamelService *service; + StoreInfo *si; + + g_return_val_if_fail (CAMEL_IS_STORE (store), NULL); + + service = CAMEL_SERVICE (store); + + si = g_slice_new0 (StoreInfo); + si->ref_count = 1; + + if (name == NULL) + si->name = camel_service_get_name (service, TRUE); + else + si->name = g_strdup (name); + + si->store = store; + camel_object_ref (store); + + /* If these are vfolders then they need to be opened now, + * otherwise they won't keep track of all folders. */ + if (store->flags & CAMEL_STORE_VTRASH) + si->vtrash = camel_store_get_trash (store, NULL); + if (store->flags & CAMEL_STORE_VJUNK) + si->vjunk = camel_store_get_junk (store, NULL); + + return si; +} + +static StoreInfo * +store_info_ref (StoreInfo *si) +{ + g_return_val_if_fail (si != NULL, si); + g_return_val_if_fail (si->ref_count > 0, si); + + g_atomic_int_add (&si->ref_count, 1); + + return si; +} + +static void +store_info_unref (StoreInfo *si) +{ + g_return_if_fail (si != NULL); + g_return_if_fail (si->ref_count > 0); + + if (g_atomic_int_exchange_and_add (&si->ref_count, -1) > 1) + return; + + if (si->vtrash != NULL) + camel_object_unref (si->vtrash); + if (si->vjunk != NULL) + camel_object_unref (si->vjunk); + camel_object_unref (si->store); + g_free (si->name); + + g_slice_free (StoreInfo, si); +} + +static void +store_hash_free (StoreInfo *si) +{ + si->removed = 1; + store_info_unref (si); +} + +static gboolean +mail_shell_module_add_store_done (CamelStore *store, + CamelFolderInfo *info, + gpointer user_data) +{ + StoreInfo *si = user_data; + + if (si->done != NULL) + si->done (store, info, si); + + if (!si->removed) { + /* Let the counters know about the already-opened + * junk and trash folders. */ + if (si->vtrash != NULL) + mail_note_folder (si->vtrash); + if (si->vjunk != NULL) + mail_note_folder (si->vjunk); + } + + store_info_unref (si); + + return TRUE; +} + +static void +mail_shell_module_add_store (EShellModule *shell_module, + CamelStore *store, + const gchar *name, + void (*done) (CamelStore *store, + CamelFolderInfo *info, + gpointer user_data)) +{ + StoreInfo *si; + + si = store_info_new (store, name); + si->done = done; + g_hash_table_insert (store_hash, store, si); + + em_folder_tree_model_add_store (folder_tree_model, store, si->name); + + mail_note_store ( + shell_module, store, NULL, + mail_shell_module_add_store_done, store_info_ref (si)); +} + +static void +mail_shell_module_add_local_store_done (CamelStore *store, + CamelFolderInfo *info, + gpointer unused) +{ + gint ii; + + for (ii = 0; ii < G_N_ELEMENTS (default_local_folders); ii++) { + if (default_local_folders[ii].folder != NULL) + mail_note_folder (default_local_folders[ii].folder); + } +} + +static void +mail_shell_module_add_local_store (EShellModule *shell_module, + CamelStore *local_store, + const gchar *name) +{ + mail_shell_module_add_store ( + shell_module, local_store, name, + mail_shell_module_add_local_store_done); +} + +static void +mail_shell_module_init_hooks (void) +{ + e_plugin_hook_register_type (em_config_hook_get_type ()); + e_plugin_hook_register_type (em_event_hook_get_type ()); + e_plugin_hook_register_type (em_format_hook_get_type ()); + e_plugin_hook_register_type (em_junk_hook_get_type ()); + + em_format_hook_register_type (em_format_get_type ()); + em_format_hook_register_type (em_format_html_get_type ()); + em_format_hook_register_type (em_format_html_display_get_type ()); + + em_junk_hook_register_type (emj_get_type ()); +} + +static void +mail_shell_module_init_importers (void) +{ + EImportClass *import_class; + EImportImporter *importer; + + import_class = g_type_class_ref (e_import_get_type ()); + + importer = mbox_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = elm_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = pine_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); +} + +static void +mail_shell_module_init_local_store (EShellModule *shell_module) +{ + CamelException ex; + CamelService *service; + CamelURL *url; + const gchar *data_dir; + gchar *temp; + gint ii; + + camel_exception_init (&ex); + + url = camel_url_new ("mbox:", NULL); + data_dir = e_shell_module_get_data_dir (shell_module); + temp = g_build_filename (data_dir, "local", NULL); + camel_url_set_path (url, temp); + g_free (temp); + + temp = camel_url_to_string (url, 0); + service = camel_session_get_service ( + session, temp, CAMEL_PROVIDER_STORE, &ex); + g_free (temp); + + if (service == NULL) + goto fail; + + for (ii = 0; ii < G_N_ELEMENTS (default_local_folders); ii++) { + /* FIXME Should this URI be account relative? */ + camel_url_set_fragment (url, default_local_folders[ii].name); + default_local_folders[ii].uri = camel_url_to_string (url, 0); + default_local_folders[ii].folder = camel_store_get_folder ( + CAMEL_STORE (service), default_local_folders[ii].name, + CAMEL_STORE_FOLDER_CREATE, &ex); + camel_exception_clear (&ex); + } + + camel_url_free (url); + + camel_object_ref (service); + g_object_ref (shell_module); + + mail_async_event_emit ( + async_event, MAIL_ASYNC_GUI, + (MailAsyncFunc) mail_shell_module_add_local_store, + shell_module, service, _("On This Computer")); + + local_store = CAMEL_STORE (service); + + return; + +fail: + g_warning ("Could not initialize local store/folder: %s", ex.desc); + + camel_exception_clear (&ex); + camel_url_free (url); +} + +static void +mail_shell_module_load_accounts (EShellModule *shell_module) +{ + EAccountList *account_list; + EIterator *iter; + + account_list = mail_config_get_accounts (); + + for (iter = e_list_get_iterator ((EList *) account_list); + e_iterator_is_valid (iter); e_iterator_next (iter)) { + + EAccountService *service; + EAccount *account; + const gchar *name; + const gchar *url; + + account = (EAccount *) e_iterator_get (iter); + service = account->source; + name = account->name; + url = service->url; + + if (!account->enabled) + continue; + + if (url == NULL || *url == '\0') + continue; + + /* HACK: mbox URL's are handled by the local store setup + * above. Any that come through as account sources + * are really movemail sources! */ + if (g_str_has_prefix (url, "mbox:")) + continue; + + e_mail_shell_module_load_store_by_uri ( + shell_module, url, name); + } + + g_object_unref (iter); +} + +static void +mail_shell_module_new_mail_cb (EShellWindow *shell_window) +{ + GtkAction *action; + + action = e_shell_window_get_shell_view_action ( + shell_window, MODULE_NAME); + g_object_set (action, "icon-name", "mail-unread", NULL); + + g_print ("Shell Event: new-mail\n"); +} + static void action_mail_folder_new_cb (GtkAction *action, EShellWindow *shell_window) @@ -83,8 +425,10 @@ static void mail_module_window_created (EShellModule *shell_module, EShellWindow *shell_window) { + EShell *shell; const gchar *module_name; + shell = e_shell_module_get_shell (shell_module); module_name = G_TYPE_MODULE (shell_module)->name; e_shell_window_register_new_item_actions ( @@ -94,6 +438,10 @@ mail_module_window_created (EShellModule *shell_module, e_shell_window_register_new_source_actions ( shell_window, module_name, source_entries, G_N_ELEMENTS (source_entries)); + + g_signal_connect_swapped ( + shell, "event::new-mail", + G_CALLBACK (mail_shell_module_new_mail_cb), shell_window); } static EShellModuleInfo module_info = { @@ -121,6 +469,24 @@ e_shell_module_init (GTypeModule *type_module) shell_module, &module_info, e_mail_shell_view_get_type (type_module)); + /* This also initializes Camel, so it needs to happen early. */ + mail_session_init (shell_module); + + mail_shell_module_init_hooks (); + mail_shell_module_init_importers (); + + /* XXX This never gets unreffed. */ + mail_shell_module = g_object_ref (shell_module); + + store_hash = g_hash_table_new_full ( + g_direct_hash, g_direct_equal, + (GDestroyNotify) NULL, + (GDestroyNotify) store_hash_free); + + async_event = mail_async_event_new (); + + folder_tree_model = em_folder_tree_model_new (shell_module); + g_signal_connect_swapped ( shell, "handle-uri", G_CALLBACK (mail_module_handle_uri), shell_module); @@ -128,48 +494,106 @@ e_shell_module_init (GTypeModule *type_module) g_signal_connect_swapped ( shell, "window-created", G_CALLBACK (mail_module_window_created), shell_module); + + mail_config_init (); + mail_msg_init (); + + mail_shell_module_init_local_store (shell_module); + mail_shell_module_load_accounts (shell_module); } -/** - * e_mail_shell_module_load_store_by_uri: - * @uri: URI of the #CamelStore - * @name: name of the #CamelStore (for display purposes) - * - * Returns the newly added #CamelStore, or %NULL if a store could not - * be loaded for @uri. - * - * Returns: the newly added #CamelStore, or %NULL - **/ -CamelStore * -e_mail_shell_module_load_store_by_uri (const gchar *uri, - const gchar *name) +/******************************** Public API *********************************/ + +CamelFolder * +e_mail_shell_module_get_folder (EShellModule *shell_module, + EMailFolderType folder_type) { - return NULL; /* FIXME */ + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + + return default_local_folders[folder_type].folder; } -EAccountList * -mail_config_get_accounts (void) +const gchar * +e_mail_shell_module_get_folder_uri (EShellModule *shell_module, + EMailFolderType folder_type) { - /* XXX Temporary placeholder. */ - return NULL; + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + + return default_local_folders[folder_type].uri; +} + +EMFolderTreeModel * +e_mail_shell_module_get_folder_tree_model (EShellModule *shell_module) +{ + /* Require a shell module in case we need it in the future. */ + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + + return folder_tree_model; } void -mail_config_save_accounts (void) +e_mail_shell_module_add_store (EShellModule *shell_module, + CamelStore *store, + const gchar *name) { - /* XXX Temporary placeholder. */ + g_return_if_fail (E_IS_SHELL_MODULE (shell_module)); + g_return_if_fail (CAMEL_IS_STORE (store)); + g_return_if_fail (name != NULL); + + mail_shell_module_add_store (shell_module, store, name, NULL); } -ESignatureList * -mail_config_get_signatures (void) +CamelStore * +e_mail_shell_module_get_local_store (EShellModule *shell_module) { - /* XXX Temporary placeholder. */ - return NULL; + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + g_return_val_if_fail (local_store != NULL, NULL); + + return local_store; } -gchar * -em_uri_from_camel (const gchar *curi) +CamelStore * +e_mail_shell_module_load_store_by_uri (EShellModule *shell_module, + const gchar *uri, + const gchar *name) { - /* XXX Temporary placeholder. */ + CamelStore *store; + CamelProvider *provider; + CamelException ex; + + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (name != NULL, NULL); + + camel_exception_init (&ex); + + /* Load the service, but don't connect. Check its provider, + * and if this belongs in the shell's folder list, add it. */ + + provider = camel_provider_get (uri, &ex); + if (provider == NULL) + goto fail; + + if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE)) + return NULL; + + store = (CamelStore *) camel_session_get_service ( + session, uri, CAMEL_PROVIDER_STORE, &ex); + if (store == NULL) + goto fail; + + e_mail_shell_module_add_store (shell_module, store, name); + + camel_object_unref (store); + + return store; + +fail: + /* FIXME: Show an error dialog. */ + g_warning ( + "Couldn't get service: %s: %s", uri, + camel_exception_get_description (&ex)); + camel_exception_clear (&ex); + return NULL; } diff --git a/mail/e-mail-shell-module.h b/mail/e-mail-shell-module.h index 4d48adbcd7..fb1cd3885d 100644 --- a/mail/e-mail-shell-module.h +++ b/mail/e-mail-shell-module.h @@ -22,19 +22,50 @@ #ifndef E_MAIL_SHELL_MODULE_H #define E_MAIL_SHELL_MODULE_H +#include <shell/e-shell-module.h> + +#include <camel/camel-folder.h> #include <camel/camel-store.h> #include <e-util/e-signature-list.h> #include <libedataserver/e-account-list.h> G_BEGIN_DECLS +/* Globally available shell module. + * + * XXX I don't like having this globally available but passing it around to + * all the various utilities that need to access to the module's data + * directory and local folders is too much of a pain for now. */ +extern EShellModule *mail_shell_module; + +typedef enum { + E_MAIL_FOLDER_INBOX, + E_MAIL_FOLDER_DRAFTS, + E_MAIL_FOLDER_OUTBOX, + E_MAIL_FOLDER_SENT, + E_MAIL_FOLDER_TEMPLATES, + E_MAIL_FOLDER_LOCAL_INBOX +} EMailFolderType; + +struct _EMFolderTreeModel; + +CamelFolder * e_mail_shell_module_get_folder (EShellModule *shell_module, + EMailFolderType folder_type); +const gchar * e_mail_shell_module_get_folder_uri + (EShellModule *shell_module, + EMailFolderType folder_type); +struct _EMFolderTreeModel * + e_mail_shell_module_get_folder_tree_model + (EShellModule *shell_module); +void e_mail_shell_module_add_store (EShellModule *shell_module, + CamelStore *store, + const gchar *name); +CamelStore * e_mail_shell_module_get_local_store + (EShellModule *shell_module); CamelStore * e_mail_shell_module_load_store_by_uri - (const gchar *uri, + (EShellModule *shell_module, + const gchar *uri, const gchar *name); -EAccountList * mail_config_get_accounts (void); -void mail_config_save_accounts (void); -ESignatureList *mail_config_get_signatures (void); -gchar * em_uri_from_camel (const gchar *curi); G_END_DECLS diff --git a/mail/e-mail-shell-sidebar.c b/mail/e-mail-shell-sidebar.c index 21dc949f6f..9c8aa9ed1b 100644 --- a/mail/e-mail-shell-sidebar.c +++ b/mail/e-mail-shell-sidebar.c @@ -21,12 +21,14 @@ #include "e-mail-shell-sidebar.h" +#include "mail/em-folder-tree.h" + #define E_MAIL_SHELL_SIDEBAR_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebarPrivate)) struct _EMailShellSidebarPrivate { - gint dummy; + GtkWidget *folder_tree; }; enum { @@ -51,6 +53,11 @@ mail_shell_sidebar_dispose (GObject *object) priv = E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (object); + if (priv->folder_tree != NULL) { + g_object_unref (priv->folder_tree); + priv->folder_tree = NULL; + } + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -70,11 +77,42 @@ static void mail_shell_sidebar_constructed (GObject *object) { EMailShellSidebarPrivate *priv; + EShellSidebar *shell_sidebar; + EShellModule *shell_module; + EShellView *shell_view; + GtkWidget *container; + GtkWidget *widget; priv = E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (object); /* Chain up to parent's constructed method. */ G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_sidebar = E_SHELL_SIDEBAR (object); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_module = e_shell_view_get_shell_module (shell_view); + + /* Build sidebar widgets. */ + + container = GTK_WIDGET (object); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = em_folder_tree_new (shell_module); + em_folder_tree_set_excluded (EM_FOLDER_TREE (widget), 0); + em_folder_tree_enable_drag_and_drop (EM_FOLDER_TREE (widget)); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->folder_tree = g_object_ref (widget); + gtk_widget_show (widget); } static void diff --git a/mail/e-mail-shell-view-actions.c b/mail/e-mail-shell-view-actions.c index fd1abe6b64..c78c562143 100644 --- a/mail/e-mail-shell-view-actions.c +++ b/mail/e-mail-shell-view-actions.c @@ -676,6 +676,46 @@ action_mail_undelete_cb (GtkAction *action, } static void +action_mail_uri_call_to_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + /* FIXME */ + g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); +} + +static void +action_mail_uri_copy_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + /* FIXME */ + g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); +} + +static void +action_mail_uri_copy_address_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + /* FIXME */ + g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); +} + +static void +action_mail_uri_to_search_folder_recipient_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + /* FIXME */ + g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); +} + +static void +action_mail_uri_to_search_folder_sender_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + /* FIXME */ + g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); +} + +static void action_mail_zoom_100_cb (GtkAction *action, EMailShellView *mail_shell_view) { @@ -744,7 +784,12 @@ static GtkActionEntry mail_entries[] = { N_("Copy selected messages to another folder"), G_CALLBACK (action_mail_copy_cb) }, - { "mail-create-search-folder" }, + { "mail-create-search-folder", + NULL, + N_("C_reate Search Folder From Search..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_create_search_folder_cb) }, { "mail-delete", "user-trash", @@ -1291,6 +1336,41 @@ static GtkActionEntry mail_entries[] = { N_("Undelete the selected messages"), G_CALLBACK (action_mail_undelete_cb) }, + { "mail-uri-call-to", + NULL, + N_("C_all To..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_uri_call_to_cb) }, + + { "mail-uri-copy", + GTK_STOCK_COPY, + N_("_Copy Link Location"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_uri_copy_cb) }, + + { "mail-uri-copy-address", + GTK_STOCK_COPY, + N_("Copy _Email Address"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_uri_copy_address_cb) }, + + { "mail-uri-to-search-folder-recipient", + NULL, + N_("_To This Address"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_uri_to_search_folder_recipient_cb) }, + + { "mail-uri-to-search-folder-sender", + NULL, + N_("_From This Address"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_uri_to_search_folder_sender_cb) }, + { "mail-zoom-100", GTK_STOCK_ZOOM_100, N_("_Normal Size"), @@ -1377,6 +1457,13 @@ static GtkActionEntry mail_entries[] = { NULL, NULL }, + { "mail-uri-to-search-folder-menu", + NULL, + N_("Create _Search Folder"), + NULL, + NULL, + NULL }, + { "mail-zoom-menu", NULL, N_("_Zoom"), diff --git a/mail/e-mail-shell-view.c b/mail/e-mail-shell-view.c index d8c386754f..1097b280fe 100644 --- a/mail/e-mail-shell-view.c +++ b/mail/e-mail-shell-view.c @@ -87,7 +87,7 @@ mail_shell_view_class_init (EMailShellViewClass *class, object_class->constructed = mail_shell_view_constructed; shell_view_class = E_SHELL_VIEW_CLASS (class); - shell_view_class->label = N_("Mail"); + shell_view_class->label = _("Mail"); shell_view_class->icon_name = "evolution-mail"; shell_view_class->ui_definition = "evolution-mail.ui"; shell_view_class->search_options = "/mail-search-options"; diff --git a/mail/em-account-editor.c b/mail/em-account-editor.c index caa8aa50f5..62f1b89d6b 100644 --- a/mail/em-account-editor.c +++ b/mail/em-account-editor.c @@ -63,13 +63,14 @@ #include "mail-session.h" #include "mail-send-recv.h" #include "mail-signature-editor.h" -#include "mail-component.h" #include "em-utils.h" #include "em-composer-prefs.h" #include "mail-config.h" #include "mail-ops.h" #include "mail-mt.h" +#include "e-mail-shell-module.h" + #if defined (HAVE_NSS) #include "smime/gui/e-cert-selector.h" #endif @@ -447,11 +448,13 @@ default_folders_clicked (GtkButton *button, gpointer user_data) EMAccountEditor *emae = user_data; const char *uri; - uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS); + uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); em_folder_selection_button_set_selection((EMFolderSelectionButton *)emae->priv->drafts_folder_button, uri); emae_account_folder_changed((EMFolderSelectionButton *)emae->priv->drafts_folder_button, emae); - uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT); + uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_SENT); em_folder_selection_button_set_selection((EMFolderSelectionButton *)emae->priv->sent_folder_button, uri); emae_account_folder_changed((EMFolderSelectionButton *)emae->priv->sent_folder_button, emae); } @@ -462,7 +465,10 @@ GtkWidget *em_account_editor_folder_selector_button_new (char *widget_name, char GtkWidget * em_account_editor_folder_selector_button_new (char *widget_name, char *string1, char *string2, int int1, int int2) { - return (GtkWidget *)em_folder_selection_button_new(string1 ? string1 : _("Select Folder"), NULL); + EMFolderTreeModel *model; + + model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); + return (GtkWidget *)em_folder_selection_button_new(model, string1 ? string1 : _("Select Folder"), NULL); } GtkWidget *em_account_editor_dropdown_new(char *widget_name, char *string1, char *string2, int int1, int int2); @@ -889,7 +895,11 @@ emae_account_folder(EMAccountEditor *emae, const char *name, int item, int deffo em_folder_selection_button_set_selection(folder, tmp); g_free(tmp); } else { - em_folder_selection_button_set_selection(folder, mail_component_get_folder_uri(NULL, deffolder)); + const gchar *uri; + + uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, deffolder); + em_folder_selection_button_set_selection(folder, uri); } g_object_set_data((GObject *)folder, "account-item", GINT_TO_POINTER(item)); @@ -2352,8 +2362,8 @@ emae_defaults_page(EConfig *ec, EConfigItem *item, struct _GtkWidget *parent, st g_free (gladefile); /* Special folders */ - gui->drafts_folder_button = (GtkButton *)emae_account_folder(emae, "drafts_button", E_ACCOUNT_DRAFTS_FOLDER_URI, MAIL_COMPONENT_FOLDER_DRAFTS, xml); - gui->sent_folder_button = (GtkButton *)emae_account_folder(emae, "sent_button", E_ACCOUNT_SENT_FOLDER_URI, MAIL_COMPONENT_FOLDER_SENT, xml); + gui->drafts_folder_button = (GtkButton *)emae_account_folder(emae, "drafts_button", E_ACCOUNT_DRAFTS_FOLDER_URI, E_MAIL_FOLDER_DRAFTS, xml); + gui->sent_folder_button = (GtkButton *)emae_account_folder(emae, "sent_button", E_ACCOUNT_SENT_FOLDER_URI, E_MAIL_FOLDER_SENT, xml); /* Special Folders "Reset Defaults" button */ gui->restore_folders_button = (GtkButton *)glade_xml_get_widget (xml, "default_folders_button"); @@ -2767,6 +2777,7 @@ emae_check_complete(EConfig *ec, const char *pageid, void *data) static void add_new_store (char *uri, CamelStore *store, void *user_data) { +#if 0 /* KILL-BONOBO: Try to actually fix this? */ MailComponent *component = mail_component_peek (); EAccount *account = user_data; @@ -2774,6 +2785,7 @@ add_new_store (char *uri, CamelStore *store, void *user_data) return; mail_component_add_store (component, store, account->name); +#endif } static void @@ -2840,13 +2852,21 @@ em_account_editor_construct(EMAccountEditor *emae, EAccount *account, em_account emae->do_signature = TRUE; } else { + const gchar *uri; + /* TODO: have a get_default_account thing?? */ emae->account = e_account_new(); emae->account->enabled = TRUE; - e_account_set_string(emae->account, E_ACCOUNT_DRAFTS_FOLDER_URI, - mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS)); - e_account_set_string(emae->account, E_ACCOUNT_SENT_FOLDER_URI, - mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT)); + + uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); + e_account_set_string ( + emae->account, E_ACCOUNT_DRAFTS_FOLDER_URI, uri); + + uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_SENT); + e_account_set_string ( + emae->account, E_ACCOUNT_SENT_FOLDER_URI, uri); } /* sort the providers, remote first */ diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c index 3d18fc824c..09f5419101 100644 --- a/mail/em-composer-utils.c +++ b/mail/em-composer-utils.c @@ -37,7 +37,6 @@ #include "mail-config.h" #include "mail-session.h" #include "mail-send-recv.h" -#include "mail-component.h" #include "e-util/e-error.h" @@ -58,6 +57,8 @@ #include <camel/camel-nntp-address.h> #include <camel/camel-vee-folder.h> +#include "e-mail-shell-module.h" + #ifdef G_OS_WIN32 /* Undef the similar macro from pthread.h, it doesn't check if * gmtime() returns NULL. @@ -436,7 +437,8 @@ em_utils_composer_send_cb (EMsgComposer *composer, gpointer user_data) if (!(message = composer_get_message (composer, FALSE))) return; - mail_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + mail_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); camel_object_ref (mail_folder); /* mail the message */ @@ -558,10 +560,10 @@ save_draft_folder (char *uri, CamelFolder *folder, gpointer data) void em_utils_composer_save_draft_cb (EMsgComposer *composer, gpointer user_data) { - const char *default_drafts_folder_uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS); - CamelFolder *drafts_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS); + CamelFolder *local_drafts_folder; EComposerHeaderTable *table; struct _save_draft_info *sdi; + const gchar *local_drafts_folder_uri; CamelFolder *folder = NULL; CamelMimeMessage *msg; CamelMessageInfo *info; @@ -571,6 +573,12 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer, gpointer user_data) * get destroyed while we're in mail_msg_wait() a little lower * down, waiting for the folder to open */ + local_drafts_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); + + local_drafts_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); + g_object_ref(composer); msg = e_msg_composer_get_message_draft (composer); table = e_msg_composer_get_header_table (composer); @@ -583,7 +591,7 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer, gpointer user_data) emcs_ref(sdi->emcs); if (account && account->drafts_folder_uri && - strcmp (account->drafts_folder_uri, default_drafts_folder_uri) != 0) { + strcmp (account->drafts_folder_uri, local_drafts_folder_uri) != 0) { int id; id = mail_get_folder (account->drafts_folder_uri, 0, save_draft_folder, &folder, mail_msg_unordered_push); @@ -599,11 +607,11 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer, gpointer user_data) return; } - folder = drafts_folder; - camel_object_ref (drafts_folder); + folder = local_drafts_folder; + camel_object_ref (local_drafts_folder); } } else { - folder = drafts_folder; + folder = local_drafts_folder; camel_object_ref (folder); } @@ -1559,7 +1567,8 @@ em_utils_send_receipt (CamelFolder *folder, CamelMimeMessage *message) } /* Send the receipt */ - out_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + out_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); info = camel_message_info_new (NULL); camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); mail_append_mail (out_folder, receipt, info, em_utils_receipt_done, NULL); diff --git a/mail/em-filter-folder-element.c b/mail/em-filter-folder-element.c index 3539881290..3f49796650 100644 --- a/mail/em-filter-folder-element.c +++ b/mail/em-filter-folder-element.c @@ -33,11 +33,12 @@ #include "em-filter-folder-element.h" #include "mail/em-folder-selection-button.h" -#include "mail/mail-component.h" #include "mail/em-utils.h" #include "libedataserver/e-sexp.h" #include "e-util/e-error.h" +#include "e-mail-shell-module.h" + #define d(x) static gboolean validate(FilterElement *fe); @@ -232,11 +233,13 @@ static GtkWidget * get_widget(FilterElement *fe) { EMFilterFolderElement *ff = (EMFilterFolderElement *)fe; + EMFolderTreeModel *model; GtkWidget *button; char *uri; uri = em_uri_to_camel(ff->uri); - button = em_folder_selection_button_new(_("Select Folder"), NULL); + model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); + button = em_folder_selection_button_new (model, _("Select Folder"), NULL); em_folder_selection_button_set_selection(EM_FOLDER_SELECTION_BUTTON(button), uri); g_free(uri); diff --git a/mail/em-folder-properties.c b/mail/em-folder-properties.c index b871d28203..a1ad47dbdd 100644 --- a/mail/em-folder-properties.c +++ b/mail/em-folder-properties.c @@ -39,12 +39,13 @@ #include "em-folder-properties.h" #include "em-config.h" -#include "mail-component.h" #include "mail-ops.h" #include "mail-mt.h" #include "mail-vfolder.h" #include "mail-config.h" +#include "e-mail-shell-module.h" + struct _prop_data { void *object; CamelArgV *argv; @@ -287,7 +288,10 @@ static EMConfigItem emfp_items[] = { static gboolean emfp_items_translated = FALSE; static void -emfp_dialog_got_folder_quota (CamelFolder *folder, CamelFolderQuotaInfo *quota, void *data) +emfp_dialog_got_folder_quota (CamelFolder *folder, + const gchar *folder_uri, + CamelFolderQuotaInfo *quota, + void *data) { GtkWidget *dialog, *w; struct _prop_data *prop_data; @@ -295,20 +299,26 @@ emfp_dialog_got_folder_quota (CamelFolder *folder, CamelFolderQuotaInfo *quota, gint32 count, i,deleted; EMConfig *ec; EMConfigTargetFolder *target; + EShellModule *shell_module; + EShellWindow *shell_window; + EShellView *shell_view; CamelArgGetV *arggetv; CamelArgV *argv; + CamelStore *local_store; gboolean hide_deleted; GConfClient *gconf; CamelStore *store; - char *uri = (char *)data; - if (folder == NULL) { - g_free (uri); + if (folder == NULL) return; - } store = folder->parent_store; + shell_view = E_SHELL_VIEW (data); + shell_module = e_shell_view_get_shell_module (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + local_store = e_mail_shell_module_get_local_store (shell_module); + prop_data = g_malloc0 (sizeof (*prop_data)); prop_data->object = folder; camel_object_ref (folder); @@ -341,7 +351,7 @@ emfp_dialog_got_folder_quota (CamelFolder *folder, CamelFolderQuotaInfo *quota, camel_object_get (folder, NULL, CAMEL_FOLDER_TOTAL, &prop_data->total, NULL); } - if (store == mail_component_peek_local_store(NULL) + if (store == local_store && (!strcmp(prop_data->name, "Drafts") || !strcmp(prop_data->name, "Inbox") || !strcmp(prop_data->name, "Outbox") @@ -386,11 +396,11 @@ emfp_dialog_got_folder_quota (CamelFolder *folder, CamelFolderQuotaInfo *quota, g_free (arggetv); prop_data->argv = argv; - dialog = gtk_dialog_new_with_buttons (_("Folder Properties"), NULL, - GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, - NULL); + dialog = gtk_dialog_new_with_buttons ( + _("Folder Properties"), GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_window_set_default_size ((GtkWindow *) dialog, 192, 160); gtk_widget_ensure_style (dialog); gtk_container_set_border_width ((GtkContainer *) ((GtkDialog *) dialog)->vbox, 12); @@ -410,7 +420,7 @@ emfp_dialog_got_folder_quota (CamelFolder *folder, CamelFolderQuotaInfo *quota, l = g_slist_prepend(l, &emfp_items[i]); e_config_add_items((EConfig *)ec, l, emfp_commit, NULL, emfp_free, prop_data); - target = em_config_target_new_folder(ec, folder, uri); + target = em_config_target_new_folder(ec, folder, folder_uri); e_config_set_target((EConfig *)ec, (EConfigTarget *)target); w = e_config_create_widget((EConfig *)ec); @@ -420,15 +430,17 @@ emfp_dialog_got_folder_quota (CamelFolder *folder, CamelFolderQuotaInfo *quota, g_signal_connect (dialog, "response", G_CALLBACK (emfp_dialog_response), prop_data); gtk_widget_show (dialog); - - g_free (uri); } static void emfp_dialog_got_folder (char *uri, CamelFolder *folder, void *data) { + EShellView *shell_view = data; + /* this should be called in a thread too */ - mail_get_folder_quota (folder, emfp_dialog_got_folder_quota, g_strdup (uri), mail_msg_unordered_push); + mail_get_folder_quota ( + folder, uri, emfp_dialog_got_folder_quota, + shell_view, mail_msg_unordered_push); } /** @@ -441,23 +453,25 @@ emfp_dialog_got_folder (char *uri, CamelFolder *folder, void *data) * as NULL, then the folder @uri will be loaded first. **/ void -em_folder_properties_show(GtkWindow *parent, CamelFolder *folder, const char *uri) +em_folder_properties_show (EShellView *shell_view, + CamelFolder *folder, + const gchar *uri) { /* HACK: its the old behaviour, not very 'neat' but it works */ - if (!strncmp(uri, "vfolder:", 8)) { - CamelURL *url = camel_url_new(uri, NULL); + if (!strncmp (uri, "vfolder:", 8)) { + CamelURL *url = camel_url_new (uri, NULL); /* MORE HACK: UNMATCHED is a special folder which you can't modify, so check for it here */ if (url == NULL || url->fragment == NULL || strcmp(url->fragment, CAMEL_UNMATCHED_NAME) != 0) { if (url) - camel_url_free(url); - vfolder_edit_rule(uri); + camel_url_free (url); + vfolder_edit_rule (uri); return; } - if (url) - camel_url_free(url); + if (url != NULL) + camel_url_free (url); } if (folder == NULL) diff --git a/mail/em-folder-properties.h b/mail/em-folder-properties.h index 8bae3848e7..35d80c293b 100644 --- a/mail/em-folder-properties.h +++ b/mail/em-folder-properties.h @@ -24,18 +24,15 @@ #ifndef __EM_FOLDER_PROPERTIES_H__ #define __EM_FOLDER_PROPERTIES_H__ -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ +#include <camel/camel-folder.h> +#include <shell/e-shell-view.h> -struct _CamelFolder; -struct _GtkWindow; +G_BEGIN_DECLS -void em_folder_properties_show(struct _GtkWindow *parent, struct _CamelFolder *folder, const char *uri); +void em_folder_properties_show (EShellView *shell_view, + CamelFolder *folder, + const gchar *uri); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS #endif /* __EM_FOLDER_PROPERTIES_H__ */ diff --git a/mail/em-folder-selection-button.c b/mail/em-folder-selection-button.c index 9257c57b5d..f85d3d84fb 100644 --- a/mail/em-folder-selection-button.c +++ b/mail/em-folder-selection-button.c @@ -25,11 +25,9 @@ #endif #include <string.h> - -#include <e-util/e-util.h> #include <glib/gi18n.h> +#include <e-util/e-util.h> -#include "mail-component.h" #include "mail-config.h" #include "em-folder-tree.h" #include "em-folder-selector.h" @@ -37,250 +35,419 @@ #include "em-folder-selection-button.h" -static void em_folder_selection_button_class_init (EMFolderSelectionButtonClass *klass); -static void em_folder_selection_button_init (EMFolderSelectionButton *emfsb); -static void em_folder_selection_button_destroy (GtkObject *obj); -static void em_folder_selection_button_finalize (GObject *obj); -static void em_folder_selection_button_clicked (GtkButton *button); - -static GtkButtonClass *parent_class = NULL; +#define EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButtonPrivate)) struct _EMFolderSelectionButtonPrivate { + gpointer model; /* weak pointer */ + GtkWidget *icon; GtkWidget *label; - GtkWidget *selector; - - char *uri; /* for single-select mode */ + gchar *uri; /* for single-select mode */ GList *uris; /* for multi-select mode */ - char *title; - char *caption; + gchar *title; + gchar *caption; gboolean multiple_select; }; enum { + PROP_0, + PROP_CAPTION, + PROP_MODEL, + PROP_MULTISELECT, + PROP_TITLE +}; + +enum { SELECTED, LAST_SIGNAL }; -static guint signals[LAST_SIGNAL] = { 0 }; +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; -GType -em_folder_selection_button_get_type (void) +static void +folder_selection_button_unselected (EMFolderSelectionButton *button) { - static GType type = 0; + const gchar *text; - if (!type) { - static const GTypeInfo info = { - sizeof (EMFolderSelectionButtonClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) em_folder_selection_button_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EMFolderSelectionButton), - 0, /* n_preallocs */ - (GInstanceInitFunc) em_folder_selection_button_init, - }; + text = _("<click here to select a folder>"); + gtk_image_set_from_pixbuf (GTK_IMAGE (button->priv->icon), NULL); + gtk_label_set_text (GTK_LABEL (button->priv->label), text); +} - type = g_type_register_static (GTK_TYPE_BUTTON, "EMFolderSelectionButton", &info, 0); +static void +folder_selection_button_set_contents (EMFolderSelectionButton *button) +{ + EAccount *account; + GtkLabel *label; + const gchar *uri; + gchar *folder_name; + + uri = button->priv->uri; + label = GTK_LABEL (button->priv->label); + folder_name = em_utils_folder_name_from_uri (uri); + + if (folder_name == NULL) { + folder_selection_button_unselected (button); + return; } - return type; + account = mail_config_get_account_by_source_url (uri); + + if (account != NULL) { + gchar *tmp = folder_name; + + folder_name = g_strdup_printf ( + "%s/%s", e_account_get_string ( + account, E_ACCOUNT_NAME), _(folder_name)); + gtk_label_set_text (label, folder_name); + g_free (tmp); + } else + gtk_label_set_text (label, _(folder_name)); + + g_free (folder_name); } static void -em_folder_selection_button_class_init (EMFolderSelectionButtonClass *klass) +folder_selection_button_set_model (EMFolderSelectionButton *button, + EMFolderTreeModel *model) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass); - GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass); - - parent_class = g_type_class_ref (GTK_TYPE_BUTTON); - - object_class->finalize = em_folder_selection_button_finalize; - gtk_object_class->destroy = em_folder_selection_button_destroy; - button_class->clicked = em_folder_selection_button_clicked; - - signals[SELECTED] = g_signal_new ("selected", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderSelectionButtonClass, selected), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + g_return_if_fail (button->priv->model == NULL); + + button->priv->model = model; + + g_object_add_weak_pointer ( + G_OBJECT (model), &button->priv->model); } static void -set_contents_unselected (EMFolderSelectionButton *button) +folder_selection_button_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - gtk_image_set_from_pixbuf (GTK_IMAGE (button->priv->icon), NULL); - gtk_label_set_text (GTK_LABEL (button->priv->label), _("<click here to select a folder>")); + switch (property_id) { + case PROP_CAPTION: + em_folder_selection_button_set_caption ( + EM_FOLDER_SELECTION_BUTTON (object), + g_value_get_string (value)); + return; + + case PROP_MODEL: + folder_selection_button_set_model ( + EM_FOLDER_SELECTION_BUTTON (object), + g_value_get_object (value)); + return; + + case PROP_MULTISELECT: + em_folder_selection_button_set_multiselect ( + EM_FOLDER_SELECTION_BUTTON (object), + g_value_get_boolean (value)); + return; + + case PROP_TITLE: + em_folder_selection_button_set_title ( + EM_FOLDER_SELECTION_BUTTON (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -set_contents (EMFolderSelectionButton *button) +folder_selection_button_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - struct _EMFolderSelectionButtonPrivate *priv = button->priv; - char *folder_name = em_utils_folder_name_from_uri (priv->uri); + switch (property_id) { + case PROP_CAPTION: + g_value_set_string ( + value, + em_folder_selection_button_get_caption ( + EM_FOLDER_SELECTION_BUTTON (object))); + return; + + case PROP_MODEL: + g_value_set_object ( + value, + em_folder_selection_button_get_model ( + EM_FOLDER_SELECTION_BUTTON (object))); + return; + + case PROP_MULTISELECT: + g_value_set_boolean ( + value, + em_folder_selection_button_get_multiselect ( + EM_FOLDER_SELECTION_BUTTON (object))); + return; + + case PROP_TITLE: + g_value_set_string ( + value, + em_folder_selection_button_get_title ( + EM_FOLDER_SELECTION_BUTTON (object))); + return; + } - if (folder_name) { - EAccount *account = mail_config_get_account_by_source_url (priv->uri); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} - if (account) { - char *tmp = folder_name; - folder_name = g_strdup_printf ("%s/%s", e_account_get_string (account, E_ACCOUNT_NAME), _(folder_name)); - g_free (tmp); - gtk_label_set_text (GTK_LABEL (priv->label), folder_name); - } else - gtk_label_set_text (GTK_LABEL (priv->label), _(folder_name)); +static void +folder_selection_button_dispose (GObject *object) +{ + EMFolderSelectionButtonPrivate *priv; - g_free (folder_name); - } else { - set_contents_unselected (button); + priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (object); + + if (priv->model != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->model), &priv->model); + priv->model = NULL; } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -em_folder_selection_button_init (EMFolderSelectionButton *emfsb) +folder_selection_button_finalize (GObject *object) { - struct _EMFolderSelectionButtonPrivate *priv; - GtkWidget *box; + EMFolderSelectionButtonPrivate *priv; - priv = g_new0 (struct _EMFolderSelectionButtonPrivate, 1); - emfsb->priv = priv; + priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (object); - priv->multiple_select = FALSE; + g_list_foreach (priv->uris, (GFunc) g_free, NULL); + g_list_free (priv->uris); - box = gtk_hbox_new (FALSE, 4); + g_free (priv->title); + g_free (priv->caption); + g_free (priv->uri); - priv->icon = gtk_image_new (); - gtk_widget_show (priv->icon); - gtk_box_pack_start (GTK_BOX (box), priv->icon, FALSE, TRUE, 0); + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} - priv->label = gtk_label_new (""); - gtk_widget_show (priv->label); - gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_LEFT); - gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.0); - gtk_box_pack_start (GTK_BOX (box), priv->label, TRUE, TRUE, 0); +static void +folder_selection_button_destroy (GtkObject *object) +{ + EMFolderSelectionButtonPrivate *priv; - gtk_widget_show (box); - gtk_container_add (GTK_CONTAINER (emfsb), box); + priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (object); - set_contents (emfsb); + /* Chain up to parent's destroy() method. */ + GTK_OBJECT_CLASS (parent_class)->destroy (object); } static void -em_folder_selection_button_destroy (GtkObject *obj) +folder_selection_button_clicked (GtkButton *button) { - struct _EMFolderSelectionButtonPrivate *priv = ((EMFolderSelectionButton *) obj)->priv; + EMFolderSelectionButtonPrivate *priv; + EMFolderTree *emft; + GtkWidget *dialog; + + priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (button); + + /* Chain up to parent's clicked() method. */ + GTK_BUTTON_CLASS (parent_class)->clicked (button); + + emft = (EMFolderTree *) em_folder_tree_new_with_model (priv->model); + + em_folder_tree_set_multiselect (emft, priv->multiple_select); + em_folder_tree_set_excluded ( + emft, EMFT_EXCLUDE_NOSELECT | + EMFT_EXCLUDE_VIRTUAL | EMFT_EXCLUDE_VTRASH); + + dialog = em_folder_selector_new ( + emft, EM_FOLDER_SELECTOR_CAN_CREATE, + priv->title, priv->caption, NULL); + + if (priv->multiple_select) + em_folder_selector_set_selected_list ( + EM_FOLDER_SELECTOR (dialog), priv->uris); + else + em_folder_selector_set_selected ( + EM_FOLDER_SELECTOR (dialog), priv->uri); - if (priv->selector) { - gtk_widget_destroy(priv->selector); - priv->selector = NULL; + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) + goto exit; + + if (priv->multiple_select) { + GList *uris; + + uris = em_folder_selector_get_selected_uris ( + EM_FOLDER_SELECTOR (dialog)); + em_folder_selection_button_set_selection_mult ( + EM_FOLDER_SELECTION_BUTTON (button), uris); + } else { + const gchar *uri; + + uri = em_folder_selector_get_selected_uri ( + EM_FOLDER_SELECTOR (dialog)); + em_folder_selection_button_set_selection ( + EM_FOLDER_SELECTION_BUTTON (button), uri); } - GTK_OBJECT_CLASS (parent_class)->destroy (obj); + g_signal_emit (button, signals[SELECTED], 0); + +exit: + gtk_widget_destroy (dialog); } static void -em_folder_selection_button_finalize (GObject *obj) +folder_selection_button_class_init (EMFolderSelectionButtonClass *class) { - struct _EMFolderSelectionButtonPrivate *priv = ((EMFolderSelectionButton *) obj)->priv; + GObjectClass *object_class; + GtkObjectClass *gtk_object_class; + GtkButtonClass *button_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFolderSelectionButtonPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = folder_selection_button_set_property; + object_class->get_property = folder_selection_button_get_property; + object_class->dispose = folder_selection_button_dispose; + object_class->finalize = folder_selection_button_finalize; + + gtk_object_class = GTK_OBJECT_CLASS (class); + gtk_object_class->destroy = folder_selection_button_destroy; + + button_class = GTK_BUTTON_CLASS (class); + button_class->clicked = folder_selection_button_clicked; + + signals[SELECTED] = g_signal_new ( + "selected", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderSelectionButtonClass, selected), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} - GList *lst = ((EMFolderSelectionButton*) obj)->priv->uris; - g_list_foreach (lst, (GFunc) g_free, NULL); - g_list_free (lst); +static void +folder_selection_button_init (EMFolderSelectionButton *emfsb) +{ + struct _EMFolderSelectionButtonPrivate *priv; + GtkWidget *box; - g_free (priv->title); - g_free (priv->caption); - g_free (priv->uri); - g_free (priv); + emfsb->priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (emfsb); + + emfsb->priv->multiple_select = FALSE; - G_OBJECT_CLASS (parent_class)->finalize (obj); + box = gtk_hbox_new (FALSE, 4); + + emfsb->priv->icon = gtk_image_new (); + gtk_widget_show (priv->icon); + gtk_box_pack_start (GTK_BOX (box), emfsb->priv->icon, FALSE, TRUE, 0); + + emfsb->priv->label = gtk_label_new (""); + gtk_widget_show (emfsb->priv->label); + gtk_label_set_justify (GTK_LABEL (emfsb->priv->label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (emfsb->priv->label), 0.0, 0.0); + gtk_box_pack_start (GTK_BOX (box), emfsb->priv->label, TRUE, TRUE, 0); + + gtk_widget_show (box); + gtk_container_add (GTK_CONTAINER (emfsb), box); + + folder_selection_button_set_contents (emfsb); } -static void -emfsb_selector_response (EMFolderSelector *emfs, int response, EMFolderSelectionButton *button) +GType +em_folder_selection_button_get_type (void) { - if (response == GTK_RESPONSE_OK) { - if (button->priv->multiple_select) { - GList *uris = em_folder_selector_get_selected_uris (emfs); + static GType type = 0; - em_folder_selection_button_set_selection_mult (button, uris); - g_signal_emit (button, signals[SELECTED], 0); - } else { - const char *uri = em_folder_selector_get_selected_uri (emfs); + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFolderSelectionButtonClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) folder_selection_button_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFolderSelectionButton), + 0, /* n_preallocs */ + (GInstanceInitFunc) folder_selection_button_init, + NULL /* value_table */ + }; - em_folder_selection_button_set_selection (button, uri); - g_signal_emit (button, signals[SELECTED], 0); - } + type = g_type_register_static ( + GTK_TYPE_BUTTON, "EMFolderSelectionButton", + &type_info, 0); } - gtk_widget_destroy ((GtkWidget *) emfs); + return type; } -static void -em_folder_selection_button_clicked (GtkButton *button) +GtkWidget * +em_folder_selection_button_new (EMFolderTreeModel *model, + const gchar *title, + const gchar *caption) { - struct _EMFolderSelectionButtonPrivate *priv = EM_FOLDER_SELECTION_BUTTON (button)->priv; - EMFolderTreeModel *model; - EMFolderTree *emft; - GtkWidget *dialog; + g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), NULL); - if (GTK_BUTTON_CLASS (parent_class)->clicked != NULL) - (* GTK_BUTTON_CLASS (parent_class)->clicked) (button); + return g_object_new ( + EM_TYPE_FOLDER_SELECTION_BUTTON, + "model", model, "title", title, + "caption", caption, NULL); +} - if (priv->selector) { - gtk_window_present((GtkWindow *)priv->selector); - return; - } +EMFolderTreeModel * +em_folder_selection_button_get_model (EMFolderSelectionButton *button) +{ + g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); - model = mail_component_peek_tree_model (mail_component_peek ()); - emft = (EMFolderTree *) em_folder_tree_new_with_model (model); - g_object_unref (model); - em_folder_tree_set_multiselect (emft, priv->multiple_select); - em_folder_tree_set_excluded(emft, EMFT_EXCLUDE_NOSELECT|EMFT_EXCLUDE_VIRTUAL|EMFT_EXCLUDE_VTRASH); - dialog = em_folder_selector_new (emft, EM_FOLDER_SELECTOR_CAN_CREATE, priv->title, priv->caption, NULL); - if (priv->multiple_select) - em_folder_selector_set_selected_list ((EMFolderSelector *) dialog, priv->uris); - else - em_folder_selector_set_selected ((EMFolderSelector *) dialog, priv->uri); - g_signal_connect (dialog, "response", G_CALLBACK (emfsb_selector_response), button); - priv->selector = dialog; - g_signal_connect(dialog, "destroy", G_CALLBACK(gtk_widget_destroyed), &priv->selector); - gtk_widget_show (dialog); + return button->priv->model; } -GtkWidget * -em_folder_selection_button_new (const char *title, const char *caption) +const gchar * +em_folder_selection_button_get_caption (EMFolderSelectionButton *button) { - EMFolderSelectionButton *button = g_object_new (EM_TYPE_FOLDER_SELECTION_BUTTON, NULL); + g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); - button->priv->title = g_strdup (title); + return button->priv->caption; +} + +void +em_folder_selection_button_set_caption (EMFolderSelectionButton *button, + const gchar *caption) +{ + g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button)); + + g_free (button->priv->caption); button->priv->caption = g_strdup (caption); - return GTK_WIDGET (button); + g_object_notify (G_OBJECT (button), "caption"); } -void -em_folder_selection_button_set_selection (EMFolderSelectionButton *button, const char *uri) +gboolean +em_folder_selection_button_get_multiselect (EMFolderSelectionButton *button) { - struct _EMFolderSelectionButtonPrivate *priv = button->priv; + g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), FALSE); + + return button->priv->multiple_select; +} +void +em_folder_selection_button_set_multiselect (EMFolderSelectionButton *button, + gboolean multiselect) +{ g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button)); - if (priv->uri != uri) { - g_free (priv->uri); - priv->uri = g_strdup (uri); - } + button->priv->multiple_select = multiselect; - set_contents (button); + g_object_notify (G_OBJECT (button), "multiselect"); } -const char * +const gchar * em_folder_selection_button_get_selection (EMFolderSelectionButton *button) { g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); @@ -289,20 +456,40 @@ em_folder_selection_button_get_selection (EMFolderSelectionButton *button) } void -em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, GList *uris) +em_folder_selection_button_set_selection (EMFolderSelectionButton *button, + const gchar *uri) +{ + g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button)); + + if (g_strcmp0 (button->priv->uri, uri) == 0) + return; + + g_free (button->priv->uri); + button->priv->uri = g_strdup (uri); + + folder_selection_button_set_contents (button); +} + +GList * +em_folder_selection_button_get_selection_mult (EMFolderSelectionButton *button) +{ + g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); + + return button->priv->uris; +} + +void +em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, + GList *uris) { - struct _EMFolderSelectionButtonPrivate *priv = button->priv; char *caption, *tmp, *tmp2; g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button)); - if (priv->uris) { - g_list_foreach (priv->uris, (GFunc) g_free, NULL); - g_list_free (priv->uris); - priv->uris = NULL; - } + g_list_foreach (button->priv->uris, (GFunc) g_free, NULL); + g_list_free (button->priv->uris); - priv->uris = uris; + button->priv->uris = uris; /* compile the name */ caption = g_strdup (""); @@ -319,34 +506,36 @@ em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, /* apparently, we do not know this folder, so we'll just skip it */ g_free (uris->data); uris = g_list_next (uris); - priv->uris = g_list_remove (priv->uris, uris->data); + button->priv->uris = g_list_remove ( + button->priv->uris, uris->data); } } if (caption[0]) - gtk_label_set_text (GTK_LABEL (priv->label), caption + 2); + gtk_label_set_text ( + GTK_LABEL (button->priv->label), caption + 2); else - set_contents_unselected (button); + folder_selection_button_unselected (button); g_free (caption); } -GList * -em_folder_selection_button_get_selection_mult (EMFolderSelectionButton *button) +const gchar * +em_folder_selection_button_get_title (EMFolderSelectionButton *button) { - g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); + g_return_val_if_fail (EM_FOLDER_SELECTION_BUTTON (button), NULL); - return button->priv->uris; + return button->priv->title; } void -em_folder_selection_button_set_multiselect (EMFolderSelectionButton *button, gboolean value) +em_folder_selection_button_set_title (EMFolderSelectionButton *button, + const gchar *title) { - button->priv->multiple_select = value; -} + g_return_if_fail (EM_FOLDER_SELECTION_BUTTON (button)); -gboolean -em_folder_selection_button_get_multiselect (EMFolderSelectionButton *button) -{ - return button->priv->multiple_select; + g_free (button->priv->title); + button->priv->title = g_strdup (title); + + g_object_notify (G_OBJECT (button), "title"); } diff --git a/mail/em-folder-selection-button.h b/mail/em-folder-selection-button.h index e9cd1c2a0e..a8b009b1c0 100644 --- a/mail/em-folder-selection-button.h +++ b/mail/em-folder-selection-button.h @@ -21,29 +21,41 @@ * */ -#ifndef __EM_FOLDER_SELECTION_BUTTON_H__ -#define __EM_FOLDER_SELECTION_BUTTON_H__ +#ifndef EM_FOLDER_SELECTION_BUTTON_H +#define EM_FOLDER_SELECTION_BUTTON_H #include <gtk/gtk.h> -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define EM_TYPE_FOLDER_SELECTION_BUTTON (em_folder_selection_button_get_type ()) -#define EM_FOLDER_SELECTION_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButton)) -#define EM_FOLDER_SELECTION_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButtonClass)) -#define EM_IS_FOLDER_SELECTION_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON)) -#define EM_IS_FOLDER_SELECTION_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON)) - -typedef struct _EMFolderSelectionButton EMFolderSelectionButton; -typedef struct _EMFolderSelectionButtonClass EMFolderSelectionButtonClass; +#include <mail/em-folder-tree-model.h> + +/* Standard GObject macros */ +#define EM_TYPE_FOLDER_SELECTION_BUTTON \ + (em_folder_selection_button_get_type ()) +#define EM_FOLDER_SELECTION_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButton)) +#define EM_FOLDER_SELECTION_BUTTON_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButtonClass)) +#define EM_IS_FOLDER_SELECTION_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON)) +#define EM_IS_FOLDER_SELECTION_BUTTON_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON)) +#define EM_FOLDER_SELECTION_BUTTON_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButtonClass)) + +G_BEGIN_DECLS + +typedef struct _EMFolderSelectionButton EMFolderSelectionButton; +typedef struct _EMFolderSelectionButtonClass EMFolderSelectionButtonClass; +typedef struct _EMFolderSelectionButtonPrivate EMFolderSelectionButtonPrivate; struct _EMFolderSelectionButton { GtkButton parent; - - struct _EMFolderSelectionButtonPrivate *priv; + EMFolderSelectionButtonPrivate *priv; }; struct _EMFolderSelectionButtonClass { @@ -51,25 +63,43 @@ struct _EMFolderSelectionButtonClass { /* Signals. */ - void (* selected) (EMFolderSelectionButton *button); + void (*selected) (EMFolderSelectionButton *button); }; - -GType em_folder_selection_button_get_type (void); - -GtkWidget *em_folder_selection_button_new (const char *title, const char *caption); - -void em_folder_selection_button_set_selection (EMFolderSelectionButton *button, const char *uri); -const char *em_folder_selection_button_get_selection (EMFolderSelectionButton *button); - -void em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, GList *uris); -GList *em_folder_selection_button_get_selection_mult (EMFolderSelectionButton *button); - -void em_folder_selection_button_set_multiselect (EMFolderSelectionButton *button, gboolean value); -gboolean em_folder_selection_button_get_multiselect (EMFolderSelectionButton *button); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __EM_FOLDER_SELECTION_BUTTON_H__ */ +GType em_folder_selection_button_get_type (void); +GtkWidget * em_folder_selection_button_new + (EMFolderTreeModel *model, + const gchar *title, + const gchar *caption); +EMFolderTreeModel * + em_folder_selection_button_get_model + (EMFolderSelectionButton *button); +const gchar * em_folder_selection_button_get_caption + (EMFolderSelectionButton *button); +void em_folder_selection_button_set_caption + (EMFolderSelectionButton *button, + const gchar *caption); +gboolean em_folder_selection_button_get_multiselect + (EMFolderSelectionButton *button); +void em_folder_selection_button_set_multiselect + (EMFolderSelectionButton *button, + gboolean multiselect); +const gchar * em_folder_selection_button_get_selection + (EMFolderSelectionButton *button); +void em_folder_selection_button_set_selection + (EMFolderSelectionButton *button, + const gchar *uri); +GList * em_folder_selection_button_get_selection_mult + (EMFolderSelectionButton *button); +void em_folder_selection_button_set_selection_mult + (EMFolderSelectionButton *button, + GList *uris); +const gchar * em_folder_selection_button_get_title + (EMFolderSelectionButton *button); +void em_folder_selection_button_set_title + (EMFolderSelectionButton *button, + const gchar *title); + +G_END_DECLS + +#endif /* EM_FOLDER_SELECTION_BUTTON_H */ diff --git a/mail/em-folder-selection.c b/mail/em-folder-selection.c index d56a470153..3a457407f7 100644 --- a/mail/em-folder-selection.c +++ b/mail/em-folder-selection.c @@ -32,7 +32,8 @@ #include "em-folder-tree.h" #include "em-folder-selector.h" #include "em-folder-selection.h" -#include "mail-component.h" + +#include "e-mail-shell-module.h" /* TODO: rmeove this file, it could just go on em-folder-selection or em-utils */ @@ -63,7 +64,7 @@ em_select_folder (GtkWindow *parent_window, const char *title, const char *oklab GtkWidget *dialog; EMFolderTree *emft; - model = mail_component_peek_tree_model (mail_component_peek ()); + model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); emft = (EMFolderTree *) em_folder_tree_new_with_model (model); if (exclude) em_folder_tree_set_excluded_func(emft, exclude, user_data); diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c index 6f716d7e13..ecefc4bc5b 100644 --- a/mail/em-folder-tree-model.c +++ b/mail/em-folder-tree-model.c @@ -10,7 +10,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> + * License along with the program; if not, see <http://www.gnu.org/licenses/> * * * Authors: @@ -20,9 +20,7 @@ * */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif +#include "em-folder-tree-model.h" #include <stdio.h> #include <string.h> @@ -37,7 +35,8 @@ #include <libedataserver/e-xml-utils.h> #include <libedataserver/e-data-server-util.h> -#include <e-util/e-mktemp.h> +#include "e-util/e-util.h" +#include "e-util/e-mktemp.h" #include <glib/gi18n.h> @@ -49,7 +48,6 @@ #include "mail-mt.h" /* sigh, these 2 only needed for outbox total count checking - a mess */ -#include "mail-component.h" #include "mail-folder-cache.h" #include "em-utils.h" @@ -57,12 +55,19 @@ #include <camel/camel-folder.h> #include <camel/camel-vee-store.h> -#include "em-marshal.h" -#include "em-folder-tree-model.h" +#include "e-mail-shell-module.h" #define u(x) /* unread count debug */ #define d(x) +#define EM_FOLDER_TREE_MODEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModelPrivate)) + +struct _EMFolderTreeModelPrivate { + gpointer shell_module; /* weak pointer */ +}; + static GType col_types[] = { G_TYPE_STRING, /* display name */ G_TYPE_POINTER, /* store object */ @@ -74,114 +79,77 @@ static GType col_types[] = { G_TYPE_BOOLEAN, /* has not-yet-loaded subfolders */ }; -/* GObject virtual method overrides */ -static void em_folder_tree_model_class_init (EMFolderTreeModelClass *klass); -static void em_folder_tree_model_init (EMFolderTreeModel *model); -static void em_folder_tree_model_finalize (GObject *obj); - -/* interface init methods */ -static void tree_model_iface_init (GtkTreeModelIface *iface); -static void tree_sortable_iface_init (GtkTreeSortableIface *iface); - static void account_changed (EAccountList *accounts, EAccount *account, gpointer user_data); static void account_removed (EAccountList *accounts, EAccount *account, gpointer user_data); enum { + PROP_0, + PROP_SHELL_MODULE +}; + +enum { LOADING_ROW, LOADED_ROW, FOLDER_ADDED, LAST_SIGNAL }; -static guint signals[LAST_SIGNAL] = { 0, }; -static GtkTreeStoreClass *parent_class = NULL; +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; -GType -em_folder_tree_model_get_type (void) +static void +store_info_free (EMFolderTreeModelStoreInfo *si) { - static GType type = 0; + camel_object_remove_event (si->store, si->created_id); + camel_object_remove_event (si->store, si->deleted_id); + camel_object_remove_event (si->store, si->renamed_id); + camel_object_remove_event (si->store, si->subscribed_id); + camel_object_remove_event (si->store, si->unsubscribed_id); - if (!type) { - static const GTypeInfo info = { - sizeof (EMFolderTreeModelClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) em_folder_tree_model_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EMFolderTreeModel), - 0, /* n_preallocs */ - (GInstanceInitFunc) em_folder_tree_model_init, - }; - static const GInterfaceInfo tree_model_info = { - (GInterfaceInitFunc) tree_model_iface_init, - NULL, - NULL - }; - static const GInterfaceInfo sortable_info = { - (GInterfaceInitFunc) tree_sortable_iface_init, - NULL, - NULL - }; + g_free (si->display_name); + camel_object_unref (si->store); + gtk_tree_row_reference_free (si->row); + g_hash_table_destroy (si->full_hash); + g_free (si); +} - type = g_type_register_static (GTK_TYPE_TREE_STORE, "EMFolderTreeModel", &info, 0); +static void +folder_tree_model_load_state (EMFolderTreeModel *model, + const gchar *filename) +{ + xmlNodePtr root, node; - g_type_add_interface_static (type, GTK_TYPE_TREE_MODEL, - &tree_model_info); - g_type_add_interface_static (type, GTK_TYPE_TREE_SORTABLE, - &sortable_info); + if (model->state) + xmlFreeDoc (model->state); + + if ((model->state = e_xml_parse_file (filename)) != NULL) { + node = xmlDocGetRootElement (model->state); + if (!node || strcmp ((char *)node->name, "tree-state") != 0) { + /* it is not expected XML file, thus free it and use the default */ + xmlFreeDoc (model->state); + } else + return; } - return type; -} + /* setup some defaults - expand "Local Folders" and "Search Folders" */ + model->state = xmlNewDoc ((const unsigned char *)"1.0"); + root = xmlNewDocNode (model->state, NULL, (const unsigned char *)"tree-state", NULL); + xmlDocSetRootElement (model->state, root); + node = xmlNewChild (root, NULL, (const unsigned char *)"node", NULL); + xmlSetProp (node, (const unsigned char *)"name", (const unsigned char *)"local"); + xmlSetProp (node, (const unsigned char *)"expand", (const unsigned char *)"true"); -static void -em_folder_tree_model_class_init (EMFolderTreeModelClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_ref (GTK_TYPE_TREE_STORE); - - object_class->finalize = em_folder_tree_model_finalize; - - /* signals */ - signals[LOADING_ROW] = - g_signal_new ("loading-row", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderTreeModelClass, loading_row), - NULL, NULL, - em_marshal_VOID__POINTER_POINTER, - G_TYPE_NONE, 2, - G_TYPE_POINTER, - G_TYPE_POINTER); - - signals[LOADED_ROW] = - g_signal_new ("loaded-row", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderTreeModelClass, loaded_row), - NULL, NULL, - em_marshal_VOID__POINTER_POINTER, - G_TYPE_NONE, 2, - G_TYPE_POINTER, - G_TYPE_POINTER); - - signals[FOLDER_ADDED] = - g_signal_new ("folder-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderTreeModelClass, folder_added), - NULL, NULL, - em_marshal_VOID__STRING_STRING, - G_TYPE_NONE, 2, - G_TYPE_STRING, - G_TYPE_STRING); + node = xmlNewChild (root, NULL, (const unsigned char *)"node", NULL); + xmlSetProp (node, (const unsigned char *)"name", (const unsigned char *)"vfolder"); + xmlSetProp (node, (const unsigned char *)"expand", (const unsigned char *)"true"); } static int -sort_cb (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) +folder_tree_model_sort (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer user_data) { extern CamelStore *vfolder_store; char *aname, *bname; @@ -190,13 +158,21 @@ sort_cb (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data guint32 aflags, bflags; int rv = -2; - gtk_tree_model_get (model, a, COL_BOOL_IS_STORE, &is_store, - COL_POINTER_CAMEL_STORE, &store, - COL_STRING_DISPLAY_NAME, &aname, COL_UINT_FLAGS, &aflags, -1); - gtk_tree_model_get (model, b, COL_STRING_DISPLAY_NAME, &bname, COL_UINT_FLAGS, &bflags, -1); + gtk_tree_model_get ( + model, a, + COL_BOOL_IS_STORE, &is_store, + COL_POINTER_CAMEL_STORE, &store, + COL_STRING_DISPLAY_NAME, &aname, + COL_UINT_FLAGS, &aflags, -1); + + gtk_tree_model_get ( + model, b, + COL_STRING_DISPLAY_NAME, &bname, + COL_UINT_FLAGS, &bflags, -1); if (is_store) { - /* On This Computer is always first and Search Folders is always last */ + /* On This Computer is always first, and Search Folders + * is always last. */ if (!strcmp (aname, _("On This Computer"))) rv = -1; else if (!strcmp (bname, _("On This Computer"))) @@ -206,13 +182,13 @@ sort_cb (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data else if (!strcmp (bname, _("Search Folders"))) rv = -1; } else if (store == vfolder_store) { - /* UNMATCHED is always last */ + /* UNMATCHED is always last. */ if (aname && !strcmp (aname, _("UNMATCHED"))) rv = 1; else if (bname && !strcmp (bname, _("UNMATCHED"))) rv = -1; } else { - /* Inbox is always first */ + /* Inbox is always first. */ if ((aflags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX) rv = -1; else if ((bflags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX) @@ -235,73 +211,56 @@ sort_cb (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data } static void -store_info_free (struct _EMFolderTreeModelStoreInfo *si) +folder_tree_model_set_shell_module (EMFolderTreeModel *model, + EShellModule *shell_module) { - camel_object_remove_event (si->store, si->created_id); - camel_object_remove_event (si->store, si->deleted_id); - camel_object_remove_event (si->store, si->renamed_id); - camel_object_remove_event (si->store, si->subscribed_id); - camel_object_remove_event (si->store, si->unsubscribed_id); + g_return_if_fail (model->priv->shell_module == NULL); - g_free (si->display_name); - camel_object_unref (si->store); - gtk_tree_row_reference_free (si->row); - g_hash_table_destroy (si->full_hash); - g_free (si); + model->priv->shell_module = shell_module; + + g_object_add_weak_pointer ( + G_OBJECT (shell_module), + &model->priv->shell_module); } static void -emft_model_unread_count_changed (GtkTreeModel *model, GtkTreeIter *iter) +folder_tree_model_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - GtkTreeIter parent_iter; - GtkTreeIter child_iter = *iter; - - g_signal_handlers_block_by_func ( - model, emft_model_unread_count_changed, NULL); - - /* Folders are displayed with a bold weight to indicate that - they contain unread messages. We signal that parent rows - have changed here to update them. */ - - while (gtk_tree_model_iter_parent (model, &parent_iter, &child_iter)) { - GtkTreePath *parent_path; - - parent_path = gtk_tree_model_get_path (model, &parent_iter); - gtk_tree_model_row_changed (model, parent_path, &parent_iter); - gtk_tree_path_free (parent_path); - child_iter = parent_iter; + switch (property_id) { + case PROP_SHELL_MODULE: + folder_tree_model_set_shell_module ( + EM_FOLDER_TREE_MODEL (object), + g_value_get_object (value)); + return; } - g_signal_handlers_unblock_by_func ( - model, emft_model_unread_count_changed, NULL); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -em_folder_tree_model_init (EMFolderTreeModel *model) +folder_tree_model_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - model->store_hash = g_hash_table_new_full ( - g_direct_hash, g_direct_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) store_info_free); - - model->uri_hash = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) gtk_tree_row_reference_free); - - gtk_tree_sortable_set_default_sort_func ((GtkTreeSortable *) model, sort_cb, NULL, NULL); + switch (property_id) { + case PROP_SHELL_MODULE: + g_value_set_object ( + value, em_folder_tree_model_get_shell_module ( + EM_FOLDER_TREE_MODEL (object))); + return; + } - model->accounts = mail_config_get_accounts (); - model->account_hash = g_hash_table_new (g_direct_hash, g_direct_equal); - model->account_changed_id = g_signal_connect (model->accounts, "account-changed", G_CALLBACK (account_changed), model); - model->account_removed_id = g_signal_connect (model->accounts, "account-removed", G_CALLBACK (account_removed), model); - //g_signal_connect (model, "row-changed", G_CALLBACK (emft_model_unread_count_changed), NULL); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -em_folder_tree_model_finalize (GObject *obj) +folder_tree_model_finalize (GObject *object) { - EMFolderTreeModel *model = (EMFolderTreeModel *) obj; + EMFolderTreeModel *model = (EMFolderTreeModel *) object; g_free (model->filename); if (model->state) @@ -314,75 +273,231 @@ em_folder_tree_model_finalize (GObject *obj) g_signal_handler_disconnect (model->accounts, model->account_changed_id); g_signal_handler_disconnect (model->accounts, model->account_removed_id); - G_OBJECT_CLASS (parent_class)->finalize (obj); + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +folder_tree_model_constructed (GObject *object) +{ + EMFolderTreeModel *model = EM_FOLDER_TREE_MODEL (object); + EShellModule *shell_module; + const gchar *config_dir; + gchar *filename; + + shell_module = model->priv->shell_module; + config_dir = e_shell_module_get_config_dir (shell_module); + + filename = g_build_filename ( + config_dir, "folder-tree-expand-state.xml", NULL); + folder_tree_model_load_state (model, filename); + model->filename = filename; } +static void +folder_tree_model_class_init (EMFolderTreeModelClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFolderTreeModelPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = folder_tree_model_set_property; + object_class->get_property = folder_tree_model_get_property; + object_class->finalize = folder_tree_model_finalize; + object_class->constructed = folder_tree_model_constructed; + + g_object_class_install_property ( + object_class, + PROP_SHELL_MODULE, + g_param_spec_object ( + "shell-module", + _("Shell Module"), + NULL, + E_TYPE_SHELL_MODULE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + signals[LOADING_ROW] = g_signal_new ( + "loading-row", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderTreeModelClass, loading_row), + NULL, NULL, + e_marshal_VOID__POINTER_POINTER, + G_TYPE_NONE, 2, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[LOADED_ROW] = g_signal_new ( + "loaded-row", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderTreeModelClass, loaded_row), + NULL, NULL, + e_marshal_VOID__POINTER_POINTER, + G_TYPE_NONE, 2, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[FOLDER_ADDED] = g_signal_new ( + "folder-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderTreeModelClass, folder_added), + NULL, NULL, + e_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_STRING); +} + +static void +folder_tree_model_init (EMFolderTreeModel *model) +{ + GHashTable *store_hash; + GHashTable *uri_hash; + + store_hash = g_hash_table_new_full ( + g_direct_hash, g_direct_equal, + (GDestroyNotify) NULL, + (GDestroyNotify) store_info_free); + + uri_hash = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) gtk_tree_row_reference_free); + + model->priv = EM_FOLDER_TREE_MODEL_GET_PRIVATE (model); + model->store_hash = store_hash; + model->uri_hash = uri_hash; + + gtk_tree_store_set_column_types ( + GTK_TREE_STORE (model), NUM_COLUMNS, col_types); + gtk_tree_sortable_set_default_sort_func ( + GTK_TREE_SORTABLE (model), + folder_tree_model_sort, NULL, NULL); + gtk_tree_sortable_set_sort_column_id ( + GTK_TREE_SORTABLE (model), + GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, + GTK_SORT_ASCENDING); + + model->accounts = mail_config_get_accounts (); + model->account_hash = g_hash_table_new (g_direct_hash, g_direct_equal); + model->account_changed_id = g_signal_connect ( + model->accounts, "account-changed", + G_CALLBACK (account_changed), model); + model->account_removed_id = g_signal_connect ( + model->accounts, "account-removed", + G_CALLBACK (account_removed), model); + //g_signal_connect ( + // model, "row-changed", + // G_CALLBACK (emft_model_unread_count_changed), NULL); +} static void tree_model_iface_init (GtkTreeModelIface *iface) { - ; } static void tree_sortable_iface_init (GtkTreeSortableIface *iface) { - ; +} + +GType +em_folder_tree_model_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFolderTreeModelClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) folder_tree_model_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFolderTreeModel), + 0, /* n_preallocs */ + (GInstanceInitFunc) folder_tree_model_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo tree_model_info = { + (GInterfaceInitFunc) tree_model_iface_init, + NULL, + NULL + }; + + static const GInterfaceInfo sortable_info = { + (GInterfaceInitFunc) tree_sortable_iface_init, + NULL, + NULL + }; + + type = g_type_register_static ( + GTK_TYPE_TREE_STORE, "EMFolderTreeModel", + &type_info, 0); + + g_type_add_interface_static ( + type, GTK_TYPE_TREE_MODEL, &tree_model_info); + g_type_add_interface_static ( + type, GTK_TYPE_TREE_SORTABLE, &sortable_info); + } + + return type; } static void -em_folder_tree_model_load_state (EMFolderTreeModel *model, const char *filename) +emft_model_unread_count_changed (GtkTreeModel *model, GtkTreeIter *iter) { - xmlNodePtr root, node; + GtkTreeIter parent_iter; + GtkTreeIter child_iter = *iter; - if (model->state) - xmlFreeDoc (model->state); + g_signal_handlers_block_by_func ( + model, emft_model_unread_count_changed, NULL); - if ((model->state = e_xml_parse_file (filename)) != NULL) { - node = xmlDocGetRootElement (model->state); - if (!node || strcmp ((char *)node->name, "tree-state") != 0) { - /* it is not expected XML file, thus free it and use the default */ - xmlFreeDoc (model->state); - } else - return; - } + /* Folders are displayed with a bold weight to indicate that + they contain unread messages. We signal that parent rows + have changed here to update them. */ - /* setup some defaults - expand "Local Folders" and "Search Folders" */ - model->state = xmlNewDoc ((const unsigned char *)"1.0"); - root = xmlNewDocNode (model->state, NULL, (const unsigned char *)"tree-state", NULL); - xmlDocSetRootElement (model->state, root); + while (gtk_tree_model_iter_parent (model, &parent_iter, &child_iter)) { + GtkTreePath *parent_path; - node = xmlNewChild (root, NULL, (const unsigned char *)"node", NULL); - xmlSetProp (node, (const unsigned char *)"name", (const unsigned char *)"local"); - xmlSetProp (node, (const unsigned char *)"expand", (const unsigned char *)"true"); + parent_path = gtk_tree_model_get_path (model, &parent_iter); + gtk_tree_model_row_changed (model, parent_path, &parent_iter); + gtk_tree_path_free (parent_path); + child_iter = parent_iter; + } - node = xmlNewChild (root, NULL, (const unsigned char *)"node", NULL); - xmlSetProp (node, (const unsigned char *)"name", (const unsigned char *)"vfolder"); - xmlSetProp (node, (const unsigned char *)"expand", (const unsigned char *)"true"); + g_signal_handlers_unblock_by_func ( + model, emft_model_unread_count_changed, NULL); } + + EMFolderTreeModel * -em_folder_tree_model_new (const char *evolution_dir) +em_folder_tree_model_new (EShellModule *shell_module) { - EMFolderTreeModel *model; - char *filename; + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); - model = g_object_new (EM_TYPE_FOLDER_TREE_MODEL, NULL); - gtk_tree_store_set_column_types ((GtkTreeStore *) model, NUM_COLUMNS, col_types); - gtk_tree_sortable_set_sort_column_id ((GtkTreeSortable *) model, - GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, - GTK_SORT_ASCENDING); + return g_object_new ( + EM_TYPE_FOLDER_TREE_MODEL, + "shell-module", shell_module, NULL); +} - filename = g_build_filename (evolution_dir, "mail", "config", "folder-tree-expand-state.xml", NULL); - em_folder_tree_model_load_state (model, filename); - model->filename = filename; +EShellModule * +em_folder_tree_model_get_shell_module (EMFolderTreeModel *model) +{ + g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), NULL); - return model; + return model->priv->shell_module; } - static void account_changed (EAccountList *accounts, EAccount *account, gpointer user_data) { @@ -438,12 +553,13 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite struct _EMFolderTreeModelStoreInfo *si, CamelFolderInfo *fi, int fully_loaded) { + EShellModule *shell_module; GtkTreeRowReference *uri_row, *path_row; unsigned int unread; GtkTreePath *path; GtkTreeIter sub; gboolean load = FALSE; - struct _CamelFolder *folder; + CamelFolder *folder; gboolean emitted = FALSE; const char *name; guint32 flags; @@ -451,7 +567,9 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite /* make sure we don't already know about it? */ if (g_hash_table_lookup (si->full_hash, fi->full_name)) return; - + + shell_module = model->priv->shell_module; + if (!fully_loaded) load = fi->child == NULL && !(fi->flags & (CAMEL_FOLDER_NOCHILDREN | CAMEL_FOLDER_NOINFERIORS)); @@ -468,7 +586,15 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite /* This is duplicated in mail-folder-cache too, should perhaps be functionised */ unread = fi->unread; if (mail_note_get_folder_from_uri(fi->uri, &folder) && folder) { - if (folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX)) { + CamelFolder *local_drafts; + CamelFolder *local_outbox; + + local_drafts = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_DRAFTS); + local_outbox = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_OUTBOX); + + if (folder == local_outbox) { int total; if ((total = camel_folder_get_message_count (folder)) > 0) { @@ -480,7 +606,7 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite unread = total > 0 ? total : 0; } - if (folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS)) { + if (folder == local_drafts) { int total; if ((total = camel_folder_get_message_count (folder)) > 0) { @@ -499,7 +625,7 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite /* TODO: maybe this should be handled by mail_get_folderinfo (except em-folder-tree doesn't use it, duh) */ flags = fi->flags; name = fi->name; - if (si->store == mail_component_peek_local_store(NULL)) { + if (si->store == e_mail_shell_module_get_local_store (shell_module)) { if (!strcmp(fi->full_name, "Drafts")) { name = _("Drafts"); } else if (!strcmp(fi->full_name, "Inbox")) { diff --git a/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h index 3247eee308..0ab0f24d6d 100644 --- a/mail/em-folder-tree-model.h +++ b/mail/em-folder-tree-model.h @@ -20,31 +20,40 @@ * */ -#ifndef __EM_FOLDER_TREE_MODEL_H__ -#define __EM_FOLDER_TREE_MODEL_H__ +#ifndef EM_FOLDER_TREE_MODEL_H +#define EM_FOLDER_TREE_MODEL_H #include <gtk/gtk.h> - #include <libxml/tree.h> - #include <camel/camel-store.h> - #include <libedataserver/e-account-list.h> -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define EM_TYPE_FOLDER_TREE_MODEL (em_folder_tree_model_get_type ()) -#define EM_FOLDER_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModel)) -#define EM_FOLDER_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModelClass)) -#define EM_IS_FOLDER_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EM_TYPE_FOLDER_TREE_MODEL)) -#define EM_IS_FOLDER_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EM_TYPE_FOLDER_TREE_MODEL)) -#define EM_FOLDER_TREE_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModelClass)) +#include <shell/e-shell-module.h> + +/* Standard GObject macros */ +#define EM_TYPE_FOLDER_TREE_MODEL \ + (em_folder_tree_model_get_type ()) +#define EM_FOLDER_TREE_MODEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModel)) +#define EM_FOLDER_TREE_MODEL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModelClass)) +#define EM_IS_FOLDER_TREE_MODEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_FOLDER_TREE_MODEL)) +#define EM_IS_FOLDER_TREE_MODEL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_TYPE_FOLDER_TREE_MODEL)) +#define EM_FOLDER_TREE_MODEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModelClass)) + +G_BEGIN_DECLS typedef struct _EMFolderTreeModel EMFolderTreeModel; typedef struct _EMFolderTreeModelClass EMFolderTreeModelClass; +typedef struct _EMFolderTreeModelPrivate EMFolderTreeModelPrivate; typedef struct _EMFolderTreeModelStoreInfo EMFolderTreeModelStoreInfo; enum { @@ -79,7 +88,8 @@ struct _EMFolderTreeModelStoreInfo { }; struct _EMFolderTreeModel { - GtkTreeStore parent_object; + GtkTreeStore parent; + EMFolderTreeModelPrivate *priv; char *filename; /* state filename */ xmlDocPtr state; /* saved expanded state from previous session */ @@ -114,11 +124,11 @@ struct _EMFolderTreeModelClass { }; -GType em_folder_tree_model_get_type (void); - - -EMFolderTreeModel *em_folder_tree_model_new (const char *evolution_dir); - +GType em_folder_tree_model_get_type (void); +EMFolderTreeModel * + em_folder_tree_model_new (EShellModule *shell_module); +EShellModule * em_folder_tree_model_get_shell_module + (EMFolderTreeModel *model); void em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *iter, struct _EMFolderTreeModelStoreInfo *si, @@ -147,8 +157,6 @@ void em_folder_tree_model_set_unread_count (EMFolderTreeModel *model, CamelStore gboolean em_folder_tree_model_is_type_inbox (EMFolderTreeModel *model, CamelStore *store, const char *full); char * em_folder_tree_model_get_folder_name (EMFolderTreeModel *model, CamelStore *store, const char *full); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS -#endif /* __EM_FOLDER_TREE_MODEL_H__ */ +#endif /* EM_FOLDER_TREE_MODEL_H */ diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c index 8181c9a91a..07fcc48759 100644 --- a/mail/em-folder-tree.c +++ b/mail/em-folder-tree.c @@ -60,13 +60,11 @@ #include "mail-ops.h" #include "mail-tools.h" #include "mail-config.h" -#include "mail-component.h" #include "mail-send-recv.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-utils.h" #include "em-folder-selector.h" @@ -74,8 +72,14 @@ #include "em-folder-properties.h" #include "em-event.h" +#include "e-mail-shell-module.h" + #define d(x) +#define EM_FOLDER_TREE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EM_TYPE_FOLDER_TREE, EMFolderTreePrivate)) + struct _selected_uri { char *key; /* store:path or account/path */ char *uri; @@ -84,7 +88,6 @@ struct _selected_uri { }; struct _EMFolderTreePrivate { - GtkTreeView *treeview; EMFolderTreeModel *model; GSList *select_uris; /* selected_uri structures of each path pending selection. */ @@ -152,11 +155,6 @@ static guint signals[LAST_SIGNAL] = { 0 }; extern CamelSession *session; -static void em_folder_tree_class_init (EMFolderTreeClass *klass); -static void em_folder_tree_init (EMFolderTree *emft); -static void em_folder_tree_destroy (GtkObject *obj); -static void em_folder_tree_finalize (GObject *obj); - static gboolean emft_save_state (EMFolderTree *emft); static void emft_queue_save_state (EMFolderTree *emft); @@ -176,68 +174,153 @@ struct _emft_selection_data { gboolean set; }; -static GtkVBoxClass *parent_class = NULL; +static gpointer parent_class = NULL; -GType -em_folder_tree_get_type (void) +static void +emft_free_select_uri (struct _selected_uri *u) { - static GType type = 0; + g_free (u->uri); + if (u->store) + camel_object_unref (u->store); + g_free (u->key); + g_free (u->path); + g_free (u); +} - if (!type) { - static const GTypeInfo info = { - sizeof (EMFolderTreeClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) em_folder_tree_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EMFolderTree), - 0, /* n_preallocs */ - (GInstanceInitFunc) em_folder_tree_init, - }; +static void +folder_tree_finalize (GObject *object) +{ + EMFolderTreePrivate *priv; + + priv = EM_FOLDER_TREE_GET_PRIVATE (object); - type = g_type_register_static (GTK_TYPE_VBOX, "EMFolderTree", &info, 0); + if (priv->select_uris != NULL) { + g_slist_foreach ( + priv->select_uris, + (GFunc) emft_free_select_uri, NULL); + g_slist_free (priv->select_uris); + g_hash_table_destroy (priv->select_uris_table); + priv->select_uris = NULL; } - return type; + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); } static void -em_folder_tree_class_init (EMFolderTreeClass *klass) +em_folder_tree_destroy (GtkObject *object) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + EMFolderTreePrivate *priv; + + priv = EM_FOLDER_TREE_GET_PRIVATE (object); + + if (priv->loaded_row_id != 0) { + g_signal_handler_disconnect (priv->model, priv->loaded_row_id); + priv->loaded_row_id = 0; + } + + if (priv->save_state_id != 0) { + g_source_remove (priv->save_state_id); + emft_save_state (EM_FOLDER_TREE (object)); + } - parent_class = g_type_class_ref (GTK_TYPE_VBOX); + if (priv->autoscroll_id != 0) { + g_source_remove (priv->autoscroll_id); + priv->autoscroll_id = 0; + } + + if (priv->autoexpand_id != 0) { + gtk_tree_row_reference_free (priv->autoexpand_row); + priv->autoexpand_row = NULL; + + g_source_remove (priv->autoexpand_id); + priv->autoexpand_id = 0; + } - object_class->finalize = em_folder_tree_finalize; + priv->model = NULL; + + /* Chain up to parent's destroy() method. */ + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +static void +folder_tree_class_init (EMFolderTreeClass *class) +{ + GObjectClass *object_class; + GtkObjectClass *gtk_object_class; + GtkWidgetClass *widget_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFolderTreePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = folder_tree_finalize; + + gtk_object_class = GTK_OBJECT_CLASS (class); gtk_object_class->destroy = em_folder_tree_destroy; + widget_class = GTK_WIDGET_CLASS (class); widget_class->popup_menu = emft_popup_menu; - signals[FOLDER_SELECTED] = - g_signal_new ("folder-selected", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderTreeClass, folder_selected), - NULL, NULL, - em_marshal_VOID__STRING_STRING_UINT, - G_TYPE_NONE, 3, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_UINT); - - signals[FOLDER_ACTIVATED] = - g_signal_new ("folder-activated", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderTreeClass, folder_activated), - NULL, NULL, - em_marshal_VOID__STRING_STRING, - G_TYPE_NONE, 2, - G_TYPE_STRING, - G_TYPE_STRING); + signals[FOLDER_SELECTED] = g_signal_new ( + "folder-selected", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderTreeClass, folder_selected), + NULL, NULL, + e_marshal_VOID__STRING_STRING_UINT, + G_TYPE_NONE, 3, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_UINT); + + signals[FOLDER_ACTIVATED] = g_signal_new ( + "folder-activated", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderTreeClass, folder_activated), + NULL, NULL, + e_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_STRING); +} + +static void +folder_tree_init (EMFolderTree *emft) +{ + GHashTable *select_uris_table; + + select_uris_table = g_hash_table_new (g_str_hash, g_str_equal); + + emft->priv = EM_FOLDER_TREE_GET_PRIVATE (emft); + emft->priv->select_uris_table = select_uris_table; +} + +GType +em_folder_tree_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFolderTreeClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) folder_tree_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFolderTree), + 0, /* n_preallocs */ + (GInstanceInitFunc) folder_tree_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_TREE_VIEW, "EMFolderTree", &type_info, 0); + } + + return type; } static gboolean @@ -414,90 +497,6 @@ emft_select_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath * return (flags & emft->priv->excluded) == 0; } -static void -emft_free_select_uri(void *v, void *data) -{ - struct _selected_uri *u = v; - - g_free(u->uri); - if (u->store) - camel_object_unref(u->store); - g_free(u->key); - g_free(u->path); - g_free(u); -} - -static void -em_folder_tree_init (EMFolderTree *emft) -{ - struct _EMFolderTreePrivate *priv; - - priv = g_new0 (struct _EMFolderTreePrivate, 1); - priv->select_uris_table = g_hash_table_new(g_str_hash, g_str_equal); - priv->treeview = NULL; - priv->model = NULL; - priv->drag_row = NULL; - - emft->priv = priv; -} - -static void -em_folder_tree_finalize (GObject *obj) -{ - EMFolderTree *emft = (EMFolderTree *) obj; - - if (emft->priv->select_uris) { - g_slist_foreach(emft->priv->select_uris, emft_free_select_uri, emft); - g_slist_free(emft->priv->select_uris); - g_hash_table_destroy(emft->priv->select_uris_table); - emft->priv->select_uris = NULL; - } - - g_free (emft->priv); - - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - -static void -em_folder_tree_destroy (GtkObject *obj) -{ - EMFolderTree *emft = (EMFolderTree *) obj; - struct _EMFolderTreePrivate *priv = emft->priv; - - if (priv->loading_row_id != 0) { - g_signal_handler_disconnect (priv->model, priv->loading_row_id); - priv->loading_row_id = 0; - } - - if (priv->loaded_row_id != 0) { - g_signal_handler_disconnect (priv->model, priv->loaded_row_id); - priv->loaded_row_id = 0; - } - - if (priv->save_state_id != 0) { - g_source_remove (priv->save_state_id); - emft_save_state (emft); - } - - if (priv->autoscroll_id != 0) { - g_source_remove (priv->autoscroll_id); - priv->autoscroll_id = 0; - } - - if (priv->autoexpand_id != 0) { - gtk_tree_row_reference_free (priv->autoexpand_row); - priv->autoexpand_row = NULL; - - g_source_remove (priv->autoexpand_id); - priv->autoexpand_id = 0; - } - - priv->treeview = NULL; - priv->model = NULL; - - GTK_OBJECT_CLASS (parent_class)->destroy (obj); -} - static GtkTreeView * folder_tree_new (EMFolderTree *emft, EMFolderTreeModel *model) { @@ -511,7 +510,10 @@ folder_tree_new (EMFolderTree *emft, EMFolderTreeModel *model) gconf = mail_config_get_gconf_client (); side_bar_search = gconf_client_get_bool (gconf, "/apps/evolution/mail/display/side_bar_search", NULL); - tree = gtk_tree_view_new_with_model ((GtkTreeModel *) model); + /* FIXME[KILL-BONOBO] Gross hack */ + tree = GTK_WIDGET (emft); + gtk_tree_view_set_model ( + GTK_TREE_VIEW (tree), GTK_TREE_MODEL (model)); GTK_WIDGET_SET_FLAGS(tree, GTK_CAN_FOCUS); column = gtk_tree_view_column_new (); @@ -543,39 +545,30 @@ em_folder_tree_construct (EMFolderTree *emft, EMFolderTreeModel *model) { struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeSelection *selection; - GtkWidget *scrolled; - - scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN); priv->model = model; - priv->treeview = folder_tree_new (emft, model); - gtk_widget_show ((GtkWidget *) priv->treeview); + folder_tree_new (emft, model); + gtk_widget_show (GTK_WIDGET (emft)); - g_signal_connect (priv->treeview, "row-expanded", G_CALLBACK (emft_tree_row_expanded), emft); - g_signal_connect (priv->treeview, "test-collapse-row", G_CALLBACK (emft_tree_test_collapse_row), emft); - g_signal_connect (priv->treeview, "row-activated", G_CALLBACK (emft_tree_row_activated), emft); - g_signal_connect (priv->treeview, "button-press-event", G_CALLBACK (emft_tree_button_press), emft); - g_signal_connect (priv->treeview, "key-press-event", G_CALLBACK (emft_tree_user_event), emft); + g_signal_connect (emft, "row-expanded", G_CALLBACK (emft_tree_row_expanded), emft); + g_signal_connect (emft, "test-collapse-row", G_CALLBACK (emft_tree_test_collapse_row), emft); + g_signal_connect (emft, "row-activated", G_CALLBACK (emft_tree_row_activated), emft); + g_signal_connect (emft, "button-press-event", G_CALLBACK (emft_tree_button_press), emft); + g_signal_connect (emft, "key-press-event", G_CALLBACK (emft_tree_user_event), emft); - selection = gtk_tree_view_get_selection ((GtkTreeView *) priv->treeview); + selection = gtk_tree_view_get_selection ((GtkTreeView *) emft); g_signal_connect (selection, "changed", G_CALLBACK (emft_tree_selection_changed), emft); - - gtk_container_add ((GtkContainer *) scrolled, (GtkWidget *) priv->treeview); - gtk_widget_show (scrolled); - - gtk_box_pack_start ((GtkBox *) emft, scrolled, TRUE, TRUE, 0); } GtkWidget * -em_folder_tree_new (void) +em_folder_tree_new (EShellModule *shell_module) { EMFolderTreeModel *model; EMFolderTree *emft; - model = em_folder_tree_model_new (e_get_user_data_dir ()); + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + + model = em_folder_tree_model_new (shell_module); emft = (EMFolderTree *) em_folder_tree_new_with_model (model); g_object_unref (model); @@ -587,18 +580,20 @@ static void emft_select_uri(EMFolderTree *emft, GtkTreePath *path, struct _selected_uri *u) { struct _EMFolderTreePrivate *priv = emft->priv; + GtkTreeView *tree_view; GtkTreeSelection *selection; - selection = gtk_tree_view_get_selection(priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); gtk_tree_selection_select_path(selection, path); if (!priv->cursor_set) { - gtk_tree_view_set_cursor (priv->treeview, path, NULL, FALSE); + gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE); priv->cursor_set = TRUE; } - gtk_tree_view_scroll_to_cell (priv->treeview, path, NULL, TRUE, 0.8f, 0.0f); + gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.8f, 0.0f); g_hash_table_remove(priv->select_uris_table, u->key); priv->select_uris = g_slist_remove(priv->select_uris, u); - emft_free_select_uri((void *)u, NULL); + emft_free_select_uri(u); } static void @@ -607,7 +602,9 @@ emft_expand_node (EMFolderTreeModel *model, const char *key, EMFolderTree *emft) struct _EMFolderTreePrivate *priv = emft->priv; struct _EMFolderTreeModelStoreInfo *si; extern CamelStore *vfolder_store; + EShellModule *shell_module; GtkTreeRowReference *row; + GtkTreeView *tree_view; GtkTreePath *path; EAccount *account; CamelStore *store; @@ -625,6 +622,9 @@ emft_expand_node (EMFolderTreeModel *model, const char *key, EMFolderTree *emft) memcpy (uid, key, n); uid[n] = '\0'; + tree_view = GTK_TREE_VIEW (emft); + shell_module = em_folder_tree_model_get_shell_module (model); + if ((account = mail_config_get_account_by_uid (uid)) && account->enabled) { CamelException ex; @@ -640,7 +640,7 @@ emft_expand_node (EMFolderTreeModel *model, const char *key, EMFolderTree *emft) camel_object_ref (store); } else if (!strcmp (uid, "local")) { - if (!(store = mail_component_peek_local_store (NULL))) + if (!(store = e_mail_shell_module_get_local_store (shell_module))) return; camel_object_ref (store); @@ -662,7 +662,7 @@ emft_expand_node (EMFolderTreeModel *model, const char *key, EMFolderTree *emft) row = si->row; path = gtk_tree_row_reference_get_path (row); - gtk_tree_view_expand_to_path (priv->treeview, path); + gtk_tree_view_expand_to_path (tree_view, path); u = g_hash_table_lookup(emft->priv->select_uris_table, key); if (u) @@ -676,6 +676,7 @@ emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTree { struct _EMFolderTreePrivate *priv = emft->priv; struct _EMFolderTreeModelStoreInfo *si; + GtkTreeView *tree_view; gboolean is_store; CamelStore *store; EAccount *account; @@ -684,6 +685,8 @@ emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTree struct _selected_uri *u; gboolean is_expanded; + tree_view = GTK_TREE_VIEW (emft); + gtk_tree_model_get ((GtkTreeModel *) model, iter, COL_STRING_FULL_NAME, &full_name, COL_POINTER_CAMEL_STORE, &store, @@ -705,8 +708,8 @@ emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTree u = g_hash_table_lookup(priv->select_uris_table, key); if (is_expanded || u) { if (is_expanded) { - gtk_tree_view_expand_to_path (priv->treeview, tree_path); - gtk_tree_view_expand_row (priv->treeview, tree_path, FALSE); + gtk_tree_view_expand_to_path (tree_view, tree_path); + gtk_tree_view_expand_row (tree_view, tree_path, FALSE); } else { char *c = strrchr (key, '/'); @@ -737,7 +740,7 @@ em_folder_tree_new_with_model (EMFolderTreeModel *model) emft->priv->loading_row_id = g_signal_connect (model, "loading-row", G_CALLBACK (emft_maybe_expand_row), emft); emft->priv->loaded_row_id = g_signal_connect (model, "loaded-row", G_CALLBACK (emft_maybe_expand_row), emft); - a11y = gtk_widget_get_accessible (GTK_WIDGET (emft->priv->treeview)); + a11y = gtk_widget_get_accessible (GTK_WIDGET (emft)); atk_object_set_name (a11y, _("Mail Folder Tree")); return (GtkWidget *) emft; @@ -1019,6 +1022,7 @@ tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, int x, int y { struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeViewDropPosition pos; + GtkTreeView *tree_view; GtkTreePath *dest_path; struct _DragDataReceivedAsync *m; gboolean is_store; @@ -1027,7 +1031,9 @@ tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, int x, int y char *full_name; int i; - if (!gtk_tree_view_get_dest_row_at_pos (priv->treeview, x, y, &dest_path, &pos)) + tree_view = GTK_TREE_VIEW (emft); + + if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &dest_path, &pos)) return; /* this means we are receiving no data */ @@ -1105,6 +1111,7 @@ emft_drop_target(EMFolderTree *emft, GdkDragContext *context, GtkTreePath *path) struct _EMFolderTreePrivate *p = emft->priv; char *full_name = NULL, *uri = NULL, *src_uri = NULL; CamelStore *local, *sstore, *dstore; + EShellModule *shell_module; GdkAtom atom = GDK_NONE; gboolean is_store; GtkTreeIter iter; @@ -1122,7 +1129,8 @@ emft_drop_target(EMFolderTree *emft, GdkDragContext *context, GtkTreePath *path) COL_POINTER_CAMEL_STORE, &dstore, COL_STRING_URI, &uri, -1); - local = mail_component_peek_local_store (NULL); + shell_module = em_folder_tree_model_get_shell_module (p->model); + local = e_mail_shell_module_get_local_store (shell_module); targets = context->targets; @@ -1300,10 +1308,13 @@ tree_drag_drop (GtkWidget *widget, GdkDragContext *context, int x, int y, guint { struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeViewColumn *column; + GtkTreeView *tree_view; int cell_x, cell_y; GtkTreePath *path; GdkAtom target; + tree_view = GTK_TREE_VIEW (emft); + if (priv->autoscroll_id != 0) { g_source_remove (priv->autoscroll_id); priv->autoscroll_id = 0; @@ -1317,7 +1328,7 @@ tree_drag_drop (GtkWidget *widget, GdkDragContext *context, int x, int y, guint priv->autoexpand_id = 0; } - if (!gtk_tree_view_get_path_at_pos (priv->treeview, x, y, &path, &column, &cell_x, &cell_y)) + if (!gtk_tree_view_get_path_at_pos (tree_view, x, y, &path, &column, &cell_x, &cell_y)) return FALSE; target = emft_drop_target(emft, context, path); @@ -1345,6 +1356,9 @@ static void tree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, EMFolderTree *emft) { struct _EMFolderTreePrivate *priv = emft->priv; + GtkTreeView *tree_view; + + tree_view = GTK_TREE_VIEW (emft); if (priv->autoscroll_id != 0) { g_source_remove (priv->autoscroll_id); @@ -1359,7 +1373,7 @@ tree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, EMFolde priv->autoexpand_id = 0; } - gtk_tree_view_set_drag_dest_row(emft->priv->treeview, NULL, GTK_TREE_VIEW_DROP_BEFORE); + gtk_tree_view_set_drag_dest_row(tree_view, NULL, GTK_TREE_VIEW_DROP_BEFORE); } @@ -1368,19 +1382,20 @@ tree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, EMFolde static gboolean tree_autoscroll (EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; GtkAdjustment *vadjustment; + GtkTreeView *tree_view; GdkRectangle rect; GdkWindow *window; int offset, y; float value; /* get the y pointer position relative to the treeview */ - window = gtk_tree_view_get_bin_window (priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + window = gtk_tree_view_get_bin_window (tree_view); gdk_window_get_pointer (window, NULL, &y, NULL); /* rect is in coorinates relative to the scrolled window relative to the treeview */ - gtk_tree_view_get_visible_rect (priv->treeview, &rect); + gtk_tree_view_get_visible_rect (tree_view, &rect); /* move y into the same coordinate system as rect */ y += rect.y; @@ -1392,7 +1407,7 @@ tree_autoscroll (EMFolderTree *emft) return TRUE; } - vadjustment = gtk_tree_view_get_vadjustment (priv->treeview); + vadjustment = gtk_tree_view_get_vadjustment (tree_view); value = CLAMP (vadjustment->value + offset, 0.0, vadjustment->upper - vadjustment->page_size); gtk_adjustment_set_value (vadjustment, value); @@ -1404,10 +1419,12 @@ static gboolean tree_autoexpand (EMFolderTree *emft) { struct _EMFolderTreePrivate *priv = emft->priv; + GtkTreeView *tree_view; GtkTreePath *path; + tree_view = GTK_TREE_VIEW (emft); path = gtk_tree_row_reference_get_path (priv->autoexpand_row); - gtk_tree_view_expand_row (priv->treeview, path, FALSE); + gtk_tree_view_expand_row (tree_view, path, FALSE); gtk_tree_path_free (path); return TRUE; @@ -1419,13 +1436,16 @@ tree_drag_motion (GtkWidget *widget, GdkDragContext *context, int x, int y, guin struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeModel *model = (GtkTreeModel *) priv->model; GtkTreeViewDropPosition pos; + GtkTreeView *tree_view; GdkDragAction action = 0; GtkTreePath *path; GtkTreeIter iter; GdkAtom target; int i; - if (!gtk_tree_view_get_dest_row_at_pos(priv->treeview, x, y, &path, &pos)) + tree_view = GTK_TREE_VIEW (emft); + + if (!gtk_tree_view_get_dest_row_at_pos(tree_view, x, y, &path, &pos)) return FALSE; if (priv->autoscroll_id == 0) @@ -1433,7 +1453,7 @@ tree_drag_motion (GtkWidget *widget, GdkDragContext *context, int x, int y, guin gtk_tree_model_get_iter (model, &iter, path); - if (gtk_tree_model_iter_has_child (model, &iter) && !gtk_tree_view_row_expanded (priv->treeview, path)) { + if (gtk_tree_model_iter_has_child (model, &iter) && !gtk_tree_view_row_expanded (tree_view, path)) { if (priv->autoexpand_id != 0) { GtkTreePath *autoexpand_path; @@ -1469,10 +1489,10 @@ tree_drag_motion (GtkWidget *widget, GdkDragContext *context, int x, int y, guin action = context->suggested_action; if (action == GDK_ACTION_COPY && (context->actions & GDK_ACTION_MOVE)) action = GDK_ACTION_MOVE; - gtk_tree_view_set_drag_dest_row(priv->treeview, path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); + gtk_tree_view_set_drag_dest_row(tree_view, path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); break; default: - gtk_tree_view_set_drag_dest_row(priv->treeview, path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); + gtk_tree_view_set_drag_dest_row(tree_view, path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); action = context->suggested_action; break; } @@ -1492,11 +1512,14 @@ void em_folder_tree_enable_drag_and_drop (EMFolderTree *emft) { struct _EMFolderTreePrivate *priv; + GtkTreeView *tree_view; static int setup = 0; int i; g_return_if_fail (EM_IS_FOLDER_TREE (emft)); + tree_view = GTK_TREE_VIEW (emft); + priv = emft->priv; if (!setup) { for (i=0; i<NUM_DRAG_TYPES; i++) @@ -1508,23 +1531,27 @@ em_folder_tree_enable_drag_and_drop (EMFolderTree *emft) setup = 1; } - gtk_drag_source_set((GtkWidget *)priv->treeview, GDK_BUTTON1_MASK, drag_types, NUM_DRAG_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); - gtk_drag_dest_set((GtkWidget *)priv->treeview, GTK_DEST_DEFAULT_ALL, drop_types, NUM_DROP_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); + gtk_drag_source_set((GtkWidget *)tree_view, GDK_BUTTON1_MASK, drag_types, NUM_DRAG_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); + gtk_drag_dest_set((GtkWidget *)tree_view, GTK_DEST_DEFAULT_ALL, drop_types, NUM_DROP_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); - g_signal_connect (priv->treeview, "drag-begin", G_CALLBACK (tree_drag_begin), emft); - g_signal_connect (priv->treeview, "drag-data-delete", G_CALLBACK (tree_drag_data_delete), emft); - g_signal_connect (priv->treeview, "drag-data-get", G_CALLBACK (tree_drag_data_get), emft); - g_signal_connect (priv->treeview, "drag-data-received", G_CALLBACK (tree_drag_data_received), emft); - g_signal_connect (priv->treeview, "drag-drop", G_CALLBACK (tree_drag_drop), emft); - g_signal_connect (priv->treeview, "drag-end", G_CALLBACK (tree_drag_end), emft); - g_signal_connect (priv->treeview, "drag-leave", G_CALLBACK (tree_drag_leave), emft); - g_signal_connect (priv->treeview, "drag-motion", G_CALLBACK (tree_drag_motion), emft); + g_signal_connect (tree_view, "drag-begin", G_CALLBACK (tree_drag_begin), emft); + g_signal_connect (tree_view, "drag-data-delete", G_CALLBACK (tree_drag_data_delete), emft); + g_signal_connect (tree_view, "drag-data-get", G_CALLBACK (tree_drag_data_get), emft); + g_signal_connect (tree_view, "drag-data-received", G_CALLBACK (tree_drag_data_received), emft); + g_signal_connect (tree_view, "drag-drop", G_CALLBACK (tree_drag_drop), emft); + g_signal_connect (tree_view, "drag-end", G_CALLBACK (tree_drag_end), emft); + g_signal_connect (tree_view, "drag-leave", G_CALLBACK (tree_drag_leave), emft); + g_signal_connect (tree_view, "drag-motion", G_CALLBACK (tree_drag_motion), emft); } void em_folder_tree_set_multiselect (EMFolderTree *tree, gboolean mode) { - GtkTreeSelection *sel = gtk_tree_view_get_selection ((GtkTreeView *) tree->priv->treeview); + GtkTreeSelection *sel; + GtkTreeView *tree_view; + + tree_view = GTK_TREE_VIEW (tree); + sel = gtk_tree_view_get_selection (tree_view); tree->priv->do_multiselect = mode; gtk_tree_selection_set_mode (sel, mode ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE); @@ -1544,10 +1571,14 @@ void em_folder_tree_set_excluded_func(EMFolderTree *emft, EMFTExcludeFunc exclud GList * em_folder_tree_get_selected_uris (EMFolderTree *emft) { - GtkTreeSelection *selection = gtk_tree_view_get_selection (emft->priv->treeview); + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkTreeModel *model; GList *list = NULL, *rows, *l; GSList *sl; - GtkTreeModel *model; + + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); /* at first, add lost uris */ for (sl = emft->priv->select_uris; sl; sl = g_slist_next(sl)) @@ -1584,9 +1615,13 @@ get_selected_uris_path_iterate (GtkTreeModel *model, GtkTreePath *treepath, GtkT GList * em_folder_tree_get_selected_paths (EMFolderTree *emft) { - GtkTreeSelection *selection = gtk_tree_view_get_selection (emft->priv->treeview); + GtkTreeSelection *selection; + GtkTreeView *tree_view; GList *list = NULL; + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + gtk_tree_selection_selected_foreach (selection, get_selected_uris_path_iterate, &list); return list; @@ -1597,7 +1632,7 @@ emft_clear_selected_list(EMFolderTree *emft) { struct _EMFolderTreePrivate *priv = emft->priv; - g_slist_foreach(priv->select_uris, emft_free_select_uri, emft); + g_slist_foreach(priv->select_uris, (GFunc) emft_free_select_uri, NULL); g_slist_free(priv->select_uris); g_hash_table_destroy(priv->select_uris_table); priv->select_uris = NULL; @@ -1735,13 +1770,13 @@ emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m) struct _EMFolderTreeModelStoreInfo *si; GtkTreeIter root, iter, titer; CamelFolderInfo *fi; + GtkTreeView *tree_view; GtkTreeStore *model; GtkTreePath *path; gboolean is_store; /* check that we haven't been destroyed */ - if (priv->treeview == NULL) - return; + g_return_if_fail (GTK_IS_TREE_VIEW (m->emft)); /* check that our parent folder hasn't been deleted/unsubscribed */ if (!gtk_tree_row_reference_valid (m->root)) @@ -1752,7 +1787,8 @@ emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m) return; } - model = (GtkTreeStore *) gtk_tree_view_get_model (priv->treeview); + tree_view = GTK_TREE_VIEW (m->emft); + model = (GtkTreeStore *) gtk_tree_view_get_model (tree_view); path = gtk_tree_row_reference_get_path (m->root); gtk_tree_model_get_iter ((GtkTreeModel *) model, &root, path); @@ -1760,7 +1796,7 @@ emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m) /* if we had an error, then we need to re-set the load subdirs state and collapse the node */ if (!m->fi && camel_exception_is_set(&m->base.ex)) { gtk_tree_store_set(model, &root, COL_BOOL_LOAD_SUBDIRS, TRUE, -1); - gtk_tree_view_collapse_row (priv->treeview, path); + gtk_tree_view_collapse_row (tree_view, path); gtk_tree_path_free (path); return; } @@ -1799,7 +1835,7 @@ emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m) if (is_store) { path = gtk_tree_model_get_path ((GtkTreeModel *) model, &root); - gtk_tree_view_collapse_row (priv->treeview, path); + gtk_tree_view_collapse_row (tree_view, path); emft_queue_save_state (m->emft); gtk_tree_path_free (path); return; @@ -2078,13 +2114,14 @@ static void emft_popup_properties (EPopup *ep, EPopupItem *pitem, void *data) { EMFolderTree *emft = data; - struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeSelection *selection; + GtkTreeView *tree_view; GtkTreeModel *model; GtkTreeIter iter; char *uri; - selection = gtk_tree_view_get_selection (priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); if (!emft_selection_get_selected (selection, &model, &iter)) return; @@ -2130,10 +2167,11 @@ emft_popup_free(EPopup *ep, GSList *items, void *data) static gboolean emft_popup (EMFolderTree *emft, GdkEvent *event) { - GtkTreeView *treeview; + GtkTreeView *tree_view; GtkTreeSelection *selection; CamelStore *local, *store; EMPopupTargetFolder *target; + EShellModule *shell_module; GtkTreeModel *model; GtkTreeIter iter; GSList *menus = NULL; @@ -2147,16 +2185,18 @@ emft_popup (EMFolderTree *emft, GdkEvent *event) CamelFolder *selfolder = NULL; int i; - treeview = emft->priv->treeview; + tree_view = GTK_TREE_VIEW (emft); /* this centralises working out when the user's done something */ - emft_tree_user_event(treeview, (GdkEvent *)event, emft); + emft_tree_user_event(tree_view, (GdkEvent *)event, emft); /* FIXME: we really need the folderinfo to build a proper menu */ - selection = gtk_tree_view_get_selection (treeview); + selection = gtk_tree_view_get_selection (tree_view); if (!emft_selection_get_selected (selection, &model, &iter)) return FALSE; + shell_module = em_folder_tree_model_get_shell_module (emft->priv->model); + gtk_tree_model_get (model, &iter, COL_POINTER_CAMEL_STORE, &store, COL_STRING_URI, &uri, COL_STRING_FULL_NAME, &full_name, COL_BOOL_IS_STORE, &isstore, COL_UINT_FLAGS, &folder_type_flags, -1); @@ -2174,7 +2214,7 @@ emft_popup (EMFolderTree *emft, GdkEvent *event) } else { flags |= EM_POPUP_FOLDER_FOLDER; - local = mail_component_peek_local_store (NULL); + local = e_mail_shell_module_get_local_store (shell_module); /* don't allow deletion of special local folders */ if (!(store == local && is_special_local_folder (full_name))) @@ -2317,6 +2357,7 @@ em_folder_tree_set_selected (EMFolderTree *emft, const char *uri, gboolean expan void em_folder_tree_select_next_path (EMFolderTree *emft, gboolean skip_read_folders) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter, parent, child; @@ -2326,7 +2367,8 @@ em_folder_tree_select_next_path (EMFolderTree *emft, gboolean skip_read_folders) g_return_if_fail (EM_IS_FOLDER_TREE (emft)); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection(tree_view); if (gtk_tree_selection_get_selected(selection, &model, &iter)) { current_path = gtk_tree_model_get_path (model, &iter); @@ -2361,16 +2403,16 @@ em_folder_tree_select_next_path (EMFolderTree *emft, gboolean skip_read_folders) } if (path) { - if (!gtk_tree_view_row_expanded (emft->priv->treeview, path)) - gtk_tree_view_expand_to_path (emft->priv->treeview, path); + if (!gtk_tree_view_row_expanded (tree_view, path)) + gtk_tree_view_expand_to_path (tree_view, path); gtk_tree_selection_select_path(selection, path); if (!priv->cursor_set) { - gtk_tree_view_set_cursor (priv->treeview, path, NULL, FALSE); + gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE); priv->cursor_set = TRUE; } - gtk_tree_view_scroll_to_cell (priv->treeview, path, NULL, TRUE, 0.5f, 0.0f); + gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5f, 0.0f); } return; } @@ -2396,6 +2438,7 @@ get_last_child (GtkTreeModel *model, GtkTreeIter *iter) void em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter, child; @@ -2405,7 +2448,8 @@ em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders) g_return_if_fail (EM_IS_FOLDER_TREE (emft)); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); if (gtk_tree_selection_get_selected(selection, &model, &iter)){ @@ -2439,17 +2483,17 @@ em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders) } if (path) { - if (!gtk_tree_view_row_expanded (priv->treeview, path)) { - gtk_tree_view_expand_to_path (priv->treeview, path); + if (!gtk_tree_view_row_expanded (tree_view, path)) { + gtk_tree_view_expand_to_path (tree_view, path); } gtk_tree_selection_select_path(selection, path); if (!priv->cursor_set) { - gtk_tree_view_set_cursor (priv->treeview, path, NULL, FALSE); + gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE); priv->cursor_set = TRUE; } - gtk_tree_view_scroll_to_cell (priv->treeview, path, NULL, TRUE, 0.5f, 0.0f); + gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5f, 0.0f); } return; } @@ -2458,6 +2502,7 @@ em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders) char * em_folder_tree_get_selected_uri (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2465,7 +2510,9 @@ em_folder_tree_get_selected_uri (EMFolderTree *emft) g_return_val_if_fail (EM_IS_FOLDER_TREE (emft), NULL); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) gtk_tree_model_get(model, &iter, COL_STRING_URI, &uri, -1); @@ -2475,6 +2522,7 @@ em_folder_tree_get_selected_uri (EMFolderTree *emft) char * em_folder_tree_get_selected_path (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2482,7 +2530,9 @@ em_folder_tree_get_selected_path (EMFolderTree *emft) g_return_val_if_fail (EM_IS_FOLDER_TREE (emft), NULL); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) gtk_tree_model_get(model, &iter, COL_STRING_FULL_NAME, &name, -1); @@ -2492,6 +2542,7 @@ em_folder_tree_get_selected_path (EMFolderTree *emft) CamelFolder * em_folder_tree_get_selected_folder (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2504,7 +2555,9 @@ em_folder_tree_get_selected_folder (EMFolderTree *emft) camel_exception_init (&ex); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + 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); @@ -2519,6 +2572,7 @@ em_folder_tree_get_selected_folder (EMFolderTree *emft) CamelFolderInfo * em_folder_tree_get_selected_folder_info (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2531,7 +2585,9 @@ em_folder_tree_get_selected_folder_info (EMFolderTree *emft) camel_exception_init (&ex); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + 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, diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h index e89be47506..1a838baea6 100644 --- a/mail/em-folder-tree.h +++ b/mail/em-folder-tree.h @@ -21,28 +21,38 @@ * */ -#ifndef __EM_FOLDER_TREE_H__ -#define __EM_FOLDER_TREE_H__ +#ifndef EM_FOLDER_TREE_H +#define EM_FOLDER_TREE_H #include <gtk/gtk.h> #include <camel/camel-store.h> - -#include "mail/em-folder-tree-model.h" - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define EM_TYPE_FOLDER_TREE (em_folder_tree_get_type ()) -#define EM_FOLDER_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EM_TYPE_FOLDER_TREE, EMFolderTree)) -#define EM_FOLDER_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EM_TYPE_FOLDER_TREE, EMFolderTreeClass)) -#define EM_IS_FOLDER_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EM_TYPE_FOLDER_TREE)) -#define EM_IS_FOLDER_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EM_TYPE_FOLDER_TREE)) -#define EM_FOLDER_TREE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EM_TYPE_FOLDER_TREE, EMFolderTreeClass)) +#include <shell/e-shell-module.h> +#include <mail/em-folder-tree-model.h> + +/* Standard GObject macros */ +#define EM_TYPE_FOLDER_TREE \ + (em_folder_tree_get_type ()) +#define EM_FOLDER_TREE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_FOLDER_TREE, EMFolderTree)) +#define EM_FOLDER_TREE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_FOLDER_TREE, EMFolderTreeClass)) +#define EM_IS_FOLDER_TREE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_FOLDER_TREE)) +#define EM_IS_FOLDER_TREE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_TYPE_FOLDER_TREE)) +#define EM_FOLDER_TREE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_FOLDER_TREE, EMFolderTreeClass)) + +G_BEGIN_DECLS typedef struct _EMFolderTree EMFolderTree; typedef struct _EMFolderTreeClass EMFolderTreeClass; +typedef struct _EMFolderTreePrivate EMFolderTreePrivate; /* not sure this api is the best, but its the easiest to implement and will cover what we need */ #define EMFT_EXCLUDE_NOSELECT CAMEL_FOLDER_NOSELECT @@ -54,22 +64,26 @@ typedef struct _EMFolderTreeClass EMFolderTreeClass; typedef gboolean (*EMFTExcludeFunc)(EMFolderTree *emft, GtkTreeModel *model, GtkTreeIter *iter, void *data); struct _EMFolderTree { - GtkVBox parent_object; - - struct _EMFolderTreePrivate *priv; + GtkTreeView parent_object; + EMFolderTreePrivate *priv; }; struct _EMFolderTreeClass { - GtkVBoxClass parent_class; + GtkTreeViewClass parent_class; /* signals */ - void (* folder_activated) (EMFolderTree *emft, const char *full_name, const char *uri); - void (* folder_selected) (EMFolderTree *emft, const char *full_name, const char *uri, guint32 flags); + void (*folder_activated) (EMFolderTree *emft, + const gchar *full_name, + const gchar *uri); + void (*folder_selected) (EMFolderTree *emft, + const gchar *full_name, + const gchar *uri, + guint32 flags); }; GType em_folder_tree_get_type (void); -GtkWidget *em_folder_tree_new (void); +GtkWidget *em_folder_tree_new (EShellModule *shell_module); GtkWidget *em_folder_tree_new_with_model (EMFolderTreeModel *model); void em_folder_tree_enable_drag_and_drop (EMFolderTree *emft); @@ -95,8 +109,6 @@ EMFolderTreeModelStoreInfo *em_folder_tree_get_model_storeinfo (EMFolderTree *em gboolean em_folder_tree_create_folder (EMFolderTree *emft, const char *full_name, const char *uri); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS -#endif /* __EM_FOLDER_TREE_H__ */ +#endif /* EM_FOLDER_TREE_H */ diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c index 195b66a815..9726f6c552 100644 --- a/mail/em-folder-utils.c +++ b/mail/em-folder-utils.c @@ -59,12 +59,10 @@ #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" @@ -72,6 +70,8 @@ #include "em-folder-selection.h" #include "em-folder-properties.h" +#include "e-mail-shell-module.h" + #define d(x) extern CamelSession *session; @@ -270,6 +270,7 @@ emfu_copy_folder_selected (const char *uri, void *data) { struct _copy_folder_data *cfd = data; CamelStore *fromstore = NULL, *tostore = NULL; + CamelStore *local_store; char *tobase = NULL; CamelException ex; CamelURL *url; @@ -281,13 +282,15 @@ emfu_copy_folder_selected (const char *uri, void *data) camel_exception_init (&ex); + local_store = e_mail_shell_module_get_local_store (mail_shell_module); + 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)) { + if (cfd->delete && fromstore == local_store && emfu_is_special_local_folder (cfd->fi->full_name)) { GtkWidget *w = e_error_new (NULL, "mail:no-rename-special-folder", cfd->fi->full_name, NULL); em_utils_show_error_silent (w); @@ -399,12 +402,12 @@ emfu_delete_response (GtkWidget *dialog, int response, gpointer data) void em_folder_utils_delete_folder (CamelFolder *folder) { - CamelStore *local; + CamelStore *local_store; GtkWidget *dialog; - local = mail_component_peek_local_store (NULL); + local_store = e_mail_shell_module_get_local_store (mail_shell_module); - if (folder->parent_store == local && emfu_is_special_local_folder (folder->full_name)) { + if (folder->parent_store == local_store && emfu_is_special_local_folder (folder->full_name)) { dialog = e_error_new (NULL, "mail:no-delete-special-folder", folder->full_name, NULL); em_utils_show_error_silent (dialog); return; @@ -427,14 +430,14 @@ em_folder_utils_rename_folder (CamelFolder *folder) { char *prompt, *new_name; const char *p; - CamelStore *local; + CamelStore *local_store; gboolean done = FALSE; size_t base_len; - local = mail_component_peek_local_store (NULL); + local_store = e_mail_shell_module_get_local_store (mail_shell_module); /* 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)) { + if (folder->parent_store == local_store && emfu_is_special_local_folder (folder->full_name)) { e_error_run(NULL, "mail:no-rename-special-folder", folder->full_name, NULL); return; @@ -684,7 +687,7 @@ em_folder_utils_create_folder (CamelFolderInfo *folderinfo, EMFolderTree *emft) EMFolderTreeModel *model; GtkWidget *dialog; - model = mail_component_peek_tree_model (mail_component_peek ()); + model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); 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:")); diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c index 90e6acb54e..20f86ca562 100644 --- a/mail/em-format-html-display.c +++ b/mail/em-format-html-display.c @@ -80,7 +80,6 @@ #include "mail-config.h" #include "em-format-html-display.h" -#include "em-marshal.h" #include "e-searching-tokenizer.h" #include "em-icon-stream.h" #include "em-utils.h" @@ -337,7 +336,7 @@ efhd_class_init(GObjectClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(EMFormatHTMLDisplayClass, popup_event), efhd_bool_accumulator, NULL, - em_marshal_BOOLEAN__BOXED_POINTER_POINTER, + e_marshal_BOOLEAN__BOXED_POINTER_POINTER, G_TYPE_BOOLEAN, 3, GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE, G_TYPE_POINTER, G_TYPE_POINTER); @@ -621,8 +620,10 @@ em_format_html_get_search_dialog (EMFormatHTMLDisplay *efhd) p->search_entry = e_icon_entry_get_entry (E_ICON_ENTRY (icon_entry)); gtk_label_set_mnemonic_widget (GTK_LABEL (label1), p->search_entry); gtk_widget_show (p->search_entry); +#if 0 /* KILL-BONOBO */ clear_button = e_icon_entry_create_button ("gtk-clear"); e_icon_entry_pack_widget (E_ICON_ENTRY (icon_entry), clear_button, FALSE); +#endif gtk_widget_show_all (icon_entry); gtk_widget_hide (clear_button); diff --git a/mail/em-format-html.c b/mail/em-format-html.c index caa5c0f51c..12e2b5975c 100644 --- a/mail/em-format-html.c +++ b/mail/em-format-html.c @@ -74,7 +74,6 @@ #include <libedataserver/e-msgport.h> -#include "mail-component.h" #include "mail-config.h" #include "mail-mt.h" @@ -262,9 +261,6 @@ em_format_html_get_type(void) const char *base_directory = e_get_user_data_dir (); char *path; - /* Trigger creation of mail component. */ - mail_component_peek (); - efh_parent = g_type_class_ref(em_format_get_type()); type = g_type_register_static(em_format_get_type(), "EMFormatHTML", &info, 0); diff --git a/mail/em-search-context.c b/mail/em-search-context.c index 5bf98614c6..a8a63ebe2d 100644 --- a/mail/em-search-context.c +++ b/mail/em-search-context.c @@ -33,35 +33,40 @@ #include "filter/filter-option.h" #include "filter/filter-int.h" -static FilterElement *em_search_new_element(RuleContext *rc, const char *type); +static gpointer parent_class; -static RuleContextClass *parent_class = NULL; - -static void -em_search_context_finalise (GObject *obj) +static FilterElement * +search_context_new_element (RuleContext *context, + const gchar *type) { - G_OBJECT_CLASS (parent_class)->finalize (obj); + if (strcmp (type, "system-flag") == 0) + return (FilterElement *) filter_option_new (); + + if (strcmp (type, "score") == 0) + return (FilterElement *) filter_int_new_type ("score", -3, 3); + + /* Chain up to parent's new_element() method. */ + return RULE_CONTEXT_CLASS (parent_class)->new_element (context, type); } static void -em_search_context_class_init (EMSearchContextClass *klass) +search_context_class_init (EMSearchContextClass *class) { - parent_class = g_type_class_ref (RULE_TYPE_CONTEXT); + RuleContextClass *rule_context_class; - ((GObjectClass *)klass)->finalize = em_search_context_finalise; - ((RuleContextClass *)klass)->new_element = em_search_new_element; + parent_class = g_type_class_peek_parent (class); + + rule_context_class = RULE_CONTEXT_CLASS (class); + rule_context_class->new_element = search_context_new_element; } static void -em_search_context_init (EMSearchContext *vc) +search_context_init (EMSearchContext *vc) { - rule_context_add_part_set ((RuleContext *)vc, "partset", filter_part_get_type (), - rule_context_add_part, rule_context_next_part); - - rule_context_add_rule_set ((RuleContext *)vc, "ruleset", filter_rule_get_type (), - rule_context_add_rule, rule_context_next_rule); + RuleContext *rule_context; - ((RuleContext *)vc)->flags = RULE_CONTEXT_THREADING | RULE_CONTEXT_GROUPING; + rule_context = RULE_CONTEXT (vc); + rule_context->flags = RULE_CONTEXT_THREADING | RULE_CONTEXT_GROUPING; } GType @@ -69,46 +74,29 @@ em_search_context_get_type (void) { static GType type = 0; - if (!type) { - static const GTypeInfo info = { + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { sizeof (EMSearchContextClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) em_search_context_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) search_context_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ sizeof (EMSearchContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) em_search_context_init, + 0, /* n_preallocs */ + (GInstanceInitFunc) search_context_init, + NULL /* value_table */ }; - type = g_type_register_static (RULE_TYPE_CONTEXT, "EMSearchContext", &info, 0); + type = g_type_register_static ( + RULE_TYPE_CONTEXT, "EMSearchContext", &type_info, 0); } return type; } -/** - * em_search_context_new: - * - * Create a new EMSearchContext object. - * - * Return value: A new #EMSearchContext object. - **/ -EMSearchContext * +RuleContext * em_search_context_new (void) { - return (EMSearchContext *) g_object_new (EM_SEARCH_TYPE_CONTEXT, NULL, NULL); -} - -static FilterElement * -em_search_new_element(RuleContext *rc, const char *type) -{ - if (!strcmp (type, "system-flag")) { - return (FilterElement *) filter_option_new (); - } else if (!strcmp (type, "score")) { - return (FilterElement *) filter_int_new_type("score", -3, 3); - } else { - return parent_class->new_element(rc, type); - } + return g_object_new (EM_SEARCH_TYPE_CONTEXT, NULL); } diff --git a/mail/em-search-context.h b/mail/em-search-context.h index 3df5c1d577..ad18570901 100644 --- a/mail/em-search-context.h +++ b/mail/em-search-context.h @@ -22,31 +22,46 @@ * */ -#ifndef _EM_SEARCH_CONTEXT_H -#define _EM_SEARCH_CONTEXT_H +#ifndef EM_SEARCH_CONTEXT_H +#define EM_SEARCH_CONTEXT_H -#include "filter/rule-context.h" +#include <filter/rule-context.h> -#define EM_SEARCH_TYPE_CONTEXT (em_search_context_get_type ()) -#define EM_SEARCH_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EM_SEARCH_TYPE_CONTEXT, EMSearchContext)) -#define EM_SEARCH_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EM_SEARCH_TYPE_CONTEXT, EMSearchContextClass)) -#define IS_EM_SEARCH_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EM_SEARCH_TYPE_CONTEXT)) -#define IS_EM_SEARCH_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EM_SEARCH_TYPE_CONTEXT)) -#define EM_SEARCH_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EM_SEARCH_TYPE_CONTEXT, EMSearchContextClass)) +/* Standard GObject macros */ +#define EM_SEARCH_TYPE_CONTEXT \ + (em_search_context_get_type ()) +#define EM_SEARCH_CONTEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_SEARCH_TYPE_CONTEXT, EMSearchContext)) +#define EM_SEARCH_CONTEXT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_SEARCH_TYPE_CONTEXT, EMSearchContextClass)) +#define EM_IS_SEARCH_CONTEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_SEARCH_TYPE_CONTEXT)) +#define EM_IS_SEARCH_CONTEXT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_SEARCH_TYPE_CONTEXT)) +#define EM_SEARCH_CONTEXT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_SEARCH_TYPE_CONTEXT, EMSearchContextClass)) + +G_BEGIN_DECLS typedef struct _EMSearchContext EMSearchContext; typedef struct _EMSearchContextClass EMSearchContextClass; struct _EMSearchContext { - RuleContext parent_object; + RuleContext parent; }; struct _EMSearchContextClass { RuleContextClass parent_class; }; -GType em_search_context_get_type (void); +GType em_search_context_get_type (void); +RuleContext * em_search_context_new (void); -EMSearchContext *em_search_context_new (void); +G_END_DECLS -#endif /* ! _EM_SEARCH_CONTEXT_H */ +#endif /* EM_SEARCH_CONTEXT_H */ diff --git a/mail/em-utils.c b/mail/em-utils.c index 01b18eb461..8db127e5ed 100644 --- a/mail/em-utils.c +++ b/mail/em-utils.c @@ -56,7 +56,6 @@ #include <gio/gio.h> -#include "mail-component.h" #include "mail-mt.h" #include "mail-ops.h" #include "mail-tools.h" @@ -78,7 +77,8 @@ #include "em-format-quote.h" #include "em-account-editor.h" #include "e-attachment.h" -#include "e-activity-handler.h" + +#include "e-mail-shell-module.h" static void emu_save_part_done (CamelMimePart *part, char *name, int done, void *data); @@ -251,11 +251,12 @@ em_filter_editor_response (GtkWidget *dialog, int button, gpointer user_data) EMFilterContext *fc; if (button == GTK_RESPONSE_OK) { + const gchar *data_dir; char *user; + data_dir = e_shell_module_get_data_dir (mail_shell_module); fc = g_object_get_data ((GObject *) dialog, "context"); - user = g_strdup_printf ("%s/filters.xml", - mail_component_peek_base_directory (mail_component_peek ())); + user = g_strdup_printf ("%s/filters.xml", data_dir); rule_context_save ((RuleContext *) fc, user); g_free (user); } @@ -282,7 +283,7 @@ static EMFilterSource em_filter_source_element_names[] = { void em_utils_edit_filters (GtkWidget *parent) { - const char *base_directory = mail_component_peek_base_directory (mail_component_peek ()); + const gchar *data_dir; char *user, *system; EMFilterContext *fc; @@ -291,8 +292,10 @@ em_utils_edit_filters (GtkWidget *parent) return; } + data_dir = e_shell_module_get_data_dir (mail_shell_module); + fc = em_filter_context_new (); - user = g_strdup_printf ("%s/filters.xml", base_directory); + user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); rule_context_load ((RuleContext *) fc, system, user); g_free (user); @@ -1376,13 +1379,17 @@ em_utils_temp_save_part(GtkWidget *parent, CamelMimePart *part, gboolean mode) gboolean em_utils_folder_is_templates (CamelFolder *folder, const char *uri) { + CamelFolder *local_templates_folder; EAccountList *accounts; EAccount *account; EIterator *iter; int is = FALSE; char *templates_uri; - if (folder == mail_component_get_folder (NULL, MAIL_COMPONENT_FOLDER_TEMPLATES)) + local_templates_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_TEMPLATES); + + if (folder == local_templates_folder) return TRUE; if (uri == NULL) @@ -1423,13 +1430,17 @@ em_utils_folder_is_templates (CamelFolder *folder, const char *uri) gboolean em_utils_folder_is_drafts(CamelFolder *folder, const char *uri) { + CamelFolder *local_drafts_folder; EAccountList *accounts; EAccount *account; EIterator *iter; int is = FALSE; char *drafts_uri; - if (folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS)) + local_drafts_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); + + if (folder == local_drafts_folder) return TRUE; if (uri == NULL) @@ -1470,13 +1481,17 @@ em_utils_folder_is_drafts(CamelFolder *folder, const char *uri) gboolean em_utils_folder_is_sent(CamelFolder *folder, const char *uri) { + CamelFolder *local_sent_folder; EAccountList *accounts; EAccount *account; EIterator *iter; int is = FALSE; char *sent_uri; - if (folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT)) + local_sent_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_SENT); + + if (folder == local_sent_folder) return TRUE; if (uri == NULL) @@ -1517,8 +1532,13 @@ em_utils_folder_is_sent(CamelFolder *folder, const char *uri) gboolean em_utils_folder_is_outbox(CamelFolder *folder, const char *uri) { + CamelFolder *local_outbox_folder; + + local_outbox_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); + /* <Highlander>There can be only one.</Highlander> */ - return folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + return folder == local_outbox_folder; } /** @@ -2348,25 +2368,34 @@ em_utils_clear_get_password_canceled_accounts_flag (void) } -static void error_response(GtkObject *o, int button, void *data) -{ - gtk_widget_destroy((GtkWidget *)o); -} - void em_utils_show_error_silent (GtkWidget *widget) { - EActivityHandler *handler = mail_component_peek_activity_handler (mail_component_peek ()); - if(!g_object_get_data ((GObject *) widget, "response-handled")) - g_signal_connect(widget, "response", G_CALLBACK(error_response), NULL); - e_activity_handler_make_error (handler, "mail", E_LOG_ERROR, widget); + EActivity *activity; + + activity = e_activity_new (NULL); + e_activity_error (activity, widget); + e_shell_module_add_activity (mail_shell_module, activity); + g_object_unref (activity); + + if (g_object_get_data (G_OBJECT (widget), "response-handled") == NULL) + g_signal_connect ( + widget, "response", + G_CALLBACK (gtk_widget_destroy), NULL); } void em_utils_show_info_silent (GtkWidget *widget) { - EActivityHandler *handler = mail_component_peek_activity_handler (mail_component_peek ()); - if(!g_object_get_data ((GObject *) widget, "response-handled")) - g_signal_connect(widget, "response", G_CALLBACK(error_response), NULL); - e_activity_handler_make_error (handler, "mail", E_LOG_WARNINGS, widget); + EActivity *activity; + + activity = e_activity_new (NULL); + e_activity_info (activity, widget); + e_shell_module_add_activity (mail_shell_module, activity); + g_object_unref (activity); + + if (g_object_get_data (G_OBJECT (widget), "response-handled") == NULL) + g_signal_connect ( + widget, "response", + G_CALLBACK (gtk_widget_destroy), NULL); } diff --git a/mail/em-vfolder-rule.c b/mail/em-vfolder-rule.c index 6e12a0456d..128b63b744 100644 --- a/mail/em-vfolder-rule.c +++ b/mail/em-vfolder-rule.c @@ -37,10 +37,11 @@ #include "mail/em-utils.h" #include "mail/em-folder-tree.h" #include "mail/em-folder-selector.h" -#include "mail/mail-component.h" #include "e-util/e-error.h" #include "e-util/e-util-private.h" +#include "e-mail-shell-module.h" + #define d(x) static int validate(FilterRule *); @@ -505,9 +506,11 @@ static void source_add(GtkWidget *widget, struct _source_data *data) { EMFolderTree *emft; + EMFolderTreeModel *model; GtkWidget *dialog; - emft =(EMFolderTree *)em_folder_tree_new_with_model(mail_component_peek_tree_model(mail_component_peek())); + model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); + emft =(EMFolderTree *)em_folder_tree_new_with_model (model); em_folder_tree_set_excluded(emft, EMFT_EXCLUDE_NOSELECT); dialog = em_folder_selector_new(emft, EM_FOLDER_SELECTOR_CAN_CREATE, _("Select Folder"), NULL, _("_Add")); diff --git a/mail/importers/evolution-mbox-importer.c b/mail/importers/evolution-mbox-importer.c index 2943772b68..36cf8768ff 100644 --- a/mail/importers/evolution-mbox-importer.c +++ b/mail/importers/evolution-mbox-importer.c @@ -40,9 +40,8 @@ #include <camel/camel-exception.h> +#include "mail/e-mail-shell-module.h" #include "mail/em-folder-selection-button.h" - -#include "mail/mail-component.h" #include "mail/mail-mt.h" #include "mail-importer.h" @@ -73,15 +72,20 @@ static GtkWidget * mbox_getwidget(EImport *ei, EImportTarget *target, EImportImporter *im) { GtkWidget *hbox, *w; + EMFolderTreeModel *model; + const gchar *local_inbox_folder_uri; + + local_inbox_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_INBOX); + model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); hbox = gtk_hbox_new(FALSE, 0); w = gtk_label_new(_("Destination folder:")); gtk_box_pack_start((GtkBox *)hbox, w, FALSE, TRUE, 6); - w = em_folder_selection_button_new(_("Select folder"), _("Select folder to import into")); - em_folder_selection_button_set_selection((EMFolderSelectionButton *)w, - mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_INBOX)); + w = em_folder_selection_button_new(model, _("Select folder"), _("Select folder to import into")); + em_folder_selection_button_set_selection((EMFolderSelectionButton *)w, local_inbox_folder_uri); g_signal_connect(w, "selected", G_CALLBACK(folder_selected), target); gtk_box_pack_start((GtkBox *)hbox, w, FALSE, TRUE, 6); diff --git a/mail/importers/mail-importer.c b/mail/importers/mail-importer.c index 3f26cddb7f..45dac0e11c 100644 --- a/mail/importers/mail-importer.c +++ b/mail/importers/mail-importer.c @@ -49,6 +49,7 @@ #include "mail/mail-mt.h" #include "mail/mail-tools.h" +#include "mail/e-mail-shell-module.h" #include "mail-importer.h" @@ -202,7 +203,8 @@ import_mbox_exec (struct _import_mbox_msg *m) } if (m->uri == NULL || m->uri[0] == 0) - folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_INBOX); + folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_INBOX); else folder = mail_tool_uri_to_folder(m->uri, CAMEL_STORE_FOLDER_CREATE, &m->base.ex); @@ -359,6 +361,7 @@ import_folders_rec(struct _import_folders_data *m, const char *filepath, const c GDir *dir; const char *d; struct stat st; + const gchar *data_dir; char *filefull, *foldersub, *uri, *utf8_filename; const char *folder; @@ -366,6 +369,8 @@ import_folders_rec(struct _import_folders_data *m, const char *filepath, const c if (dir == NULL) return; + data_dir = e_shell_module_get_data_dir (mail_shell_module); + utf8_filename = g_filename_to_utf8 (filepath, -1, NULL, NULL, NULL); camel_operation_start(NULL, _("Scanning %s"), utf8_filename); g_free (utf8_filename); @@ -394,9 +399,9 @@ import_folders_rec(struct _import_folders_data *m, const char *filepath, const c break; } /* FIXME: need a better way to get default store location */ - uri = g_strdup_printf("mbox:%s/local#%s", mail_component_peek_base_directory(NULL), folder); + uri = g_strdup_printf("mbox:%s/local#%s", data_dir, folder); } else { - uri = g_strdup_printf("mbox:%s/local#%s/%s", mail_component_peek_base_directory(NULL), folderparent, folder); + uri = g_strdup_printf("mbox:%s/local#%s/%s", data_dir, folderparent, folder); } printf("importing to uri %s\n", uri); diff --git a/mail/mail-autofilter.c b/mail/mail-autofilter.c index af5f26093f..9ad44a6599 100644 --- a/mail/mail-autofilter.c +++ b/mail/mail-autofilter.c @@ -35,7 +35,6 @@ #include "mail-vfolder.h" #include "mail-autofilter.h" -#include "mail-component.h" #include "em-utils.h" #include "e-util/e-error.h" #include "e-util/e-util-private.h" @@ -52,6 +51,8 @@ #include <camel/camel-internet-address.h> #include <camel/camel-mime-message.h> +#include "e-mail-shell-module.h" + #define d(x) static void @@ -349,14 +350,15 @@ void filter_gui_add_from_message (CamelMimeMessage *msg, const char *source, int flags) { EMFilterContext *fc; + const gchar *data_dir; char *user, *system; FilterRule *rule; g_return_if_fail (msg != NULL); fc = em_filter_context_new (); - user = g_strdup_printf ("%s/filters.xml", - mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); rule_context_load ((RuleContext *)fc, system, user); g_free (system); @@ -374,6 +376,7 @@ void mail_filter_rename_uri(CamelStore *store, const char *olduri, const char *newuri) { EMFilterContext *fc; + const gchar *data_dir; char *user, *system; GList *changed; char *eolduri, *enewuri; @@ -382,7 +385,8 @@ mail_filter_rename_uri(CamelStore *store, const char *olduri, const char *newuri enewuri = em_uri_from_camel(newuri); fc = em_filter_context_new (); - user = g_strdup_printf ("%s/filters.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); rule_context_load ((RuleContext *)fc, system, user); g_free (system); @@ -406,6 +410,7 @@ void mail_filter_delete_uri(CamelStore *store, const char *uri) { EMFilterContext *fc; + const gchar *data_dir; char *user, *system; GList *deleted; char *euri; @@ -413,7 +418,8 @@ mail_filter_delete_uri(CamelStore *store, const char *uri) euri = em_uri_from_camel(uri); fc = em_filter_context_new (); - user = g_strdup_printf ("%s/filters.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); rule_context_load ((RuleContext *)fc, system, user); g_free (system); diff --git a/mail/mail-component-factory.c b/mail/mail-component-factory.c index 04d44e9725..a3de3be8b9 100644 --- a/mail/mail-component-factory.c +++ b/mail/mail-component-factory.c @@ -93,23 +93,23 @@ make_factory (PortableServer_POA poa, const char *iid, gpointer impl_ptr, CORBA_ mail_config_init(); mail_msg_init(); - e_plugin_hook_register_type(em_popup_hook_get_type()); - e_plugin_hook_register_type(em_menu_hook_get_type()); - e_plugin_hook_register_type(em_config_hook_get_type()); - - em_format_hook_register_type(em_format_get_type()); - em_format_hook_register_type(em_format_html_get_type()); - em_format_hook_register_type(em_format_html_display_get_type()); - em_junk_hook_register_type(emj_get_type()); - - e_plugin_hook_register_type(em_format_hook_get_type()); - e_plugin_hook_register_type(em_event_hook_get_type()); - e_plugin_hook_register_type(em_junk_hook_get_type()); - - klass = g_type_class_ref(e_import_get_type()); - e_import_class_add_importer(klass, mbox_importer_peek(), NULL, NULL); - e_import_class_add_importer(klass, elm_importer_peek(), NULL, NULL); - e_import_class_add_importer(klass, pine_importer_peek(), NULL, NULL); +// e_plugin_hook_register_type(em_popup_hook_get_type()); +// e_plugin_hook_register_type(em_menu_hook_get_type()); +// e_plugin_hook_register_type(em_config_hook_get_type()); +// +// em_format_hook_register_type(em_format_get_type()); +// em_format_hook_register_type(em_format_html_get_type()); +// em_format_hook_register_type(em_format_html_display_get_type()); +// em_junk_hook_register_type(emj_get_type()); +// +// e_plugin_hook_register_type(em_format_hook_get_type()); +// e_plugin_hook_register_type(em_event_hook_get_type()); +// e_plugin_hook_register_type(em_junk_hook_get_type()); +// +// klass = g_type_class_ref(e_import_get_type()); +// e_import_class_add_importer(klass, mbox_importer_peek(), NULL, NULL); +// e_import_class_add_importer(klass, elm_importer_peek(), NULL, NULL); +// e_import_class_add_importer(klass, pine_importer_peek(), NULL, NULL); } return bonobo_shlib_factory_std (FACTORY_ID, poa, impl_ptr, factory, NULL, ev); diff --git a/mail/mail-component.c b/mail/mail-component.c index ba39c9f273..45bafd3719 100644 --- a/mail/mail-component.c +++ b/mail/mail-component.c @@ -103,21 +103,21 @@ static BonoboObjectClass *parent_class = NULL; #define OFFLINE 0 #define ONLINE 1 -struct _store_info { - CamelStore *store; - char *name; - - /* we keep a reference to these so they remain around for the session */ - CamelFolder *vtrash; - CamelFolder *vjunk; - - /* for setup only */ - void (*done)(CamelStore *store, CamelFolderInfo *info, void *data); - void *done_data; - - int ref_count:31; - guint removed:1; -}; +//struct _store_info { +// CamelStore *store; +// char *name; +// +// /* we keep a reference to these so they remain around for the session */ +// CamelFolder *vtrash; +// CamelFolder *vjunk; +// +// /* for setup only */ +// void (*done)(CamelStore *store, CamelFolderInfo *info, void *data); +// void *done_data; +// +// int ref_count:31; +// guint removed:1; +//}; struct _MailComponentPrivate { GMutex *lock; @@ -150,225 +150,225 @@ struct _MailComponentPrivate { }; /* indexed by _mail_component_folder_t */ -static struct { - char *name; - char *uri; - CamelFolder *folder; -} mc_default_folders[] = { - /* translators: standard local mailbox names */ - { N_("Inbox"), }, - { N_("Drafts"), }, - { N_("Outbox"), }, - { N_("Sent"), }, - { N_("Templates"), }, - { "Inbox", }, /* 'always local' inbox */ -}; - -static struct _store_info * -store_info_new(CamelStore *store, const char *name) -{ - struct _store_info *si; - - si = g_malloc0(sizeof(*si)); - si->ref_count = 1; - if (name == NULL) - si->name = camel_service_get_name((CamelService *)store, TRUE); - else - si->name = g_strdup(name); - si->store = store; - camel_object_ref(store); - /* If these are vfolders then they need to be opened now, - * otherwise they wont keep track of all folders */ - if ((store->flags & CAMEL_STORE_VTRASH) != 0) - si->vtrash = camel_store_get_trash(store, NULL); - if ((store->flags & CAMEL_STORE_VJUNK) != 0) - si->vjunk = camel_store_get_junk(store, NULL); - - return si; -} - -static void -store_info_ref(struct _store_info *si) -{ - si->ref_count++; -} - -static void -store_info_unref(struct _store_info *si) -{ - if (si->ref_count > 1) { - si->ref_count--; - return; - } - - if (si->vtrash) - camel_object_unref(si->vtrash); - if (si->vjunk) - camel_object_unref(si->vjunk); - camel_object_unref(si->store); - g_free(si->name); - g_free(si); -} - -static gboolean -mc_add_store_done(CamelStore *store, CamelFolderInfo *info, void *data) -{ - struct _store_info *si = data; - - if (si->done) - si->done(store, info, si); - - if (!si->removed) { - /* let the counters know about the already opened junk/trash folders */ - if (si->vtrash) - mail_note_folder(si->vtrash); - if (si->vjunk) - mail_note_folder(si->vjunk); - } - - store_info_unref(si); - - return TRUE; -} +//static struct { +// char *name; +// char *uri; +// CamelFolder *folder; +//} mc_default_folders[] = { +// /* translators: standard local mailbox names */ +// { N_("Inbox"), }, +// { N_("Drafts"), }, +// { N_("Outbox"), }, +// { N_("Sent"), }, +// { N_("Templates"), }, +// { "Inbox", }, /* 'always local' inbox */ +//}; + +//static struct _store_info * +//store_info_new(CamelStore *store, const char *name) +//{ +// struct _store_info *si; +// +// si = g_malloc0(sizeof(*si)); +// si->ref_count = 1; +// if (name == NULL) +// si->name = camel_service_get_name((CamelService *)store, TRUE); +// else +// si->name = g_strdup(name); +// si->store = store; +// camel_object_ref(store); +// /* If these are vfolders then they need to be opened now, +// * otherwise they wont keep track of all folders */ +// if ((store->flags & CAMEL_STORE_VTRASH) != 0) +// si->vtrash = camel_store_get_trash(store, NULL); +// if ((store->flags & CAMEL_STORE_VJUNK) != 0) +// si->vjunk = camel_store_get_junk(store, NULL); +// +// return si; +//} + +//static void +//store_info_ref(struct _store_info *si) +//{ +// si->ref_count++; +//} + +//static void +//store_info_unref(struct _store_info *si) +//{ +// if (si->ref_count > 1) { +// si->ref_count--; +// return; +// } +// +// if (si->vtrash) +// camel_object_unref(si->vtrash); +// if (si->vjunk) +// camel_object_unref(si->vjunk); +// camel_object_unref(si->store); +// g_free(si->name); +// g_free(si); +//} + +//static gboolean +//mc_add_store_done(CamelStore *store, CamelFolderInfo *info, void *data) +//{ +// struct _store_info *si = data; +// +// if (si->done) +// si->done(store, info, si); +// +// if (!si->removed) { +// /* let the counters know about the already opened junk/trash folders */ +// if (si->vtrash) +// mail_note_folder(si->vtrash); +// if (si->vjunk) +// mail_note_folder(si->vjunk); +// } +// +// store_info_unref(si); +// +// return TRUE; +//} /* Utility functions. */ -static void -mc_add_store(MailComponent *component, CamelStore *store, const char *name, void (*done)(CamelStore *store, CamelFolderInfo *info, void *data)) -{ - struct _store_info *si; - - MAIL_COMPONENT_DEFAULT(component); - - si = store_info_new(store, name); - si->done = done; - g_hash_table_insert(component->priv->store_hash, store, si); - em_folder_tree_model_add_store(component->priv->model, store, si->name); - store_info_ref(si); - mail_note_store(store, NULL, mc_add_store_done, si); -} - -static void -mc_add_local_store_done(CamelStore *store, CamelFolderInfo *info, void *data) -{ - /*MailComponent *mc = data;*/ - int i; - - for (i=0;i<sizeof(mc_default_folders)/sizeof(mc_default_folders[0]);i++) { - if (mc_default_folders[i].folder) - mail_note_folder(mc_default_folders[i].folder); - } -} - -static void -mc_add_local_store(CamelStore *store, const char *name, MailComponent *mc) -{ - mc_add_store(mc, store, name, mc_add_local_store_done); - camel_object_unref(store); - g_object_unref(mc); -} - -static void -mc_setup_local_store(MailComponent *mc) -{ - MailComponentPrivate *p = mc->priv; - CamelURL *url; - char *tmp; - CamelException ex; - int i; - - g_mutex_lock(p->lock); - if (p->local_store != NULL) { - g_mutex_unlock(p->lock); - return; - } - - camel_exception_init(&ex); - - url = camel_url_new("mbox:", NULL); - tmp = g_build_filename (p->base_directory, "local", NULL); - camel_url_set_path(url, tmp); - g_free(tmp); - tmp = camel_url_to_string(url, 0); - p->local_store = (CamelStore *)camel_session_get_service(session, tmp, CAMEL_PROVIDER_STORE, &ex); - g_free(tmp); - if (p->local_store == NULL) - goto fail; - - for (i=0;i<sizeof(mc_default_folders)/sizeof(mc_default_folders[0]);i++) { - /* FIXME: should this uri be account relative? */ - camel_url_set_fragment(url, mc_default_folders[i].name); - mc_default_folders[i].uri = camel_url_to_string(url, 0); - mc_default_folders[i].folder = camel_store_get_folder(p->local_store, mc_default_folders[i].name, - CAMEL_STORE_FOLDER_CREATE, &ex); - camel_exception_clear(&ex); - } - - camel_url_free(url); - g_mutex_unlock(p->lock); - - g_object_ref(mc); - camel_object_ref(p->local_store); - mail_async_event_emit(p->async_event, MAIL_ASYNC_GUI, (MailAsyncFunc)mc_add_local_store, p->local_store, _("On This Computer"), mc); - - return; -fail: - g_mutex_unlock(p->lock); - - g_warning("Could not setup local store/folder: %s", ex.desc); - - camel_url_free(url); - camel_exception_clear(&ex); -} - -static void -load_accounts (MailComponent *component, EAccountList *accounts) -{ - EIterator *iter; - - /* Load each service (don't connect!). Check its provider and - * see if this belongs in the shell's folder list. If so, add - * it. - */ - - iter = e_list_get_iterator ((EList *) accounts); - while (e_iterator_is_valid (iter)) { - EAccountService *service; - EAccount *account; - const char *name; - - account = (EAccount *) e_iterator_get (iter); - service = account->source; - name = account->name; - - /* HACK: mbox url's are handled by the local store setup above, - any that come through as account sources are really movemail sources! */ - if (account->enabled - && service->url != NULL - && service->url[0] - && strncmp(service->url, "mbox:", 5) != 0) - mail_component_load_store_by_uri (component, service->url, name); - - e_iterator_next (iter); - } - - g_object_unref (iter); -} - -static void -setup_search_context (MailComponent *component) -{ - MailComponentPrivate *priv = component->priv; - - if (priv->search_context == NULL) { - char *user = g_build_filename(component->priv->base_directory, "searches.xml", NULL); - char *system = g_build_filename (EVOLUTION_PRIVDATADIR, "searchtypes.xml", NULL); - - priv->search_context = (RuleContext *)em_search_context_new (); - g_object_set_data_full (G_OBJECT (priv->search_context), "user", user, g_free); - g_object_set_data_full (G_OBJECT (priv->search_context), "system", system, g_free); - rule_context_load (priv->search_context, system, user); - } -} +//static void +//mc_add_store(MailComponent *component, CamelStore *store, const char *name, void (*done)(CamelStore *store, CamelFolderInfo *info, void *data)) +//{ +// struct _store_info *si; +// +// MAIL_COMPONENT_DEFAULT(component); +// +// si = store_info_new(store, name); +// si->done = done; +// g_hash_table_insert(component->priv->store_hash, store, si); +// em_folder_tree_model_add_store(component->priv->model, store, si->name); +// store_info_ref(si); +// mail_note_store(store, NULL, mc_add_store_done, si); +//} + +//static void +//mc_add_local_store_done(CamelStore *store, CamelFolderInfo *info, void *data) +//{ +// /*MailComponent *mc = data;*/ +// int i; +// +// for (i=0;i<sizeof(mc_default_folders)/sizeof(mc_default_folders[0]);i++) { +// if (mc_default_folders[i].folder) +// mail_note_folder(mc_default_folders[i].folder); +// } +//} + +//static void +//mc_add_local_store(CamelStore *store, const char *name, MailComponent *mc) +//{ +// mc_add_store(mc, store, name, mc_add_local_store_done); +// camel_object_unref(store); +// g_object_unref(mc); +//} + +//static void +//mc_setup_local_store(MailComponent *mc) +//{ +// MailComponentPrivate *p = mc->priv; +// CamelURL *url; +// char *tmp; +// CamelException ex; +// int i; +// +// g_mutex_lock(p->lock); +// if (p->local_store != NULL) { +// g_mutex_unlock(p->lock); +// return; +// } +// +// camel_exception_init(&ex); +// +// url = camel_url_new("mbox:", NULL); +// tmp = g_build_filename (p->base_directory, "local", NULL); +// camel_url_set_path(url, tmp); +// g_free(tmp); +// tmp = camel_url_to_string(url, 0); +// p->local_store = (CamelStore *)camel_session_get_service(session, tmp, CAMEL_PROVIDER_STORE, &ex); +// g_free(tmp); +// if (p->local_store == NULL) +// goto fail; +// +// for (i=0;i<sizeof(mc_default_folders)/sizeof(mc_default_folders[0]);i++) { +// /* FIXME: should this uri be account relative? */ +// camel_url_set_fragment(url, mc_default_folders[i].name); +// mc_default_folders[i].uri = camel_url_to_string(url, 0); +// mc_default_folders[i].folder = camel_store_get_folder(p->local_store, mc_default_folders[i].name, +// CAMEL_STORE_FOLDER_CREATE, &ex); +// camel_exception_clear(&ex); +// } +// +// camel_url_free(url); +// g_mutex_unlock(p->lock); +// +// g_object_ref(mc); +// camel_object_ref(p->local_store); +// mail_async_event_emit(p->async_event, MAIL_ASYNC_GUI, (MailAsyncFunc)mc_add_local_store, p->local_store, _("On This Computer"), mc); +// +// return; +//fail: +// g_mutex_unlock(p->lock); +// +// g_warning("Could not setup local store/folder: %s", ex.desc); +// +// camel_url_free(url); +// camel_exception_clear(&ex); +//} + +//static void +//load_accounts (MailComponent *component, EAccountList *accounts) +//{ +// EIterator *iter; +// +// /* Load each service (don't connect!). Check its provider and +// * see if this belongs in the shell's folder list. If so, add +// * it. +// */ +// +// iter = e_list_get_iterator ((EList *) accounts); +// while (e_iterator_is_valid (iter)) { +// EAccountService *service; +// EAccount *account; +// const char *name; +// +// account = (EAccount *) e_iterator_get (iter); +// service = account->source; +// name = account->name; +// +// /* HACK: mbox url's are handled by the local store setup above, +// any that come through as account sources are really movemail sources! */ +// if (account->enabled +// && service->url != NULL +// && service->url[0] +// && strncmp(service->url, "mbox:", 5) != 0) +// mail_component_load_store_by_uri (component, service->url, name); +// +// e_iterator_next (iter); +// } +// +// g_object_unref (iter); +//} + +//static void +//setup_search_context (MailComponent *component) +//{ +// MailComponentPrivate *priv = component->priv; +// +// if (priv->search_context == NULL) { +// char *user = g_build_filename(component->priv->base_directory, "searches.xml", NULL); +// char *system = g_build_filename (EVOLUTION_PRIVDATADIR, "searchtypes.xml", NULL); +// +// priv->search_context = (RuleContext *)em_search_context_new (); +// g_object_set_data_full (G_OBJECT (priv->search_context), "user", user, g_free); +// g_object_set_data_full (G_OBJECT (priv->search_context), "system", system, g_free); +// rule_context_load (priv->search_context, system, user); +// } +//} static void mc_startup(MailComponent *mc) @@ -750,29 +750,29 @@ impl_createView (PortableServer_Servant servant, g_signal_connect (view_widget, "on-url", G_CALLBACK (view_on_url), mail_component); em_folder_view_set_statusbar ((EMFolderView*)view_widget, FALSE); - statusbar_widget = e_task_bar_new (); - e_activity_handler_attach_task_bar (priv->activity_handler, E_TASK_BAR (statusbar_widget)); +// statusbar_widget = e_task_bar_new (); +// e_activity_handler_attach_task_bar (priv->activity_handler, E_TASK_BAR (statusbar_widget)); gtk_widget_show (tree_widget); gtk_widget_show (view_widget); gtk_widget_show (statusbar_widget); - vbox = gtk_vbox_new(FALSE, 0); - info = e_info_label_new("evolution-mail"); - e_info_label_set_info((EInfoLabel *)info, _("Mail"), ""); - gtk_box_pack_start((GtkBox *)vbox, info, FALSE, TRUE, 0); - gtk_box_pack_start((GtkBox *)vbox, tree_widget, TRUE, TRUE, 0); +// vbox = gtk_vbox_new(FALSE, 0); +// info = e_info_label_new("evolution-mail"); +// e_info_label_set_info((EInfoLabel *)info, _("Mail"), ""); +// gtk_box_pack_start((GtkBox *)vbox, info, FALSE, TRUE, 0); +// gtk_box_pack_start((GtkBox *)vbox, tree_widget, TRUE, TRUE, 0); gtk_widget_show(info); gtk_widget_show(vbox); - component_view = e_component_view_new(parent, "mail", vbox, view_widget, statusbar_widget); - - g_object_set_data((GObject *)component_view, "info-label", info); - - g_object_set_data_full((GObject *)view_widget, "e-creatable-items-handler", - e_user_creatable_items_handler_new("mail", create_local_item_cb, tree_widget), - (GDestroyNotify)g_object_unref); +// component_view = e_component_view_new(parent, "mail", vbox, view_widget, statusbar_widget); +// +// g_object_set_data((GObject *)component_view, "info-label", info); +// +// g_object_set_data_full((GObject *)view_widget, "e-creatable-items-handler", +// e_user_creatable_items_handler_new("mail", create_local_item_cb, tree_widget), +// (GDestroyNotify)g_object_unref); g_signal_connect (component_view->view_control, "activate", G_CALLBACK (view_control_activate_cb), view_widget); @@ -907,35 +907,35 @@ impl_quit(PortableServer_Servant servant, CORBA_Environment *ev) return TRUE; } -static GNOME_Evolution_CreatableItemTypeList * -impl__get_userCreatableItems (PortableServer_Servant servant, CORBA_Environment *ev) -{ - GNOME_Evolution_CreatableItemTypeList *list = GNOME_Evolution_CreatableItemTypeList__alloc (); - - list->_length = 2; - list->_maximum = list->_length; - list->_buffer = GNOME_Evolution_CreatableItemTypeList_allocbuf (list->_length); - - CORBA_sequence_set_release (list, FALSE); - - list->_buffer[0].id = "message"; - list->_buffer[0].description = _("New Mail Message"); - list->_buffer[0].menuDescription = (char *) C_("New", "_Mail Message"); - list->_buffer[0].tooltip = _("Compose a new mail message"); - list->_buffer[0].menuShortcut = 'm'; - list->_buffer[0].iconName = "mail-message-new"; - list->_buffer[0].type = GNOME_Evolution_CREATABLE_OBJECT; - - list->_buffer[1].id = "folder"; - list->_buffer[1].description = _("New Mail Folder"); - list->_buffer[1].menuDescription = (char *) C_("New", "Mail _Folder"); - list->_buffer[1].tooltip = _("Create a new mail folder"); - list->_buffer[1].menuShortcut = '\0'; - list->_buffer[1].iconName = "folder-new"; - list->_buffer[1].type = GNOME_Evolution_CREATABLE_FOLDER; - - return list; -} +//static GNOME_Evolution_CreatableItemTypeList * +//impl__get_userCreatableItems (PortableServer_Servant servant, CORBA_Environment *ev) +//{ +// GNOME_Evolution_CreatableItemTypeList *list = GNOME_Evolution_CreatableItemTypeList__alloc (); +// +// list->_length = 2; +// list->_maximum = list->_length; +// list->_buffer = GNOME_Evolution_CreatableItemTypeList_allocbuf (list->_length); +// +// CORBA_sequence_set_release (list, FALSE); +// +// list->_buffer[0].id = "message"; +// list->_buffer[0].description = _("New Mail Message"); +// list->_buffer[0].menuDescription = (char *) C_("New", "_Mail Message"); +// list->_buffer[0].tooltip = _("Compose a new mail message"); +// list->_buffer[0].menuShortcut = 'm'; +// list->_buffer[0].iconName = "mail-message-new"; +// list->_buffer[0].type = GNOME_Evolution_CREATABLE_OBJECT; +// +// list->_buffer[1].id = "folder"; +// list->_buffer[1].description = _("New Mail Folder"); +// list->_buffer[1].menuDescription = (char *) C_("New", "Mail _Folder"); +// list->_buffer[1].tooltip = _("Create a new mail folder"); +// list->_buffer[1].menuShortcut = '\0'; +// list->_buffer[1].iconName = "folder-new"; +// list->_buffer[1].type = GNOME_Evolution_CREATABLE_FOLDER; +// +// return list; +//} static int create_item(const char *type, EMFolderTreeModel *model, const char *uri, gpointer tree) @@ -1063,26 +1063,26 @@ impl_sendAndReceive (PortableServer_Servant servant, CORBA_Environment *ev) mail_send_receive (); } -static void -impl_upgradeFromVersion (PortableServer_Servant servant, const short major, const short minor, const short revision, CORBA_Environment *ev) -{ - MailComponent *component; - CamelException ex; - - component = mail_component_peek (); - - camel_exception_init (&ex); - if (em_migrate (e_get_user_data_dir (), major, minor, revision, &ex) == -1) { - GNOME_Evolution_Component_UpgradeFailed *failedex; - - failedex = GNOME_Evolution_Component_UpgradeFailed__alloc(); - failedex->what = CORBA_string_dup(_("Failed upgrading Mail settings or folders.")); - failedex->why = CORBA_string_dup(ex.desc); - CORBA_exception_set(ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Component_UpgradeFailed, failedex); - } - - camel_exception_clear (&ex); -} +//static void +//impl_upgradeFromVersion (PortableServer_Servant servant, const short major, const short minor, const short revision, CORBA_Environment *ev) +//{ +// MailComponent *component; +// CamelException ex; +// +// component = mail_component_peek (); +// +// camel_exception_init (&ex); +// if (em_migrate (e_get_user_data_dir (), major, minor, revision, &ex) == -1) { +// GNOME_Evolution_Component_UpgradeFailed *failedex; +// +// failedex = GNOME_Evolution_Component_UpgradeFailed__alloc(); +// failedex->what = CORBA_string_dup(_("Failed upgrading Mail settings or folders.")); +// failedex->why = CORBA_string_dup(ex.desc); +// CORBA_exception_set(ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Component_UpgradeFailed, failedex); +// } +// +// camel_exception_clear (&ex); +//} static void mc_sync_store_done (CamelStore *store, void *data) @@ -1310,34 +1310,34 @@ mail_component_init (MailComponent *component) } /* Public API. */ -MailComponent * -mail_component_peek (void) -{ - static MailComponent *component = NULL; - - if (component == NULL) - component = g_object_new(mail_component_get_type(), NULL); - - return component; -} - -const char * -mail_component_peek_base_directory (MailComponent *component) -{ - MAIL_COMPONENT_DEFAULT(component); - - return component->priv->base_directory; -} - -RuleContext * -mail_component_peek_search_context (MailComponent *component) -{ - MAIL_COMPONENT_DEFAULT(component); - - setup_search_context(component); - - return component->priv->search_context; -} +//MailComponent * +//mail_component_peek (void) +//{ +// static MailComponent *component = NULL; +// +// if (component == NULL) +// component = g_object_new(mail_component_get_type(), NULL); +// +// return component; +//} + +//const char * +//mail_component_peek_base_directory (MailComponent *component) +//{ +// MAIL_COMPONENT_DEFAULT(component); +// +// return component->priv->base_directory; +//} + +//RuleContext * +//mail_component_peek_search_context (MailComponent *component) +//{ +// MAIL_COMPONENT_DEFAULT(component); +// +// setup_search_context(component); +// +// return component->priv->search_context; +//} EActivityHandler * mail_component_peek_activity_handler (MailComponent *component) @@ -1354,11 +1354,11 @@ struct _CamelSession *mail_component_peek_session(MailComponent *component) return session; } -void -mail_component_add_store (MailComponent *component, CamelStore *store, const char *name) -{ - mc_add_store(component, store, name, NULL); -} +//void +//mail_component_add_store (MailComponent *component, CamelStore *store, const char *name) +//{ +// mc_add_store(component, store, name, NULL); +//} /** * mail_component_load_store_by_uri: @@ -1369,48 +1369,48 @@ mail_component_add_store (MailComponent *component, CamelStore *store, const cha * Return value: Pointer to the newly added CamelStore. The caller is supposed * to ref the object if it wants to store it. **/ -CamelStore * -mail_component_load_store_by_uri (MailComponent *component, const char *uri, const char *name) -{ - CamelException ex; - CamelStore *store; - CamelProvider *prov; - - MAIL_COMPONENT_DEFAULT(component); - - camel_exception_init (&ex); - - /* Load the service (don't connect!). Check its provider and - * see if this belongs in the shell's folder list. If so, add - * it. - */ - - prov = camel_provider_get(uri, &ex); - if (prov == NULL) { - /* EPFIXME: real error dialog */ - g_warning ("couldn't get service %s: %s\n", uri, - camel_exception_get_description (&ex)); - camel_exception_clear (&ex); - return NULL; - } - - if (!(prov->flags & CAMEL_PROVIDER_IS_STORAGE)) - return NULL; - - store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex); - if (store == NULL) { - /* EPFIXME: real error dialog */ - g_warning ("couldn't get service %s: %s\n", uri, - camel_exception_get_description (&ex)); - camel_exception_clear (&ex); - return NULL; - } - - mail_component_add_store(component, store, name); - camel_object_unref (store); - - return store; -} +//CamelStore * +//mail_component_load_store_by_uri (MailComponent *component, const char *uri, const char *name) +//{ +// CamelException ex; +// CamelStore *store; +// CamelProvider *prov; +// +// MAIL_COMPONENT_DEFAULT(component); +// +// camel_exception_init (&ex); +// +// /* Load the service (don't connect!). Check its provider and +// * see if this belongs in the shell's folder list. If so, add +// * it. +// */ +// +// prov = camel_provider_get(uri, &ex); +// if (prov == NULL) { +// /* EPFIXME: real error dialog */ +// g_warning ("couldn't get service %s: %s\n", uri, +// camel_exception_get_description (&ex)); +// camel_exception_clear (&ex); +// return NULL; +// } +// +// if (!(prov->flags & CAMEL_PROVIDER_IS_STORAGE)) +// return NULL; +// +// store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex); +// if (store == NULL) { +// /* EPFIXME: real error dialog */ +// g_warning ("couldn't get service %s: %s\n", uri, +// camel_exception_get_description (&ex)); +// camel_exception_clear (&ex); +// return NULL; +// } +// +// mail_component_add_store(component, store, name); +// camel_object_unref (store); +// +// return store; +//} static void store_disconnect (CamelStore *store, void *event_data, void *user_data) @@ -1470,13 +1470,14 @@ mail_component_remove_store_by_uri (MailComponent *component, const char *uri) } } -int -mail_component_get_store_count (MailComponent *component) -{ - MAIL_COMPONENT_DEFAULT(component); - - return g_hash_table_size (component->priv->store_hash); -} +// [KILL-BONOBO] Unused. +//int +//mail_component_get_store_count (MailComponent *component) +//{ +// MAIL_COMPONENT_DEFAULT(component); +// +// return g_hash_table_size (component->priv->store_hash); +//} /* need to map from internal struct to external api */ struct _store_foreach_data { @@ -1500,30 +1501,30 @@ mail_component_stores_foreach (MailComponent *component, GHFunc func, void *user g_hash_table_foreach (component->priv->store_hash, (GHFunc)mc_stores_foreach, &data); } -void -mail_component_remove_folder (MailComponent *component, CamelStore *store, const char *path) -{ - MAIL_COMPONENT_DEFAULT(component); - - /* FIXME: implement me. but first, am I really even needed? */ -} - -EMFolderTreeModel * -mail_component_peek_tree_model (MailComponent *component) -{ - MAIL_COMPONENT_DEFAULT(component); - - return component->priv->model; -} - -CamelStore * -mail_component_peek_local_store (MailComponent *mc) -{ - MAIL_COMPONENT_DEFAULT (mc); - mc_setup_local_store (mc); - - return mc->priv->local_store; -} +//void +//mail_component_remove_folder (MailComponent *component, CamelStore *store, const char *path) +//{ +// MAIL_COMPONENT_DEFAULT(component); +// +// /* FIXME: implement me. but first, am I really even needed? */ +//} + +//EMFolderTreeModel * +//mail_component_peek_tree_model (MailComponent *component) +//{ +// MAIL_COMPONENT_DEFAULT(component); +// +// return component->priv->model; +//} + +//CamelStore * +//mail_component_peek_local_store (MailComponent *mc) +//{ +// MAIL_COMPONENT_DEFAULT (mc); +// mc_setup_local_store (mc); +// +// return mc->priv->local_store; +//} /** * mail_component_get_folder: @@ -1534,16 +1535,16 @@ mail_component_peek_local_store (MailComponent *mc) * * Return value: **/ -struct _CamelFolder * -mail_component_get_folder(MailComponent *mc, enum _mail_component_folder_t id) -{ - g_return_val_if_fail (id <= MAIL_COMPONENT_FOLDER_LOCAL_INBOX, NULL); - - MAIL_COMPONENT_DEFAULT(mc); - mc_setup_local_store(mc); - - return mc_default_folders[id].folder; -} +//struct _CamelFolder * +//mail_component_get_folder(MailComponent *mc, enum _mail_component_folder_t id) +//{ +// g_return_val_if_fail (id <= MAIL_COMPONENT_FOLDER_LOCAL_INBOX, NULL); +// +// MAIL_COMPONENT_DEFAULT(mc); +// mc_setup_local_store(mc); +// +// return mc_default_folders[id].folder; +//} /** * mail_component_get_folder_uri: @@ -1554,36 +1555,36 @@ mail_component_get_folder(MailComponent *mc, enum _mail_component_folder_t id) * * Return value: **/ -const char * -mail_component_get_folder_uri(MailComponent *mc, enum _mail_component_folder_t id) -{ - g_return_val_if_fail (id <= MAIL_COMPONENT_FOLDER_LOCAL_INBOX, NULL); - - MAIL_COMPONENT_DEFAULT(mc); - mc_setup_local_store(mc); - - return mc_default_folders[id].uri; -} +//const char * +//mail_component_get_folder_uri(MailComponent *mc, enum _mail_component_folder_t id) +//{ +// g_return_val_if_fail (id <= MAIL_COMPONENT_FOLDER_LOCAL_INBOX, NULL); +// +// MAIL_COMPONENT_DEFAULT(mc); +// mc_setup_local_store(mc); +// +// return mc_default_folders[id].uri; +//} /** * mail_indicate_new_mail * Indicates new mail in a shell window. * @param have_new_mail TRUE when have new mail, false otherwise. **/ -void -mail_indicate_new_mail (gboolean have_new_mail) -{ - const char *icon = NULL; - MailComponent *mc = mail_component_peek (); - - g_return_if_fail (mc != NULL); - - if (have_new_mail) - icon = "mail-unread"; - - if (mc->priv->component_view) - e_component_view_set_button_icon (mc->priv->component_view, icon); -} +//void +//mail_indicate_new_mail (gboolean have_new_mail) +//{ +// const char *icon = NULL; +// MailComponent *mc = mail_component_peek (); +// +// g_return_if_fail (mc != NULL); +// +// if (have_new_mail) +// icon = "mail-unread"; +// +// if (mc->priv->component_view) +// e_component_view_set_button_icon (mc->priv->component_view, icon); +//} struct _log_data { int level; diff --git a/mail/mail-config.c b/mail/mail-config.c index 9c2bff8a61..4ae2b0f885 100644 --- a/mail/mail-config.c +++ b/mail/mail-config.c @@ -70,12 +70,13 @@ #include <libedataserverui/e-passwords.h> -#include "mail-component.h" #include "mail-session.h" #include "mail-config.h" #include "mail-mt.h" #include "mail-tools.h" +#include "e-mail-shell-module.h" + typedef struct { GConfClient *gconf; @@ -966,17 +967,19 @@ mail_config_get_default_transport (void) static char * uri_to_evname (const char *uri, const char *prefix) { - const char *base_directory = mail_component_peek_base_directory (mail_component_peek ()); + const gchar *data_dir; char *safe; char *tmp; + data_dir = e_shell_module_get_data_dir (mail_shell_module); + safe = g_strdup (uri); e_filename_make_safe (safe); /* blah, easiest thing to do */ if (prefix[0] == '*') - tmp = g_strdup_printf ("%s/%s%s.xml", base_directory, prefix + 1, safe); + tmp = g_strdup_printf ("%s/%s%s.xml", data_dir, prefix + 1, safe); else - tmp = g_strdup_printf ("%s/%s%s", base_directory, prefix, safe); + tmp = g_strdup_printf ("%s/%s%s", data_dir, prefix, safe); g_free (safe); return tmp; } @@ -1039,9 +1042,14 @@ mail_config_uri_deleted (GCompareFunc uri_cmp, const char *uri) EAccount *account; EIterator *iter; int work = 0; + const gchar *local_drafts_folder_uri; + const gchar *local_sent_folder_uri; + /* assumes these can't be removed ... */ - const char *default_sent_folder_uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT); - const char *default_drafts_folder_uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS); + local_drafts_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); + local_sent_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_SENT); iter = e_list_get_iterator ((EList *) config->accounts); while (e_iterator_is_valid (iter)) { @@ -1049,13 +1057,13 @@ mail_config_uri_deleted (GCompareFunc uri_cmp, const char *uri) if (account->sent_folder_uri && uri_cmp (account->sent_folder_uri, uri)) { g_free (account->sent_folder_uri); - account->sent_folder_uri = g_strdup (default_sent_folder_uri); + account->sent_folder_uri = g_strdup (local_sent_folder_uri); work = 1; } if (account->drafts_folder_uri && uri_cmp (account->drafts_folder_uri, uri)) { g_free (account->drafts_folder_uri); - account->drafts_folder_uri = g_strdup (default_drafts_folder_uri); + account->drafts_folder_uri = g_strdup (local_drafts_folder_uri); work = 1; } @@ -1088,13 +1096,13 @@ char * mail_config_folder_to_cachename (CamelFolder *folder, const char *prefix) { char *url, *basename, *filename; - const char *evolution_dir; + const gchar *config_dir; - evolution_dir = mail_component_peek_base_directory (mail_component_peek ()); + config_dir = e_shell_module_get_config_dir (mail_shell_module); url = mail_config_folder_to_safe_url (folder); basename = g_strdup_printf ("%s%s", prefix, url); - filename = g_build_filename (evolution_dir, "config", basename, NULL); + filename = g_build_filename (config_dir, basename, NULL); g_free (basename); g_free (url); diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c index 546526c8ab..8f85f3f521 100644 --- a/mail/mail-folder-cache.c +++ b/mail/mail-folder-cache.c @@ -50,12 +50,13 @@ #include <libedataserver/e-data-server-util.h> #include <libedataserver/e-msgport.h> #include "e-util/e-util.h" +#include "shell/e-shell.h" #include "mail-mt.h" #include "mail-folder-cache.h" #include "mail-ops.h" #include "mail-session.h" -#include "mail-component.h" +#include "e-mail-shell-module.h" /* For notifications of changes */ #include "mail-vfolder.h" @@ -109,6 +110,8 @@ struct _folder_update { }; struct _store_info { + EShellModule *shell_module; + GHashTable *folders; /* by full_name */ GHashTable *folders_uri; /* by uri */ @@ -149,14 +152,14 @@ free_update(struct _folder_update *up) } static void -real_flush_updates(void *o, void *event_data, void *data) +real_flush_updates (EShellModule *shell_module) { - struct _MailComponent *component; + EShell *shell; struct _EMFolderTreeModel *model; struct _folder_update *up; - component = mail_component_peek (); - model = mail_component_peek_tree_model (component); + shell = e_shell_module_get_shell (shell_module); + model = e_mail_shell_module_get_folder_tree_model (shell_module); LOCK(info_lock); while ((up = (struct _folder_update *)e_dlist_remhead(&updates))) { @@ -195,7 +198,7 @@ real_flush_updates(void *o, void *event_data, void *data) t->name = em_folder_tree_model_get_folder_name (model, up->store, up->full_name); if (t->new > 0) - mail_indicate_new_mail (TRUE); + e_shell_event (shell, "new-mail"); /** @Event: folder.changed * @Title: Folder changed @@ -229,10 +232,13 @@ real_flush_updates(void *o, void *event_data, void *data) } static void -flush_updates(void) +flush_updates (EShellModule *shell_module) { if (update_id == -1 && !e_dlist_empty(&updates)) - update_id = mail_async_event_emit(mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc)real_flush_updates, NULL, NULL, NULL); + update_id = mail_async_event_emit ( + mail_async_event, MAIL_ASYNC_GUI, + (MailAsyncFunc) real_flush_updates, + shell_module, NULL, NULL); } static void @@ -245,7 +251,7 @@ unset_folder_info(struct _folder_info *mfi, int delete, int unsub) if (mfi->folder) { CamelFolder *folder = mfi->folder; - camel_object_unhook_event(folder, "folder_changed", folder_changed, NULL); + camel_object_unhook_event(folder, "folder_changed", folder_changed, mfi->store_info->shell_module); camel_object_unhook_event(folder, "renamed", folder_renamed, NULL); camel_object_unhook_event(folder, "finalize", folder_finalised, NULL); } @@ -262,7 +268,7 @@ unset_folder_info(struct _folder_info *mfi, int delete, int unsub) up->uri = g_strdup(mfi->uri); e_dlist_addtail(&updates, (EDListNode *)up); - flush_updates(); + flush_updates(mfi->store_info->shell_module); } } @@ -300,21 +306,32 @@ static void update_1folder(struct _folder_info *mfi, int new, CamelFolderInfo *info) { struct _folder_update *up; + EShellModule *shell_module; CamelFolder *folder; + CamelFolder *local_drafts; + CamelFolder *local_outbox; + CamelFolder *local_sent; int unread = -1; int deleted; + shell_module = mfi->store_info->shell_module; + local_drafts = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_DRAFTS); + local_outbox = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_OUTBOX); + local_sent = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_SENT); + folder = mfi->folder; if (folder) { d(printf("update 1 folder '%s'\n", folder->full_name)); if ((count_trash && (CAMEL_IS_VTRASH_FOLDER (folder))) - || folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX) - || folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS) - || (count_sent && folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT))) { + || folder == local_drafts + || folder == local_outbox + || (count_sent && folder == local_sent)) { d(printf(" total count\n")); unread = camel_folder_get_message_count (folder); - if (folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX) - || folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS)) { + if (folder == local_drafts || folder == local_outbox) { guint32 junked = 0; if ((deleted = camel_folder_get_deleted_message_count (folder)) > 0) @@ -348,7 +365,7 @@ update_1folder(struct _folder_info *mfi, int new, CamelFolderInfo *info) up->uri = g_strdup(mfi->uri); camel_object_ref(up->store); e_dlist_addtail(&updates, (EDListNode *)up); - flush_updates(); + flush_updates(shell_module); } static void @@ -382,7 +399,7 @@ setup_folder(CamelFolderInfo *fi, struct _store_info *si) up->add = TRUE; e_dlist_addtail(&updates, (EDListNode *)up); - flush_updates(); + flush_updates(si->shell_module); } } @@ -405,8 +422,12 @@ static void folder_changed (CamelObject *o, gpointer event_data, gpointer user_data) { static time_t last_newmail = 0; + EShellModule *shell_module = user_data; CamelFolderChangeInfo *changes = event_data; CamelFolder *folder = (CamelFolder *)o; + CamelFolder *local_drafts; + CamelFolder *local_outbox; + CamelFolder *local_sent; CamelStore *store = folder->parent_store; CamelMessageInfo *info; struct _store_info *si; @@ -417,10 +438,17 @@ folder_changed (CamelObject *o, gpointer event_data, gpointer user_data) d(printf("folder '%s' changed\n", folder->full_name)); + local_drafts = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_DRAFTS); + local_outbox = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_OUTBOX); + local_sent = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_SENT); + if (!CAMEL_IS_VEE_FOLDER(folder) - && folder != mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX) - && folder != mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS) - && folder != mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT) + && folder != local_drafts + && folder != local_outbox + && folder != local_sent && changes && (changes->uid_added->len > 0)) { /* for each added message, check to see that it is brand new, not junk and not already deleted */ @@ -511,7 +539,7 @@ void mail_note_folder(CamelFolder *folder) UNLOCK(info_lock); - camel_object_hook_event(folder, "folder_changed", folder_changed, NULL); + camel_object_hook_event(folder, "folder_changed", folder_changed, si->shell_module); camel_object_hook_event(folder, "renamed", folder_renamed, NULL); camel_object_hook_event(folder, "finalize", folder_finalised, NULL); } @@ -607,6 +635,7 @@ rename_folders(struct _store_info *si, const char *oldbase, const char *newbase, char *old, *olduri, *oldfile, *newuri, *newfile; struct _folder_info *mfi; struct _folder_update *up; + const gchar *config_dir; up = g_malloc0(sizeof(*up)); @@ -653,7 +682,7 @@ rename_folders(struct _store_info *si, const char *oldbase, const char *newbase, up->add = TRUE; e_dlist_addtail(&updates, (EDListNode *)up); - flush_updates(); + flush_updates(si->shell_module); #if 0 if (fi->sibling) rename_folders(si, oldbase, newbase, fi->sibling, folders); @@ -662,17 +691,18 @@ rename_folders(struct _store_info *si, const char *oldbase, const char *newbase, #endif /* rename the meta-data we maintain ourselves */ + config_dir = e_shell_module_get_config_dir (si->shell_module); olduri = folder_to_url(si->store, old); e_filename_make_safe(olduri); newuri = folder_to_url(si->store, fi->full_name); e_filename_make_safe(newuri); - oldfile = g_strdup_printf("%s/config/custom_view-%s.xml", mail_component_peek_base_directory(NULL), olduri); - newfile = g_strdup_printf("%s/config/custom_view-%s.xml", mail_component_peek_base_directory(NULL), newuri); + oldfile = g_strdup_printf("%s/custom_view-%s.xml", config_dir, olduri); + newfile = g_strdup_printf("%s/custom_view-%s.xml", config_dir, newuri); g_rename(oldfile, newfile); g_free(oldfile); g_free(newfile); - oldfile = g_strdup_printf("%s/config/current_view-%s.xml", mail_component_peek_base_directory(NULL), olduri); - newfile = g_strdup_printf("%s/config/current_view-%s.xml", mail_component_peek_base_directory(NULL), newuri); + oldfile = g_strdup_printf("%s/current_view-%s.xml", config_dir, olduri); + newfile = g_strdup_printf("%s/current_view-%s.xml", config_dir, newuri); g_rename(oldfile, newfile); g_free(oldfile); g_free(newfile); @@ -776,6 +806,8 @@ mail_note_store_remove(CamelStore *store) if (si) { g_hash_table_remove(stores, store); + g_object_unref(si->shell_module); + camel_object_unhook_event(store, "folder_opened", store_folder_opened, NULL); camel_object_unhook_event(store, "folder_created", store_folder_created, NULL); camel_object_unhook_event(store, "folder_deleted", store_folder_deleted, NULL); @@ -928,7 +960,7 @@ store_online_cb (CamelStore *store, void *data) } void -mail_note_store(CamelStore *store, CamelOperation *op, +mail_note_store(EShellModule *shell_module, CamelStore *store, CamelOperation *op, gboolean (*done)(CamelStore *store, CamelFolderInfo *info, void *data), void *data) { struct _store_info *si; @@ -937,6 +969,7 @@ mail_note_store(CamelStore *store, CamelOperation *op, guint timeout; int hook = 0; + g_return_if_fail (E_IS_SHELL_MODULE (shell_module)); g_return_if_fail (CAMEL_IS_STORE(store)); g_return_if_fail (mail_in_main_thread()); @@ -956,6 +989,7 @@ mail_note_store(CamelStore *store, CamelOperation *op, d(printf("Noting a new store: %p: %s\n", store, camel_url_to_string(((CamelService *)store)->url, 0))); si = g_malloc0(sizeof(*si)); + si->shell_module = g_object_ref (shell_module); si->folders = g_hash_table_new(g_str_hash, g_str_equal); si->folders_uri = g_hash_table_new(CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(store))->hash_folder_name, CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(store))->compare_folder_name); diff --git a/mail/mail-folder-cache.h b/mail/mail-folder-cache.h index f62d94169b..b97184fdac 100644 --- a/mail/mail-folder-cache.h +++ b/mail/mail-folder-cache.h @@ -27,13 +27,14 @@ #define _MAIL_FOLDER_CACHE_H #include <camel/camel-store.h> +#include <shell/e-shell-module.h> /* Add a store whose folders should appear in the shell The folders are scanned from the store, and/or added at runtime via the folder_created event. The 'done' function returns if we can free folder info. */ void -mail_note_store (CamelStore *store, CamelOperation *op, +mail_note_store (EShellModule *shell_module, CamelStore *store, CamelOperation *op, gboolean (*done) (CamelStore *store, CamelFolderInfo *info, void *data), void *data); diff --git a/mail/mail-mt.c b/mail/mail-mt.c index 2fa9969cc0..1f367e758f 100644 --- a/mail/mail-mt.c +++ b/mail/mail-mt.c @@ -37,14 +37,14 @@ #include "misc/e-gui-utils.h" #include "e-util/e-error.h" #include "e-util/e-icon-factory.h" - -#include "e-activity-handler.h" +#include "widgets/misc/e-activity.h" #include "mail-config.h" -#include "mail-component.h" #include "mail-session.h" #include "mail-mt.h" +#include "e-mail-shell-module.h" + /*#define MALLOC_CHECK*/ #define LOG_OPS #define LOG_LOCKS @@ -65,7 +65,7 @@ static void mail_operation_status(struct _CamelOperation *op, const char *what, struct _MailMsgPrivate { int activity_state; /* sigh sigh sigh, we need to keep track of the state external to the pointer itself for locking/race conditions */ - int activity_id; + EActivity *activity; GtkWidget *error; gboolean cancelable; }; @@ -140,20 +140,17 @@ mail_msg_new (MailMsgInfo *info) } static void -end_event_callback (CamelObject *o, void *event_data, void *error) +end_event_callback (CamelObject *o, EActivity *activity, void *error) { - MailComponent *component; - EActivityHandler *activity_handler; - guint activity_id = GPOINTER_TO_INT (event_data); - - component = mail_component_peek (); - activity_handler = mail_component_peek_activity_handler (component); - if (!error) { - e_activity_handler_operation_finished (activity_handler, activity_id); - } else { - d(printf("Yahooooo, we got it nonintrusively\n")); - e_activity_handler_operation_set_error (activity_handler, activity_id, error); - } + if (error == NULL) { + e_activity_complete (activity); + g_object_unref (activity); + } else if (activity == NULL) { + activity = e_activity_new (NULL); + e_activity_error (activity, error); + e_shell_module_add_activity (mail_shell_module, activity); + } else + e_activity_error (activity, error); } @@ -184,6 +181,9 @@ checkmem(void *p) static void mail_msg_free (MailMsg *mail_msg) { + if (mail_msg->priv->activity != NULL) + g_object_unref (mail_msg->priv->activity); + if (mail_msg->cancel != NULL) { camel_operation_mute (mail_msg->cancel); camel_operation_unref (mail_msg->cancel); @@ -210,7 +210,7 @@ void mail_msg_unref (gpointer msg) { MailMsg *mail_msg = msg; - gint activity_id; + EActivity *activity = NULL; GtkWidget *error = NULL; g_return_if_fail (mail_msg != NULL); @@ -254,24 +254,19 @@ mail_msg_unref (gpointer msg) MAIL_MT_UNLOCK(mail_msg_lock); return; } else { - activity_id = mail_msg->priv->activity_id; + activity = mail_msg->priv->activity; error = mail_msg->priv->error; - if (error && !activity_id) { - e_activity_handler_make_error (mail_component_peek_activity_handler (mail_component_peek ()), "mail", E_LOG_ERROR, error); - printf("Making error\n"); - } - } MAIL_MT_UNLOCK(mail_msg_lock); mail_msg_free (mail_msg); - if (activity_id != 0) + if (activity != NULL) mail_async_event_emit ( mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc) end_event_callback, - NULL, GINT_TO_POINTER (activity_id), error); + NULL, g_object_ref (activity), error); } /* hash table of ops->dialogue of active errors */ @@ -939,7 +934,6 @@ struct _op_status_msg { static void op_status_exec (struct _op_status_msg *m) { - EActivityHandler *activity_handler = mail_component_peek_activity_handler (mail_component_peek ()); MailMsg *msg; MailMsgPrivate *data; char *out, *p, *o, c; @@ -970,7 +964,7 @@ op_status_exec (struct _op_status_msg *m) pc = m->pc; - if (data->activity_id == 0) { + if (data->activity == NULL) { char *what; /* its being created/removed? well leave it be */ @@ -990,28 +984,39 @@ op_status_exec (struct _op_status_msg *m) what = g_strdup(""); } - data->activity_id = e_activity_handler_cancelable_operation_started (activity_handler, "evolution-mail", what, TRUE, (void (*) (gpointer)) camel_operation_cancel, msg->cancel); + data->activity = e_activity_new (what); + e_activity_set_cancellable (data->activity, TRUE); + e_activity_set_percent (data->activity, 0.0); + e_shell_module_add_activity (mail_shell_module, data->activity); + + g_signal_connect_swapped ( + data->activity, "cancelled", + G_CALLBACK (camel_operation_cancel), + msg->cancel); g_free (what); MAIL_MT_LOCK (mail_msg_lock); if (data->activity_state == 3) { - int activity_id = data->activity_id; + EActivity *activity; + + activity = g_object_ref (data->activity); MAIL_MT_UNLOCK (mail_msg_lock); mail_msg_free (msg); - if (activity_id != 0) - mail_async_event_emit (mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc) end_event_callback, - NULL, GINT_TO_POINTER (activity_id), NULL); + if (activity != 0) + mail_async_event_emit ( + mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc) end_event_callback, + NULL, activity, NULL); } else { data->activity_state = 2; MAIL_MT_UNLOCK (mail_msg_lock); } return; } - } else if (data->activity_id != 0) { + } else if (data->activity != NULL) { MAIL_MT_UNLOCK (mail_msg_lock); - e_activity_handler_operation_progressing (activity_handler, data->activity_id, out, (double)(pc/100.0)); + e_activity_set_percent (data->activity, pc / 100.0); } else { MAIL_MT_UNLOCK (mail_msg_lock); } diff --git a/mail/mail-ops.c b/mail/mail-ops.c index d12ac23a13..402afea97d 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -62,7 +62,6 @@ #include "em-filter-rule.h" #include "em-utils.h" -#include "mail-component.h" #include "mail-config.h" #include "mail-mt.h" #include "mail-ops.h" @@ -70,6 +69,8 @@ #include "mail-tools.h" #include "mail-vfolder.h" +#include "e-mail-shell-module.h" + #define w(x) #define d(x) @@ -244,7 +245,7 @@ uid_cachename_hack (CamelStore *store) { CamelURL *url = CAMEL_SERVICE (store)->url; char *encoded_url, *filename; - const char *evolution_dir; + const gchar *data_dir; encoded_url = g_strdup_printf ("%s%s%s@%s", url->user, url->authmech ? ";auth=" : "", @@ -252,8 +253,8 @@ uid_cachename_hack (CamelStore *store) url->host); e_filename_make_safe (encoded_url); - evolution_dir = mail_component_peek_base_directory (mail_component_peek ()); - filename = g_build_filename (evolution_dir, "pop", encoded_url, "uid-cache", NULL); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + filename = g_build_filename (data_dir, "pop", encoded_url, "uid-cache", NULL); g_free (encoded_url); return filename; @@ -274,9 +275,11 @@ fetch_mail_exec (struct _fetch_mail_msg *m) if (m->cancel) camel_operation_register (m->cancel); - if ((fm->destination = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_LOCAL_INBOX)) == NULL) + fm->destination = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_LOCAL_INBOX); + if (fm->destination == NULL) goto fail; - camel_object_ref(fm->destination); + camel_object_ref (fm->destination); /* FIXME: this should support keep_on_server too, which would then perform a spool access thingy, right? problem is matching raw messages to uid's etc. */ @@ -578,7 +581,8 @@ mail_send_message(CamelFolder *queue, const char *uid, const char *destination, } if (!folder) { - folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT); + folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_SENT); camel_object_ref(folder); } @@ -591,7 +595,8 @@ mail_send_message(CamelFolder *queue, const char *uid, const char *destination, if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_USER_CANCEL) goto exit; - sent_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT); + sent_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_SENT); if (folder != sent_folder) { const char *name; @@ -686,13 +691,16 @@ report_status (struct _send_queue_msg *m, enum camel_filter_status_t status, int static void send_queue_exec (struct _send_queue_msg *m) { - CamelFolder *sent_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT); + CamelFolder *sent_folder; GPtrArray *uids, *send_uids = NULL; CamelException ex; int i, j; d(printf("sending queue\n")); + sent_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_SENT); + if (!(uids = camel_folder_get_uids (m->queue))) return; @@ -1263,7 +1271,8 @@ struct _get_quota_msg { CamelFolder *folder; CamelFolderQuotaInfo *quota; - void (*done) (CamelFolder *folder, CamelFolderQuotaInfo *quota, void *data); + void (*done) (CamelFolder *folder, const gchar *folder_uri, CamelFolderQuotaInfo *quota, void *data); + gchar *folder_uri; void *data; }; @@ -1283,7 +1292,7 @@ static void get_quota_done (struct _get_quota_msg *m) { if (m->done) - m->done (m->folder, m->quota, m->data); + m->done (m->folder, m->folder_uri, m->quota, m->data); } static void @@ -1293,6 +1302,7 @@ get_quota_free (struct _get_quota_msg *m) camel_object_unref (m->folder); if (m->quota) camel_folder_quota_info_free (m->quota); + g_free (m->folder_uri); } static MailMsgInfo get_quota_info = { @@ -1305,7 +1315,8 @@ static MailMsgInfo get_quota_info = { int mail_get_folder_quota (CamelFolder *folder, - void (*done)(CamelFolder *folder, CamelFolderQuotaInfo *quota, void *data), + const gchar *folder_uri, + void (*done)(CamelFolder *folder, const gchar *uri, CamelFolderQuotaInfo *quota, void *data), void *data, MailMsgDispatchFunc dispatch) { struct _get_quota_msg *m; @@ -1315,6 +1326,7 @@ mail_get_folder_quota (CamelFolder *folder, m = mail_msg_new (&get_quota_info); m->folder = folder; + m->folder_uri = g_strdup (folder_uri); m->data = data; m->done = done; @@ -1743,15 +1755,15 @@ empty_trash_desc (struct _empty_trash_msg *m) static void empty_trash_exec (struct _empty_trash_msg *m) { - const char *evolution_dir; + const gchar *data_dir; CamelFolder *trash; char *uri; if (m->account) { trash = mail_tool_get_trash (m->account->source->url, FALSE, &m->base.ex); } else { - evolution_dir = mail_component_peek_base_directory (mail_component_peek ()); - uri = g_strdup_printf ("mbox:%s/local", evolution_dir); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + uri = g_strdup_printf ("mbox:%s/local", data_dir); trash = mail_tool_get_trash (uri, TRUE, &m->base.ex); g_free (uri); } diff --git a/mail/mail-ops.h b/mail/mail-ops.h index e615a9121d..68ae9037df 100644 --- a/mail/mail-ops.h +++ b/mail/mail-ops.h @@ -74,7 +74,8 @@ int mail_get_folder (const char *uri, guint32 flags, /* get quota information for a folder */ int mail_get_folder_quota (CamelFolder *folder, - void (*done)(CamelFolder *folder, CamelFolderQuotaInfo *quota, void *data), + const gchar *folder_uri, + void (*done)(CamelFolder *folder, const gchar *folder_uri, CamelFolderQuotaInfo *quota, void *data), void *data, MailMsgDispatchFunc dispatch); /* and for a store */ diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c index 29cbb57322..9894ec2fa5 100644 --- a/mail/mail-send-recv.c +++ b/mail/mail-send-recv.c @@ -38,7 +38,6 @@ #include "camel/camel-store.h" #include "mail-mt.h" -#include "mail-component.h" #include "mail-config.h" #include "mail-session.h" #include "mail-tools.h" @@ -48,6 +47,8 @@ #include "em-event.h" #include <e-util/gconf-bridge.h> +#include "e-mail-shell-module.h" + #define d(x) /* ms between status updates to the gui */ @@ -160,7 +161,8 @@ setup_send_data(void) g_str_hash, g_str_equal, (GDestroyNotify) NULL, (GDestroyNotify) free_folder_info); - data->inbox = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_LOCAL_INBOX); + data->inbox = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_LOCAL_INBOX); camel_object_ref(data->inbox); data->active = g_hash_table_new_full ( g_str_hash, g_str_equal, @@ -677,8 +679,13 @@ receive_done (char *uri, void *data) /* if we've been called to run again - run again */ if (info->type == SEND_SEND && info->state == SEND_ACTIVE && info->again) { + CamelFolder *local_outbox_folder; + + local_outbox_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); + info->again = 0; - mail_send_queue (mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX), + mail_send_queue (local_outbox_folder, info->uri, FILTER_SOURCE_OUTGOING, info->cancel, @@ -890,7 +897,7 @@ receive_update_got_store (char *uri, CamelStore *store, void *data) struct _send_info *info = data; if (store) { - mail_note_store(store, info->cancel, receive_update_got_folderinfo, info); + mail_note_store(mail_shell_module, store, info->cancel, receive_update_got_folderinfo, info); } else { receive_done("", info); } @@ -922,7 +929,8 @@ mail_send_receive (void) accounts = mail_config_get_accounts (); - outbox_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + outbox_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); data = build_dialog (accounts, outbox_folder, account->transport->url); scan = data->infos; while (scan) { @@ -1139,7 +1147,8 @@ mail_receive_uri (const char *uri, int keep) break; case SEND_SEND: /* todo, store the folder in info? */ - outbox_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + outbox_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); mail_send_queue (outbox_folder, info->uri, FILTER_SOURCE_OUTGOING, info->cancel, @@ -1201,7 +1210,8 @@ mail_send (void) g_hash_table_insert (data->active, SEND_URI_KEY, info); /* todo, store the folder in info? */ - outbox_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + outbox_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); mail_send_queue (outbox_folder, info->uri, FILTER_SOURCE_OUTGOING, info->cancel, diff --git a/mail/mail-session.c b/mail/mail-session.c index 9009bb607b..1de1ecfe61 100644 --- a/mail/mail-session.c +++ b/mail/mail-session.c @@ -50,7 +50,6 @@ #include "em-filter-context.h" #include "em-filter-rule.h" #include "em-utils.h" -#include "mail-component.h" #include "mail-config.h" #include "mail-mt.h" #include "mail-ops.h" @@ -82,6 +81,7 @@ typedef struct _MailSessionClass { } MailSessionClass; +static EShellModule *mail_shell_module; static CamelSessionClass *ms_parent_class; static char *get_password(CamelSession *session, CamelService *service, const char *domain, const char *prompt, const char *item, guint32 flags, CamelException *ex); @@ -499,13 +499,15 @@ main_get_filter_driver (CamelSession *session, const char *type, CamelException { CamelFilterDriver *driver; FilterRule *rule = NULL; + const gchar *data_dir; char *user, *system; GConfClient *gconf; RuleContext *fc; gconf = mail_config_get_gconf_client (); - user = g_strdup_printf ("%s/filters.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); fc = (RuleContext *) em_filter_context_new (); rule_context_load (fc, system, user); @@ -688,12 +690,15 @@ mail_session_check_junk_notify (GConfClient *gconf, guint id, GConfEntry *entry, } void -mail_session_init (const char *base_directory) +mail_session_init (EShellModule *shell_module) { - char *camel_dir; + const gchar *data_dir; GConfClient *gconf; - if (camel_init (base_directory, TRUE) != 0) + mail_shell_module = shell_module; + data_dir = e_shell_module_get_data_dir (shell_module); + + if (camel_init (data_dir, TRUE) != 0) exit (0); camel_provider_init(); @@ -702,8 +707,7 @@ mail_session_init (const char *base_directory) e_account_combo_box_set_session (session); /* XXX Don't ask... */ e_account_writable(NULL, E_ACCOUNT_SOURCE_SAVE_PASSWD); /* Init the EAccount Setup */ - camel_dir = g_strdup_printf ("%s/mail", base_directory); - camel_session_construct (session, camel_dir); + camel_session_construct (session, data_dir); gconf = mail_config_get_gconf_client (); gconf_client_add_dir (gconf, "/apps/evolution/mail/junk", GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); @@ -716,7 +720,6 @@ mail_session_init (const char *base_directory) /* The shell will tell us to go online. */ camel_session_set_online ((CamelSession *) session, FALSE); mail_config_reload_junk_headers (); - g_free (camel_dir); } void diff --git a/mail/mail-session.h b/mail/mail-session.h index a2a5e9706f..a885081327 100644 --- a/mail/mail-session.h +++ b/mail/mail-session.h @@ -26,13 +26,14 @@ #include <glib.h> #include <bonobo/bonobo-ui-component.h> #include <camel/camel-session.h> +#include <shell/e-shell-module.h> #ifdef __cplusplus extern "C" { #pragma } #endif /* __cplusplus */ -void mail_session_init (const char *base_directory); +void mail_session_init (EShellModule *shell_module); void mail_session_shutdown (void); gboolean mail_session_get_interactive (void); void mail_session_set_interactive (gboolean interactive); diff --git a/mail/mail-tools.c b/mail/mail-tools.c index 7278829501..4c7131dacc 100644 --- a/mail/mail-tools.c +++ b/mail/mail-tools.c @@ -51,7 +51,6 @@ #include "em-utils.h" #include "em-vfolder-context.h" #include "em-vfolder-rule.h" -#include "mail-component.h" #include "mail-config.h" #include "mail-folder-cache.h" #include "mail-mt.h" @@ -59,6 +58,8 @@ #include "mail-tools.h" #include "mail-vfolder.h" +#include "e-mail-shell-module.h" + /* **************************************** */ CamelFolder * @@ -107,6 +108,7 @@ static char * mail_tool_get_local_movemail_path (const unsigned char *uri, CamelException *ex) { unsigned char *safe_uri, *c; + const gchar *data_dir; char *path, *full; struct stat st; @@ -115,7 +117,9 @@ mail_tool_get_local_movemail_path (const unsigned char *uri, CamelException *ex) if (strchr("/:;=|%&#!*^()\\, ", *c) || !isprint((int) *c)) *c = '_'; - path = g_strdup_printf("%s/spool", mail_component_peek_base_directory(NULL)); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + path = g_build_filename (data_dir, "spool", NULL); + if (g_stat(path, &st) == -1 && g_mkdir_with_parents(path, 0777) == -1) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Could not create spool directory `%s': %s"), path, g_strerror(errno)); diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c index 951bcc51e7..5df6d9e4cd 100644 --- a/mail/mail-vfolder.c +++ b/mail/mail-vfolder.c @@ -42,7 +42,6 @@ #include "em-vfolder-editor.h" #include "em-vfolder-rule.h" #include "mail-autofilter.h" -#include "mail-component.h" #include "mail-config.h" #include "mail-folder-cache.h" #include "mail-mt.h" @@ -50,6 +49,8 @@ #include "mail-tools.h" #include "mail-vfolder.h" +#include "e-mail-shell-module.h" + #define d(x) /* (printf("%s:%s: ", G_STRLOC, G_STRFUNC), (x))*/ static EMVFolderContext *context; /* context remains open all time */ @@ -336,16 +337,26 @@ uri_is_ignore(CamelStore *store, const char *uri) EAccountList *accounts; EAccount *account; EIterator *iter; + const gchar *local_drafts_folder_uri; + const gchar *local_outbox_folder_uri; + const gchar *local_sent_folder_uri; int found = FALSE; + local_drafts_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); + local_outbox_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); + local_sent_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_SENT); + d(printf("checking '%s' against:\n %s\n %s\n %s\n", uri, - mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_OUTBOX), - mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT), - mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS))); + local_outbox_folder_uri, + local_sent_folder_uri, + local_drafts_folder_uri)); - found = camel_store_folder_uri_equal(store, mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_OUTBOX), uri) - || camel_store_folder_uri_equal(store, mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT), uri) - || camel_store_folder_uri_equal(store, mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS), uri); + found = camel_store_folder_uri_equal(store, local_outbox_folder_uri, uri) + || camel_store_folder_uri_equal(store, local_sent_folder_uri, uri) + || camel_store_folder_uri_equal(store, local_drafts_folder_uri, uri); if (found) return found; @@ -591,13 +602,14 @@ done: if (changed->str[0]) { GtkWidget *dialog; + const gchar *data_dir; char *user; dialog = e_error_new(NULL, "mail:vfolder-updated", changed->str, uri, NULL); em_utils_show_info_silent (dialog); - user = g_strdup_printf ("%s/vfolders.xml", - mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save ((RuleContext *) context, user); g_free (user); } @@ -660,10 +672,12 @@ mail_vfolder_rename_uri(CamelStore *store, const char *cfrom, const char *cto) UNLOCK(); if (changed) { + const gchar *data_dir; char *user; d(printf("Vfolders updated from renamed folder\n")); - user = g_strdup_printf("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); } @@ -784,21 +798,12 @@ static void context_rule_added(RuleContext *ctx, FilterRule *rule) static void context_rule_removed(RuleContext *ctx, FilterRule *rule) { - char *path; - gpointer key, folder = NULL; d(printf("rule removed; %s\n", rule->name)); /* TODO: remove from folder info cache? */ - /* FIXME: is this even necessary? if we remove the folder from - * the CamelStore, the tree should pick it up auto-magically - * because it listens to CamelStore events... */ - path = g_strdup_printf("/%s", rule->name); - mail_component_remove_folder (mail_component_peek (), vfolder_store, path); - g_free(path); - LOCK(); if (g_hash_table_lookup_extended (vfolder_hash, rule->name, &key, &folder)) { g_hash_table_remove (vfolder_hash, key); @@ -840,6 +845,8 @@ store_folder_deleted(CamelObject *o, void *event_data, void *data) /* delete it from our list */ rule = rule_context_find_rule((RuleContext *)context, info->full_name, NULL); if (rule) { + const gchar *data_dir; + /* We need to stop listening to removed events, otherwise we'll try and remove it again */ g_signal_handlers_disconnect_matched(context, G_SIGNAL_MATCH_FUNC|G_SIGNAL_MATCH_DATA, 0, 0, NULL, context_rule_removed, context); @@ -847,7 +854,8 @@ store_folder_deleted(CamelObject *o, void *event_data, void *data) g_object_unref(rule); g_signal_connect(context, "rule_removed", G_CALLBACK(context_rule_removed), context); - user = g_strdup_printf("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); } else { @@ -874,6 +882,8 @@ store_folder_renamed(CamelObject *o, void *event_data, void *data) LOCK(); d(printf("Changing folder name in hash table to '%s'\n", info->new->full_name)); if (g_hash_table_lookup_extended (vfolder_hash, info->old_base, &key, &folder)) { + const gchar *data_dir; + g_hash_table_remove (vfolder_hash, key); g_free (key); g_hash_table_insert (vfolder_hash, g_strdup(info->new->full_name), folder); @@ -890,7 +900,8 @@ store_folder_renamed(CamelObject *o, void *event_data, void *data) filter_rule_set_name(rule, info->new->full_name); g_signal_connect(rule, "changed", G_CALLBACK(rule_changed), folder); - user = g_strdup_printf("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); @@ -907,6 +918,7 @@ vfolder_load_storage(void) /* lock for loading storage, it is safe to call it more than once */ static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + const gchar *data_dir; char *user, *storeuri; FilterRule *rule; char *xmlfile; @@ -925,7 +937,8 @@ vfolder_load_storage(void) pthread_mutex_unlock (&lock); /* first, create the vfolder store, and set it up */ - storeuri = g_strdup_printf("vfolder:%s/vfolder", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + storeuri = g_strdup_printf("vfolder:%s/vfolder", data_dir); vfolder_store = camel_session_get_store(session, storeuri, NULL); if (vfolder_store == NULL) { g_warning("Cannot open vfolder store - no vfolders available"); @@ -942,7 +955,7 @@ vfolder_load_storage(void) d(printf("got store '%s' = %p\n", storeuri, vfolder_store)); /* load our rules */ - user = g_strdup_printf ("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + user = g_build_filename (data_dir, "vfolders.xml", NULL); context = em_vfolder_context_new (); xmlfile = g_build_filename (EVOLUTION_PRIVDATADIR, "vfoldertypes.xml", NULL); @@ -957,7 +970,8 @@ vfolder_load_storage(void) g_signal_connect(context, "rule_removed", G_CALLBACK(context_rule_removed), context); /* load store to mail component */ - mail_component_load_store_by_uri (mail_component_peek (), storeuri, _("Search Folders")); + e_mail_shell_module_load_store_by_uri ( + mail_shell_module, storeuri, _("Search Folders")); /* and setup the rules we have */ rule = NULL; @@ -980,10 +994,12 @@ vfolder_load_storage(void) void vfolder_revert(void) { + const gchar *data_dir; char *user; d(printf("vfolder_revert\n")); - user = g_strdup_printf("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_revert((RuleContext *)context, user); g_free(user); } @@ -993,9 +1009,11 @@ static GtkWidget *vfolder_editor = NULL; static void em_vfolder_editor_response (GtkWidget *dialog, int button, void *data) { + const gchar *data_dir; char *user; - user = g_strdup_printf ("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); switch(button) { case GTK_RESPONSE_OK: @@ -1034,12 +1052,14 @@ static void edit_rule_response(GtkWidget *w, int button, void *data) { if (button == GTK_RESPONSE_OK) { + const gchar *data_dir; char *user; FilterRule *rule = g_object_get_data (G_OBJECT (w), "rule"); FilterRule *orig = g_object_get_data (G_OBJECT (w), "orig"); filter_rule_copy(orig, rule); - user = g_strdup_printf("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); } @@ -1096,6 +1116,7 @@ static void new_rule_clicked(GtkWidget *w, int button, void *data) { if (button == GTK_RESPONSE_OK) { + const gchar *data_dir; char *user; FilterRule *rule = g_object_get_data((GObject *)w, "rule"); @@ -1112,7 +1133,8 @@ new_rule_clicked(GtkWidget *w, int button, void *data) g_object_ref(rule); rule_context_add_rule((RuleContext *)context, rule); - user = g_strdup_printf("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); } diff --git a/shell/e-shell-content.c b/shell/e-shell-content.c index 87c1bbfd50..7a9d7cf3f0 100644 --- a/shell/e-shell-content.c +++ b/shell/e-shell-content.c @@ -207,6 +207,7 @@ shell_content_entry_key_press_cb (EShellContent *shell_content, static void shell_content_init_search_context (EShellContent *shell_content) { + EShellContentClass *shell_content_class; EShellView *shell_view; EShellViewClass *shell_view_class; EShellModule *shell_module; @@ -221,9 +222,12 @@ shell_content_init_search_context (EShellContent *shell_content) shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); g_return_if_fail (shell_view_class->search_rules != NULL); - /* The filename for built-in searches is specified in a - * module's EShellModuleInfo. All built-in search rules - * live in the same directory. */ + shell_content_class = E_SHELL_CONTENT_GET_CLASS (shell_content); + g_return_if_fail (shell_content_class->new_search_context != NULL); + + /* The basename for built-in searches is specified in the + * shell view class. All built-in search rules live in the + * same directory. */ system_filename = g_build_filename ( EVOLUTION_RULEDIR, shell_view_class->search_rules, NULL); @@ -233,7 +237,7 @@ shell_content_init_search_context (EShellContent *shell_content) e_shell_module_get_data_dir (shell_module), "searches.xml", NULL); - context = rule_context_new (); + context = shell_content_class->new_search_context (); rule_context_add_part_set ( context, "partset", FILTER_TYPE_PART, rule_context_add_part, rule_context_next_part); @@ -533,25 +537,8 @@ shell_content_constructed (GObject *object) widget = shell_content->priv->search_bar; gtk_size_group_add_widget (size_group, widget); -} -static void -shell_content_realize (GtkWidget *widget) -{ - EShellContent *shell_content; - - /* We can't call this during object construction because the - * shell view is still in its instance initialization phase, - * and so its GET_CLASS() macro won't work correctly. So we - * delay the bits of our own initialization that require the - * E_SHELL_VIEW_GET_CLASS() macro until after the shell view - * is fully constructed. */ - - shell_content = E_SHELL_CONTENT (widget); shell_content_init_search_context (shell_content); - - /* Chain up to parent's realize() method. */ - GTK_WIDGET_CLASS (parent_class)->realize (widget); } static void @@ -664,7 +651,6 @@ shell_content_class_init (EShellContentClass *class) object_class->constructed = shell_content_constructed; widget_class = GTK_WIDGET_CLASS (class); - widget_class->realize = shell_content_realize; widget_class->size_request = shell_content_size_request; widget_class->size_allocate = shell_content_size_allocate; @@ -672,6 +658,8 @@ shell_content_class_init (EShellContentClass *class) container_class->remove = shell_content_remove; container_class->forall = shell_content_forall; + class->new_search_context = rule_context_new; + g_object_class_install_property ( object_class, PROP_FILTER_ACTION, diff --git a/shell/e-shell-content.h b/shell/e-shell-content.h index 68e80f7dac..8d1276c94e 100644 --- a/shell/e-shell-content.h +++ b/shell/e-shell-content.h @@ -73,6 +73,9 @@ struct _EShellContent { struct _EShellContentClass { GtkBinClass parent_class; + + /* Factory Methods */ + RuleContext * (*new_search_context) (void); }; GType e_shell_content_get_type (void); diff --git a/shell/e-shell-module.c b/shell/e-shell-module.c index 1fff07ee97..5ec13e00bc 100644 --- a/shell/e-shell-module.c +++ b/shell/e-shell-module.c @@ -49,6 +49,7 @@ struct _EShellModulePrivate { gchar *data_dir; GType shell_view_type; + GHashTable *events; /* Initializes the loaded type module. */ void (*init) (GTypeModule *type_module); diff --git a/shell/e-shell-module.h b/shell/e-shell-module.h index 24bc690533..7186b13a62 100644 --- a/shell/e-shell-module.h +++ b/shell/e-shell-module.h @@ -60,6 +60,9 @@ typedef struct _EShellModuleInfo EShellModuleInfo; typedef struct _EShellModuleClass EShellModuleClass; typedef struct _EShellModulePrivate EShellModulePrivate; +typedef struct _EShellModuleEvent EShellModuleEvent; +typedef void (*EShellModuleEventFunc) (EShellModuleEvent *event); + /** * EShellModuleInfo: * @name: The name of the module. Also becomes the name of @@ -85,6 +88,10 @@ typedef struct _EShellModulePrivate EShellModulePrivate; * settings from the given version. Returns %TRUE if the * migration was successful or if no action was necessary. * Returns %FALSE and sets a #GError if the migration failed. + * + * Provides basic information about an #EShellModule instance. Shell + * modules should pass this structure to e_shell_module_set_info() in + * their "e_shell_module_init" functions. **/ struct _EShellModuleInfo { const gchar *name; diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c index dad31c3f2e..e307847116 100644 --- a/shell/e-shell-view.c +++ b/shell/e-shell-view.c @@ -623,8 +623,8 @@ e_shell_view_get_name (EShellView *shell_view) * * Returns the switcher action for @shell_view. * - * An #EShellWindow creates a #GtkRadioAction for each #EShellView class - * it instantiates. This action gets passed to the #EShellSwitcher, which + * An #EShellWindow creates a #GtkRadioAction for each registered subclass + * of #EShellView. This action gets passed to the #EShellSwitcher, which * displays a button that proxies the action. The icon at the top of the * sidebar also proxies the action. When @shell_view is active, the * action's icon becomes the #EShellWindow icon. diff --git a/shell/e-shell-window-actions.c b/shell/e-shell-window-actions.c index a5ca5b310d..2dcdd4c4d4 100644 --- a/shell/e-shell-window-actions.c +++ b/shell/e-shell-window-actions.c @@ -2192,7 +2192,6 @@ e_shell_window_update_search_menu (EShellWindow *shell_window) FilterRule *rule; GtkUIManager *ui_manager; GtkActionGroup *action_group; - GList *list, *iter; const gchar *source; const gchar *view_name; gboolean sensitive; @@ -2223,13 +2222,7 @@ e_shell_window_update_search_menu (EShellWindow *shell_window) /* Unmerge the previous menu. */ gtk_ui_manager_remove_ui (ui_manager, merge_id); - - /* XXX Annoying that GTK+ doesn't provide a function for this. - * http://bugzilla.gnome.org/show_bug.cgi?id=550485 */ - list = gtk_action_group_list_actions (action_group); - for (iter = list; iter != NULL; iter = iter->next) - gtk_action_group_remove_action (action_group, iter->data); - g_list_free (list); + e_action_group_remove_all_actions (action_group); rule = rule_context_next_rule (context, NULL, source); while (rule != NULL) { diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c index 0d54b92bd8..de68d343e4 100644 --- a/shell/e-shell-window.c +++ b/shell/e-shell-window.c @@ -56,9 +56,8 @@ shell_window_new_view (EShellWindow *shell_window, page_num = gtk_notebook_get_n_pages (notebook); /* Get the switcher action for this view. */ - action_name = g_strdup_printf (SWITCHER_FORMAT, view_name); - action = e_shell_window_get_action (shell_window, action_name); - g_free (action_name); + action = e_shell_window_get_shell_view_action ( + shell_window, view_name); /* Create the shell view. */ shell_view = g_object_new ( @@ -434,6 +433,39 @@ e_shell_window_get_shell_view (EShellWindow *shell_window, } /** + * e_shell_window_get_shell_view_action: + * @shell_window: an #EShellWindow + * @view_name: name of a shell view + * + * Returns the switcher action for @view_name. + * + * An #EShellWindow creates a #GtkRadioAction for each registered subclass + * of #EShellView. This action gets passed to the #EShellSwitcher, which + * displays a button that proxies the action. The icon at the top of the + * sidebar also proxies the action. When the #EShellView named @view_name + * is active, the action's icon becomes the @shell_window icon. + * + * Returns: the switcher action for the #EShellView named @view_name, + * or %NULL if no such shell view exists + **/ +GtkAction * +e_shell_window_get_shell_view_action (EShellWindow *shell_window, + const gchar *view_name) +{ + GtkAction *action; + gchar *action_name; + + g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); + g_return_val_if_fail (view_name != NULL, NULL); + + action_name = g_strdup_printf (SWITCHER_FORMAT, view_name); + action = e_shell_window_get_action (shell_window, action_name); + g_free (action_name); + + return action; +} + +/** * e_shell_window_get_ui_manager: * @shell_window: an #EShellWindow * diff --git a/shell/e-shell-window.h b/shell/e-shell-window.h index e3bc22beef..00887cadea 100644 --- a/shell/e-shell-window.h +++ b/shell/e-shell-window.h @@ -80,6 +80,9 @@ EShell * e_shell_window_get_shell (EShellWindow *shell_window); struct _EShellView * e_shell_window_get_shell_view (EShellWindow *shell_window, const gchar *view_name); +GtkAction * e_shell_window_get_shell_view_action + (EShellWindow *shell_window, + const gchar *view_name); GtkUIManager * e_shell_window_get_ui_manager (EShellWindow *shell_window); GtkAction * e_shell_window_get_action (EShellWindow *shell_window, const gchar *action_name); diff --git a/shell/e-shell.c b/shell/e-shell.c index 71eaec483d..c875dcb5cf 100644 --- a/shell/e-shell.c +++ b/shell/e-shell.c @@ -54,6 +54,7 @@ enum { }; enum { + EVENT, HANDLE_URI, SEND_RECEIVE, WINDOW_CREATED, @@ -356,6 +357,14 @@ shell_class_init (EShellClass *class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + signals[EVENT] = g_signal_new ( + "event", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[HANDLE_URI] = g_signal_new ( "handle-uri", G_OBJECT_CLASS_TYPE (object_class), @@ -615,6 +624,19 @@ e_shell_get_preferences_window (void) return preferences_window; } +void +e_shell_event (EShell *shell, + const gchar *event_name) +{ + GQuark detail; + + g_return_if_fail (E_IS_SHELL (shell)); + g_return_if_fail (event_name != NULL); + + detail = g_quark_from_string (event_name); + g_signal_emit (shell, signals[EVENT], detail); +} + gboolean e_shell_is_busy (EShell *shell) { diff --git a/shell/e-shell.h b/shell/e-shell.h index 183028948c..7bee6b9fff 100644 --- a/shell/e-shell.h +++ b/shell/e-shell.h @@ -103,6 +103,8 @@ EShellLineStatus void e_shell_set_line_status (EShell *shell, EShellLineStatus status); GtkWidget * e_shell_get_preferences_window (void); +void e_shell_event (EShell *shell, + const gchar *event_name); gboolean e_shell_is_busy (EShell *shell); gboolean e_shell_do_quit (EShell *shell); gboolean e_shell_quit (EShell *shell); diff --git a/ui/evolution-mail.ui b/ui/evolution-mail.ui index ec1934d0ef..16d4d9e67e 100644 --- a/ui/evolution-mail.ui +++ b/ui/evolution-mail.ui @@ -189,6 +189,15 @@ <menuitem action='mail-flag-for-followup'/> <menu action='mail-label-menu'/> </popup> + <popup name='mail-uri-popup'> + <menuitem action='mail-uri-call-to'/> + <menuitem action='mail-uri-copy'/> + <menuitem action='mail-uri-copy-address'/> + <menu action='mail-uri-to-search-folder-menu'/> + <menuitem action='mail-uri-to-search-folder-sender'/> + <menuitem action='mail-uri-to-search-folder-recipient'/> + </menu> + </popup> <popup name='mail-search-options'> <menuitem action='mail-search-subject-or-sender-contains'/> <menuitem action='mail-search-subject-or-recipients-contains'/> diff --git a/widgets/misc/e-activity-proxy.c b/widgets/misc/e-activity-proxy.c index 56b8ed33d4..6ce89016cd 100644 --- a/widgets/misc/e-activity-proxy.c +++ b/widgets/misc/e-activity-proxy.c @@ -30,9 +30,10 @@ struct _EActivityProxyPrivate { EActivity *activity; + GtkWidget *button; GtkWidget *image; GtkWidget *label; - GtkWidget *button; + GtkWidget *cancel; GtkWidget *spinner; }; @@ -50,12 +51,14 @@ activity_proxy_update (EActivityProxy *proxy) const gchar *icon_name; gboolean cancellable; gboolean cancelled; + gboolean clickable; gboolean completed; gboolean sensitive; gchar *description; cancellable = e_activity_get_cancellable (activity); cancelled = e_activity_is_cancelled (activity); + clickable = e_activity_get_clickable (activity); completed = e_activity_is_completed (activity); icon_name = e_activity_get_icon_name (activity); @@ -64,26 +67,39 @@ activity_proxy_update (EActivityProxy *proxy) gtk_label_set_text (GTK_LABEL (proxy->priv->label), description); g_free (description); + /* Note, an activity requires an icon name in order to + * be clickable. We don't support spinner buttons. */ if (icon_name != NULL) { gtk_image_set_from_icon_name ( GTK_IMAGE (proxy->priv->image), icon_name, GTK_ICON_SIZE_MENU); + gtk_button_set_image ( + GTK_BUTTON (proxy->priv->button), + gtk_image_new_from_icon_name ( + icon_name, GTK_ICON_SIZE_MENU)); e_spinner_stop (E_SPINNER (proxy->priv->spinner)); - gtk_widget_show (proxy->priv->image); gtk_widget_hide (proxy->priv->spinner); + if (clickable) { + gtk_widget_show (proxy->priv->button); + gtk_widget_hide (proxy->priv->image); + } else { + gtk_widget_hide (proxy->priv->button); + gtk_widget_show (proxy->priv->image); + } } else { e_spinner_start (E_SPINNER (proxy->priv->spinner)); gtk_widget_show (proxy->priv->spinner); + gtk_widget_hide (proxy->priv->button); gtk_widget_hide (proxy->priv->image); } if (cancellable) - gtk_widget_show (proxy->priv->button); + gtk_widget_show (proxy->priv->cancel); else - gtk_widget_hide (proxy->priv->button); + gtk_widget_hide (proxy->priv->cancel); sensitive = !(cancelled || completed); - gtk_widget_set_sensitive (proxy->priv->button, sensitive); + gtk_widget_set_sensitive (proxy->priv->cancel, sensitive); } static void @@ -141,6 +157,11 @@ activity_proxy_dispose (GObject *object) priv->activity = NULL; } + if (priv->button != NULL) { + g_object_unref (priv->button); + priv->image = NULL; + } + if (priv->image != NULL) { g_object_unref (priv->image); priv->image = NULL; @@ -151,9 +172,9 @@ activity_proxy_dispose (GObject *object) priv->label = NULL; } - if (priv->button != NULL) { - g_object_unref (priv->button); - priv->button = NULL; + if (priv->cancel != NULL) { + g_object_unref (priv->cancel); + priv->cancel = NULL; } if (priv->spinner != NULL) { @@ -174,6 +195,10 @@ activity_proxy_constructed (GObject *object) g_signal_connect_swapped ( proxy->priv->button, "clicked", + G_CALLBACK (e_activity_clicked), proxy->priv->activity); + + g_signal_connect_swapped ( + proxy->priv->cancel, "clicked", G_CALLBACK (e_activity_cancel), proxy->priv->activity); g_signal_connect_swapped ( @@ -240,18 +265,24 @@ activity_proxy_init (EActivityProxy *proxy) container = widget; + widget = gtk_image_new (); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + proxy->priv->image = g_object_ref (widget); + gtk_widget_hide (widget); + + widget = gtk_button_new (); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + proxy->priv->button = g_object_ref (widget); + gtk_widget_hide (widget); + widget = e_spinner_new (); e_spinner_set_size (E_SPINNER (widget), GTK_ICON_SIZE_MENU); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); proxy->priv->spinner = g_object_ref (widget); gtk_widget_show (widget); - widget = gtk_image_new (); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - proxy->priv->image = g_object_ref (widget); - gtk_widget_hide (widget); - widget = gtk_label_new (NULL); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); proxy->priv->label = g_object_ref (widget); @@ -264,7 +295,7 @@ activity_proxy_init (EActivityProxy *proxy) gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); gtk_widget_set_tooltip_text (widget, _("Cancel")); - proxy->priv->button = g_object_ref (widget); + proxy->priv->cancel = g_object_ref (widget); gtk_widget_show (widget); } diff --git a/widgets/misc/e-activity.c b/widgets/misc/e-activity.c index 434225a5a2..7905c4062f 100644 --- a/widgets/misc/e-activity.c +++ b/widgets/misc/e-activity.c @@ -32,14 +32,20 @@ struct _EActivityPrivate { gchar *primary_text; gchar *secondary_text; gdouble percent; - gboolean cancellable; - guint cancelled : 1; - guint completed : 1; + guint timeout_id; + + guint blocking : 1; + guint cancellable : 1; + guint cancelled : 1; + guint clickable : 1; + guint completed : 1; }; enum { PROP_0, + PROP_BLOCKING, PROP_CANCELLABLE, + PROP_CLICKABLE, PROP_ICON_NAME, PROP_PERCENT, PROP_PRIMARY_TEXT, @@ -48,13 +54,23 @@ enum { enum { CANCELLED, + CLICKED, COMPLETED, + TIMEOUT, LAST_SIGNAL }; static gpointer parent_class; static gulong signals[LAST_SIGNAL]; +static gboolean +activity_timeout_cb (EActivity *activity) +{ + g_signal_emit (activity, signals[TIMEOUT], 0); + + return FALSE; +} + static void activity_set_property (GObject *object, guint property_id, @@ -62,12 +78,24 @@ activity_set_property (GObject *object, GParamSpec *pspec) { switch (property_id) { + case PROP_BLOCKING: + e_activity_set_blocking ( + E_ACTIVITY (object), + g_value_get_boolean (value)); + return; + case PROP_CANCELLABLE: e_activity_set_cancellable ( E_ACTIVITY (object), g_value_get_boolean (value)); return; + case PROP_CLICKABLE: + e_activity_set_clickable ( + E_ACTIVITY (object), + g_value_get_boolean (value)); + return; + case PROP_ICON_NAME: e_activity_set_icon_name ( E_ACTIVITY (object), @@ -103,12 +131,24 @@ activity_get_property (GObject *object, GParamSpec *pspec) { switch (property_id) { + case PROP_BLOCKING: + g_value_set_boolean ( + value, e_activity_get_blocking ( + E_ACTIVITY (object))); + return; + case PROP_CANCELLABLE: g_value_set_boolean ( value, e_activity_get_cancellable ( E_ACTIVITY (object))); return; + case PROP_CLICKABLE: + g_value_set_boolean ( + value, e_activity_get_clickable ( + E_ACTIVITY (object))); + return; + case PROP_ICON_NAME: g_value_set_string ( value, e_activity_get_icon_name ( @@ -148,6 +188,9 @@ activity_finalize (GObject *object) g_free (priv->primary_text); g_free (priv->secondary_text); + if (priv->timeout_id > 0) + g_source_remove (priv->timeout_id); + /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -167,6 +210,17 @@ activity_class_init (EActivityClass *class) g_object_class_install_property ( object_class, + PROP_BLOCKING, + g_param_spec_boolean ( + "blocking", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, PROP_CANCELLABLE, g_param_spec_boolean ( "cancellable", @@ -178,6 +232,17 @@ activity_class_init (EActivityClass *class) g_object_class_install_property ( object_class, + PROP_CLICKABLE, + g_param_spec_boolean ( + "clickable", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, PROP_ICON_NAME, g_param_spec_string ( "icon-name", @@ -225,7 +290,15 @@ activity_class_init (EActivityClass *class) signals[CANCELLED] = g_signal_new ( "cancelled", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[CLICKED] = g_signal_new ( + "clicked", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); @@ -233,7 +306,15 @@ activity_class_init (EActivityClass *class) signals[COMPLETED] = g_signal_new ( "completed", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[TIMEOUT] = g_signal_new ( + "timeout", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); @@ -310,6 +391,14 @@ e_activity_complete (EActivity *activity) g_signal_emit (activity, signals[COMPLETED], 0); } +void +e_activity_clicked (EActivity *activity) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + g_signal_emit (activity, signals[CLICKED], 0); +} + gchar * e_activity_describe (EActivity *activity) { @@ -336,7 +425,7 @@ e_activity_describe (EActivity *activity) } else if (percent < 0.0) { /* Translators: This is an activity whose percent * complete is unknown. */ - g_string_printf (string, _("%s (...)"), text); + g_string_printf (string, _("%s..."), text); } else { /* Translators: This is an activity whose percent * complete is known. */ @@ -364,6 +453,48 @@ e_activity_is_completed (EActivity *activity) return activity->priv->completed; } +void +e_activity_add_timeout (EActivity *activity, + guint seconds) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + e_activity_cancel_timeout (activity); + + activity->priv->timeout_id = g_timeout_add_seconds ( + seconds, (GSourceFunc) activity_timeout_cb, activity); +} + +void +e_activity_cancel_timeout (EActivity *activity) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + if (activity->priv->timeout_id > 0) { + g_source_remove (activity->priv->timeout_id); + activity->priv->timeout_id = 0; + } +} + +gboolean +e_activity_get_blocking (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); + + return activity->priv->blocking; +} + +void +e_activity_set_blocking (EActivity *activity, + gboolean blocking) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + activity->priv->blocking = blocking; + + g_object_notify (G_OBJECT (activity), "blocking"); +} + gboolean e_activity_get_cancellable (EActivity *activity) { @@ -383,6 +514,25 @@ e_activity_set_cancellable (EActivity *activity, g_object_notify (G_OBJECT (activity), "cancellable"); } +gboolean +e_activity_get_clickable (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); + + return activity->priv->clickable; +} + +void +e_activity_set_clickable (EActivity *activity, + gboolean clickable) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + activity->priv->clickable = clickable; + + g_object_notify (G_OBJECT (activity), "clickable"); +} + const gchar * e_activity_get_icon_name (EActivity *activity) { @@ -461,3 +611,105 @@ e_activity_set_secondary_text (EActivity *activity, g_object_notify (G_OBJECT (activity), "secondary-text"); } + +/************************* Error Dialog Integration **************************/ + +void +e_activity_error (EActivity *activity, + GtkWidget *error_dialog) +{ + GObject *object; + const gchar *primary_text; + const gchar *secondary_text; + + /* XXX Convert an activity to a clickable error message. + * Clicking on the activity completes it and displays + * the error dialog. Eventually I'd like to eliminate + * error dialogs altogether and show errors directly + * in the shell window. */ + + g_return_if_fail (E_IS_ACTIVITY (activity)); + g_return_if_fail (GTK_IS_DIALOG (error_dialog)); + + object = G_OBJECT (error_dialog); + primary_text = g_object_get_data (object, "primary"); + secondary_text = g_object_get_data (object, "secondary"); + + e_activity_set_primary_text (activity, primary_text); + e_activity_set_secondary_text (activity, secondary_text); + e_activity_set_icon_name (activity, "dialog-warning"); + e_activity_set_clickable (activity, TRUE); + + g_signal_connect ( + activity, "cancelled", + G_CALLBACK (e_activity_cancel_timeout), NULL); + + g_signal_connect ( + activity, "completed", + G_CALLBACK (e_activity_cancel_timeout), NULL); + + g_signal_connect ( + activity, "clicked", + G_CALLBACK (e_activity_complete), NULL); + + g_signal_connect_swapped ( + activity, "clicked", + G_CALLBACK (gtk_dialog_run), error_dialog); + + g_signal_connect ( + activity, "timeout", + G_CALLBACK (e_activity_complete), NULL); + + /* XXX Allow for a configurable timeout. */ + e_activity_add_timeout (activity, 60); +} + +void +e_activity_info (EActivity *activity, + GtkWidget *info_dialog) +{ + GObject *object; + const gchar *primary_text; + const gchar *secondary_text; + + /* XXX Convert an activity to a clickable info message. + * Clicking on the activity completes it and displays + * the info dialog. Eventually I'd like to eliminate + * info dialogs altogether and show errors directly + * in the shell window. */ + + g_return_if_fail (E_IS_ACTIVITY (activity)); + g_return_if_fail (GTK_IS_DIALOG (info_dialog)); + + object = G_OBJECT (info_dialog); + primary_text = g_object_get_data (object, "primary"); + secondary_text = g_object_get_data (object, "secondary"); + + e_activity_set_primary_text (activity, primary_text); + e_activity_set_secondary_text (activity, secondary_text); + e_activity_set_icon_name (activity, "dialog-warning"); + e_activity_set_clickable (activity, TRUE); + + g_signal_connect ( + activity, "cancelled", + G_CALLBACK (e_activity_cancel_timeout), NULL); + + g_signal_connect ( + activity, "completed", + G_CALLBACK (e_activity_cancel_timeout), NULL); + + g_signal_connect ( + activity, "clicked", + G_CALLBACK (e_activity_complete), NULL); + + g_signal_connect_swapped ( + activity, "clicked", + G_CALLBACK (gtk_dialog_run), info_dialog); + + g_signal_connect ( + activity, "timeout", + G_CALLBACK (e_activity_complete), NULL); + + /* XXX Allow for a configurable timeout. */ + e_activity_add_timeout (activity, 60); +} diff --git a/widgets/misc/e-activity.h b/widgets/misc/e-activity.h index 48a19ff91d..d949860333 100644 --- a/widgets/misc/e-activity.h +++ b/widgets/misc/e-activity.h @@ -22,7 +22,7 @@ #ifndef E_ACTIVITY_H #define E_ACTIVITY_H -#include <glib-object.h> +#include <gtk/gtk.h> /* Standard GObject macros */ #define E_TYPE_ACTIVITY \ @@ -62,12 +62,22 @@ GType e_activity_get_type (void); EActivity * e_activity_new (const gchar *primary_text); void e_activity_cancel (EActivity *activity); void e_activity_complete (EActivity *activity); +void e_activity_clicked (EActivity *activity); gchar * e_activity_describe (EActivity *activity); gboolean e_activity_is_cancelled (EActivity *activity); gboolean e_activity_is_completed (EActivity *activity); +void e_activity_add_timeout (EActivity *activity, + guint seconds); +void e_activity_cancel_timeout (EActivity *activity); +gboolean e_activity_get_blocking (EActivity *activity); +void e_activity_set_blocking (EActivity *activity, + gboolean blocking); gboolean e_activity_get_cancellable (EActivity *activity); void e_activity_set_cancellable (EActivity *activity, gboolean cancellable); +gboolean e_activity_get_clickable (EActivity *activity); +void e_activity_set_clickable (EActivity *activity, + gboolean clickable); const gchar * e_activity_get_icon_name (EActivity *activity); void e_activity_set_icon_name (EActivity *activity, const gchar *icon_name); @@ -81,6 +91,12 @@ const gchar * e_activity_get_secondary_text (EActivity *activity); void e_activity_set_secondary_text (EActivity *activity, const gchar *secondary_text); +/* XXX Hacky integration with error dialogs. */ +void e_activity_error (EActivity *activity, + GtkWidget *error_dialog); +void e_activity_info (EActivity *activity, + GtkWidget *info_dialog); + G_END_DECLS #endif /* E_ACTIVITY_H */ |