diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2011-12-09 23:34:55 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2011-12-11 10:34:19 +0800 |
commit | 7c0c40f83317228e0a725bfb5ca8854339d25588 (patch) | |
tree | db1197dd9f336e175c590c3a41201dfa78ee303e | |
parent | 2f32e1cc68cd416f4530ecc3d2ff08b0e6498d45 (diff) | |
download | gsoc2013-evolution-7c0c40f83317228e0a725bfb5ca8854339d25588.tar gsoc2013-evolution-7c0c40f83317228e0a725bfb5ca8854339d25588.tar.gz gsoc2013-evolution-7c0c40f83317228e0a725bfb5ca8854339d25588.tar.bz2 gsoc2013-evolution-7c0c40f83317228e0a725bfb5ca8854339d25588.tar.lz gsoc2013-evolution-7c0c40f83317228e0a725bfb5ca8854339d25588.tar.xz gsoc2013-evolution-7c0c40f83317228e0a725bfb5ca8854339d25588.tar.zst gsoc2013-evolution-7c0c40f83317228e0a725bfb5ca8854339d25588.zip |
Reorder accounts by drag-and-drop.
This implements https://bugzilla.gnome.org/show_bug.cgi?id=663527#c3.
Account reordering is now done by drag-and-drop instead of up/down
buttons.
Turned out to be a wee bit more complicated than I initially thought.
This scraps EAccountManager and EAccountTreeView and replaces them with
new classes centered around EMailAccountStore, which EMailSession owns.
EMailAccountStore is the model behind the account list in Preferences.
The folder tree model now uses it to sort its own top-level rows using
gtk_tree_path_compare(). It also broadcasts account operations through
signals so we don't have to rely so heavily on EAccountList signals,
since EAccountList is going away soon.
Also as part of this work, the e-mail-local.h and e-mail-store.h APIs
have been merged into EMailSession and MailFolderCache.
60 files changed, 4263 insertions, 4254 deletions
diff --git a/capplet/settings/mail-capplet-shell.c b/capplet/settings/mail-capplet-shell.c index 2bf464c7c0..707efe3f35 100644 --- a/capplet/settings/mail-capplet-shell.c +++ b/capplet/settings/mail-capplet-shell.c @@ -40,7 +40,6 @@ #include <mail/em-composer-utils.h> #include <mail/mail-config.h> #include <mail/mail-mt.h> -#include <mail/e-mail-store.h> #include <shell/e-shell.h> @@ -208,7 +207,6 @@ mail_capplet_shell_construct (MailCappletShell *shell, GtkStyle *style = gtk_widget_get_default_style (); EShell *eshell; EMailSession *session; - gchar *custom_dir; gtk_window_set_icon_name ((GtkWindow *)shell, "evolution"); gtk_window_set_title ((GtkWindow *)shell, _("Evolution account assistant")); @@ -277,9 +275,6 @@ mail_capplet_shell_construct (MailCappletShell *shell, mail_config_init (session); mail_msg_init (); - custom_dir = g_build_filename (e_get_user_data_dir (), "mail", NULL); - e_mail_store_init (session, custom_dir); - g_free (custom_dir); if (just_druid) { MailViewChild *mc; diff --git a/e-util/e-marshal.list b/e-util/e-marshal.list index 884886c83f..6d3c1fcdb0 100644 --- a/e-util/e-marshal.list +++ b/e-util/e-marshal.list @@ -7,6 +7,7 @@ BOOLEAN:INT,POINTER,INT,BOXED BOOLEAN:INT,POINTER,INT,OBJECT,INT,INT,UINT BOOLEAN:NONE BOOLEAN:OBJECT +BOOLEAN:OBJECT,OBJECT BOOLEAN:OBJECT,DOUBLE,DOUBLE,BOOLEAN BOOLEAN:POINTER BOOLEAN:POINTER,BOOLEAN,POINTER diff --git a/mail/Makefile.am b/mail/Makefile.am index 0859c55c06..8310cff129 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -46,6 +46,9 @@ libevolution_mail_la_CPPFLAGS = \ mailinclude_HEADERS = \ e-mail.h \ + e-mail-account-manager.h \ + e-mail-account-store.h \ + e-mail-account-tree-view.h \ e-mail-attachment-bar.h \ e-mail-backend.h \ e-mail-browser.h \ @@ -61,7 +64,6 @@ mailinclude_HEADERS = \ e-mail-label-list-store.h \ e-mail-label-manager.h \ e-mail-label-tree-view.h \ - e-mail-local.h \ e-mail-message-pane.h \ e-mail-migrate.h \ e-mail-notebook-view.h \ @@ -72,7 +74,6 @@ mailinclude_HEADERS = \ e-mail-session.h \ e-mail-sidebar.h \ e-mail-store-utils.h \ - e-mail-store.h \ e-mail-tag-editor.h \ e-mail-view.h \ em-account-editor.h \ @@ -121,6 +122,9 @@ mailinclude_HEADERS += \ endif libevolution_mail_la_SOURCES = \ + e-mail-account-manager.c \ + e-mail-account-store.c \ + e-mail-account-tree-view.c \ e-mail-attachment-bar.c \ e-mail-backend.c \ e-mail-browser.c \ @@ -135,7 +139,6 @@ libevolution_mail_la_SOURCES = \ e-mail-label-list-store.c \ e-mail-label-manager.c \ e-mail-label-tree-view.c \ - e-mail-local.c \ e-mail-message-pane.c \ e-mail-migrate.c \ e-mail-notebook-view.c \ @@ -146,7 +149,6 @@ libevolution_mail_la_SOURCES = \ e-mail-session.c \ e-mail-sidebar.c \ e-mail-store-utils.c \ - e-mail-store.c \ e-mail-tag-editor.c \ e-mail-view.c \ em-account-editor.c \ diff --git a/mail/e-mail-account-manager.c b/mail/e-mail-account-manager.c new file mode 100644 index 0000000000..97a4fe3fe0 --- /dev/null +++ b/mail/e-mail-account-manager.c @@ -0,0 +1,565 @@ +/* + * e-mail-account-manager.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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/> + * + */ + +#include "e-mail-account-manager.h" + +#include <config.h> +#include <glib/gi18n-lib.h> +#include <gdk/gdkkeysyms.h> + +#include <mail/e-mail-account-tree-view.h> + +#define E_MAIL_ACCOUNT_MANAGER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManagerPrivate)) + +#define DEFAULT_ORDER_RESPONSE GTK_RESPONSE_APPLY + +struct _EMailAccountManagerPrivate { + EMailAccountStore *store; + gulong row_changed_handler_id; + + GtkWidget *tree_view; /* not referenced */ + GtkWidget *add_button; /* not referenced */ + GtkWidget *edit_button; /* not referenced */ + GtkWidget *delete_button; /* not referenced */ + GtkWidget *default_button; /* not referenced */ +}; + +enum { + PROP_0, + PROP_STORE +}; + +enum { + ADD_ACCOUNT, + EDIT_ACCOUNT, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_TYPE ( + EMailAccountManager, + e_mail_account_manager, + GTK_TYPE_TABLE) + +static void +mail_account_manager_add_cb (EMailAccountManager *manager) +{ + e_mail_account_manager_add_account (manager); +} + +static void +mail_account_manager_edit_cb (EMailAccountManager *manager) +{ + EMailAccountTreeView *tree_view; + EAccount *account; + CamelService *service; + const gchar *uid; + + tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view); + service = e_mail_account_tree_view_get_selected_service (tree_view); + + uid = camel_service_get_uid (service); + account = e_get_account_by_uid (uid); + g_return_if_fail (account != NULL); + + e_mail_account_manager_edit_account (manager, account); +} + +static void +mail_account_manager_remove_cb (EMailAccountManager *manager) +{ + EMailAccountTreeView *tree_view; + EMailAccountStore *store; + CamelService *service; + gpointer parent; + + tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view); + service = e_mail_account_tree_view_get_selected_service (tree_view); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); + parent = gtk_widget_is_toplevel (parent) ? parent : NULL; + + store = e_mail_account_manager_get_store (manager); + e_mail_account_store_remove_service (store, parent, service); +} + +static void +mail_account_manager_enable_cb (EMailAccountManager *manager) +{ + EMailAccountTreeView *tree_view; + EMailAccountStore *store; + CamelService *service; + gpointer parent; + + tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view); + service = e_mail_account_tree_view_get_selected_service (tree_view); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); + parent = gtk_widget_is_toplevel (parent) ? parent : NULL; + + store = e_mail_account_manager_get_store (manager); + e_mail_account_store_enable_service (store, parent, service); +} + +static void +mail_account_manager_disable_cb (EMailAccountManager *manager) +{ + EMailAccountTreeView *tree_view; + EMailAccountStore *store; + CamelService *service; + gpointer parent; + + tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view); + service = e_mail_account_tree_view_get_selected_service (tree_view); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); + parent = gtk_widget_is_toplevel (parent) ? parent : NULL; + + store = e_mail_account_manager_get_store (manager); + e_mail_account_store_disable_service (store, parent, service); +} + +static void +mail_account_manager_default_cb (EMailAccountManager *manager) +{ + EMailAccountTreeView *tree_view; + EMailAccountStore *store; + CamelService *service; + + tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view); + service = e_mail_account_tree_view_get_selected_service (tree_view); + + store = e_mail_account_manager_get_store (manager); + e_mail_account_store_set_default_service (store, service); +} + +static void +mail_account_manager_info_bar_response_cb (EMailAccountManager *manager, + gint response) +{ + EMailAccountStore *store; + + store = e_mail_account_manager_get_store (manager); + + if (response == DEFAULT_ORDER_RESPONSE) + e_mail_account_store_reorder_services (store, NULL); +} + +static gboolean +mail_account_manager_key_press_event_cb (EMailAccountManager *manager, + GdkEventKey *event) +{ + if (event->keyval == GDK_KEY_Delete) { + mail_account_manager_remove_cb (manager); + return TRUE; + } + + return FALSE; +} + +static void +mail_account_manager_row_changed_cb (GtkTreeModel *tree_model, + GtkTreePath *path, + GtkTreeIter *iter, + EMailAccountManager *manager) +{ + GtkTreeView *tree_view; + GtkTreeSelection *selection; + + tree_view = GTK_TREE_VIEW (manager->priv->tree_view); + selection = gtk_tree_view_get_selection (tree_view); + + /* Update buttons for the selected row (which is not + * necessarily the row that changed, but do it anyway). */ + g_signal_emit_by_name (selection, "changed"); +} + +static void +mail_account_manager_selection_changed_cb (EMailAccountManager *manager, + GtkTreeSelection *selection) +{ + GtkTreeModel *tree_model; + GtkTreeIter iter; + EMailAccountStore *store; + CamelService *default_service; + CamelService *service; + GtkWidget *add_button; + GtkWidget *edit_button; + GtkWidget *delete_button; + GtkWidget *default_button; + gboolean builtin; + gboolean sensitive; + gboolean not_default; + + add_button = manager->priv->add_button; + edit_button = manager->priv->edit_button; + delete_button = manager->priv->delete_button; + default_button = manager->priv->default_button; + + if (gtk_tree_selection_get_selected (selection, &tree_model, &iter)) { + gtk_tree_model_get ( + tree_model, &iter, + E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, &service, + E_MAIL_ACCOUNT_STORE_COLUMN_BUILTIN, &builtin, + -1); + } else { + service = NULL; + builtin = FALSE; + } + + store = e_mail_account_manager_get_store (manager); + default_service = e_mail_account_store_get_default_service (store); + not_default = (service != default_service); + + if (service == NULL) + gtk_widget_grab_focus (add_button); + + sensitive = (service != NULL && !builtin); + gtk_widget_set_sensitive (edit_button, sensitive); + + sensitive = (service != NULL && !builtin); + gtk_widget_set_sensitive (delete_button, sensitive); + + sensitive = (service != NULL && !builtin && not_default); + gtk_widget_set_sensitive (default_button, sensitive); +} + +static void +mail_account_manager_set_store (EMailAccountManager *manager, + EMailAccountStore *store) +{ + g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store)); + g_return_if_fail (manager->priv->store == NULL); + + manager->priv->store = g_object_ref (store); +} + +static void +mail_account_manager_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_STORE: + mail_account_manager_set_store ( + E_MAIL_ACCOUNT_MANAGER (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_account_manager_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_STORE: + g_value_set_object ( + value, + e_mail_account_manager_get_store ( + E_MAIL_ACCOUNT_MANAGER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_account_manager_dispose (GObject *object) +{ + EMailAccountManagerPrivate *priv; + + priv = E_MAIL_ACCOUNT_MANAGER_GET_PRIVATE (object); + + if (priv->store != NULL) { + g_signal_handler_disconnect ( + priv->store, priv->row_changed_handler_id); + g_object_unref (priv->store); + priv->store = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_account_manager_parent_class)->dispose (object); +} + +static void +mail_account_manager_constructed (GObject *object) +{ + EMailAccountManager *manager; + EMailAccountStore *store; + GtkTreeSelection *selection; + GtkWidget *container; + GtkWidget *widget; + gulong handler_id; + + manager = E_MAIL_ACCOUNT_MANAGER (object); + store = e_mail_account_manager_get_store (manager); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_account_manager_parent_class)-> + constructed (object); + + g_object_bind_property ( + store, "busy", + manager, "sensitive", + G_BINDING_SYNC_CREATE | + G_BINDING_INVERT_BOOLEAN); + + handler_id = g_signal_connect ( + store, "row-changed", + G_CALLBACK (mail_account_manager_row_changed_cb), + manager); + + /* We disconnect the handler in dispose(). */ + manager->priv->row_changed_handler_id = handler_id; + + gtk_table_resize (GTK_TABLE (manager), 2, 2); + gtk_table_set_col_spacings (GTK_TABLE (manager), 6); + gtk_table_set_row_spacings (GTK_TABLE (manager), 0); + + container = GTK_WIDGET (manager); + + 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_table_attach ( + GTK_TABLE (container), widget, 0, 1, 0, 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_widget_show (widget); + + container = widget; + + widget = e_mail_account_tree_view_new (store); + gtk_container_add (GTK_CONTAINER (container), widget); + manager->priv->tree_view = widget; /* not referenced */ + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "enable", + G_CALLBACK (mail_account_manager_enable_cb), manager); + + g_signal_connect_swapped ( + widget, "disable", + G_CALLBACK (mail_account_manager_disable_cb), manager); + + g_signal_connect_swapped ( + widget, "key-press-event", + G_CALLBACK (mail_account_manager_key_press_event_cb), + manager); + + g_signal_connect_swapped ( + widget, "row-activated", + G_CALLBACK (mail_account_manager_edit_cb), manager); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)); + + g_signal_connect_swapped ( + selection, "changed", + G_CALLBACK (mail_account_manager_selection_changed_cb), + manager); + + container = GTK_WIDGET (manager); + + widget = gtk_frame_new (NULL); + gtk_frame_set_shadow_type ( + GTK_FRAME (widget), GTK_SHADOW_IN); + gtk_table_attach ( + GTK_TABLE (container), widget, + 0, 1, 1, 2, GTK_FILL, 0, 0, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_info_bar_new (); + gtk_info_bar_set_message_type ( + GTK_INFO_BAR (widget), GTK_MESSAGE_INFO); + gtk_info_bar_add_button ( + GTK_INFO_BAR (widget), + _("_Restore Default"), + DEFAULT_ORDER_RESPONSE); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "response", + G_CALLBACK (mail_account_manager_info_bar_response_cb), + manager); + + container = gtk_info_bar_get_content_area (GTK_INFO_BAR (widget)); + + widget = gtk_label_new ( + _("You can drag and drop account names to reorder them.")); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + gtk_widget_show (widget); + + container = GTK_WIDGET (manager); + + widget = gtk_vbutton_box_new (); + gtk_button_box_set_layout ( + GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START); + gtk_box_set_spacing (GTK_BOX (widget), 6); + gtk_table_attach ( + GTK_TABLE (container), widget, + 1, 2, 0, 2, 0, GTK_FILL, 0, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_button_new_from_stock (GTK_STOCK_ADD); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->add_button = widget; /* not referenced */ + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (mail_account_manager_add_cb), manager); + + widget = gtk_button_new_from_stock (GTK_STOCK_EDIT); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->edit_button = widget; /* not referenced */ + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (mail_account_manager_edit_cb), manager); + + widget = gtk_button_new_from_stock (GTK_STOCK_DELETE); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->delete_button = widget; /* not referenced */ + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (mail_account_manager_remove_cb), manager); + + widget = gtk_button_new_with_mnemonic (_("De_fault")); + gtk_button_set_image ( + GTK_BUTTON (widget), + gtk_image_new_from_icon_name ( + "emblem-default", GTK_ICON_SIZE_BUTTON)); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->default_button = widget; /* not referenced */ + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (mail_account_manager_default_cb), manager); + + /* Initialize button states. */ + g_signal_emit_by_name (selection, "changed"); +} + +static void +e_mail_account_manager_class_init (EMailAccountManagerClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EMailAccountManagerPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_account_manager_set_property; + object_class->get_property = mail_account_manager_get_property; + object_class->dispose = mail_account_manager_dispose; + object_class->constructed = mail_account_manager_constructed; + + g_object_class_install_property ( + object_class, + PROP_STORE, + g_param_spec_object ( + "store", + "Store", + NULL, + E_TYPE_MAIL_ACCOUNT_STORE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + signals[ADD_ACCOUNT] = g_signal_new ( + "add-account", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountManagerClass, add_account), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[EDIT_ACCOUNT] = g_signal_new ( + "edit-account", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountManagerClass, edit_account), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_ACCOUNT); +} + +static void +e_mail_account_manager_init (EMailAccountManager *manager) +{ + manager->priv = E_MAIL_ACCOUNT_MANAGER_GET_PRIVATE (manager); +} + +GtkWidget * +e_mail_account_manager_new (EMailAccountStore *store) +{ + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), NULL); + + return g_object_new ( + E_TYPE_MAIL_ACCOUNT_MANAGER, + "store", store, NULL); +} + +EMailAccountStore * +e_mail_account_manager_get_store (EMailAccountManager *manager) +{ + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager), NULL); + + return manager->priv->store; +} + +void +e_mail_account_manager_add_account (EMailAccountManager *manager) +{ + g_return_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager)); + + g_signal_emit (manager, signals[ADD_ACCOUNT], 0); +} + +void +e_mail_account_manager_edit_account (EMailAccountManager *manager, + EAccount *account) +{ + g_return_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager)); + g_return_if_fail (E_IS_ACCOUNT (account)); + + g_signal_emit (manager, signals[EDIT_ACCOUNT], 0, account); +} + diff --git a/mail/e-mail-account-manager.h b/mail/e-mail-account-manager.h new file mode 100644 index 0000000000..23f7890500 --- /dev/null +++ b/mail/e-mail-account-manager.h @@ -0,0 +1,78 @@ +/* + * e-mail-account-manager.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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/> + * + */ + +#ifndef E_MAIL_ACCOUNT_MANAGER_H +#define E_MAIL_ACCOUNT_MANAGER_H + +#include <gtk/gtk.h> +#include <e-util/e-account-utils.h> +#include <mail/e-mail-account-store.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_ACCOUNT_MANAGER \ + (e_mail_account_manager_get_type ()) +#define E_MAIL_ACCOUNT_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManager)) +#define E_MAIL_ACCOUNT_MANAGER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManagerClass)) +#define E_IS_MAIL_ACCOUNT_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_ACCOUNT_MANAGER)) +#define E_IS_MAIL_ACCOUNT_MANAGER_CLASS(cls) \ + (G_TYPE_CHECK_INSTANCE_CLASS \ + ((cls), E_TYPE_MAIL_ACCOUNT_MANAGER)) +#define E_MAIL_ACCOUNT_MANAGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManagerClass)) + +G_BEGIN_DECLS + +typedef struct _EMailAccountManager EMailAccountManager; +typedef struct _EMailAccountManagerClass EMailAccountManagerClass; +typedef struct _EMailAccountManagerPrivate EMailAccountManagerPrivate; + +struct _EMailAccountManager { + GtkTable parent; + EMailAccountManagerPrivate *priv; +}; + +struct _EMailAccountManagerClass { + GtkTableClass parent_class; + + /* Signals */ + void (*add_account) (EMailAccountManager *manager); + void (*edit_account) (EMailAccountManager *manager, + EAccount *account); +}; + +GType e_mail_account_manager_get_type (void) G_GNUC_CONST; +GtkWidget * e_mail_account_manager_new (EMailAccountStore *store); +EMailAccountStore * + e_mail_account_manager_get_store + (EMailAccountManager *manager); +void e_mail_account_manager_add_account + (EMailAccountManager *manager); +void e_mail_account_manager_edit_account + (EMailAccountManager *manager, + EAccount *account); + +G_END_DECLS + +#endif /* E_MAIL_ACCOUNT_MANAGER_H */ diff --git a/mail/e-mail-account-store.c b/mail/e-mail-account-store.c new file mode 100644 index 0000000000..ccfbe3b879 --- /dev/null +++ b/mail/e-mail-account-store.c @@ -0,0 +1,1439 @@ +/* + * e-mail-account-store.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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/> + * + */ + +#include "e-mail-account-store.h" + +#include <config.h> +#include <glib/gstdio.h> +#include <glib/gi18n-lib.h> + +#include <libebackend/e-extensible.h> + +#include <e-util/e-marshal.h> +#include <e-util/e-account-utils.h> +#include <e-util/e-alert-dialog.h> +#include <mail/mail-ops.h> +#include <mail/mail-vfolder.h> + +#define E_MAIL_ACCOUNT_STORE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_ACCOUNT_STORE, EMailAccountStorePrivate)) + +typedef struct _IndexItem IndexItem; + +struct _EMailAccountStorePrivate { + CamelService *default_service; + GHashTable *service_index; + gchar *sort_order_filename; + gboolean express_mode; + gpointer session; /* weak pointer */ + guint busy_count; +}; + +struct _IndexItem { + CamelService *service; + GtkTreeRowReference *reference; + gulong notify_handler_id; +}; + +enum { + PROP_0, + PROP_BUSY, + PROP_DEFAULT_SERVICE, + PROP_EXPRESS_MODE, + PROP_SESSION +}; + +enum { + SERVICE_ADDED, + SERVICE_REMOVED, + SERVICE_ENABLED, + SERVICE_DISABLED, + SERVICES_REORDERED, + REMOVE_REQUESTED, + ENABLE_REQUESTED, + DISABLE_REQUESTED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +/* Forward Declarations */ +static void e_mail_account_store_interface_init + (GtkTreeModelIface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + EMailAccountStore, + e_mail_account_store, + GTK_TYPE_LIST_STORE, + G_IMPLEMENT_INTERFACE ( + GTK_TYPE_TREE_MODEL, + e_mail_account_store_interface_init) + G_IMPLEMENT_INTERFACE ( + E_TYPE_EXTENSIBLE, NULL)) + +static void +index_item_free (IndexItem *item) +{ + g_signal_handler_disconnect ( + item->service, item->notify_handler_id); + + g_object_unref (item->service); + gtk_tree_row_reference_free (item->reference); + + g_slice_free (IndexItem, item); +} + +static void +mail_account_store_save_default (EMailAccountStore *store) +{ + EAccountList *account_list; + EAccount *account; + CamelService *service; + const gchar *uid; + + service = e_mail_account_store_get_default_service (store); + + account_list = e_get_account_list (); + uid = camel_service_get_uid (service); + account = e_get_account_by_uid (uid); + g_return_if_fail (account != NULL); + + e_account_list_set_default (account_list, account); +} + +static gboolean +mail_account_store_get_iter (EMailAccountStore *store, + CamelService *service, + GtkTreeIter *iter) +{ + IndexItem *item; + GtkTreeModel *model; + GtkTreePath *path; + gboolean iter_set; + + g_return_val_if_fail (service != NULL, FALSE); + + item = g_hash_table_lookup (store->priv->service_index, service); + + if (item == NULL) + return FALSE; + + if (!gtk_tree_row_reference_valid (item->reference)) + return FALSE; + + model = gtk_tree_row_reference_get_model (item->reference); + path = gtk_tree_row_reference_get_path (item->reference); + iter_set = gtk_tree_model_get_iter (model, iter, path); + gtk_tree_path_free (path); + + return iter_set; +} + +static gint +mail_account_store_default_compare (CamelService *service_a, + CamelService *service_b, + EMailAccountStore *store) +{ + const gchar *display_name_a; + const gchar *display_name_b; + const gchar *uid_a; + const gchar *uid_b; + + uid_a = camel_service_get_uid (service_a); + uid_b = camel_service_get_uid (service_b); + + /* Check for special cases first. */ + + if (e_mail_account_store_get_express_mode (store)) { + if (g_str_equal (uid_a, E_MAIL_SESSION_LOCAL_UID) && + g_str_equal (uid_b, E_MAIL_SESSION_VFOLDER_UID)) + return -1; + else if (g_str_equal (uid_b, E_MAIL_SESSION_LOCAL_UID) && + g_str_equal (uid_a, E_MAIL_SESSION_VFOLDER_UID)) + return 1; + else if (g_str_equal (uid_a, E_MAIL_SESSION_LOCAL_UID)) + return 1; + else if (g_str_equal (uid_b, E_MAIL_SESSION_LOCAL_UID)) + return -1; + else if (g_str_equal (uid_a, E_MAIL_SESSION_VFOLDER_UID)) + return 1; + else if (g_str_equal (uid_a, E_MAIL_SESSION_VFOLDER_UID)) + return -1; + } else { + if (g_str_equal (uid_a, E_MAIL_SESSION_LOCAL_UID)) + return -1; + else if (g_str_equal (uid_b, E_MAIL_SESSION_LOCAL_UID)) + return 1; + else if (g_str_equal (uid_a, E_MAIL_SESSION_VFOLDER_UID)) + return 1; + else if (g_str_equal (uid_b, E_MAIL_SESSION_VFOLDER_UID)) + return -1; + } + + /* Otherwise sort them alphabetically. */ + + display_name_a = camel_service_get_display_name (service_a); + display_name_b = camel_service_get_display_name (service_b); + + if (display_name_a == NULL) + display_name_a = ""; + + if (display_name_b == NULL) + display_name_b = ""; + + return g_utf8_collate (display_name_a, display_name_b); +} + +static void +mail_account_store_update_row (EMailAccountStore *store, + CamelService *service, + GtkTreeIter *iter) +{ + CamelProvider *provider; + gboolean is_default; + const gchar *backend_name; + const gchar *display_name; + + is_default = (service == store->priv->default_service); + display_name = camel_service_get_display_name (service); + + provider = camel_service_get_provider (service); + backend_name = (provider != NULL) ? provider->protocol : NULL; + + gtk_list_store_set ( + GTK_LIST_STORE (store), iter, + E_MAIL_ACCOUNT_STORE_COLUMN_DEFAULT, is_default, + E_MAIL_ACCOUNT_STORE_COLUMN_BACKEND_NAME, backend_name, + E_MAIL_ACCOUNT_STORE_COLUMN_DISPLAY_NAME, display_name, + -1); +} + +static void +mail_account_store_service_notify_cb (CamelService *service, + GParamSpec *pspec, + EMailAccountStore *store) +{ + GtkTreeIter iter; + + if (mail_account_store_get_iter (store, service, &iter)) + mail_account_store_update_row (store, service, &iter); +} + +static void +mail_account_store_clean_index (EMailAccountStore *store) +{ + GQueue trash = G_QUEUE_INIT; + GHashTable *hash_table; + GHashTableIter iter; + gpointer key, value; + + hash_table = store->priv->service_index; + g_hash_table_iter_init (&iter, hash_table); + + /* Remove index items with invalid GtkTreeRowReferences. */ + + while (g_hash_table_iter_next (&iter, &key, &value)) { + IndexItem *item = value; + + if (!gtk_tree_row_reference_valid (item->reference)) + g_queue_push_tail (&trash, key); + } + + while ((key = g_queue_pop_head (&trash)) != NULL) + g_hash_table_remove (hash_table, key); +} + +static void +mail_account_store_update_index (EMailAccountStore *store, + GtkTreePath *path, + GtkTreeIter *iter) +{ + CamelService *service = NULL; + GHashTable *hash_table; + GtkTreeModel *model; + IndexItem *item; + + model = GTK_TREE_MODEL (store); + hash_table = store->priv->service_index; + + gtk_tree_model_get ( + model, iter, + E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, &service, -1); + + if (service == NULL) + return; + + item = g_hash_table_lookup (hash_table, service); + + if (item == NULL) { + item = g_slice_new0 (IndexItem); + item->service = g_object_ref (service); + + item->notify_handler_id = g_signal_connect ( + service, "notify", G_CALLBACK ( + mail_account_store_service_notify_cb), store); + + g_hash_table_insert (hash_table, item->service, item); + } + + /* Update the row reference so the IndexItem will survive + * drag-and-drop (new row is inserted, old row is deleted). */ + gtk_tree_row_reference_free (item->reference); + item->reference = gtk_tree_row_reference_new (model, path); + + g_object_unref (service); +} + +static void +mail_account_store_set_session (EMailAccountStore *store, + EMailSession *session) +{ + g_return_if_fail (E_IS_MAIL_SESSION (session)); + g_return_if_fail (store->priv->session == NULL); + + store->priv->session = session; + + g_object_add_weak_pointer ( + G_OBJECT (store->priv->session), + &store->priv->session); +} + +static void +mail_account_store_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_DEFAULT_SERVICE: + e_mail_account_store_set_default_service ( + E_MAIL_ACCOUNT_STORE (object), + g_value_get_object (value)); + return; + + case PROP_EXPRESS_MODE: + e_mail_account_store_set_express_mode ( + E_MAIL_ACCOUNT_STORE (object), + g_value_get_boolean (value)); + return; + + case PROP_SESSION: + mail_account_store_set_session ( + E_MAIL_ACCOUNT_STORE (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_account_store_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_BUSY: + g_value_set_boolean ( + value, + e_mail_account_store_get_busy ( + E_MAIL_ACCOUNT_STORE (object))); + return; + + case PROP_DEFAULT_SERVICE: + g_value_set_object ( + value, + e_mail_account_store_get_default_service ( + E_MAIL_ACCOUNT_STORE (object))); + return; + + case PROP_EXPRESS_MODE: + g_value_set_boolean ( + value, + e_mail_account_store_get_express_mode ( + E_MAIL_ACCOUNT_STORE (object))); + return; + + case PROP_SESSION: + g_value_set_object ( + value, + e_mail_account_store_get_session ( + E_MAIL_ACCOUNT_STORE (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_account_store_dispose (GObject *object) +{ + EMailAccountStorePrivate *priv; + + priv = E_MAIL_ACCOUNT_STORE_GET_PRIVATE (object); + + if (priv->session != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->session), &priv->session); + priv->session = NULL; + } + + if (priv->default_service != NULL) { + g_object_unref (priv->default_service); + priv->default_service = NULL; + } + + g_hash_table_remove_all (priv->service_index); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_account_store_parent_class)->dispose (object); +} + +static void +mail_account_store_finalize (GObject *object) +{ + EMailAccountStorePrivate *priv; + + priv = E_MAIL_ACCOUNT_STORE_GET_PRIVATE (object); + + g_warn_if_fail (priv->busy_count == 0); + g_hash_table_destroy (priv->service_index); + g_free (priv->sort_order_filename); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_mail_account_store_parent_class)->finalize (object); +} + +static void +mail_account_store_constructed (GObject *object) +{ + EMailAccountStore *store; + const gchar *config_dir; + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_account_store_parent_class)->constructed (object); + + store = E_MAIL_ACCOUNT_STORE (object); + config_dir = mail_session_get_config_dir (); + + /* XXX Should we take the filename as a constructor property? */ + store->priv->sort_order_filename = g_build_filename ( + config_dir, "sortorder.ini", NULL); + + /* XXX This is kinda lame, but should work until EAccount dies. */ + g_signal_connect ( + object, "notify::default-service", + G_CALLBACK (mail_account_store_save_default), NULL); + + e_extensible_load_extensions (E_EXTENSIBLE (object)); +} + +static void +mail_account_store_service_added (EMailAccountStore *store, + CamelService *service) +{ + /* Placeholder so subclasses can safely chain up. */ +} + +static void +mail_account_store_service_removed (EMailAccountStore *store, + CamelService *service) +{ + /* XXX On the account-mgmt branch this operation is asynchronous. + * The 'busy_count' is bumped until changes are written back + * to the D-Bus service. For now I guess we'll just block. */ + + EAccountList *account_list; + EAccount *account; + const gchar *uid; + + account_list = e_get_account_list (); + uid = camel_service_get_uid (service); + account = e_get_account_by_uid (uid); + g_return_if_fail (account != NULL); + + if (account->enabled) { + CamelProvider *provider; + + provider = camel_service_get_provider (service); + g_return_if_fail (provider != NULL); + + if (provider->flags & CAMEL_PROVIDER_IS_STORAGE) + mail_disconnect_store (CAMEL_STORE (service)); + } + + /* Remove all the proxies the account has created. + * FIXME This proxy stuff belongs in evolution-groupwise. */ + e_account_list_remove_account_proxies (account_list, account); + + e_account_list_remove (account_list, account); + + e_account_list_save (account_list); +} + +static void +mail_account_store_service_enabled (EMailAccountStore *store, + CamelService *service) +{ + /* XXX On the account-mgmt branch this operation is asynchronous. + * The 'busy_count' is bumped until changes are written back + * to the D-Bus service. For now I guess we'll just block. */ + + GSettings *settings; + const gchar *uid; + + uid = camel_service_get_uid (service); + + /* Handle built-in services that don't have an EAccount. */ + + if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0) { + settings = g_settings_new ("org.gnome.evolution.mail"); + g_settings_set_boolean (settings, "enable-local", TRUE); + g_object_unref (settings); + + } else if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0) { + settings = g_settings_new ("org.gnome.evolution.mail"); + g_settings_set_boolean (settings, "enable-vfolders", TRUE); + g_object_unref (settings); + + } else { + EAccountList *account_list; + EAccount *account; + + account_list = e_get_account_list (); + account = e_get_account_by_uid (uid); + g_return_if_fail (account != NULL); + + account->enabled = TRUE; + + e_account_list_change (account_list, account); + e_account_list_save (account_list); + } +} + +static void +mail_account_store_service_disabled (EMailAccountStore *store, + CamelService *service) +{ + /* XXX On the account-mgmt branch this operation is asynchronous. + * The 'busy_count' is bumped until changes are written back + * to the D-Bus service. For now I guess we'll just block. */ + + GSettings *settings; + const gchar *uid; + + uid = camel_service_get_uid (service); + + /* Handle built-in services that don't have an EAccount. */ + + if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0) { + settings = g_settings_new ("org.gnome.evolution.mail"); + g_settings_set_boolean (settings, "enable-local", FALSE); + g_object_unref (settings); + + } else if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0) { + settings = g_settings_new ("org.gnome.evolution.mail"); + g_settings_set_boolean (settings, "enable-vfolders", FALSE); + g_object_unref (settings); + + } else { + EAccountList *account_list; + EAccount *account; + CamelProvider *provider; + + account_list = e_get_account_list (); + account = e_get_account_by_uid (uid); + g_return_if_fail (account != NULL); + + account->enabled = FALSE; + + provider = camel_service_get_provider (service); + g_return_if_fail (provider != NULL); + + if (provider->flags & CAMEL_PROVIDER_IS_STORAGE) + mail_disconnect_store (CAMEL_STORE (service)); + + /* FIXME This proxy stuff belongs in evolution-groupwise. */ + e_account_list_remove_account_proxies (account_list, account); + + if (account->parent_uid != NULL) + e_account_list_remove (account_list, account); + + e_account_list_change (account_list, account); + e_account_list_save (account_list); + } +} + +static void +mail_account_store_services_reordered (EMailAccountStore *store, + gboolean default_restored) +{ + /* XXX Should this be made asynchronous? */ + + GError *error = NULL; + + if (default_restored) { + const gchar *filename; + + filename = store->priv->sort_order_filename; + + if (g_file_test (filename, G_FILE_TEST_EXISTS)) + g_unlink (filename); + + return; + } + + if (!e_mail_account_store_save_sort_order (store, &error)) { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + } +} + +static gboolean +mail_account_store_remove_requested (EMailAccountStore *store, + GtkWindow *parent_window, + CamelService *service) +{ + EAccountList *account_list; + EAccount *account; + const gchar *alert; + const gchar *uid; + gint response; + + account_list = e_get_account_list (); + uid = camel_service_get_uid (service); + account = e_get_account_by_uid (uid); + + g_return_val_if_fail (account != NULL, FALSE); + + /* FIXME This proxy stuff belongs in evolution-groupwise. */ + if (e_account_list_account_has_proxies (account_list, account)) + alert = "mail:ask-delete-account-with-proxies"; + else + alert = "mail:ask-delete-account"; + + response = e_alert_run_dialog_for_args (parent_window, alert, NULL); + + return (response == GTK_RESPONSE_YES); +} + +static gboolean +mail_account_store_enable_requested (EMailAccountStore *store, + GtkWindow *parent_window, + CamelService *service) +{ + return TRUE; +} + +static gboolean +mail_account_store_disable_requested (EMailAccountStore *store, + GtkWindow *parent_window, + CamelService *service) +{ + EAccountList *account_list; + EAccount *account; + const gchar *uid; + gint response; + + account_list = e_get_account_list (); + uid = camel_service_get_uid (service); + account = e_get_account_by_uid (uid); + + /* "On This Computer" and "Search Folders" do not have + * EAccounts, so just silently return TRUE if we failed + * to find a matching EAccount for the CamelService. */ + + /* Silently return TRUE if we failed to find a matching + * EAccount since "On This Computer" and "Search Folders" + * do not have EAccounts. */ + if (account == NULL) + return TRUE; + + /* FIXME This proxy stuff belongs in evolution-groupwise. */ + if (e_account_list_account_has_proxies (account_list, account)) + response = e_alert_run_dialog_for_args ( + parent_window, + "mail:ask-delete-proxy-accounts", NULL); + else + response = GTK_RESPONSE_YES; + + return (response == GTK_RESPONSE_YES); +} + +static void +mail_account_store_row_changed (GtkTreeModel *tree_model, + GtkTreePath *path, + GtkTreeIter *iter) +{ + EMailAccountStore *store; + + /* Neither GtkTreeModel nor GtkListStore implements + * this method, so there is nothing to chain up to. */ + + store = E_MAIL_ACCOUNT_STORE (tree_model); + mail_account_store_update_index (store, path, iter); +} + +static void +mail_account_store_row_inserted (GtkTreeModel *tree_model, + GtkTreePath *path, + GtkTreeIter *iter) +{ + EMailAccountStore *store; + + /* Neither GtkTreeModel nor GtkListStore implements + * this method, so there is nothing to chain up to. */ + + store = E_MAIL_ACCOUNT_STORE (tree_model); + mail_account_store_update_index (store, path, iter); +} + +static gboolean +mail_account_store_true_proceed (GSignalInvocationHint *ihint, + GValue *return_accumulator, + const GValue *handler_return, + gpointer not_used) +{ + gboolean proceed; + + proceed = g_value_get_boolean (handler_return); + g_value_set_boolean (return_accumulator, proceed); + + return proceed; +} + +static void +e_mail_account_store_class_init (EMailAccountStoreClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EMailAccountStorePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_account_store_set_property; + object_class->get_property = mail_account_store_get_property; + object_class->dispose = mail_account_store_dispose; + object_class->finalize = mail_account_store_finalize; + object_class->constructed = mail_account_store_constructed; + + class->service_added = mail_account_store_service_added; + class->service_removed = mail_account_store_service_removed; + class->service_enabled = mail_account_store_service_enabled; + class->service_disabled = mail_account_store_service_disabled; + class->services_reordered = mail_account_store_services_reordered; + class->remove_requested = mail_account_store_remove_requested; + class->enable_requested = mail_account_store_enable_requested; + class->disable_requested = mail_account_store_disable_requested; + + g_object_class_install_property ( + object_class, + PROP_BUSY, + g_param_spec_boolean ( + "busy", + "Busy", + "Whether async operations are in progress", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_DEFAULT_SERVICE, + g_param_spec_object ( + "default-service", + "Default Service", + "Default mail store", + CAMEL_TYPE_SERVICE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_EXPRESS_MODE, + g_param_spec_boolean ( + "express-mode", + "Express Mode", + "Whether express mode is enabled", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_SESSION, + g_param_spec_object ( + "session", + "Session", + "Mail session", + E_TYPE_MAIL_SESSION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + signals[SERVICE_ADDED] = g_signal_new ( + "service-added", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountStoreClass, service_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CAMEL_TYPE_SERVICE); + + signals[SERVICE_REMOVED] = g_signal_new ( + "service-removed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountStoreClass, service_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CAMEL_TYPE_SERVICE); + + signals[SERVICE_ENABLED] = g_signal_new ( + "service-enabled", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountStoreClass, service_enabled), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CAMEL_TYPE_SERVICE); + + signals[SERVICE_DISABLED] = g_signal_new ( + "service-disabled", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountStoreClass, service_disabled), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CAMEL_TYPE_SERVICE); + + signals[SERVICES_REORDERED] = g_signal_new ( + "services-reordered", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountStoreClass, services_reordered), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, + G_TYPE_BOOLEAN); + + signals[REMOVE_REQUESTED] = g_signal_new ( + "remove-requested", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountStoreClass, remove_requested), + mail_account_store_true_proceed, NULL, + e_marshal_BOOLEAN__OBJECT_OBJECT, + G_TYPE_BOOLEAN, 2, + GTK_TYPE_WINDOW, + CAMEL_TYPE_SERVICE); + + signals[ENABLE_REQUESTED] = g_signal_new ( + "enable-requested", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountStoreClass, enable_requested), + mail_account_store_true_proceed, NULL, + e_marshal_BOOLEAN__OBJECT_OBJECT, + G_TYPE_BOOLEAN, 2, + GTK_TYPE_WINDOW, + CAMEL_TYPE_SERVICE); + + signals[DISABLE_REQUESTED] = g_signal_new ( + "disable-requested", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountStoreClass, disable_requested), + mail_account_store_true_proceed, NULL, + e_marshal_BOOLEAN__OBJECT_OBJECT, + G_TYPE_BOOLEAN, 2, + GTK_TYPE_WINDOW, + CAMEL_TYPE_SERVICE); +} + +static void +e_mail_account_store_interface_init (GtkTreeModelIface *interface) +{ + interface->row_changed = mail_account_store_row_changed; + interface->row_inserted = mail_account_store_row_inserted; +} + +static void +e_mail_account_store_init (EMailAccountStore *store) +{ + GType types[E_MAIL_ACCOUNT_STORE_NUM_COLUMNS]; + GHashTable *service_index; + gint ii = 0; + + service_index = g_hash_table_new_full ( + (GHashFunc) g_direct_hash, + (GEqualFunc) g_direct_equal, + (GDestroyNotify) NULL, + (GDestroyNotify) index_item_free); + + store->priv = E_MAIL_ACCOUNT_STORE_GET_PRIVATE (store); + store->priv->service_index = service_index; + + types[ii++] = CAMEL_TYPE_SERVICE; /* COLUMN_SERVICE */ + types[ii++] = G_TYPE_BOOLEAN; /* COLUMN_BUILTIN */ + types[ii++] = G_TYPE_BOOLEAN; /* COLUMN_ENABLED */ + types[ii++] = G_TYPE_BOOLEAN; /* COLUMN_DEFAULT */ + types[ii++] = G_TYPE_STRING; /* COLUMN_BACKEND_NAME */ + types[ii++] = G_TYPE_STRING; /* COLUMN_DISPLAY_NAME */ + + g_assert (ii == E_MAIL_ACCOUNT_STORE_NUM_COLUMNS); + + gtk_list_store_set_column_types ( + GTK_LIST_STORE (store), + G_N_ELEMENTS (types), types); +} + +EMailAccountStore * +e_mail_account_store_new (EMailSession *session) +{ + g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); + + return g_object_new ( + E_TYPE_MAIL_ACCOUNT_STORE, + "session", session, NULL); +} + +void +e_mail_account_store_clear (EMailAccountStore *store) +{ + g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store)); + + gtk_list_store_clear (GTK_LIST_STORE (store)); + g_hash_table_remove_all (store->priv->service_index); +} + +gboolean +e_mail_account_store_get_busy (EMailAccountStore *store) +{ + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), FALSE); + + return (store->priv->busy_count > 0); +} + +EMailSession * +e_mail_account_store_get_session (EMailAccountStore *store) +{ + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), NULL); + + return E_MAIL_SESSION (store->priv->session); +} + +CamelService * +e_mail_account_store_get_default_service (EMailAccountStore *store) +{ + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), NULL); + + return store->priv->default_service; +} + +void +e_mail_account_store_set_default_service (EMailAccountStore *store, + CamelService *service) +{ + GtkTreeModel *model; + GtkTreeIter iter; + gboolean iter_set; + + g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store)); + + if (service == store->priv->default_service) + return; + + if (service != NULL) { + g_return_if_fail (CAMEL_IS_SERVICE (service)); + g_object_ref (service); + } + + if (store->priv->default_service != NULL) + g_object_unref (store->priv->default_service); + + store->priv->default_service = service; + + model = GTK_TREE_MODEL (store); + iter_set = gtk_tree_model_get_iter_first (model, &iter); + + while (iter_set) { + CamelService *candidate; + + gtk_tree_model_get ( + model, &iter, + E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, + &candidate, -1); + + gtk_list_store_set ( + GTK_LIST_STORE (model), &iter, + E_MAIL_ACCOUNT_STORE_COLUMN_DEFAULT, + service == candidate, -1); + + g_object_unref (candidate); + + iter_set = gtk_tree_model_iter_next (model, &iter); + } + + g_object_notify (G_OBJECT (store), "default-service"); +} + +gboolean +e_mail_account_store_get_express_mode (EMailAccountStore *store) +{ + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), FALSE); + + return store->priv->express_mode; +} + +void +e_mail_account_store_set_express_mode (EMailAccountStore *store, + gboolean express_mode) +{ + g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store)); + + store->priv->express_mode = express_mode; + + g_object_notify (G_OBJECT (store), "express-mode"); +} + +void +e_mail_account_store_add_service (EMailAccountStore *store, + CamelService *service) +{ + GSettings *settings; + GtkTreeIter iter; + const gchar *filename; + const gchar *uid; + gboolean builtin; + gboolean enabled; + + g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store)); + g_return_if_fail (CAMEL_IS_SERVICE (service)); + + /* Avoid duplicate services in the account store. */ + if (mail_account_store_get_iter (store, service, &iter)) + g_return_if_reached (); + + uid = camel_service_get_uid (service); + + /* Handle built-in services that don't have an EAccount. */ + + if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0) { + builtin = TRUE; + + settings = g_settings_new ("org.gnome.evolution.mail"); + enabled = g_settings_get_boolean (settings, "enable-local"); + g_object_unref (settings); + + } else if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0) { + builtin = TRUE; + + settings = g_settings_new ("org.gnome.evolution.mail"); + enabled = g_settings_get_boolean (settings, "enable-vfolders"); + g_object_unref (settings); + + } else { + EAccount *account; + + account = e_get_account_by_uid (uid); + g_return_if_fail (account != NULL); + + builtin = FALSE; + enabled = account->enabled; + } + + /* Where do we insert new services now that accounts can be + * reordered? This is just a simple policy I came up with. + * It's certainly subject to debate and tweaking. + * + * Always insert new services in row 0 initially. Then test + * for the presence of the sort order file. If present, the + * user has messed around with the ordering so leave the new + * service at row 0. If not present, services are sorted in + * their default order. So re-apply the default order using + * e_mail_account_store_reorder_services(store, NULL) so the + * new service moves to its proper default position. */ + + gtk_list_store_prepend (GTK_LIST_STORE (store), &iter); + + gtk_list_store_set ( + GTK_LIST_STORE (store), &iter, + E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, service, + E_MAIL_ACCOUNT_STORE_COLUMN_BUILTIN, builtin, + E_MAIL_ACCOUNT_STORE_COLUMN_ENABLED, enabled, + -1); + + /* This populates the rest of the columns. */ + mail_account_store_update_row (store, service, &iter); + + g_signal_emit (store, signals[SERVICE_ADDED], 0, service); + + if (enabled) + g_signal_emit (store, signals[SERVICE_ENABLED], 0, service); + else + g_signal_emit (store, signals[SERVICE_DISABLED], 0, service); + + filename = store->priv->sort_order_filename; + + if (!g_file_test (filename, G_FILE_TEST_EXISTS)) + e_mail_account_store_reorder_services (store, NULL); +} + +void +e_mail_account_store_remove_service (EMailAccountStore *store, + GtkWindow *parent_window, + CamelService *service) +{ + GtkTreeIter iter; + gboolean proceed; + + g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store)); + g_return_if_fail (CAMEL_IS_SERVICE (service)); + + if (!mail_account_store_get_iter (store, service, &iter)) + g_return_if_reached (); + + /* Possibly request user confirmation. */ + g_signal_emit ( + store, signals[REMOVE_REQUESTED], 0, + parent_window, service, &proceed); + + if (proceed) { + g_object_ref (service); + + gtk_list_store_remove (GTK_LIST_STORE (store), &iter); + + mail_account_store_clean_index (store); + + g_signal_emit (store, signals[SERVICE_REMOVED], 0, service); + + g_object_unref (service); + } +} + +void +e_mail_account_store_enable_service (EMailAccountStore *store, + GtkWindow *parent_window, + CamelService *service) +{ + GtkTreeIter iter; + gboolean proceed; + + g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store)); + g_return_if_fail (CAMEL_IS_SERVICE (service)); + + if (!mail_account_store_get_iter (store, service, &iter)) + g_return_if_reached (); + + /* Possibly request user confirmation. */ + g_signal_emit ( + store, signals[ENABLE_REQUESTED], 0, + parent_window, service, &proceed); + + if (proceed) { + gtk_list_store_set ( + GTK_LIST_STORE (store), &iter, + E_MAIL_ACCOUNT_STORE_COLUMN_ENABLED, TRUE, -1); + + g_signal_emit (store, signals[SERVICE_ENABLED], 0, service); + } +} + +void +e_mail_account_store_disable_service (EMailAccountStore *store, + GtkWindow *parent_window, + CamelService *service) +{ + GtkTreeIter iter; + gboolean proceed; + + g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store)); + g_return_if_fail (CAMEL_IS_SERVICE (service)); + + if (!mail_account_store_get_iter (store, service, &iter)) + g_return_if_reached (); + + /* Possibly request user confirmation. */ + g_signal_emit ( + store, signals[DISABLE_REQUESTED], 0, + parent_window, service, &proceed); + + if (proceed) { + gtk_list_store_set ( + GTK_LIST_STORE (store), &iter, + E_MAIL_ACCOUNT_STORE_COLUMN_ENABLED, FALSE, -1); + + g_signal_emit (store, signals[SERVICE_DISABLED], 0, service); + } +} + +void +e_mail_account_store_reorder_services (EMailAccountStore *store, + GQueue *ordered_services) +{ + GQueue *current_order = NULL; + GQueue *default_order = NULL; + GtkTreeModel *tree_model; + GtkTreeIter iter; + gboolean use_default_order; + gboolean iter_set; + GList *head, *link; + gint *new_order; + gint n_children; + gint new_pos = 0; + guint length; + + g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store)); + + tree_model = GTK_TREE_MODEL (store); + n_children = gtk_tree_model_iter_n_children (tree_model, NULL); + + /* Treat NULL queues and empty queues the same. */ + if (ordered_services != NULL && g_queue_is_empty (ordered_services)) + ordered_services = NULL; + + use_default_order = (ordered_services == NULL); + + if (ordered_services != NULL) { + length = g_queue_get_length (ordered_services); + g_return_if_fail (length == n_children); + } + + current_order = g_queue_new (); + iter_set = gtk_tree_model_get_iter_first (tree_model, &iter); + + /* Build a queue of CamelServices in the order they appear in + * the list store. We'll use this to construct the mapping to + * pass to gtk_list_store_reorder(). */ + while (iter_set) { + GValue value = G_VALUE_INIT; + const gint column = E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE; + + gtk_tree_model_get_value (tree_model, &iter, column, &value); + g_queue_push_tail (current_order, g_value_get_object (&value)); + g_value_unset (&value); + + iter_set = gtk_tree_model_iter_next (tree_model, &iter); + } + + /* If a custom ordering was not given, revert to default. */ + if (use_default_order) { + default_order = g_queue_copy (current_order); + + g_queue_sort ( + default_order, (GCompareDataFunc) + mail_account_store_default_compare, store); + + ordered_services = default_order; + } + + new_order = g_new0 (gint, n_children); + head = g_queue_peek_head_link (ordered_services); + + for (link = head; link != NULL; link = g_list_next (link)) { + GList *matching_link; + gint old_pos; + + matching_link = g_queue_find (current_order, link->data); + + if (matching_link == NULL || matching_link->data == NULL) + break; + + old_pos = g_queue_link_index (current_order, matching_link); + + matching_link->data = NULL; + new_order[new_pos++] = old_pos; + } + + if (new_pos == n_children) { + gtk_list_store_reorder (GTK_LIST_STORE (store), new_order); + g_signal_emit ( + store, signals[SERVICES_REORDERED], 0, + use_default_order); + } + + g_free (new_order); + + if (current_order != NULL) + g_queue_free (current_order); + + if (default_order != NULL) + g_queue_free (default_order); +} + +gint +e_mail_account_store_compare_services (EMailAccountStore *store, + CamelService *service_a, + CamelService *service_b) +{ + GtkTreeModel *model; + GtkTreePath *path_a; + GtkTreePath *path_b; + GtkTreeIter iter_a; + GtkTreeIter iter_b; + gboolean iter_a_set; + gboolean iter_b_set; + gint result; + + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), -1); + g_return_val_if_fail (CAMEL_IS_SERVICE (service_a), -1); + g_return_val_if_fail (CAMEL_IS_SERVICE (service_b), -1); + + /* XXX This is horribly inefficient but should be + * over a small enough set to not be noticable. */ + + iter_a_set = mail_account_store_get_iter (store, service_a, &iter_a); + iter_b_set = mail_account_store_get_iter (store, service_b, &iter_b); + + if (!iter_a_set && !iter_b_set) + return 0; + + if (!iter_a_set) + return -1; + + if (!iter_b_set) + return 1; + + model = GTK_TREE_MODEL (store); + + path_a = gtk_tree_model_get_path (model, &iter_a); + path_b = gtk_tree_model_get_path (model, &iter_b); + + result = gtk_tree_path_compare (path_a, path_b); + + gtk_tree_path_free (path_a); + gtk_tree_path_free (path_b); + + return result; +} + +gboolean +e_mail_account_store_load_sort_order (EMailAccountStore *store, + GError **error) +{ + GQueue service_queue = G_QUEUE_INIT; + EMailSession *session; + GKeyFile *key_file; + const gchar *filename; + gchar **service_uids; + gboolean success = TRUE; + gsize ii, length; + + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), FALSE); + + session = e_mail_account_store_get_session (store); + + key_file = g_key_file_new (); + filename = store->priv->sort_order_filename; + + if (g_file_test (filename, G_FILE_TEST_EXISTS)) + success = g_key_file_load_from_file ( + key_file, filename, G_KEY_FILE_NONE, error); + + if (!success) { + g_key_file_free (key_file); + return FALSE; + } + + /* If the key is not present, length is set to zero. */ + service_uids = g_key_file_get_string_list ( + key_file, "Accounts", "SortOrder", &length, NULL); + + for (ii = 0; ii < length; ii++) { + CamelService *service; + + service = camel_session_get_service ( + CAMEL_SESSION (session), service_uids[ii]); + if (service != NULL) + g_queue_push_tail (&service_queue, service); + } + + e_mail_account_store_reorder_services (store, &service_queue); + + g_queue_clear (&service_queue); + g_strfreev (service_uids); + + g_key_file_free (key_file); + + return TRUE; +} + +gboolean +e_mail_account_store_save_sort_order (EMailAccountStore *store, + GError **error) +{ + GKeyFile *key_file; + GtkTreeModel *model; + GtkTreeIter iter; + const gchar **service_uids; + const gchar *filename; + gchar *contents; + gboolean iter_set; + gboolean success; + gsize length; + gsize ii = 0; + + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), FALSE); + + model = GTK_TREE_MODEL (store); + length = gtk_tree_model_iter_n_children (model, NULL); + + /* Empty store, nothing to save. */ + if (length == 0) + return TRUE; + + service_uids = g_new0 (const gchar *, length); + + iter_set = gtk_tree_model_get_iter_first (model, &iter); + + while (iter_set) { + GValue value = G_VALUE_INIT; + const gint column = E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE; + CamelService *service; + + gtk_tree_model_get_value (model, &iter, column, &value); + service = g_value_get_object (&value); + service_uids[ii++] = camel_service_get_uid (service); + g_value_unset (&value); + + iter_set = gtk_tree_model_iter_next (model, &iter); + } + + key_file = g_key_file_new (); + filename = store->priv->sort_order_filename; + + g_key_file_set_string_list ( + key_file, "Accounts", "SortOrder", service_uids, length); + + contents = g_key_file_to_data (key_file, &length, NULL); + success = g_file_set_contents (filename, contents, length, error); + g_free (contents); + + g_key_file_free (key_file); + + g_free (service_uids); + + return success; +} + diff --git a/mail/e-mail-account-store.h b/mail/e-mail-account-store.h new file mode 100644 index 0000000000..e4355da3a8 --- /dev/null +++ b/mail/e-mail-account-store.h @@ -0,0 +1,144 @@ +/* + * e-mail-account-store.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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/> + * + */ + +#ifndef E_MAIL_ACCOUNT_STORE_H +#define E_MAIL_ACCOUNT_STORE_H + +#include <gtk/gtk.h> +#include <camel/camel.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_ACCOUNT_STORE \ + (e_mail_account_store_get_type ()) +#define E_MAIL_ACCOUNT_STORE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_ACCOUNT_STORE, EMailAccountStore)) +#define E_MAIL_ACCOUNT_STORE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_ACCOUNT_STORE, EMailAccountStoreClass)) +#define E_IS_MAIL_ACCOUNT_STORE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_ACCOUNT_STORE)) +#define E_IS_MAIL_ACOCUNT_STORE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_ACCOUNT_STORE)) +#define E_MAIL_ACCOUNT_STORE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_ACCOUNT_STORE, EMailAccountStoreClass)) + +G_BEGIN_DECLS + +/* Avoid a circular dependency. */ +typedef struct _EMailSession EMailSession; + +typedef enum { + E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, + E_MAIL_ACCOUNT_STORE_COLUMN_BUILTIN, + E_MAIL_ACCOUNT_STORE_COLUMN_ENABLED, + E_MAIL_ACCOUNT_STORE_COLUMN_DEFAULT, + E_MAIL_ACCOUNT_STORE_COLUMN_BACKEND_NAME, + E_MAIL_ACCOUNT_STORE_COLUMN_DISPLAY_NAME, + E_MAIL_ACCOUNT_STORE_NUM_COLUMNS +} EMailAccountStoreColumn; + +typedef struct _EMailAccountStore EMailAccountStore; +typedef struct _EMailAccountStoreClass EMailAccountStoreClass; +typedef struct _EMailAccountStorePrivate EMailAccountStorePrivate; + +struct _EMailAccountStore { + GtkListStore parent; + EMailAccountStorePrivate *priv; +}; + +struct _EMailAccountStoreClass { + GtkListStoreClass parent_class; + + /* Signals */ + void (*service_added) (EMailAccountStore *store, + CamelService *service); + void (*service_removed) (EMailAccountStore *store, + CamelService *service); + void (*service_enabled) (EMailAccountStore *store, + CamelService *service); + void (*service_disabled) (EMailAccountStore *store, + CamelService *service); + void (*services_reordered) (EMailAccountStore *store, + gboolean default_restored); + + /* These signals are for confirmation dialogs. + * Signal handler should return FALSE to abort. */ + gboolean (*remove_requested) (EMailAccountStore *store, + GtkWindow *parent_window, + CamelService *service); + gboolean (*enable_requested) (EMailAccountStore *store, + GtkWindow *parent_window, + CamelService *service); + gboolean (*disable_requested) (EMailAccountStore *store, + GtkWindow *parent_window, + CamelService *service); +}; + +GType e_mail_account_store_get_type (void) G_GNUC_CONST; +EMailAccountStore * + e_mail_account_store_new (EMailSession *session); +void e_mail_account_store_clear (EMailAccountStore *store); +gboolean e_mail_account_store_get_busy (EMailAccountStore *store); +EMailSession * e_mail_account_store_get_session + (EMailAccountStore *store); +CamelService * e_mail_account_store_get_default_service + (EMailAccountStore *store); +void e_mail_account_store_set_default_service + (EMailAccountStore *store, + CamelService *service); +gboolean e_mail_account_store_get_express_mode + (EMailAccountStore *store); +void e_mail_account_store_set_express_mode + (EMailAccountStore *store, + gboolean express_mode); +void e_mail_account_store_add_service + (EMailAccountStore *store, + CamelService *service); +void e_mail_account_store_remove_service + (EMailAccountStore *store, + GtkWindow *parent_window, + CamelService *service); +void e_mail_account_store_enable_service + (EMailAccountStore *store, + GtkWindow *parent_window, + CamelService *service); +void e_mail_account_store_disable_service + (EMailAccountStore *store, + GtkWindow *parent_window, + CamelService *service); +void e_mail_account_store_reorder_services + (EMailAccountStore *store, + GQueue *ordered_services); +gint e_mail_account_store_compare_services + (EMailAccountStore *store, + CamelService *service_a, + CamelService *service_b); +gboolean e_mail_account_store_load_sort_order + (EMailAccountStore *store, + GError **error); +gboolean e_mail_account_store_save_sort_order + (EMailAccountStore *store, + GError **error); + +G_END_DECLS + +#endif /* E_MAIL_ACCOUNT_STORE_H */ diff --git a/mail/e-mail-account-tree-view.c b/mail/e-mail-account-tree-view.c new file mode 100644 index 0000000000..269a03d777 --- /dev/null +++ b/mail/e-mail-account-tree-view.c @@ -0,0 +1,283 @@ +/* + * e-mail-account-tree-view.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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/> + * + */ + +#include "e-mail-account-tree-view.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#define E_MAIL_ACCOUNT_TREE_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeViewPrivate)) + +struct _EMailAccountTreeViewPrivate { + gint placeholder; +}; + +enum { + ENABLE, + DISABLE, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_TYPE ( + EMailAccountTreeView, + e_mail_account_tree_view, + GTK_TYPE_TREE_VIEW) + +static void +mail_account_tree_view_enabled_toggled_cb (GtkCellRendererToggle *cell_renderer, + const gchar *path_string, + EMailAccountTreeView *tree_view) +{ + GtkTreeSelection *selection; + GtkTreePath *path; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + + /* Change the selection first so we act on the correct service. */ + path = gtk_tree_path_new_from_string (path_string); + gtk_tree_selection_select_path (selection, path); + gtk_tree_path_free (path); + + if (gtk_cell_renderer_toggle_get_active (cell_renderer)) + g_signal_emit (tree_view, signals[DISABLE], 0); + else + g_signal_emit (tree_view, signals[ENABLE], 0); +} + +static void +mail_account_tree_view_constructed (GObject *object) +{ + GtkTreeView *tree_view; + GtkTreeViewColumn *column; + GtkCellRenderer *cell_renderer; + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_account_tree_view_parent_class)-> + constructed (object); + + tree_view = GTK_TREE_VIEW (object); + + gtk_tree_view_set_reorderable (tree_view, TRUE); + + /* Column: Enabled */ + + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_expand (column, FALSE); + gtk_tree_view_column_set_title (column, _("Enabled")); + + cell_renderer = gtk_cell_renderer_toggle_new (); + gtk_tree_view_column_pack_start (column, cell_renderer, TRUE); + + g_signal_connect ( + cell_renderer, "toggled", + G_CALLBACK (mail_account_tree_view_enabled_toggled_cb), + tree_view); + + gtk_tree_view_column_add_attribute ( + column, cell_renderer, "active", + E_MAIL_ACCOUNT_STORE_COLUMN_ENABLED); + + gtk_tree_view_append_column (tree_view, column); + + /* Column: Account Name */ + + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_column_set_title (column, _("Account Name")); + + cell_renderer = gtk_cell_renderer_text_new (); + g_object_set (cell_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); + gtk_tree_view_column_pack_start (column, cell_renderer, TRUE); + + gtk_tree_view_column_add_attribute ( + column, cell_renderer, "text", + E_MAIL_ACCOUNT_STORE_COLUMN_DISPLAY_NAME); + + cell_renderer = gtk_cell_renderer_text_new (); + g_object_set (cell_renderer, "text", _("Default"), NULL); + gtk_tree_view_column_pack_end (column, cell_renderer, FALSE); + + gtk_tree_view_column_add_attribute ( + column, cell_renderer, "visible", + E_MAIL_ACCOUNT_STORE_COLUMN_DEFAULT); + + cell_renderer = gtk_cell_renderer_pixbuf_new (); + g_object_set ( + cell_renderer, "icon-name", "emblem-default", + "stock-size", GTK_ICON_SIZE_MENU, NULL); + gtk_tree_view_column_pack_end (column, cell_renderer, FALSE); + + gtk_tree_view_column_add_attribute ( + column, cell_renderer, "visible", + E_MAIL_ACCOUNT_STORE_COLUMN_DEFAULT); + + gtk_tree_view_append_column (tree_view, column); + + /* Column: Type */ + + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_expand (column, FALSE); + gtk_tree_view_column_set_title (column, _("Type")); + + cell_renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, cell_renderer, TRUE); + + gtk_tree_view_column_add_attribute ( + column, cell_renderer, "text", + E_MAIL_ACCOUNT_STORE_COLUMN_BACKEND_NAME); + + gtk_tree_view_append_column (tree_view, column); +} + +static void +mail_account_tree_view_drag_end (GtkWidget *widget, + GdkDragContext *context) +{ + GtkTreeModel *tree_model; + + /* Chain up to parent's drag_end() method. */ + GTK_WIDGET_CLASS (e_mail_account_tree_view_parent_class)-> + drag_end (widget, context); + + tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); + g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (tree_model)); + + g_signal_emit_by_name (tree_model, "services-reordered", FALSE); +} + +static void +e_mail_account_tree_view_class_init (EMailAccountTreeViewClass *class) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + + g_type_class_add_private (class, sizeof (EMailAccountTreeViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->constructed = mail_account_tree_view_constructed; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->drag_end = mail_account_tree_view_drag_end; + + signals[ENABLE] = g_signal_new ( + "enable", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountTreeViewClass, enable), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[DISABLE] = g_signal_new ( + "disable", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailAccountTreeViewClass, disable), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +e_mail_account_tree_view_init (EMailAccountTreeView *tree_view) +{ + tree_view->priv = E_MAIL_ACCOUNT_TREE_VIEW_GET_PRIVATE (tree_view); +} + +GtkWidget * +e_mail_account_tree_view_new (EMailAccountStore *store) +{ + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), NULL); + + return g_object_new ( + E_TYPE_MAIL_ACCOUNT_TREE_VIEW, + "model", store, NULL); +} + +CamelService * +e_mail_account_tree_view_get_selected_service (EMailAccountTreeView *tree_view) +{ + GtkTreeSelection *selection; + GtkTreeModel *tree_model; + GtkTreeIter iter; + CamelService *service; + GValue value = G_VALUE_INIT; + gint column; + + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view), NULL); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + + if (!gtk_tree_selection_get_selected (selection, &tree_model, &iter)) + return NULL; + + /* By convention, "get" functions don't return a new object + * reference, so use gtk_tree_model_get_value() to avoid it. + * The caller can always reference the object if needed. */ + + column = E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE; + gtk_tree_model_get_value (tree_model, &iter, column, &value); + service = g_value_get_object (&value); + g_value_unset (&value); + + g_warn_if_fail (CAMEL_IS_SERVICE (service)); + + return service; +} + +void +e_mail_account_tree_view_set_selected_service (EMailAccountTreeView *tree_view, + CamelService *service) +{ + GtkTreeSelection *selection; + GtkTreeModel *tree_model; + GtkTreeIter iter; + gboolean iter_set; + + g_return_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view)); + g_return_if_fail (CAMEL_IS_SERVICE (service)); + + tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + + iter_set = gtk_tree_model_get_iter_first (tree_model, &iter); + + while (iter_set) { + GValue value = G_VALUE_INIT; + CamelService *candidate; + gint column; + + column = E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE; + gtk_tree_model_get_value (tree_model, &iter, column, &value); + candidate = g_value_get_object (&value); + g_value_unset (&value); + + g_warn_if_fail (CAMEL_IS_SERVICE (candidate)); + + if (service == candidate) { + gtk_tree_selection_select_iter (selection, &iter); + break; + } + + iter_set = gtk_tree_model_iter_next (tree_model, &iter); + } +} diff --git a/mail/e-mail-account-tree-view.h b/mail/e-mail-account-tree-view.h new file mode 100644 index 0000000000..e1fff8385a --- /dev/null +++ b/mail/e-mail-account-tree-view.h @@ -0,0 +1,75 @@ +/* + * e-mail-account-tree-view.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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/> + * + */ + +#ifndef E_MAIL_ACCOUNT_TREE_VIEW_H +#define E_MAIL_ACCOUNT_TREE_VIEW_H + +#include <gtk/gtk.h> +#include <mail/e-mail-account-store.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_ACCOUNT_TREE_VIEW \ + (e_mail_account_tree_view_get_type ()) +#define E_MAIL_ACCOUNT_TREE_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeView)) +#define E_MAIL_ACCOUNT_TREE_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeViewClass)) +#define E_IS_MAIL_ACCOUNT_TREE_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW)) +#define E_IS_MAIL_ACCOUNT_TREE_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_ACCOUNT_TREE_VIEW)) +#define E_MAIL_ACCOUNT_TREE_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeViewClass)) + +G_BEGIN_DECLS + +typedef struct _EMailAccountTreeView EMailAccountTreeView; +typedef struct _EMailAccountTreeViewClass EMailAccountTreeViewClass; +typedef struct _EMailAccountTreeViewPrivate EMailAccountTreeViewPrivate; + +struct _EMailAccountTreeView { + GtkTreeView parent; + EMailAccountTreeViewPrivate *priv; +}; + +struct _EMailAccountTreeViewClass { + GtkTreeViewClass parent_class; + + /* Signals */ + void (*enable) (EMailAccountTreeView *tree_view); + void (*disable) (EMailAccountTreeView *tree_view); +}; + +GType e_mail_account_tree_view_get_type + (void) G_GNUC_CONST; +GtkWidget * e_mail_account_tree_view_new + (EMailAccountStore *store); +CamelService * e_mail_account_tree_view_get_selected_service + (EMailAccountTreeView *tree_view); +void e_mail_account_tree_view_set_selected_service + (EMailAccountTreeView *tree_view, + CamelService *service); + +G_END_DECLS + +#endif /* E_MAIL_ACCOUNT_TREE_VIEW_H */ diff --git a/mail/e-mail-backend.c b/mail/e-mail-backend.c index aedbdd2626..0640c7ff53 100644 --- a/mail/e-mail-backend.c +++ b/mail/e-mail-backend.c @@ -41,10 +41,8 @@ #include "shell/e-shell.h" #include "mail/e-mail-folder-utils.h" -#include "mail/e-mail-local.h" #include "mail/e-mail-migrate.h" #include "mail/e-mail-session.h" -#include "mail/e-mail-store.h" #include "mail/e-mail-store-utils.h" #include "mail/em-event.h" #include "mail/em-folder-tree-model.h" @@ -71,16 +69,9 @@ enum { PROP_SESSION }; -enum { - ACCOUNT_SORT_ORDER_CHANGED, - LAST_SIGNAL -}; - /* FIXME Kill this thing. It's a horrible hack. */ extern gint camel_application_is_exiting; -static guint signals[LAST_SIGNAL]; - G_DEFINE_ABSTRACT_TYPE ( EMailBackend, e_mail_backend, @@ -135,18 +126,6 @@ mail_backend_store_operation_done_cb (CamelStore *store, g_object_unref (activity); } -/* Helper for mail_backend_prepare_for_offline_cb() */ -static void -mail_store_prepare_for_offline_cb (CamelService *service, - EActivity *activity) -{ - /* FIXME Not passing a GCancellable. */ - e_mail_store_go_offline ( - CAMEL_STORE (service), G_PRIORITY_DEFAULT, NULL, - (GAsyncReadyCallback) mail_backend_store_operation_done_cb, - g_object_ref (activity)); -} - static void mail_backend_prepare_for_offline_cb (EShell *shell, EActivity *activity, @@ -154,6 +133,7 @@ mail_backend_prepare_for_offline_cb (EShell *shell, { GtkWindow *window; EMailSession *session; + GList *list, *link; gboolean synchronize = FALSE; window = e_shell_get_active_window (shell); @@ -170,20 +150,25 @@ mail_backend_prepare_for_offline_cb (EShell *shell, CAMEL_SESSION (session), FALSE); } - e_mail_store_foreach ( - session, (GFunc) mail_store_prepare_for_offline_cb, activity); -} + list = camel_session_list_services (CAMEL_SESSION (session)); -/* Helper for mail_backend_prepare_for_online_cb() */ -static void -mail_store_prepare_for_online_cb (CamelService *service, - EActivity *activity) -{ - /* FIXME Not passing a GCancellable. */ - e_mail_store_go_online ( - CAMEL_STORE (service), G_PRIORITY_DEFAULT, NULL, - (GAsyncReadyCallback) mail_backend_store_operation_done_cb, - g_object_ref (activity)); + for (link = list; link != NULL; link = g_list_next (link)) { + CamelService *service; + + service = CAMEL_SERVICE (link->data); + + if (!CAMEL_IS_STORE (service)) + continue; + + /* FIXME Not passing a GCancellable. */ + e_mail_store_go_offline ( + CAMEL_STORE (service), G_PRIORITY_DEFAULT, + NULL, (GAsyncReadyCallback) + mail_backend_store_operation_done_cb, + g_object_ref (activity)); + } + + g_list_free (list); } static void @@ -192,17 +177,35 @@ mail_backend_prepare_for_online_cb (EShell *shell, EMailBackend *backend) { EMailSession *session; + GList *list, *link; session = e_mail_backend_get_session (backend); camel_session_set_online (CAMEL_SESSION (session), TRUE); - e_mail_store_foreach ( - session, (GFunc) mail_store_prepare_for_online_cb, activity); + list = camel_session_list_services (CAMEL_SESSION (session)); + + for (link = list; link != NULL; link = g_list_next (link)) { + CamelService *service; + + service = CAMEL_SERVICE (link->data); + + if (!CAMEL_IS_STORE (service)) + continue; + + /* FIXME Not passing a GCancellable. */ + e_mail_store_go_online ( + CAMEL_STORE (service), G_PRIORITY_DEFAULT, + NULL, (GAsyncReadyCallback) + mail_backend_store_operation_done_cb, + g_object_ref (activity)); + } + + g_list_free (link); } /* Helper for mail_backend_prepare_for_quit_cb() */ static void -mail_backend_delete_junk (CamelStore *store, +mail_backend_delete_junk (CamelService *service, EMailBackend *backend) { CamelFolder *folder; @@ -212,7 +215,8 @@ mail_backend_delete_junk (CamelStore *store, guint ii; /* FIXME camel_store_get_junk_folder_sync() may block. */ - folder = camel_store_get_junk_folder_sync (store, NULL, NULL); + folder = camel_store_get_junk_folder_sync ( + CAMEL_STORE (service), NULL, NULL); if (folder == NULL) return; @@ -232,24 +236,6 @@ mail_backend_delete_junk (CamelStore *store, } /* Helper for mail_backend_prepare_for_quit_cb() */ -static void -mail_backend_final_sync (CamelStore *store, - gpointer user_data) -{ - struct { - EActivity *activity; - gboolean empty_trash; - } *sync_data = user_data; - - /* FIXME Not passing a GCancellable. */ - /* FIXME This operation should be queued. */ - camel_store_synchronize ( - store, sync_data->empty_trash, G_PRIORITY_DEFAULT, NULL, - (GAsyncReadyCallback) mail_backend_store_operation_done_cb, - g_object_ref (sync_data->activity)); -} - -/* Helper for mail_backend_prepare_for_quit_cb() */ static gboolean mail_backend_poll_to_quit (EActivity *activity) { @@ -273,14 +259,10 @@ mail_backend_prepare_for_quit_cb (EShell *shell, { EAccountList *account_list; EMailSession *session; + GList *list, *link; gboolean delete_junk; gboolean empty_trash; - struct { - EActivity *activity; - gboolean empty_trash; - } sync_data; - session = e_mail_backend_get_session (backend); delete_junk = e_mail_backend_delete_junk_policy_decision (backend); @@ -296,15 +278,40 @@ mail_backend_prepare_for_quit_cb (EShell *shell, /* Cancel all pending activities. */ mail_cancel_all (); - if (delete_junk) - e_mail_store_foreach ( - session, (GFunc) mail_backend_delete_junk, backend); + list = camel_session_list_services (CAMEL_SESSION (session)); + + if (delete_junk) { + for (link = list; link != NULL; link = g_list_next (link)) { + CamelService *service; + + service = CAMEL_SERVICE (link->data); + + if (!CAMEL_IS_STORE (service)) + continue; + + mail_backend_delete_junk (service, backend); + } + } + + for (link = list; link != NULL; link = g_list_next (link)) { + CamelService *service; - sync_data.activity = activity; - sync_data.empty_trash = empty_trash; + service = CAMEL_SERVICE (link->data); - e_mail_store_foreach ( - session, (GFunc) mail_backend_final_sync, &sync_data); + if (!CAMEL_IS_STORE (service)) + continue; + + /* FIXME Not passing a GCancellable. */ + /* FIXME This operation should be queued. */ + camel_store_synchronize ( + CAMEL_STORE (service), + empty_trash, G_PRIORITY_DEFAULT, + NULL, (GAsyncReadyCallback) + mail_backend_store_operation_done_cb, + g_object_ref (activity)); + } + + g_list_free (list); /* Now we poll until all activities are actually cancelled or finished. * Reffing the activity delays quitting; the reference count @@ -324,6 +331,8 @@ mail_backend_quit_requested_cb (EShell *shell, EShellQuitReason reason, EShellBackend *mail_shell_backend) { + EMailBackend *backend; + EMailSession *session; CamelFolder *folder; GtkWindow *window; gint response; @@ -348,7 +357,11 @@ mail_backend_quit_requested_cb (EShell *shell, /* Check Outbox for any unsent messages. */ - folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX); + backend = E_MAIL_BACKEND (mail_shell_backend); + session = e_mail_backend_get_session (backend); + + folder = e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_OUTBOX); if (folder == NULL) return; @@ -373,6 +386,7 @@ mail_backend_folder_deleted_cb (MailFolderCache *folder_cache, CamelStoreClass *class; EAccountList *account_list; EIterator *iterator; + EMailSession *session; const gchar *local_drafts_folder_uri; const gchar *local_sent_folder_uri; gboolean write_config = FALSE; @@ -385,10 +399,15 @@ mail_backend_folder_deleted_cb (MailFolderCache *folder_cache, class = CAMEL_STORE_GET_CLASS (store); g_return_if_fail (class->compare_folder_name != NULL); + session = e_mail_backend_get_session (backend); + local_drafts_folder_uri = - e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_DRAFTS); + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_DRAFTS); + local_sent_folder_uri = - e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_SENT); + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_SENT); uri = e_mail_folder_uri_build (store, folder_name); @@ -744,7 +763,6 @@ mail_backend_constructed (GObject *object) EMailBackendPrivate *priv; EShell *shell; EShellBackend *shell_backend; - EMFolderTreeModel *folder_tree_model; MailFolderCache *folder_cache; priv = E_MAIL_BACKEND_GET_PRIVATE (object); @@ -779,14 +797,6 @@ mail_backend_constructed (GObject *object) * Give EAccountComboBox a CamelSession property. */ e_account_combo_box_set_session (CAMEL_SESSION (priv->session)); - /* FIXME EMailBackend should own the default EMFolderTreeModel. */ - folder_tree_model = em_folder_tree_model_get_default (); - - /* FIXME This is creating a circular reference. Perhaps the - * should only hold a weak pointer to EMailBackend? */ - em_folder_tree_model_set_backend ( - folder_tree_model, E_MAIL_BACKEND (object)); - g_signal_connect ( shell, "prepare-for-offline", G_CALLBACK (mail_backend_prepare_for_offline_cb), @@ -856,15 +866,6 @@ e_mail_backend_class_init (EMailBackendClass *class) NULL, E_TYPE_MAIL_SESSION, G_PARAM_READABLE)); - - signals[ACCOUNT_SORT_ORDER_CHANGED] = g_signal_new ( - "account-sort-order-changed", - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EMailBackendClass, account_sort_order_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); } static void @@ -965,11 +966,3 @@ e_mail_backend_submit_alert (EMailBackend *backend, va_end (va); } -void -e_mail_backend_account_sort_order_changed (EMailBackend *backend) -{ - g_return_if_fail (backend != NULL); - g_return_if_fail (E_IS_MAIL_BACKEND (backend)); - - g_signal_emit (backend, signals[ACCOUNT_SORT_ORDER_CHANGED], 0); -} diff --git a/mail/e-mail-backend.h b/mail/e-mail-backend.h index 4d3cc10799..6d425197f3 100644 --- a/mail/e-mail-backend.h +++ b/mail/e-mail-backend.h @@ -67,10 +67,6 @@ struct _EMailBackendClass { (EMailBackend *backend); gboolean (*empty_trash_policy_decision) (EMailBackend *backend); - - /* Signals */ - void (*account_sort_order_changed) - (EMailBackend *backend); }; GType e_mail_backend_get_type (void); @@ -83,9 +79,6 @@ void e_mail_backend_submit_alert (EMailBackend *backend, const gchar *tag, ...) G_GNUC_NULL_TERMINATED; -void e_mail_backend_account_sort_order_changed - (EMailBackend *backend); - G_END_DECLS #endif /* E_MAIL_BACKEND_H */ diff --git a/mail/e-mail-local.c b/mail/e-mail-local.c deleted file mode 100644 index 28d174e303..0000000000 --- a/mail/e-mail-local.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * e-mail-local.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-mail-local.h" - -#include <glib/gi18n.h> - -#include "e-mail-folder-utils.h" - -#define CHECK_LOCAL_FOLDER_TYPE(type) \ - ((type) < G_N_ELEMENTS (default_local_folders)) - -/* The array elements correspond to EMailLocalFolder. */ -static struct { - const gchar *display_name; - CamelFolder *folder; - gchar *folder_uri; -} default_local_folders[] = { - { N_("Inbox") }, - { N_("Drafts") }, - { N_("Outbox") }, - { N_("Sent") }, - { N_("Templates") }, - { "Inbox" } /* "always local" inbox */ -}; - -static CamelStore *local_store; -static gboolean mail_local_initialized = FALSE; - -void -e_mail_local_init (EMailSession *session, - const gchar *data_dir) -{ - CamelSettings *settings; - CamelService *service; - gchar *path; - gint ii; - GError *error = NULL; - - if (mail_local_initialized) - return; - - g_return_if_fail (E_IS_MAIL_SESSION (session)); - g_return_if_fail (data_dir != NULL); - - mail_local_initialized = TRUE; - - service = camel_session_add_service ( - CAMEL_SESSION (session), - "local", "maildir", - CAMEL_PROVIDER_STORE, &error); - - camel_service_set_display_name (service, _("On This Computer")); - - settings = camel_service_get_settings (service); - - path = g_build_filename (data_dir, "local", NULL); - g_object_set (settings, "path", path, NULL); - g_free (path); - - /* Shouldn't need to worry about other mail applications - * altering files in our local mail store. */ - g_object_set (service, "need-summary-check", FALSE, NULL); - - if (error != NULL) - goto fail; - - /* Populate the rest of the default_local_folders array. */ - for (ii = 0; ii < G_N_ELEMENTS (default_local_folders); ii++) { - const gchar *display_name; - - display_name = default_local_folders[ii].display_name; - - default_local_folders[ii].folder_uri = - e_mail_folder_uri_build ( - CAMEL_STORE (service), display_name); - - /* FIXME camel_store_get_folder() may block. */ - if (!strcmp (display_name, "Inbox")) - default_local_folders[ii].folder = - camel_store_get_inbox_folder_sync ( - CAMEL_STORE (service), NULL, &error); - else - default_local_folders[ii].folder = - camel_store_get_folder_sync ( - CAMEL_STORE (service), display_name, - CAMEL_STORE_FOLDER_CREATE, NULL, &error); - - if (error != NULL) { - g_critical ("%s", error->message); - g_clear_error (&error); - } - } - - local_store = g_object_ref (service); - - return; - -fail: - g_critical ( - "Could not initialize local store/folder: %s", - error->message); - - g_error_free (error); -} - -CamelFolder * -e_mail_local_get_folder (EMailLocalFolder type) -{ - g_return_val_if_fail (mail_local_initialized, NULL); - g_return_val_if_fail (CHECK_LOCAL_FOLDER_TYPE (type), NULL); - - return default_local_folders[type].folder; -} - -const gchar * -e_mail_local_get_folder_uri (EMailLocalFolder type) -{ - g_return_val_if_fail (mail_local_initialized, NULL); - g_return_val_if_fail (CHECK_LOCAL_FOLDER_TYPE (type), NULL); - - return default_local_folders[type].folder_uri; -} - -CamelStore * -e_mail_local_get_store (void) -{ - g_return_val_if_fail (mail_local_initialized, NULL); - g_return_val_if_fail (CAMEL_IS_STORE (local_store), NULL); - - return local_store; -} diff --git a/mail/e-mail-local.h b/mail/e-mail-local.h deleted file mode 100644 index 282a0feacb..0000000000 --- a/mail/e-mail-local.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * e-mail-local.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MAIL_LOCAL_H -#define E_MAIL_LOCAL_H - -#include <camel/camel.h> -#include <mail/e-mail-enums.h> -#include <mail/e-mail-session.h> - -G_BEGIN_DECLS - -void e_mail_local_init (EMailSession *session, - const gchar *data_dir); -CamelFolder * e_mail_local_get_folder (EMailLocalFolder type); -const gchar * e_mail_local_get_folder_uri (EMailLocalFolder type); -CamelStore * e_mail_local_get_store (void); - -G_END_DECLS - -#endif /* E_MAIL_LOCAL_H */ diff --git a/mail/e-mail-migrate.c b/mail/e-mail-migrate.c index f3ce503012..fdf5684e0a 100644 --- a/mail/e-mail-migrate.c +++ b/mail/e-mail-migrate.c @@ -64,8 +64,6 @@ #include "e-mail-backend.h" #include "e-mail-folder-utils.h" -#include "e-mail-local.h" -#include "e-mail-store.h" #include "em-utils.h" #define d(x) x @@ -277,7 +275,7 @@ emm_setup_initial (const gchar *data_dir) d(printf("Setting up initial mail tree\n")); - base = g_build_filename(data_dir, "local", NULL); + base = g_build_filename (data_dir, "local", NULL); if (g_mkdir_with_parents (base, 0700) == -1 && errno != EEXIST) { g_free (base); return FALSE; @@ -671,7 +669,7 @@ create_mbox_account (EShellBackend *shell_backend, { EMailBackend *mail_backend; EMailSession *mail_session; - CamelStore *store; + CamelService *service; CamelURL *url; EAccountList *accounts; EAccount *account; @@ -682,9 +680,6 @@ create_mbox_account (EShellBackend *shell_backend, mail_session = e_mail_backend_get_session (mail_backend); data_dir = e_shell_backend_get_data_dir (shell_backend); - /* Initialize the mail stores early so we can add a new one. */ - e_mail_store_init (mail_session, data_dir); - account = e_account_new (); account->enabled = TRUE; @@ -716,15 +711,20 @@ create_mbox_account (EShellBackend *shell_backend, goto exit; } + /* This will also add it to the EMailSession. */ e_account_list_add (accounts, account); - store = e_mail_store_add_by_account (mail_session, account); - folder_uri = e_mail_folder_uri_build (store, "Sent"); + service = camel_session_get_service ( + CAMEL_SESSION (mail_session), account->uid); + + folder_uri = e_mail_folder_uri_build ( + CAMEL_STORE (service), "Sent"); e_account_set_string ( account, E_ACCOUNT_SENT_FOLDER_URI, folder_uri); g_free (folder_uri); - folder_uri = e_mail_folder_uri_build (store, "Drafts"); + folder_uri = e_mail_folder_uri_build ( + CAMEL_STORE (service), "Drafts"); e_account_set_string ( account, E_ACCOUNT_DRAFTS_FOLDER_URI, folder_uri); g_free (folder_uri); @@ -743,6 +743,8 @@ exit: static void change_sent_and_drafts_local_folders (EShellBackend *shell_backend) { + EMailBackend *backend; + EMailSession *session; EAccountList *accounts; EIterator *iter; const gchar *data_dir; @@ -754,6 +756,9 @@ change_sent_and_drafts_local_folders (EShellBackend *shell_backend) if (!accounts) return; + backend = E_MAIL_BACKEND (shell_backend); + session = e_mail_backend_get_session (backend); + data_dir = e_shell_backend_get_data_dir (shell_backend); tmp_uri = g_strconcat ("mbox:", data_dir, "/", "local", NULL); @@ -797,8 +802,8 @@ change_sent_and_drafts_local_folders (EShellBackend *shell_backend) changed = TRUE; e_account_set_string ( account, E_ACCOUNT_DRAFTS_FOLDER_URI, - e_mail_local_get_folder_uri ( - E_MAIL_LOCAL_FOLDER_DRAFTS)); + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_DRAFTS)); } uri = e_account_get_string (account, E_ACCOUNT_SENT_FOLDER_URI); @@ -806,8 +811,8 @@ change_sent_and_drafts_local_folders (EShellBackend *shell_backend) changed = TRUE; e_account_set_string ( account, E_ACCOUNT_SENT_FOLDER_URI, - e_mail_local_get_folder_uri ( - E_MAIL_LOCAL_FOLDER_SENT)); + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_SENT)); } } diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c index a58eb1f441..ffca3d89ac 100644 --- a/mail/e-mail-reader-utils.c +++ b/mail/e-mail-reader-utils.c @@ -40,7 +40,6 @@ #include "mail/e-mail-backend.h" #include "mail/e-mail-browser.h" #include "mail/e-mail-folder-utils.h" -#include "mail/e-mail-local.h" #include "mail/em-composer-utils.h" #include "mail/em-format-html-print.h" #include "mail/em-utils.h" @@ -191,15 +190,16 @@ void e_mail_reader_delete_folder (EMailReader *reader, CamelFolder *folder) { - CamelStore *local_store; - CamelStore *parent_store; EMailBackend *backend; EMailSession *session; EAlertSink *alert_sink; + CamelStore *parent_store; MailFolderCache *folder_cache; GtkWindow *parent = e_shell_get_active_window (NULL); GtkWidget *dialog; + gboolean store_is_local; const gchar *full_name; + const gchar *uid; CamelFolderInfoFlags flags = 0; gboolean have_flags; @@ -209,14 +209,16 @@ e_mail_reader_delete_folder (EMailReader *reader, full_name = camel_folder_get_full_name (folder); parent_store = camel_folder_get_parent_store (folder); + uid = camel_service_get_uid (CAMEL_SERVICE (parent_store)); + store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0); + backend = e_mail_reader_get_backend (reader); session = e_mail_backend_get_session (backend); - local_store = e_mail_local_get_store (); alert_sink = e_mail_reader_get_alert_sink (reader); folder_cache = e_mail_session_get_folder_cache (session); - if (parent_store == local_store && + if (store_is_local && mail_reader_is_special_local_folder (full_name)) { e_mail_backend_submit_alert ( backend, "mail:no-delete-special-folder", diff --git a/mail/e-mail-session-utils.c b/mail/e-mail-session-utils.c index eca58bcad0..f1c27a3425 100644 --- a/mail/e-mail-session-utils.c +++ b/mail/e-mail-session-utils.c @@ -27,7 +27,6 @@ #include <glib/gi18n-lib.h> #include <mail/mail-tools.h> -#include <mail/e-mail-local.h> #include <mail/e-mail-folder-utils.h> #include <e-util/e-account-utils.h> #include <filter/e-filter-rule.h> @@ -508,7 +507,9 @@ mail_session_send_to_thread (GSimpleAsyncResult *simple, /* Append the sent message to a Sent folder. */ - local_sent_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT); + local_sent_folder = + e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_SENT); /* Try to extract a CamelFolder from the Sent folder URI. */ if (context->sent_folder_uri != NULL) { diff --git a/mail/e-mail-session.c b/mail/e-mail-session.c index 03f4961206..6d04c2c23d 100644 --- a/mail/e-mail-session.c +++ b/mail/e-mail-session.c @@ -52,9 +52,9 @@ #include "e-util/e-alert-dialog.h" #include "e-util/e-util-private.h" +#include "e-mail-account-store.h" #include "e-mail-folder-utils.h" #include "e-mail-junk-filter.h" -#include "e-mail-local.h" #include "e-mail-session.h" #include "em-composer-utils.h" #include "em-filter-context.h" @@ -71,13 +71,26 @@ ((obj), E_TYPE_MAIL_SESSION, EMailSessionPrivate)) typedef struct _AsyncContext AsyncContext; +typedef struct _SourceContext SourceContext; struct _EMailSessionPrivate { + EMailAccountStore *account_store; MailFolderCache *folder_cache; + EAccountList *account_list; + gulong account_added_handler_id; + gulong account_changed_handler_id; + + CamelStore *local_store; + CamelStore *vfolder_store; + FILE *filter_logfile; GHashTable *junk_filters; EProxy *proxy; + + /* Local folder cache. */ + GPtrArray *local_folders; + GPtrArray *local_folder_uris; }; struct _AsyncContext { @@ -90,10 +103,27 @@ struct _AsyncContext { CamelFolder *folder; }; +struct _SourceContext { + EMailSession *session; + CamelService *service; +}; + enum { PROP_0, + PROP_ACCOUNT_STORE, PROP_FOLDER_CACHE, - PROP_JUNK_FILTER_NAME + PROP_JUNK_FILTER_NAME, + PROP_LOCAL_STORE, + PROP_VFOLDER_STORE +}; + +static const gchar *local_folder_names[E_MAIL_NUM_LOCAL_FOLDERS] = { + N_("Inbox"), /* E_MAIL_LOCAL_FOLDER_INBOX */ + N_("Drafts"), /* E_MAIL_LOCAL_FOLDER_DRAFTS */ + N_("Outbox"), /* E_MAIL_LOCAL_FOLDER_OUTBOX */ + N_("Sent"), /* E_MAIL_LOCAL_FOLDER_SENT */ + N_("Templates"), /* E_MAIL_LOCAL_FOLDER_TEMPLATES */ + "Inbox" /* E_MAIL_LOCAL_FOLDER_LOCAL_INBOX */ }; static gchar *mail_data_dir; @@ -463,6 +493,18 @@ async_context_free (AsyncContext *context) g_slice_free (AsyncContext, context); } +static void +source_context_free (SourceContext *context) +{ + if (context->session != NULL) + g_object_unref (context->session); + + if (context->service != NULL) + g_object_unref (context->service); + + g_slice_free (SourceContext, context); +} + static gchar * mail_session_make_key (CamelService *service, const gchar *item) @@ -553,6 +595,270 @@ mail_session_set_junk_filter_name (EMailSession *session, } static void +mail_session_add_by_account (EMailSession *session, + EAccount *account) +{ + CamelService *service = NULL; + CamelProvider *provider; + CamelURL *url; + gboolean transport_only; + GError *error = NULL; + + /* check whether it's transport-only accounts */ + transport_only = + (account->source == NULL) || + (account->source->url == NULL) || + (*account->source->url == '\0'); + if (transport_only) + goto handle_transport; + + /* Load the service, but don't connect. Check its provider, + * and if this belongs in the folder tree model, add it. */ + + url = camel_url_new (account->source->url, NULL); + if (url != NULL) { + provider = camel_provider_get (url->protocol, NULL); + camel_url_free (url); + } else { + provider = NULL; + } + + if (provider == NULL) { + /* In case we do not have a provider here, we handle + * the special case of having multiple mail identities + * eg. a dummy account having just SMTP server defined */ + goto handle_transport; + } + + service = camel_session_add_service ( + CAMEL_SESSION (session), + account->uid, provider->protocol, + CAMEL_PROVIDER_STORE, &error); + + if (error != NULL) { + g_warning ( + "Failed to add service: %s: %s", + account->name, error->message); + g_error_free (error); + return; + } + + camel_service_set_display_name (service, account->name); + +handle_transport: + + /* While we're at it, add the account's transport (if it has one) + * to the CamelSession. The transport's UID is a kludge for now. + * We take the EAccount's UID and tack on "-transport". */ + + if (account->transport) { + GError *transport_error = NULL; + + url = camel_url_new ( + account->transport->url, + &transport_error); + + if (url != NULL) { + provider = camel_provider_get ( + url->protocol, &transport_error); + camel_url_free (url); + } else + provider = NULL; + + if (provider != NULL) { + gchar *transport_uid; + + transport_uid = g_strconcat ( + account->uid, "-transport", NULL); + + camel_session_add_service ( + CAMEL_SESSION (session), + transport_uid, provider->protocol, + CAMEL_PROVIDER_TRANSPORT, &transport_error); + + g_free (transport_uid); + } + + if (transport_error) { + g_warning ( + "%s: Failed to add transport service: %s", + G_STRFUNC, transport_error->message); + g_error_free (transport_error); + } + } +} + +static void +mail_session_account_added_cb (EAccountList *account_list, + EAccount *account, + EMailSession *session) +{ + mail_session_add_by_account (session, account); +} + +static void +mail_session_account_changed_cb (EAccountList *account_list, + EAccount *account, + EMailSession *session) +{ + EMFolderTreeModel *folder_tree_model; + CamelService *service; + + service = camel_session_get_service ( + CAMEL_SESSION (session), account->uid); + + if (!CAMEL_IS_STORE (service)) + return; + + /* Update the display name of the corresponding CamelStore. + * EMailAccountStore listens for "notify" signals from each + * service so it will detect this and update the model. + * + * XXX If EAccount defined GObject properties we could just + * bind EAccount:name to CamelService:display-name and + * be done with it. Oh well. + */ + + camel_service_set_display_name (service, account->name); + + /* Remove the store from the folder tree model and, if the + * account is still enabled, re-add it. Easier than trying + * to update the model with the store in place. + * + * em_folder_tree_model_add_store() already knows which types + * of stores to disregard, so we don't have to deal with that + * here. */ + + folder_tree_model = em_folder_tree_model_get_default (); + + em_folder_tree_model_remove_store ( + folder_tree_model, CAMEL_STORE (service)); + + if (account->enabled) + em_folder_tree_model_add_store ( + folder_tree_model, CAMEL_STORE (service)); +} + +static gboolean +mail_session_add_service_cb (SourceContext *context) +{ + EMailAccountStore *store; + + store = e_mail_session_get_account_store (context->session); + e_mail_account_store_add_service (store, context->service); + + return FALSE; +} + +static void +mail_session_add_local_store (EMailSession *session) +{ + CamelLocalSettings *local_settings; + CamelSession *camel_session; + CamelSettings *settings; + CamelService *service; + const gchar *data_dir; + gchar *path; + gint ii; + GError *error = NULL; + + camel_session = CAMEL_SESSION (session); + + service = camel_session_add_service ( + camel_session, E_MAIL_SESSION_LOCAL_UID, + "maildir", CAMEL_PROVIDER_STORE, &error); + + /* XXX One could argue this is a fatal error + * since we depend on it in so many places. */ + if (error != NULL) { + g_critical ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + return; + } + + g_return_if_fail (CAMEL_IS_SERVICE (service)); + + camel_service_set_display_name (service, _("On This Computer")); + + settings = camel_service_get_settings (service); + local_settings = CAMEL_LOCAL_SETTINGS (settings); + data_dir = camel_session_get_user_data_dir (camel_session); + + path = g_build_filename (data_dir, E_MAIL_SESSION_LOCAL_UID, NULL); + camel_local_settings_set_path (local_settings, path); + g_free (path); + + /* Shouldn't need to worry about other mail applications + * altering files in our local mail store. */ + g_object_set (service, "need-summary-check", FALSE, NULL); + + /* Populate the local folder cache. */ + for (ii = 0; ii < E_MAIL_NUM_LOCAL_FOLDERS; ii++) { + CamelFolder *folder; + gchar *folder_uri; + const gchar *display_name; + GError *error = NULL; + + display_name = local_folder_names[ii]; + + /* XXX This blocks but should be fast. */ + if (ii == E_MAIL_LOCAL_FOLDER_LOCAL_INBOX) + folder = camel_store_get_inbox_folder_sync ( + CAMEL_STORE (service), NULL, &error); + else + folder = camel_store_get_folder_sync ( + CAMEL_STORE (service), display_name, + CAMEL_STORE_FOLDER_CREATE, NULL, &error); + + folder_uri = e_mail_folder_uri_build ( + CAMEL_STORE (service), display_name); + + /* The arrays take ownership of the items added. */ + g_ptr_array_add (session->priv->local_folders, folder); + g_ptr_array_add (session->priv->local_folder_uris, folder_uri); + + if (error != NULL) { + g_critical ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + } + } + + session->priv->local_store = g_object_ref (service); +} + +static void +mail_session_add_vfolder_store (EMailSession *session) +{ + CamelSession *camel_session; + CamelService *service; + GError *error = NULL; + + camel_session = CAMEL_SESSION (session); + + service = camel_session_add_service ( + camel_session, E_MAIL_SESSION_VFOLDER_UID, + "vfolder", CAMEL_PROVIDER_STORE, &error); + + if (error != NULL) { + g_critical ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + return; + } + + g_return_if_fail (CAMEL_IS_SERVICE (service)); + + camel_service_set_display_name (service, _("Search Folders")); + em_utils_connect_service_sync (service, NULL, NULL); + + /* XXX There's more configuration to do in vfolder_load_storage() + * but it requires an EMailBackend, which we don't have access + * to from here, so it has to be called from elsewhere. Kinda + * thinking about reworking that... */ + + session->priv->vfolder_store = g_object_ref (service); +} + +static void mail_session_set_property (GObject *object, guint property_id, const GValue *value, @@ -576,6 +882,13 @@ mail_session_get_property (GObject *object, GParamSpec *pspec) { switch (property_id) { + case PROP_ACCOUNT_STORE: + g_value_set_object ( + value, + e_mail_session_get_account_store ( + E_MAIL_SESSION (object))); + return; + case PROP_FOLDER_CACHE: g_value_set_object ( value, @@ -589,6 +902,20 @@ mail_session_get_property (GObject *object, mail_session_get_junk_filter_name ( E_MAIL_SESSION (object))); return; + + case PROP_LOCAL_STORE: + g_value_set_object ( + value, + e_mail_session_get_local_store ( + E_MAIL_SESSION (object))); + return; + + case PROP_VFOLDER_STORE: + g_value_set_object ( + value, + e_mail_session_get_vfolder_store ( + E_MAIL_SESSION (object))); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -601,11 +928,41 @@ mail_session_dispose (GObject *object) priv = E_MAIL_SESSION_GET_PRIVATE (object); + if (priv->account_store != NULL) { + e_mail_account_store_clear (priv->account_store); + g_object_unref (priv->account_store); + priv->account_store = NULL; + } + if (priv->folder_cache != NULL) { g_object_unref (priv->folder_cache); priv->folder_cache = NULL; } + if (priv->account_list != NULL) { + g_signal_handler_disconnect ( + priv->account_list, + priv->account_added_handler_id); + g_signal_handler_disconnect ( + priv->account_list, + priv->account_changed_handler_id); + g_object_unref (priv->account_list); + priv->account_list = NULL; + } + + if (priv->local_store != NULL) { + g_object_unref (priv->local_store); + priv->local_store = NULL; + } + + if (priv->vfolder_store != NULL) { + g_object_unref (priv->vfolder_store); + priv->vfolder_store = NULL; + } + + g_ptr_array_set_size (priv->local_folders, 0); + g_ptr_array_set_size (priv->local_folder_uris, 0); + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_mail_session_parent_class)->dispose (object); } @@ -620,6 +977,9 @@ mail_session_finalize (GObject *object) g_hash_table_destroy (priv->junk_filters); g_object_unref (priv->proxy); + g_ptr_array_free (priv->local_folders, TRUE); + g_ptr_array_free (priv->local_folder_uris, TRUE); + g_free (mail_data_dir); g_free (mail_config_dir); @@ -642,17 +1002,87 @@ mail_session_notify (GObject *object, static void mail_session_constructed (GObject *object) { - EMailSessionPrivate *priv; + EMFolderTreeModel *folder_tree_model; + EMailSession *session; EExtensible *extensible; GType extension_type; - GList *list, *iter; + GList *list, *link; GSettings *settings; + EAccountList *account_list; + EIterator *iter; + EAccount *account; + gulong handler_id; - priv = E_MAIL_SESSION_GET_PRIVATE (object); + session = E_MAIL_SESSION (object); /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_mail_session_parent_class)->constructed (object); + account_list = e_get_account_list (); + session->priv->account_list = g_object_ref (account_list); + + session->priv->account_store = e_mail_account_store_new (session); + + /* This must be created after the account store. */ + session->priv->folder_cache = mail_folder_cache_new (session); + + /* XXX Make sure the folder tree model is created before we + * add built-in CamelStores so it gets signals from the + * EMailAccountStore. + * + * XXX This is creating a circular reference. Perhaps the + * model should only hold a weak pointer to EMailSession? + * + * FIXME EMailSession should just own the default instance. + */ + folder_tree_model = em_folder_tree_model_get_default (); + em_folder_tree_model_set_session (folder_tree_model, session); + + /* Add built-in CamelStores. */ + + mail_session_add_local_store (session); + mail_session_add_vfolder_store (session); + + /* Load user-defined mail accounts. */ + + iter = e_list_get_iterator (E_LIST (account_list)); + + while (e_iterator_is_valid (iter)) { + /* XXX EIterator misuses const. */ + account = (EAccount *) e_iterator_get (iter); + + if (account->enabled) + mail_session_add_by_account (session, account); + + e_iterator_next (iter); + } + + g_object_unref (iter); + + /* Initialize which account is default. */ + + account = e_get_default_account (); + if (account != NULL) { + CamelService *service; + + service = camel_session_get_service ( + CAMEL_SESSION (session), account->uid); + e_mail_account_store_set_default_service ( + session->priv->account_store, service); + } + + /* Listen for account list updates. */ + + handler_id = g_signal_connect ( + account_list, "account-added", + G_CALLBACK (mail_session_account_added_cb), session); + session->priv->account_added_handler_id = handler_id; + + handler_id = g_signal_connect ( + account_list, "account-changed", + G_CALLBACK (mail_session_account_changed_cb), session); + session->priv->account_changed_handler_id = handler_id; + extensible = E_EXTENSIBLE (object); e_extensible_load_extensions (extensible); @@ -661,11 +1091,11 @@ mail_session_constructed (GObject *object) extension_type = E_TYPE_MAIL_JUNK_FILTER; list = e_extensible_list_extensions (extensible, extension_type); - for (iter = list; iter != NULL; iter = g_list_next (iter)) { + for (link = list; link != NULL; link = g_list_next (link)) { EMailJunkFilter *junk_filter; EMailJunkFilterClass *class; - junk_filter = E_MAIL_JUNK_FILTER (iter->data); + junk_filter = E_MAIL_JUNK_FILTER (link->data); class = E_MAIL_JUNK_FILTER_GET_CLASS (junk_filter); if (!CAMEL_IS_JUNK_FILTER (junk_filter)) { @@ -693,17 +1123,21 @@ mail_session_constructed (GObject *object) /* No need to reference the EMailJunkFilter since * EMailSession owns the reference to it already. */ g_hash_table_insert ( - priv->junk_filters, + session->priv->junk_filters, (gpointer) class->filter_name, junk_filter); } g_list_free (list); - /* Bind the "junk-default-plugin" GSettings key to our "junk-filter-name" property. */ + /* Bind the "junk-default-plugin" GSettings + * key to our "junk-filter-name" property. */ settings = g_settings_new ("org.gnome.evolution.mail"); - g_settings_bind (settings, "junk-default-plugin", object, "junk-filter-name", G_SETTINGS_BIND_DEFAULT); + g_settings_bind ( + settings, "junk-default-plugin", + object, "junk-filter-name", + G_SETTINGS_BIND_DEFAULT); g_object_unref (settings); } @@ -765,6 +1199,22 @@ mail_session_add_service (CamelSession *session, } } + /* Inform the EMailAccountStore of the new CamelService + * from an idle callback so the service has a chance to + * fully initialize first. */ + if (CAMEL_IS_STORE (service)) { + SourceContext *context; + + context = g_slice_new0 (SourceContext); + context->session = g_object_ref (session); + context->service = g_object_ref (service); + + g_idle_add_full ( + G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc) mail_session_add_service_cb, + context, (GDestroyNotify) source_context_free); + } + return service; } @@ -1073,7 +1523,8 @@ mail_session_forward_to (CamelSession *session, /* and send it */ info = camel_message_info_new (NULL); - out_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX); + out_folder = e_mail_session_get_local_folder ( + E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_OUTBOX); camel_message_info_set_flags ( info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); @@ -1300,6 +1751,28 @@ e_mail_session_class_init (EMailSessionClass *class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_LOCAL_STORE, + g_param_spec_object ( + "local-store", + "Local Store", + "Built-in local store", + CAMEL_TYPE_STORE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_VFOLDER_STORE, + g_param_spec_object ( + "vfolder-store", + "Search Folder Store", + "Built-in search folder store", + CAMEL_TYPE_STORE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); } static void @@ -1308,11 +1781,17 @@ e_mail_session_init (EMailSession *session) GSettings *settings; session->priv = E_MAIL_SESSION_GET_PRIVATE (session); - session->priv->folder_cache = mail_folder_cache_new (); session->priv->junk_filters = g_hash_table_new ( (GHashFunc) g_str_hash, (GEqualFunc) g_str_equal); session->priv->proxy = e_proxy_new (); + session->priv->local_folders = + g_ptr_array_new_with_free_func ( + (GDestroyNotify) g_object_unref); + session->priv->local_folder_uris = + g_ptr_array_new_with_free_func ( + (GDestroyNotify) g_free); + /* Initialize the EAccount setup. */ e_account_writable (NULL, E_ACCOUNT_SOURCE_SAVE_PASSWD); @@ -1348,6 +1827,14 @@ e_mail_session_new (void) NULL); } +EMailAccountStore * +e_mail_session_get_account_store (EMailSession *session) +{ + g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); + + return session->priv->account_store; +} + MailFolderCache * e_mail_session_get_folder_cache (EMailSession *session) { @@ -1356,6 +1843,58 @@ e_mail_session_get_folder_cache (EMailSession *session) return session->priv->folder_cache; } +CamelStore * +e_mail_session_get_local_store (EMailSession *session) +{ + g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); + + return session->priv->local_store; +} + +CamelStore * +e_mail_session_get_vfolder_store (EMailSession *session) +{ + g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); + + return session->priv->vfolder_store; +} + +CamelFolder * +e_mail_session_get_local_folder (EMailSession *session, + EMailLocalFolder type) +{ + GPtrArray *local_folders; + CamelFolder *folder; + + g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); + + local_folders = session->priv->local_folders; + g_return_val_if_fail (type < local_folders->len, NULL); + + folder = g_ptr_array_index (local_folders, type); + g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL); + + return folder; +} + +const gchar * +e_mail_session_get_local_folder_uri (EMailSession *session, + EMailLocalFolder type) +{ + GPtrArray *local_folder_uris; + const gchar *folder_uri; + + g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); + + local_folder_uris = session->priv->local_folder_uris; + g_return_val_if_fail (type < local_folder_uris->len, NULL); + + folder_uri = g_ptr_array_index (local_folder_uris, type); + g_return_val_if_fail (folder_uri != NULL, NULL); + + return folder_uri; +} + GList * e_mail_session_get_available_junk_filters (EMailSession *session) { diff --git a/mail/e-mail-session.h b/mail/e-mail-session.h index 165b335a19..e10e3c3d1f 100644 --- a/mail/e-mail-session.h +++ b/mail/e-mail-session.h @@ -26,6 +26,8 @@ #define E_MAIL_SESSION_H #include <camel/camel.h> +#include <mail/e-mail-enums.h> +#include <mail/e-mail-account-store.h> #include <mail/mail-folder-cache.h> /* Standard GObject macros */ @@ -47,8 +49,15 @@ (G_TYPE_INSTANCE_GET_CLASS \ ((obj), E_TYPE_MAIL_SESSION, EMailSessionClass)) +/* Built-in CamelServices */ +#define E_MAIL_SESSION_LOCAL_UID "local" /* "On This Computer" */ +#define E_MAIL_SESSION_VFOLDER_UID "vfolder" /* "Search Folders" */ + G_BEGIN_DECLS +/* Avoids a circular dependency. */ +typedef struct _EMailAccountStore EMailAccountStore; + typedef struct _EMailSession EMailSession; typedef struct _EMailSessionClass EMailSessionClass; typedef struct _EMailSessionPrivate EMailSessionPrivate; @@ -64,8 +73,19 @@ struct _EMailSessionClass { GType e_mail_session_get_type (void); EMailSession * e_mail_session_new (void); +EMailAccountStore * + e_mail_session_get_account_store + (EMailSession *session); MailFolderCache * e_mail_session_get_folder_cache (EMailSession *session); +CamelStore * e_mail_session_get_local_store (EMailSession *session); +CamelStore * e_mail_session_get_vfolder_store + (EMailSession *session); +CamelFolder * e_mail_session_get_local_folder (EMailSession *session, + EMailLocalFolder type); +const gchar * e_mail_session_get_local_folder_uri + (EMailSession *session, + EMailLocalFolder type); GList * e_mail_session_get_available_junk_filters (EMailSession *session); CamelFolder * e_mail_session_get_inbox_sync (EMailSession *session, diff --git a/mail/e-mail-sidebar.c b/mail/e-mail-sidebar.c index 35048f8293..9a935819c8 100644 --- a/mail/e-mail-sidebar.c +++ b/mail/e-mail-sidebar.c @@ -28,7 +28,6 @@ #include <string.h> #include <camel/camel.h> -#include "mail/e-mail-local.h" #include "mail/em-utils.h" #define E_MAIL_SIDEBAR_GET_PRIVATE(obj) \ @@ -338,6 +337,8 @@ mail_sidebar_check_state (EMailSidebar *sidebar) GtkTreeIter iter; CamelStore *store; gchar *full_name; + const gchar *uid; + gboolean store_is_local; gboolean allows_children = TRUE; gboolean can_delete = TRUE; gboolean is_junk = FALSE; @@ -360,12 +361,12 @@ mail_sidebar_check_state (EMailSidebar *sidebar) COL_BOOL_IS_STORE, &is_store, COL_UINT_FLAGS, &folder_flags, -1); + uid = camel_service_get_uid (CAMEL_SERVICE (store)); + store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0); + if (!is_store && full_name != NULL) { - CamelStore *local_store; guint32 folder_type; - local_store = e_mail_local_get_store (); - /* Is this a virtual junk or trash folder? */ is_junk = (strcmp (full_name, CAMEL_VJUNK_NAME) == 0); is_trash = (strcmp (full_name, CAMEL_VTRASH_NAME) == 0); @@ -378,7 +379,7 @@ mail_sidebar_check_state (EMailSidebar *sidebar) allows_children = !(is_junk || is_trash); /* Don't allow deletion of special local folders. */ - if (store == local_store) { + if (store_is_local) { can_delete = (strcmp (full_name, "Drafts") != 0) && (strcmp (full_name, "Inbox") != 0) && diff --git a/mail/e-mail-store.c b/mail/e-mail-store.c deleted file mode 100644 index 283a8608e9..0000000000 --- a/mail/e-mail-store.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * e-mail-store.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-mail-store.h" - -#include <glib/gi18n.h> -#include <camel/camel.h> -#include <libedataserver/e-account.h> -#include <libedataserver/e-account-list.h> - -#include "e-util/e-account-utils.h" - -#include "mail/e-mail-local.h" -#include "mail/em-folder-tree-model.h" -#include "mail/em-utils.h" -#include "mail/mail-folder-cache.h" -#include "mail/mail-mt.h" -#include "mail/mail-ops.h" - -#include "shell/e-shell.h" -#include "shell/e-shell-settings.h" - -typedef struct _StoreInfo StoreInfo; - -typedef void (*AddStoreCallback) (MailFolderCache *folder_cache, - CamelStore *store, - CamelFolderInfo *info, - StoreInfo *store_info); - -struct _StoreInfo { - gint ref_count; - - CamelStore *store; - - /* Hold a reference to keep them alive. */ - CamelFolder *vtrash; - CamelFolder *vjunk; - - AddStoreCallback callback; - - guint removed : 1; -}; - -static GHashTable *store_table; - -static StoreInfo * -store_info_new (CamelStore *store) -{ - StoreInfo *store_info; - - g_return_val_if_fail (CAMEL_IS_STORE (store), NULL); - - store_info = g_slice_new0 (StoreInfo); - store_info->ref_count = 1; - - store_info->store = g_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) - store_info->vtrash = - camel_store_get_trash_folder_sync (store, NULL, NULL); - if (store->flags & CAMEL_STORE_VJUNK) - store_info->vjunk = - camel_store_get_junk_folder_sync (store, NULL, NULL); - - return store_info; -} - -static StoreInfo * -store_info_ref (StoreInfo *store_info) -{ - g_return_val_if_fail (store_info != NULL, store_info); - g_return_val_if_fail (store_info->ref_count > 0, store_info); - - g_atomic_int_inc (&store_info->ref_count); - - return store_info; -} - -static void -store_info_unref (StoreInfo *store_info) -{ - g_return_if_fail (store_info != NULL); - g_return_if_fail (store_info->ref_count > 0); - - if (g_atomic_int_dec_and_test (&store_info->ref_count)) { - - g_object_unref (store_info->store); - - if (store_info->vtrash != NULL) - g_object_unref (store_info->vtrash); - - if (store_info->vjunk != NULL) - g_object_unref (store_info->vjunk); - - g_slice_free (StoreInfo, store_info); - } -} - -static void -store_table_free (StoreInfo *store_info) -{ - store_info->removed = 1; - store_info_unref (store_info); -} - -static gboolean -mail_store_note_store_cb (MailFolderCache *folder_cache, - CamelStore *store, - CamelFolderInfo *info, - gpointer user_data) -{ - StoreInfo *store_info = user_data; - - if (store_info->callback != NULL) - store_info->callback ( - folder_cache, store, info, store_info); - - if (!store_info->removed) { - /* This keeps message counters up-to-date. */ - if (store_info->vtrash != NULL) - mail_folder_cache_note_folder ( - folder_cache, store_info->vtrash); - if (store_info->vjunk != NULL) - mail_folder_cache_note_folder ( - folder_cache, store_info->vjunk); - } - - store_info_unref (store_info); - - return TRUE; -} - -static gboolean -special_mail_store_is_enabled (CamelStore *store) -{ - CamelService *service; - EShell *shell; - EShellSettings *shell_settings; - const gchar *uid, *prop = NULL; - - service = CAMEL_SERVICE (store); - g_return_val_if_fail (service, FALSE); - - uid = camel_service_get_uid (service); - if (g_strcmp0 (uid, "local") == 0) - prop = "mail-enable-local-folders"; - else if (g_strcmp0 (uid, "vfolder") == 0) - prop = "mail-enable-search-folders"; - - if (!prop) - return TRUE; - - shell = e_shell_get_default (); - shell_settings = e_shell_get_shell_settings (shell); - - return e_shell_settings_get_boolean (shell_settings, prop); -} - -static void -mail_store_add (EMailSession *session, - CamelStore *store, - AddStoreCallback callback) -{ - EMFolderTreeModel *default_model; - MailFolderCache *folder_cache; - StoreInfo *store_info; - - g_return_if_fail (store_table != NULL); - g_return_if_fail (CAMEL_IS_STORE (store)); - - default_model = em_folder_tree_model_get_default (); - folder_cache = e_mail_session_get_folder_cache (session); - - store_info = store_info_new (store); - store_info->callback = callback; - - g_hash_table_insert (store_table, store, store_info); - - if (special_mail_store_is_enabled (store)) - em_folder_tree_model_add_store (default_model, store); - - mail_folder_cache_note_store ( - folder_cache, store, NULL, - mail_store_note_store_cb, store_info_ref (store_info)); -} - -static void -mail_store_add_local_done_cb (MailFolderCache *folder_cache, - CamelStore *store, - CamelFolderInfo *info, - StoreInfo *store_info) -{ - CamelFolder *folder; - gint ii; - - for (ii = 0; ii < E_MAIL_NUM_LOCAL_FOLDERS; ii++) { - folder = e_mail_local_get_folder (ii); - if (folder == NULL) - continue; - mail_folder_cache_note_folder (folder_cache, folder); - } -} - -static void -mail_store_load_accounts (EMailSession *session, - const gchar *data_dir) -{ - CamelStore *local_store; - EAccountList *account_list; - EIterator *iter; - - /* Add the local store. */ - - e_mail_local_init (session, data_dir); - local_store = e_mail_local_get_store (); - - mail_store_add ( - session, local_store, (AddStoreCallback) - mail_store_add_local_done_cb); - - /* Add mail accounts.. */ - - account_list = e_get_account_list (); - - for (iter = e_list_get_iterator ((EList *) account_list); - e_iterator_is_valid (iter); e_iterator_next (iter)) { - EAccount *account; - - account = (EAccount *) e_iterator_get (iter); - - if (!account->enabled) - continue; - - e_mail_store_add_by_account (session, account); - } - - g_object_unref (iter); -} - -void -e_mail_store_init (EMailSession *session, - const gchar *data_dir) -{ - static gboolean initialized = FALSE; - - g_return_if_fail (E_IS_MAIL_SESSION (session)); - - /* This function is idempotent because mail - * migration code may need to call it early. */ - if (initialized) - return; - - /* Initialize global variables. */ - - store_table = g_hash_table_new_full ( - g_direct_hash, g_direct_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) store_table_free); - - mail_store_load_accounts (session, data_dir); - - initialized = TRUE; -} - -void -e_mail_store_add (EMailSession *session, - CamelStore *store) -{ - g_return_if_fail (E_IS_MAIL_SESSION (session)); - g_return_if_fail (CAMEL_IS_STORE (store)); - - mail_store_add (session, store, NULL); -} - -CamelStore * -e_mail_store_add_by_account (EMailSession *session, - EAccount *account) -{ - CamelService *service = NULL; - CamelProvider *provider; - CamelURL *url; - gboolean transport_only; - gboolean service_is_local_delivery; - gboolean service_belongs_in_tree_model; - GError *error = NULL; - - g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); - g_return_val_if_fail (E_IS_ACCOUNT (account), NULL); - - /* check whether it's transport-only accounts */ - transport_only = - (account->source == NULL) || - (account->source->url == NULL) || - (*account->source->url == '\0'); - if (transport_only) - goto handle_transport; - - /* Load the service, but don't connect. Check its provider, - * and if this belongs in the folder tree model, add it. */ - - url = camel_url_new (account->source->url, NULL); - if (url != NULL) { - service_is_local_delivery = - em_utils_is_local_delivery_mbox_file (url); - provider = camel_provider_get (url->protocol, NULL); - camel_url_free (url); - } else { - service_is_local_delivery = FALSE; - provider = NULL; - } - - if (provider == NULL) { - /* In case we do not have a provider here, we handle - * the special case of having multiple mail identities - * eg. a dummy account having just SMTP server defined */ - goto handle_transport; - } - - service = camel_session_add_service ( - CAMEL_SESSION (session), - account->uid, provider->protocol, - CAMEL_PROVIDER_STORE, &error); - - if (!CAMEL_IS_STORE (service)) - goto fail; - - camel_service_set_display_name (service, account->name); - - service_belongs_in_tree_model = - (provider->flags & CAMEL_PROVIDER_IS_STORAGE) && - !service_is_local_delivery; - - if (service_belongs_in_tree_model && store_table != NULL) - e_mail_store_add (session, CAMEL_STORE (service)); - -handle_transport: - - /* While we're at it, add the account's transport (if it has one) - * to the CamelSession. The transport's UID is a kludge for now. - * We take the EAccount's UID and tack on "-transport". */ - - if (account->transport) { - GError *transport_error = NULL; - - url = camel_url_new ( - account->transport->url, - &transport_error); - - if (url != NULL) { - provider = camel_provider_get ( - url->protocol, &transport_error); - camel_url_free (url); - } else - provider = NULL; - - if (provider != NULL) { - gchar *transport_uid; - - transport_uid = g_strconcat ( - account->uid, "-transport", NULL); - - camel_session_add_service ( - CAMEL_SESSION (session), - transport_uid, provider->protocol, - CAMEL_PROVIDER_TRANSPORT, &transport_error); - - g_free (transport_uid); - } - - if (transport_error) { - g_warning ( - "%s: Failed to add transport service: %s", - G_STRFUNC, transport_error->message); - g_error_free (transport_error); - } - } - - if (transport_only) - return NULL; - - return CAMEL_STORE (service); - -fail: - /* FIXME: Show an error dialog. */ - g_warning ( - "Couldn't get service: %s: %s", account->name, - error ? error->message : "Not a CamelStore"); - if (error) - g_error_free (error); - - return NULL; -} - -void -e_mail_store_remove (EMailSession *session, - CamelStore *store) -{ - MailFolderCache *folder_cache; - EMFolderTreeModel *default_model; - - g_return_if_fail (E_IS_MAIL_SESSION (session)); - g_return_if_fail (CAMEL_IS_STORE (store)); - g_return_if_fail (store_table != NULL); - - /* Because the store table holds a reference to each store used - * as a key in it, none of them will ever be gc'ed, meaning any - * call to camel_session_get_{service,store} with the same URL - * will always return the same object. So this works. */ - - if (g_hash_table_lookup (store_table, store) == NULL) - return; - - g_object_ref (store); - - g_hash_table_remove (store_table, store); - - folder_cache = e_mail_session_get_folder_cache (session); - mail_folder_cache_note_store_remove (folder_cache, store); - - default_model = em_folder_tree_model_get_default (); - em_folder_tree_model_remove_store (default_model, store); - - mail_disconnect_store (store); - - g_object_unref (store); -} - -void -e_mail_store_remove_by_account (EMailSession *session, - EAccount *account) -{ - CamelService *service; - CamelProvider *provider; - const gchar *uid; - - g_return_if_fail (E_IS_MAIL_SESSION (session)); - g_return_if_fail (E_IS_ACCOUNT (account)); - - uid = account->uid; - - service = camel_session_get_service (CAMEL_SESSION (session), uid); - g_return_if_fail (CAMEL_IS_STORE (service)); - - provider = camel_service_get_provider (service); - g_return_if_fail (provider != NULL); - - if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE) || store_table == NULL) - return; - - e_mail_store_remove (session, CAMEL_STORE (service)); -} - -void -e_mail_store_foreach (EMailSession *session, - GFunc func, - gpointer user_data) -{ - GList *list, *link; - - /* XXX This is a silly convenience function. - * Could probably just get rid of it. */ - - g_return_if_fail (E_IS_MAIL_SESSION (session)); - g_return_if_fail (func != NULL); - - list = camel_session_list_services (CAMEL_SESSION (session)); - - for (link = list; link != NULL; link = g_list_next (link)) { - CamelService *service = CAMEL_SERVICE (link->data); - - if (CAMEL_IS_STORE (service)) - func (service, user_data); - } - - g_list_free (list); -} diff --git a/mail/e-mail-store.h b/mail/e-mail-store.h deleted file mode 100644 index 5dca416e09..0000000000 --- a/mail/e-mail-store.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * e-mail-store.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MAIL_STORE_H -#define E_MAIL_STORE_H - -#include <camel/camel.h> -#include <mail/e-mail-session.h> -#include <libedataserver/e-account.h> - -G_BEGIN_DECLS - -void e_mail_store_init (EMailSession *session, - const gchar *data_dir); -void e_mail_store_add (EMailSession *session, - CamelStore *store); -CamelStore * e_mail_store_add_by_account (EMailSession *session, - EAccount *account); -void e_mail_store_remove (EMailSession *session, - CamelStore *store); -void e_mail_store_remove_by_account (EMailSession *session, - EAccount *account); -void e_mail_store_foreach (EMailSession *session, - GFunc func, - gpointer user_data); - -G_END_DECLS - -#endif /* E_MAIL_STORE_H */ diff --git a/mail/e-mail.h b/mail/e-mail.h index 7c40b20947..02c169cd10 100644 --- a/mail/e-mail.h +++ b/mail/e-mail.h @@ -32,7 +32,6 @@ #include <mail/e-mail-label-list-store.h> #include <mail/e-mail-label-manager.h> #include <mail/e-mail-label-tree-view.h> -#include <mail/e-mail-local.h> #include <mail/e-mail-message-pane.h> #include <mail/e-mail-migrate.h> #include <mail/e-mail-notebook-view.h> @@ -42,7 +41,6 @@ #include <mail/e-mail-session.h> #include <mail/e-mail-session-utils.h> #include <mail/e-mail-sidebar.h> -#include <mail/e-mail-store.h> #include <mail/e-mail-store-utils.h> #include <mail/e-mail-tag-editor.h> #include <mail/e-mail-view.h> diff --git a/mail/em-account-editor.c b/mail/em-account-editor.c index 6bd96ef299..7b84112a34 100644 --- a/mail/em-account-editor.c +++ b/mail/em-account-editor.c @@ -60,8 +60,6 @@ #include "e-mail-backend.h" #include "e-mail-folder-utils.h" #include "e-mail-junk-options.h" -#include "e-mail-local.h" -#include "e-mail-store.h" #include "em-config.h" #include "em-folder-selection-button.h" #include "em-account-editor.h" @@ -301,26 +299,10 @@ emae_set_original_account (EMAccountEditor *emae, modified_account = e_account_new (); modified_account->enabled = TRUE; emae->priv->new_account = TRUE; - - e_account_set_string ( - modified_account, E_ACCOUNT_DRAFTS_FOLDER_URI, - e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_DRAFTS)); - - e_account_set_string ( - modified_account, E_ACCOUNT_SENT_FOLDER_URI, - e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_SENT)); - - /* encrypt to self by default */ - e_account_set_bool (modified_account, E_ACCOUNT_PGP_ENCRYPT_TO_SELF, TRUE); - e_account_set_bool (modified_account, E_ACCOUNT_SMIME_ENCRYPT_TO_SELF, TRUE); } emae->priv->original_account = original_account; emae->priv->modified_account = modified_account; - - g_signal_connect_swapped ( - emae->priv->modified_account, "changed", - G_CALLBACK (emae_config_target_changed_cb), emae); } static void @@ -909,6 +891,52 @@ emae_finalize (GObject *object) } static void +emae_constructed (GObject *object) +{ + EMAccountEditor *emae; + + emae = EM_ACCOUNT_EDITOR (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (em_account_editor_parent_class)->constructed (object); + + /* Set some defaults on the new account before we get started. */ + if (emae->priv->new_account) { + EMailBackend *backend; + EMailSession *session; + + backend = em_account_editor_get_backend (emae); + session = e_mail_backend_get_session (backend); + + /* Pick local Drafts folder. */ + e_account_set_string ( + emae->priv->modified_account, + E_ACCOUNT_DRAFTS_FOLDER_URI, + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_DRAFTS)); + + /* Pick local Sent folder. */ + e_account_set_string ( + emae->priv->modified_account, + E_ACCOUNT_SENT_FOLDER_URI, + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_SENT)); + + /* Encrypt to self by default. */ + e_account_set_bool ( + emae->priv->modified_account, + E_ACCOUNT_PGP_ENCRYPT_TO_SELF, TRUE); + e_account_set_bool ( + emae->priv->modified_account, + E_ACCOUNT_SMIME_ENCRYPT_TO_SELF, TRUE); + } + + g_signal_connect_swapped ( + emae->priv->modified_account, "changed", + G_CALLBACK (emae_config_target_changed_cb), emae); +} + +static void em_account_editor_class_init (EMAccountEditorClass *class) { GObjectClass *object_class; @@ -920,6 +948,7 @@ em_account_editor_class_init (EMAccountEditorClass *class) object_class->get_property = emae_get_property; object_class->dispose = emae_dispose; object_class->finalize = emae_finalize; + object_class->constructed = emae_constructed; g_object_class_install_property ( object_class, @@ -1295,15 +1324,29 @@ default_folders_clicked (GtkButton *button, gpointer user_data) { EMAccountEditor *emae = user_data; - const gchar *uri; + EMFolderSelectionButton *folder_button; + EMailBackend *backend; + EMailSession *session; + const gchar *folder_uri; - uri = e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_DRAFTS); - em_folder_selection_button_set_folder_uri ((EMFolderSelectionButton *) emae->priv->drafts_folder_button, uri); - emae_account_folder_changed ((EMFolderSelectionButton *) emae->priv->drafts_folder_button, emae); + backend = em_account_editor_get_backend (emae); + session = e_mail_backend_get_session (backend); - uri = e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_SENT); - em_folder_selection_button_set_folder_uri ((EMFolderSelectionButton *) emae->priv->sent_folder_button, uri); - emae_account_folder_changed ((EMFolderSelectionButton *) emae->priv->sent_folder_button, emae); + folder_button = + EM_FOLDER_SELECTION_BUTTON ( + emae->priv->drafts_folder_button); + folder_uri = e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_DRAFTS); + em_folder_selection_button_set_folder_uri (folder_button, folder_uri); + emae_account_folder_changed (folder_button, emae); + + folder_button = + EM_FOLDER_SELECTION_BUTTON ( + emae->priv->sent_folder_button); + folder_uri = e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_SENT); + em_folder_selection_button_set_folder_uri (folder_button, folder_uri); + emae_account_folder_changed (folder_button, emae); gtk_toggle_button_set_active (emae->priv->trash_folder_check, FALSE); gtk_toggle_button_set_active (emae->priv->junk_folder_check, FALSE); @@ -1805,10 +1848,12 @@ emae_account_folder (EMAccountEditor *emae, EAccount *account; EMFolderSelectionButton *folder; EMailBackend *backend; + EMailSession *session; const gchar *uri; account = em_account_editor_get_modified_account (emae); backend = em_account_editor_get_backend (emae); + session = e_mail_backend_get_session (backend); folder = (EMFolderSelectionButton *) e_builder_get_widget (builder, name); em_folder_selection_button_set_backend (folder, backend); @@ -1817,7 +1862,7 @@ emae_account_folder (EMAccountEditor *emae, if (uri != NULL) { em_folder_selection_button_set_folder_uri (folder, uri); } else { - uri = e_mail_local_get_folder_uri (deffolder); + uri = e_mail_session_get_local_folder_uri (session, deffolder); em_folder_selection_button_set_folder_uri (folder, uri); } @@ -5136,7 +5181,6 @@ emae_commit (EConfig *ec, camel_url_free (url); if (original_account != NULL) { - d (printf ("Committing account '%s'\n", e_account_get_string (modified_account, E_ACCOUNT_NAME))); forget_password_if_needed (original_account, modified_account, E_ACCOUNT_SOURCE_SAVE_PASSWD, E_ACCOUNT_SOURCE_URL); forget_password_if_needed (original_account, modified_account, E_ACCOUNT_TRANSPORT_SAVE_PASSWD, E_ACCOUNT_TRANSPORT_URL); @@ -5144,30 +5188,25 @@ emae_commit (EConfig *ec, account = original_account; e_account_list_change (accounts, account); } else { - CamelProvider *provider; - - d (printf ("Adding new account '%s'\n", e_account_get_string (modified_account, E_ACCOUNT_NAME))); e_account_list_add (accounts, modified_account); account = modified_account; + } - provider = emae_get_store_provider (emae); + if (gtk_toggle_button_get_active (emae->priv->default_account)) { + EMailBackend *backend; + EMailSession *session; + EMailAccountStore *store; + CamelService *service; - /* HACK: this will add the account to the folder tree. - * We should just be listening to the account list directly for changed events */ - if (account->enabled - && provider != NULL - && (provider->flags & CAMEL_PROVIDER_IS_STORAGE)) { - EMailBackend *backend; - EMailSession *session; - - backend = em_account_editor_get_backend (emae); - session = e_mail_backend_get_session (backend); - e_mail_store_add_by_account (session, account); - } - } + backend = em_account_editor_get_backend (emae); + session = e_mail_backend_get_session (backend); - if (gtk_toggle_button_get_active (emae->priv->default_account)) - e_account_list_set_default (accounts, account); + service = camel_session_get_service ( + CAMEL_SESSION (session), account->uid); + + store = e_mail_session_get_account_store (session); + e_mail_account_store_set_default_service (store, service); + } e_account_list_save (accounts); } diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c index 0eceeea228..f6a938bdac 100644 --- a/mail/em-composer-utils.c +++ b/mail/em-composer-utils.c @@ -45,7 +45,6 @@ #include "shell/e-shell.h" #include "e-mail-folder-utils.h" -#include "e-mail-local.h" #include "e-mail-session.h" #include "e-mail-session-utils.h" #include "em-utils.h" @@ -74,6 +73,7 @@ typedef struct _ForwardData ForwardData; struct _AsyncContext { CamelMimeMessage *message; + EMailSession *session; EMsgComposer *composer; EActivity *activity; EMailReader *reader; @@ -98,6 +98,9 @@ async_context_free (AsyncContext *context) if (context->message != NULL) g_object_unref (context->message); + if (context->session != NULL) + g_object_unref (context->session); + if (context->composer != NULL) g_object_unref (context->composer); @@ -206,7 +209,8 @@ is_group_definition (const gchar *str) } static gboolean -composer_presend_check_recipients (EMsgComposer *composer) +composer_presend_check_recipients (EMsgComposer *composer, + EMailSession *session) { EDestination **recipients; EDestination **recipients_bcc; @@ -358,7 +362,8 @@ finished: } static gboolean -composer_presend_check_account (EMsgComposer *composer) +composer_presend_check_account (EMsgComposer *composer, + EMailSession *session) { EComposerHeaderTable *table; EAccount *account; @@ -377,7 +382,8 @@ composer_presend_check_account (EMsgComposer *composer) } static gboolean -composer_presend_check_downloads (EMsgComposer *composer) +composer_presend_check_downloads (EMsgComposer *composer, + EMailSession *session) { EAttachmentView *view; EAttachmentStore *store; @@ -396,7 +402,8 @@ composer_presend_check_downloads (EMsgComposer *composer) } static gboolean -composer_presend_check_plugins (EMsgComposer *composer) +composer_presend_check_plugins (EMsgComposer *composer, + EMailSession *session) { EMEvent *eme; EMEventTargetComposer *target; @@ -428,7 +435,8 @@ composer_presend_check_plugins (EMsgComposer *composer) } static gboolean -composer_presend_check_subject (EMsgComposer *composer) +composer_presend_check_subject (EMsgComposer *composer, + EMailSession *session) { EComposerHeaderTable *table; const gchar *subject; @@ -446,7 +454,8 @@ composer_presend_check_subject (EMsgComposer *composer) } static gboolean -composer_presend_check_unwanted_html (EMsgComposer *composer) +composer_presend_check_unwanted_html (EMsgComposer *composer, + EMailSession *session) { EDestination **recipients; EComposerHeaderTable *table; @@ -556,10 +565,10 @@ exit: static void em_utils_composer_send_cb (EMsgComposer *composer, CamelMimeMessage *message, - EActivity *activity) + EActivity *activity, + EMailSession *session) { AsyncContext *context; - CamelSession *session; GCancellable *cancellable; context = g_slice_new0 (AsyncContext); @@ -568,10 +577,9 @@ em_utils_composer_send_cb (EMsgComposer *composer, context->activity = g_object_ref (activity); cancellable = e_activity_get_cancellable (activity); - session = e_msg_composer_get_session (context->composer); e_mail_session_send_to ( - E_MAIL_SESSION (session), message, + session, message, G_PRIORITY_DEFAULT, cancellable, NULL, NULL, (GAsyncReadyCallback) composer_send_completed, context); @@ -593,6 +601,7 @@ composer_set_no_change (EMsgComposer *composer) /* delete original messages from Outbox folder */ static void manage_x_evolution_replace_outbox (EMsgComposer *composer, + EMailSession *session, CamelMimeMessage *message, GCancellable *cancellable) { @@ -610,7 +619,8 @@ manage_x_evolution_replace_outbox (EMsgComposer *composer, if (!message_uid) return; - outbox = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX); + outbox = e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_OUTBOX); g_return_if_fail (outbox != NULL); camel_folder_set_message_flags ( @@ -708,7 +718,8 @@ composer_save_to_drafts_append_mail (AsyncContext *context, CamelMessageInfo *info; local_drafts_folder = - e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_DRAFTS); + e_mail_session_get_local_folder ( + context->session, E_MAIL_LOCAL_FOLDER_DRAFTS); if (drafts_folder == NULL) drafts_folder = g_object_ref (local_drafts_folder); @@ -778,24 +789,24 @@ composer_save_to_drafts_got_folder (EMailSession *session, static void em_utils_composer_save_to_drafts_cb (EMsgComposer *composer, CamelMimeMessage *message, - EActivity *activity) + EActivity *activity, + EMailSession *session) { AsyncContext *context; EComposerHeaderTable *table; const gchar *drafts_folder_uri = NULL; const gchar *local_drafts_folder_uri; - CamelSession *session; EAccount *account; context = g_slice_new0 (AsyncContext); context->message = g_object_ref (message); + context->session = g_object_ref (session); context->composer = g_object_ref (composer); context->activity = g_object_ref (activity); - session = e_msg_composer_get_session (composer); - local_drafts_folder_uri = - e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_DRAFTS); + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_DRAFTS); table = e_msg_composer_get_header_table (composer); account = e_composer_header_table_get_account (table); @@ -816,9 +827,9 @@ em_utils_composer_save_to_drafts_cb (EMsgComposer *composer, context->folder_uri = g_strdup (drafts_folder_uri); e_mail_session_uri_to_folder ( - E_MAIL_SESSION (session), - drafts_folder_uri, 0, G_PRIORITY_DEFAULT, - cancellable, (GAsyncReadyCallback) + session, drafts_folder_uri, 0, + G_PRIORITY_DEFAULT, cancellable, + (GAsyncReadyCallback) composer_save_to_drafts_got_folder, context); } } @@ -851,7 +862,7 @@ composer_save_to_outbox_completed (CamelFolder *outbox_folder, /* special processing for Outbox folder */ manage_x_evolution_replace_outbox ( - context->composer, context->message, + context->composer, context->session, context->message, e_activity_get_cancellable (context->activity)); e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED); @@ -869,7 +880,8 @@ exit: static void em_utils_composer_save_to_outbox_cb (EMsgComposer *composer, CamelMimeMessage *message, - EActivity *activity) + EActivity *activity, + EMailSession *session) { AsyncContext *context; CamelFolder *outbox_folder; @@ -878,11 +890,15 @@ em_utils_composer_save_to_outbox_cb (EMsgComposer *composer, context = g_slice_new0 (AsyncContext); context->message = g_object_ref (message); + context->session = g_object_ref (session); context->composer = g_object_ref (composer); context->activity = g_object_ref (activity); cancellable = e_activity_get_cancellable (activity); - outbox_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX); + + outbox_folder = + e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_OUTBOX); info = camel_message_info_new (NULL); camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0); @@ -900,7 +916,8 @@ static void em_utils_composer_print_cb (EMsgComposer *composer, GtkPrintOperationAction action, CamelMimeMessage *message, - EActivity *activity) + EActivity *activity, + EMailSession *session) { EMFormatHTMLPrint *efhp; @@ -2719,7 +2736,7 @@ em_utils_reply_to_message (EShell *shell, static void post_header_clicked_cb (EComposerPostHeader *header, - EMsgComposer *composer) + EMailSession *session) { EShell *shell; EShellBackend *shell_backend; @@ -2731,14 +2748,14 @@ post_header_clicked_cb (EComposerPostHeader *header, GList *list; /* FIXME Figure out a way to pass the mail backend in. */ - shell = e_msg_composer_get_shell (composer); + shell = e_shell_get_default (); shell_backend = e_shell_get_backend_by_name (shell, "mail"); /* FIXME Limit the folder tree to the NNTP account? */ model = em_folder_tree_model_get_default (); dialog = em_folder_selector_new ( - GTK_WINDOW (composer), + /* FIXME GTK_WINDOW (composer) */ NULL, E_MAIL_BACKEND (shell_backend), model, EM_FOLDER_SELECTOR_CAN_CREATE, _("Posting destination"), @@ -2788,13 +2805,15 @@ exit: * things the #EMsgComposer instance can't do itself. **/ void -em_configure_new_composer (EMsgComposer *composer) +em_configure_new_composer (EMsgComposer *composer, + EMailSession *session) { EComposerHeaderTable *table; EComposerHeaderType header_type; EComposerHeader *header; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + g_return_if_fail (E_IS_MAIL_SESSION (session)); header_type = E_COMPOSER_HEADER_POST_TO; table = e_msg_composer_get_header_table (composer); @@ -2802,43 +2821,43 @@ em_configure_new_composer (EMsgComposer *composer) g_signal_connect ( composer, "presend", - G_CALLBACK (composer_presend_check_recipients), NULL); + G_CALLBACK (composer_presend_check_recipients), session); g_signal_connect ( composer, "presend", - G_CALLBACK (composer_presend_check_account), NULL); + G_CALLBACK (composer_presend_check_account), session); g_signal_connect ( composer, "presend", - G_CALLBACK (composer_presend_check_downloads), NULL); + G_CALLBACK (composer_presend_check_downloads), session); g_signal_connect ( composer, "presend", - G_CALLBACK (composer_presend_check_plugins), NULL); + G_CALLBACK (composer_presend_check_plugins), session); g_signal_connect ( composer, "presend", - G_CALLBACK (composer_presend_check_subject), NULL); + G_CALLBACK (composer_presend_check_subject), session); g_signal_connect ( composer, "presend", - G_CALLBACK (composer_presend_check_unwanted_html), NULL); + G_CALLBACK (composer_presend_check_unwanted_html), session); g_signal_connect ( composer, "send", - G_CALLBACK (em_utils_composer_send_cb), NULL); + G_CALLBACK (em_utils_composer_send_cb), session); g_signal_connect ( composer, "save-to-drafts", - G_CALLBACK (em_utils_composer_save_to_drafts_cb), NULL); + G_CALLBACK (em_utils_composer_save_to_drafts_cb), session); g_signal_connect ( composer, "save-to-outbox", - G_CALLBACK (em_utils_composer_save_to_outbox_cb), NULL); + G_CALLBACK (em_utils_composer_save_to_outbox_cb), session); g_signal_connect ( composer, "print", - G_CALLBACK (em_utils_composer_print_cb), NULL); + G_CALLBACK (em_utils_composer_print_cb), session); /* Handle "Post To:" button clicks, which displays a folder tree * widget. The composer doesn't know about folder tree widgets, @@ -2849,5 +2868,5 @@ em_configure_new_composer (EMsgComposer *composer) * the folder selector dialog. See the handler function. */ g_signal_connect ( header, "clicked", - G_CALLBACK (post_header_clicked_cb), composer); + G_CALLBACK (post_header_clicked_cb), session); } diff --git a/mail/em-composer-utils.h b/mail/em-composer-utils.h index 215e6bb2bc..093001dfd0 100644 --- a/mail/em-composer-utils.h +++ b/mail/em-composer-utils.h @@ -79,7 +79,8 @@ EMsgComposer * em_utils_reply_to_message (EShell *shell, CamelInternetAddress *address); EDestination ** em_utils_camel_address_to_destination (CamelInternetAddress *iaddr); -void em_configure_new_composer (EMsgComposer *composer); +void em_configure_new_composer (EMsgComposer *composer, + EMailSession *session); G_END_DECLS diff --git a/mail/em-folder-properties.c b/mail/em-folder-properties.c index 310aa76740..9dbffba2e2 100644 --- a/mail/em-folder-properties.c +++ b/mail/em-folder-properties.c @@ -34,7 +34,6 @@ #include "e-mail-backend.h" #include "e-mail-folder-utils.h" -#include "e-mail-local.h" #include "mail-ops.h" #include "mail-mt.h" #include "mail-vfolder.h" @@ -249,25 +248,26 @@ emfp_dialog_run (AsyncContext *context) EMConfigTargetFolder *target; EShellWindow *shell_window; EShellView *shell_view; - CamelStore *local_store; CamelStore *parent_store; + CamelFolderSummary *summary; + gboolean store_is_local; gboolean hide_deleted; GSettings *settings; const gchar *name; + const gchar *uid; shell_view = context->shell_view; shell_window = e_shell_view_get_shell_window (shell_view); - local_store = e_mail_local_get_store (); parent_store = camel_folder_get_parent_store (context->folder); /* Get number of VISIBLE and DELETED messages, instead of TOTAL * messages. VISIBLE+DELETED gives the correct count that matches * the label below the Send & Receive button. */ - name = camel_folder_get_display_name (context->folder); - context->total = camel_folder_summary_get_visible_count (context->folder->summary); - context->unread = camel_folder_summary_get_unread_count (context->folder->summary); - deleted = camel_folder_summary_get_deleted_count (context->folder->summary); + summary = context->folder->summary; + context->total = camel_folder_summary_get_visible_count (summary); + context->unread = camel_folder_summary_get_unread_count (summary); + deleted = camel_folder_summary_get_deleted_count (summary); settings = g_settings_new ("org.gnome.evolution.mail"); hide_deleted = !g_settings_get_boolean (settings, "show-deleted"); @@ -290,7 +290,12 @@ emfp_dialog_run (AsyncContext *context) context->total = camel_folder_summary_count ( context->folder->summary); - if (parent_store == local_store + name = camel_folder_get_display_name (context->folder); + + uid = camel_service_get_uid (CAMEL_SERVICE (parent_store)); + store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0); + + if (store_is_local && (!strcmp (name, "Drafts") || !strcmp (name, "Templates") || !strcmp (name, "Inbox") @@ -474,7 +479,7 @@ em_folder_properties_show (EShellView *shell_view, /* Show the Edit Rule dialog for Search Folders, but not "Unmatched". * "Unmatched" is a special Search Folder which can't be modified. */ - if (g_strcmp0 (uid, "vfolder") == 0) { + if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0) { if (g_strcmp0 (folder_name, CAMEL_UNMATCHED_NAME) != 0) { gchar *folder_uri; diff --git a/mail/em-folder-selection-button.c b/mail/em-folder-selection-button.c index 1b8ef6cd71..1532e42364 100644 --- a/mail/em-folder-selection-button.c +++ b/mail/em-folder-selection-button.c @@ -258,6 +258,7 @@ folder_selection_button_clicked (GtkButton *button) EMFolderSelector *selector; EMFolderTree *folder_tree; EMFolderTreeModel *model = NULL; + EMailSession *session; GtkWidget *dialog; GtkTreeSelection *selection; gpointer parent; @@ -267,9 +268,11 @@ folder_selection_button_clicked (GtkButton *button) parent = gtk_widget_get_toplevel (GTK_WIDGET (button)); parent = gtk_widget_is_toplevel (parent) ? parent : NULL; + session = e_mail_backend_get_session (priv->backend); + if (priv->store != NULL) { model = em_folder_tree_model_new (); - em_folder_tree_model_set_backend (model, priv->backend); + em_folder_tree_model_set_session (model, session); em_folder_tree_model_add_store (model, priv->store); } diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c index 27fa44aea4..dea9daa7ff 100644 --- a/mail/em-folder-tree-model.c +++ b/mail/em-folder-tree-model.c @@ -51,8 +51,6 @@ #include "em-event.h" #include "e-mail-folder-utils.h" -#include "e-mail-local.h" -#include "e-mail-store.h" #include "shell/e-shell.h" #define EM_FOLDER_TREE_MODEL_GET_PRIVATE(obj) \ @@ -67,24 +65,20 @@ struct _EMFolderTreeModelPrivate { * mimic the sidebar. */ GtkTreeSelection *selection; /* weak reference */ - EAccountList *accounts; - EMailBackend *backend; + EMailSession *session; + EMailAccountStore *account_store; /* CamelStore -> EMFolderTreeStoreInfo */ GHashTable *store_index; /* URI -> GtkTreeRowReference */ GHashTable *uri_index; - - gulong account_changed_id; - gulong account_removed_id; - gulong account_added_id; }; enum { PROP_0, PROP_SELECTION, - PROP_BACKEND + PROP_SESSION }; enum { @@ -123,111 +117,66 @@ folder_tree_model_sort (GtkTreeModel *model, gpointer unused) { EMFolderTreeModel *folder_tree_model; - EMailBackend *backend; gchar *aname, *bname; - CamelStore *store; - gboolean is_store; + CamelService *service_a; + CamelService *service_b; + gboolean a_is_store; + gboolean b_is_store; const gchar *store_uid = NULL; - guint32 aflags, bflags; - guint asortorder, bsortorder; + guint32 flags_a, flags_b; gint rv = -2; folder_tree_model = EM_FOLDER_TREE_MODEL (model); - backend = em_folder_tree_model_get_backend (folder_tree_model); - g_return_val_if_fail (backend != NULL, -1); gtk_tree_model_get ( model, a, - COL_BOOL_IS_STORE, &is_store, - COL_POINTER_CAMEL_STORE, &store, + COL_BOOL_IS_STORE, &a_is_store, + COL_POINTER_CAMEL_STORE, &service_a, COL_STRING_DISPLAY_NAME, &aname, - COL_UINT_FLAGS, &aflags, - COL_UINT_SORTORDER, &asortorder, + COL_UINT_FLAGS, &flags_a, -1); gtk_tree_model_get ( model, b, + COL_BOOL_IS_STORE, &b_is_store, + COL_POINTER_CAMEL_STORE, &service_b, COL_STRING_DISPLAY_NAME, &bname, - COL_UINT_FLAGS, &bflags, - COL_UINT_SORTORDER, &bsortorder, + COL_UINT_FLAGS, &flags_b, -1); - if (CAMEL_IS_SERVICE (store)) - store_uid = camel_service_get_uid (CAMEL_SERVICE (store)); + if (CAMEL_IS_SERVICE (service_a)) + store_uid = camel_service_get_uid (service_a); - if (is_store) { - EShell *shell; - EShellBackend *shell_backend; - EShellSettings *shell_settings; - - shell_backend = E_SHELL_BACKEND (backend); - shell = e_shell_backend_get_shell (shell_backend); - shell_settings = e_shell_get_shell_settings (shell); - - if (e_shell_settings_get_boolean ( - shell_settings, "mail-sort-accounts-alpha")) { - const gchar *on_this_computer = _("On This Computer"); - const gchar *search_folders = _("Search Folders"); - - /* On This Computer is always first, and Search Folders - * is always last. */ - if (e_shell_get_express_mode (shell)) { - if (g_str_equal (aname, on_this_computer) && - g_str_equal (bname, search_folders)) - rv = -1; - else if (g_str_equal (bname, on_this_computer) && - g_str_equal (aname, search_folders)) - rv = 1; - else if (g_str_equal (aname, on_this_computer)) - rv = 1; - else if (g_str_equal (bname, on_this_computer)) - rv = -1; - else if (g_str_equal (aname, search_folders)) - rv = 1; - else if (g_str_equal (bname, search_folders)) - rv = -1; - } else { - if (g_str_equal (aname, on_this_computer)) - rv = -1; - else if (g_str_equal (bname, on_this_computer)) - rv = 1; - else if (g_str_equal (aname, search_folders)) - rv = 1; - else if (g_str_equal (bname, search_folders)) - rv = -1; - } - } else if (asortorder || bsortorder) { - if (asortorder < bsortorder) - rv = -1; - else if (asortorder > bsortorder) - rv = 1; - else - rv = 0; - } - } else if (g_strcmp0 (store_uid, "vfolder") == 0) { + if (a_is_store && b_is_store) { + rv = e_mail_account_store_compare_services ( + folder_tree_model->priv->account_store, + service_a, service_b); + + } else if (g_strcmp0 (store_uid, E_MAIL_SESSION_VFOLDER_UID) == 0) { /* UNMATCHED is always last. */ if (aname && !strcmp (aname, _("UNMATCHED"))) rv = 1; else if (bname && !strcmp (bname, _("UNMATCHED"))) rv = -1; + } else { /* Inbox is always first. */ - if ((aflags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX) + if ((flags_a & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX) rv = -1; - else if ((bflags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX) + else if ((flags_b & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX) rv = 1; } - if (aname == NULL) { - if (bname == NULL) + if (rv == -2) { + if (aname != NULL && bname != NULL) + rv = g_utf8_collate (aname, bname); + else if (aname == bname) rv = 0; - else + else if (aname == NULL) rv = -1; - } else if (bname == NULL) - rv = 1; - - if (rv == -2) - rv = g_utf8_collate (aname, bname); + else + rv = 1; + } g_free (aname); g_free (bname); @@ -236,175 +185,44 @@ folder_tree_model_sort (GtkTreeModel *model, } static void -account_changed_cb (EAccountList *accounts, - EAccount *account, - EMFolderTreeModel *model) +folder_tree_model_service_removed (EMailAccountStore *account_store, + CamelService *service, + EMFolderTreeModel *folder_tree_model) { - EMailBackend *backend; - EMailSession *session; - CamelService *service; - - backend = em_folder_tree_model_get_backend (model); - session = e_mail_backend_get_session (backend); - - service = camel_session_get_service ( - CAMEL_SESSION (session), account->uid); - - if (!CAMEL_IS_STORE (service)) - return; - - em_folder_tree_model_remove_store (model, CAMEL_STORE (service)); - - /* check if store needs to be added at all*/ - if (!account->enabled) - return; - - em_folder_tree_model_add_store (model, CAMEL_STORE (service)); + em_folder_tree_model_remove_store ( + folder_tree_model, CAMEL_STORE (service)); } static void -account_removed_cb (EAccountList *accounts, - EAccount *account, - EMFolderTreeModel *model) +folder_tree_model_service_enabled (EMailAccountStore *account_store, + CamelService *service, + EMFolderTreeModel *folder_tree_model) { - EMailBackend *backend; - EMailSession *session; - CamelService *service; - - backend = em_folder_tree_model_get_backend (model); - session = e_mail_backend_get_session (backend); - - service = camel_session_get_service ( - CAMEL_SESSION (session), account->uid); - - if (!CAMEL_IS_STORE (service)) - return; - - em_folder_tree_model_remove_store (model, CAMEL_STORE (service)); + em_folder_tree_model_add_store ( + folder_tree_model, CAMEL_STORE (service)); } -/* HACK: FIXME: the component should listen to the account object directly */ static void -account_added_cb (EAccountList *accounts, - EAccount *account, - EMFolderTreeModel *model) +folder_tree_model_service_disabled (EMailAccountStore *account_store, + CamelService *service, + EMFolderTreeModel *folder_tree_model) { - EMailBackend *backend; - EMailSession *session; - - backend = em_folder_tree_model_get_backend (model); - session = e_mail_backend_get_session (backend); - - e_mail_store_add_by_account (session, account); + em_folder_tree_model_remove_store ( + folder_tree_model, CAMEL_STORE (service)); } static void -folder_tree_model_sort_changed (EMFolderTreeModel *tree_model) +folder_tree_model_services_reordered (EMailAccountStore *account_store, + gboolean default_restored, + EMFolderTreeModel *folder_tree_model) { - GtkTreeModel *model; - - g_return_if_fail (tree_model != NULL); - g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (tree_model)); - - model = GTK_TREE_MODEL (tree_model); - if (!model) - return; - - /* this invokes also sort on a GtkTreeStore */ + /* This forces the tree store to re-sort. */ gtk_tree_sortable_set_default_sort_func ( - GTK_TREE_SORTABLE (model), + GTK_TREE_SORTABLE (folder_tree_model), folder_tree_model_sort, NULL, NULL); } static void -account_sort_order_changed_cb (EMFolderTreeModel *folder_tree_model) -{ - EMailBackend *mail_backend; - GtkTreeModel *model; - GtkTreeStore *tree_store; - GtkTreeIter iter; - - g_return_if_fail (folder_tree_model != NULL); - - model = GTK_TREE_MODEL (folder_tree_model); - g_return_if_fail (model != NULL); - - tree_store = GTK_TREE_STORE (folder_tree_model); - g_return_if_fail (tree_store != NULL); - - if (!gtk_tree_model_get_iter_first (model, &iter)) - return; - - mail_backend = em_folder_tree_model_get_backend (folder_tree_model); - - do { - CamelStore *store = NULL; - - gtk_tree_model_get (model, &iter, COL_POINTER_CAMEL_STORE, &store, -1); - - if (store) { - const gchar *account_uid; - guint sortorder; - - account_uid = camel_service_get_uid (CAMEL_SERVICE (store)); - sortorder = em_utils_get_account_sort_order (mail_backend, account_uid); - - gtk_tree_store_set (tree_store, &iter, COL_UINT_SORTORDER, sortorder, -1); - } - } while (gtk_tree_model_iter_next (model, &iter)); - - folder_tree_model_sort_changed (folder_tree_model); -} - -static void -add_remove_special_folder (EMFolderTreeModel *model, - const gchar *account_uid, - gboolean add) -{ - EMailBackend *backend; - EMailSession *session; - CamelService *service; - - backend = em_folder_tree_model_get_backend (model); - session = e_mail_backend_get_session (backend); - - service = camel_session_get_service ( - CAMEL_SESSION (session), account_uid); - - if (!CAMEL_IS_STORE (service)) - return; - - if (add) - em_folder_tree_model_add_store (model, CAMEL_STORE (service)); - else - em_folder_tree_model_remove_store (model, CAMEL_STORE (service)); -} - -static void -enable_local_folders_changed_cb (EMFolderTreeModel *model, - GParamSpec *spec, - EShellSettings *shell_settings) -{ - g_return_if_fail (model != NULL); - g_return_if_fail (shell_settings != NULL); - - add_remove_special_folder (model, "local", - e_shell_settings_get_boolean (shell_settings, "mail-enable-local-folders")); -} - -static void -enable_search_folders_changed_cb (EMFolderTreeModel *model, - GParamSpec *spec, - EShellSettings *shell_settings) -{ - g_return_if_fail (model != NULL); - g_return_if_fail (shell_settings != NULL); - - add_remove_special_folder (model, "vfolder", - e_shell_settings_get_boolean (shell_settings, "mail-enable-search-folders")); -} - -static void folder_tree_model_selection_finalized_cb (EMFolderTreeModel *model) { model->priv->selection = NULL; @@ -425,8 +243,8 @@ folder_tree_model_set_property (GObject *object, g_value_get_object (value)); return; - case PROP_BACKEND: - em_folder_tree_model_set_backend ( + case PROP_SESSION: + em_folder_tree_model_set_session ( EM_FOLDER_TREE_MODEL (object), g_value_get_object (value)); return; @@ -449,10 +267,10 @@ folder_tree_model_get_property (GObject *object, EM_FOLDER_TREE_MODEL (object))); return; - case PROP_BACKEND: + case PROP_SESSION: g_value_set_object ( value, - em_folder_tree_model_get_backend ( + em_folder_tree_model_get_session ( EM_FOLDER_TREE_MODEL (object))); return; } @@ -474,26 +292,17 @@ folder_tree_model_dispose (GObject *object) priv->selection = NULL; } - if (priv->backend != NULL) { - EShell *shell; - EShellBackend *shell_backend; - EShellSettings *shell_settings; - - shell_backend = E_SHELL_BACKEND (priv->backend); - shell = e_shell_backend_get_shell (shell_backend); - shell_settings = e_shell_get_shell_settings (shell); - - g_signal_handlers_disconnect_by_func ( - priv->backend, account_sort_order_changed_cb, object); - g_signal_handlers_disconnect_by_func ( - shell_settings, account_sort_order_changed_cb, object); - g_signal_handlers_disconnect_by_func ( - shell_settings, enable_local_folders_changed_cb, object); - g_signal_handlers_disconnect_by_func ( - shell_settings, enable_search_folders_changed_cb, object); - - g_object_unref (priv->backend); - priv->backend = NULL; + if (priv->session != NULL) { + g_object_unref (priv->session); + priv->session = NULL; + } + + if (priv->account_store != NULL) { + g_signal_handlers_disconnect_matched ( + priv->account_store, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->account_store); + priv->account_store = NULL; } /* Chain up to parent's dispose() method. */ @@ -510,13 +319,6 @@ folder_tree_model_finalize (GObject *object) g_hash_table_destroy (priv->store_index); g_hash_table_destroy (priv->uri_index); - g_signal_handler_disconnect ( - priv->accounts, priv->account_changed_id); - g_signal_handler_disconnect ( - priv->accounts, priv->account_removed_id); - g_signal_handler_disconnect ( - priv->accounts, priv->account_added_id); - /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -524,8 +326,6 @@ folder_tree_model_finalize (GObject *object) static void folder_tree_model_constructed (GObject *object) { - EMFolderTreeModelPrivate *priv; - GType col_types[] = { G_TYPE_STRING, /* display name */ G_TYPE_POINTER, /* store object */ @@ -542,8 +342,6 @@ folder_tree_model_constructed (GObject *object) G_TYPE_UINT /* user's sortorder */ }; - priv = EM_FOLDER_TREE_MODEL_GET_PRIVATE (object); - gtk_tree_store_set_column_types ( GTK_TREE_STORE (object), NUM_COLUMNS, col_types); gtk_tree_sortable_set_default_sort_func ( @@ -554,17 +352,6 @@ folder_tree_model_constructed (GObject *object) GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING); - priv->accounts = e_get_account_list (); - priv->account_changed_id = g_signal_connect ( - priv->accounts, "account-changed", - G_CALLBACK (account_changed_cb), object); - priv->account_removed_id = g_signal_connect ( - priv->accounts, "account-removed", - G_CALLBACK (account_removed_cb), object); - priv->account_added_id = g_signal_connect ( - priv->accounts, "account-added", - G_CALLBACK (account_added_cb), object); - /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (parent_class)->constructed (object); } @@ -586,12 +373,12 @@ em_folder_tree_model_class_init (EMFolderTreeModelClass *class) g_object_class_install_property ( object_class, - PROP_BACKEND, + PROP_SESSION, g_param_spec_object ( - "backend", + "session", NULL, NULL, - E_TYPE_MAIL_BACKEND, + E_TYPE_MAIL_SESSION, G_PARAM_READWRITE)); g_object_class_install_property ( @@ -754,60 +541,63 @@ em_folder_tree_model_set_selection (EMFolderTreeModel *model, g_object_notify (G_OBJECT (model), "selection"); } -EMailBackend * -em_folder_tree_model_get_backend (EMFolderTreeModel *model) +EMailSession * +em_folder_tree_model_get_session (EMFolderTreeModel *model) { g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), NULL); - return model->priv->backend; + return model->priv->session; } void -em_folder_tree_model_set_backend (EMFolderTreeModel *model, - EMailBackend *backend) +em_folder_tree_model_set_session (EMFolderTreeModel *model, + EMailSession *session) { g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model)); - if (backend != NULL) { - g_return_if_fail (E_IS_MAIL_BACKEND (backend)); - g_object_ref (backend); + if (session != NULL) { + g_return_if_fail (E_IS_MAIL_SESSION (session)); + g_object_ref (session); } - if (model->priv->backend != NULL) - g_object_unref (model->priv->backend); + if (model->priv->session != NULL) + g_object_unref (model->priv->session); - model->priv->backend = backend; + model->priv->session = session; /* FIXME Technically we should be disconnecting this signal - * when replacing an old backend with a new backend, + * when replacing an old session with a new session, * but at present this function is only called once. */ - if (backend != NULL) { + if (session != NULL) { + EMailAccountStore *account_store; MailFolderCache *folder_cache; - EMailSession *session; - EShell *shell; - EShellBackend *shell_backend; - EShellSettings *shell_settings; - - shell_backend = E_SHELL_BACKEND (backend); - shell = e_shell_backend_get_shell (shell_backend); - shell_settings = e_shell_get_shell_settings (shell); - session = e_mail_backend_get_session (backend); folder_cache = e_mail_session_get_folder_cache (session); + account_store = e_mail_session_get_account_store (session); - g_signal_connect_swapped ( - backend, "account-sort-order-changed", - G_CALLBACK (account_sort_order_changed_cb), model); + /* Keep our own reference since we connect to its signals. */ + g_warn_if_fail (model->priv->account_store == NULL); + model->priv->account_store = g_object_ref (account_store); - g_signal_connect_swapped ( - shell_settings, "notify::mail-sort-accounts-alpha", - G_CALLBACK (account_sort_order_changed_cb), model); - g_signal_connect_swapped ( - shell_settings, "notify::mail-enable-local-folders", - G_CALLBACK (enable_local_folders_changed_cb), model); - g_signal_connect_swapped ( - shell_settings, "notify::mail-enable-search-folders", - G_CALLBACK (enable_search_folders_changed_cb), model); + g_signal_connect ( + account_store, "service-removed", + G_CALLBACK (folder_tree_model_service_removed), + model); + + g_signal_connect ( + account_store, "service-enabled", + G_CALLBACK (folder_tree_model_service_enabled), + model); + + g_signal_connect ( + account_store, "service-disabled", + G_CALLBACK (folder_tree_model_service_disabled), + model); + + g_signal_connect ( + account_store, "services-reordered", + G_CALLBACK (folder_tree_model_services_reordered), + model); g_signal_connect_swapped ( folder_cache, "folder-unread-updated", @@ -815,7 +605,7 @@ em_folder_tree_model_set_backend (EMFolderTreeModel *model, model); } - g_object_notify (G_OBJECT (model), "backend"); + g_object_notify (G_OBJECT (model), "session"); } void @@ -828,7 +618,6 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeRowReference *uri_row, *path_row; GtkTreeStore *tree_store; MailFolderCache *folder_cache; - EMailBackend *backend; EMailSession *session; EAccount *account; guint unread; @@ -845,6 +634,7 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, gboolean folder_is_drafts = FALSE; gboolean folder_is_outbox = FALSE; gboolean folder_is_templates = FALSE; + gboolean store_is_local; gchar *uri; /* Make sure we don't already know about it. */ @@ -853,11 +643,11 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, tree_store = GTK_TREE_STORE (model); - backend = em_folder_tree_model_get_backend (model); - session = e_mail_backend_get_session (backend); + session = em_folder_tree_model_get_session (model); folder_cache = e_mail_session_get_folder_cache (session); uid = camel_service_get_uid (CAMEL_SERVICE (si->store)); + store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0); account = e_get_account_by_uid (uid); if (!fully_loaded) @@ -907,7 +697,7 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, flags = fi->flags; display_name = fi->display_name; - if (si->store == e_mail_local_get_store ()) { + if (store_is_local) { if (strcmp (fi->full_name, "Drafts") == 0) { folder_is_drafts = TRUE; display_name = _("Drafts"); @@ -1202,7 +992,6 @@ void em_folder_tree_model_add_store (EMFolderTreeModel *model, CamelStore *store) { - EMailBackend *mail_backend; EMFolderTreeModelStoreInfo *si; GtkTreeRowReference *reference; GtkTreeStore *tree_store; @@ -1212,7 +1001,6 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model, CamelProvider *provider; CamelURL *service_url; const gchar *display_name; - const gchar *account_uid; gchar *uri; g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model)); @@ -1223,7 +1011,6 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model, service = CAMEL_SERVICE (store); provider = camel_service_get_provider (service); display_name = camel_service_get_display_name (service); - account_uid = camel_service_get_uid (service); /* Ignore stores that should not be added to the tree model. */ @@ -1245,8 +1032,6 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model, if (si != NULL) em_folder_tree_model_remove_store (model, store); - mail_backend = em_folder_tree_model_get_backend (model); - /* Add the store to the tree. */ gtk_tree_store_append (tree_store, &iter, NULL); gtk_tree_store_set ( @@ -1257,7 +1042,6 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model, COL_BOOL_LOAD_SUBDIRS, TRUE, COL_BOOL_IS_STORE, TRUE, COL_STRING_URI, uri, - COL_UINT_SORTORDER, em_utils_get_account_sort_order (mail_backend, account_uid), -1); path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter); diff --git a/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h index 0ed007aa96..1bf5483367 100644 --- a/mail/em-folder-tree-model.h +++ b/mail/em-folder-tree-model.h @@ -26,7 +26,6 @@ #include <gtk/gtk.h> #include <camel/camel.h> -#include <mail/e-mail-backend.h> #include <mail/e-mail-session.h> /* Standard GObject macros */ @@ -73,7 +72,6 @@ enum { * been added to the tree */ COL_UINT_UNREAD_LAST_SEL, /* last known unread count */ COL_BOOL_IS_DRAFT, /* %TRUE for a draft folder */ - COL_UINT_SORTORDER, /* user sort-order for the node */ NUM_COLUMNS }; @@ -120,11 +118,11 @@ GtkTreeSelection * void em_folder_tree_model_set_selection (EMFolderTreeModel *model, GtkTreeSelection *selection); -EMailBackend * em_folder_tree_model_get_backend +EMailSession * em_folder_tree_model_get_session (EMFolderTreeModel *model); -void em_folder_tree_model_set_backend +void em_folder_tree_model_set_session (EMFolderTreeModel *model, - EMailBackend *backend); + EMailSession *session); void em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *iter, diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c index 48cf6af40d..5ef1845304 100644 --- a/mail/em-folder-tree.c +++ b/mail/em-folder-tree.c @@ -62,9 +62,7 @@ #include "em-event.h" #include "e-mail-folder-utils.h" -#include "e-mail-local.h" #include "e-mail-session.h" -#include "e-mail-store.h" #define d(x) @@ -720,15 +718,17 @@ folder_tree_render_display_name (GtkTreeViewColumn *column, GtkTreeModel *model, GtkTreeIter *iter) { + CamelService *service; PangoWeight weight; gboolean is_store, bold, subdirs_unread = FALSE; gboolean editable; guint unread; - gchar *display; gchar *name; gtk_tree_model_get ( - model, iter, COL_STRING_DISPLAY_NAME, &name, + model, iter, + COL_STRING_DISPLAY_NAME, &name, + COL_POINTER_CAMEL_STORE, &service, COL_BOOL_IS_STORE, &is_store, COL_UINT_UNREAD, &unread, -1); @@ -747,8 +747,17 @@ folder_tree_render_display_name (GtkTreeViewColumn *column, bold = !editable && (bold || subdirs_unread); weight = bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL; + g_object_set (renderer, "weight", weight, NULL); + + if (is_store) { + const gchar *display_name; + + display_name = camel_service_get_display_name (service); + g_object_set (renderer, "text", display_name, NULL); + + } else if (!editable && unread > 0) { + gchar *name_and_unread; - if (!is_store && !editable && unread) { /* Translators: This is the string used for displaying the * folder names in folder trees. The first "%s" will be * replaced by the folder's name and "%u" will be replaced @@ -767,16 +776,17 @@ folder_tree_render_display_name (GtkTreeViewColumn *column, * Do not translate the "folder-display|" part. Remove it * from your translation. */ - display = g_strdup_printf ( + name_and_unread = g_strdup_printf ( C_("folder-display", "%s (%u%s)"), name, unread, subdirs_unread ? "+" : ""); - g_free (name); - } else - display = name; + g_object_set (renderer, "text", name_and_unread, NULL); + g_free (name_and_unread); - g_object_set (renderer, "text", display, "weight", weight, NULL); + } else { + g_object_set (renderer, "text", name, NULL); + } - g_free (display); + g_free (name); } static void @@ -1783,18 +1793,10 @@ em_folder_tree_new_with_model (EMailBackend *backend, EAlertSink *alert_sink, EMFolderTreeModel *model) { - EMailSession *session; - const gchar *data_dir; - g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL); g_return_val_if_fail (E_IS_ALERT_SINK (alert_sink), NULL); g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), NULL); - session = e_mail_backend_get_session (backend); - data_dir = e_shell_backend_get_data_dir (E_SHELL_BACKEND (backend)); - - e_mail_store_init (session, data_dir); - return g_object_new ( EM_TYPE_FOLDER_TREE, "alert-sink", alert_sink, @@ -2283,7 +2285,6 @@ folder_tree_drop_target (EMFolderTree *folder_tree, EMFolderTreePrivate *p = folder_tree->priv; gchar *dst_full_name = NULL; gchar *src_full_name = NULL; - CamelStore *local; CamelStore *dst_store; CamelStore *src_store = NULL; GdkAtom atom = GDK_NONE; @@ -2292,6 +2293,7 @@ folder_tree_drop_target (EMFolderTree *folder_tree, GtkTreeIter iter; GList *targets; const gchar *uid; + gboolean src_is_local; gboolean src_is_vfolder; gboolean dst_is_vfolder; guint32 flags = 0; @@ -2314,10 +2316,8 @@ folder_tree_drop_target (EMFolderTree *folder_tree, COL_STRING_FULL_NAME, &dst_full_name, COL_UINT_FLAGS, &flags, -1); - local = e_mail_local_get_store (); - uid = camel_service_get_uid (CAMEL_SERVICE (dst_store)); - dst_is_vfolder = (g_strcmp0 (uid, "vfolder") == 0); + dst_is_vfolder = (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0); targets = gdk_drag_context_list_targets (context); @@ -2392,13 +2392,17 @@ folder_tree_drop_target (EMFolderTree *folder_tree, if (src_store != NULL && src_full_name != NULL) { uid = camel_service_get_uid (CAMEL_SERVICE (src_store)); - src_is_vfolder = (g_strcmp0 (uid, "vfolder") == 0); + + src_is_local = + (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0); + src_is_vfolder = + (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0); /* FIXME: this is a total hack, but i think all we can do at present */ /* Check for dragging from special folders which can't be moved/copied */ /* Don't allow moving any of the the special local folders. */ - if (src_store == local && is_special_local_folder (src_full_name)) { + if (src_is_local && is_special_local_folder (src_full_name)) { GdkAtom xfolder; /* force copy for special local folders */ diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c index e72b8014ad..2ac87d7efd 100644 --- a/mail/em-folder-utils.c +++ b/mail/em-folder-utils.c @@ -59,9 +59,7 @@ #include "em-folder-properties.h" #include "e-mail-folder-utils.h" -#include "e-mail-local.h" #include "e-mail-session.h" -#include "e-mail-store.h" #include "e-mail-store-utils.h" #define d(x) @@ -339,15 +337,15 @@ emfu_copy_folder_selected (EMailBackend *backend, EMailSession *session; struct _copy_folder_data *cfd = data; CamelStore *tostore = NULL; - CamelStore *local_store; CamelService *service; + gboolean store_is_local; + const gchar *uid; gchar *tobase = NULL; GError *local_error = NULL; if (uri == NULL) goto fail; - local_store = e_mail_local_get_store (); session = e_mail_backend_get_session (backend); service = CAMEL_SERVICE (cfd->source_store); @@ -365,7 +363,10 @@ emfu_copy_folder_selected (EMailBackend *backend, g_return_if_fail (CAMEL_IS_STORE (service)); - if (cfd->delete && cfd->source_store == local_store && + uid = camel_service_get_uid (CAMEL_SERVICE (cfd->source_store)); + store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0); + + if (cfd->delete && store_is_local && emfu_is_special_local_folder (cfd->source_folder_name)) { e_mail_backend_submit_alert ( backend, "mail:no-rename-special-folder", @@ -426,7 +427,7 @@ emfu_copy_folder_exclude (EMFolderTree *tree, /* handles moving to/from vfolders */ uid = camel_service_get_uid (CAMEL_SERVICE (cfd->source_store)); - fromvfolder = (g_strcmp0 (uid, "vfolder") == 0); + fromvfolder = (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0); gtk_tree_model_get ( model, iter, @@ -434,7 +435,7 @@ emfu_copy_folder_exclude (EMFolderTree *tree, COL_POINTER_CAMEL_STORE, &store, -1); uid = camel_service_get_uid (CAMEL_SERVICE (store)); - tovfolder = (g_strcmp0 (uid, "vfolder") == 0); + tovfolder = (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0); /* moving from vfolder to normal- not allowed */ if (fromvfolder && !tovfolder && cfd->delete) @@ -566,9 +567,9 @@ em_folder_utils_create_folder (GtkWindow *parent, shell_settings = e_shell_get_shell_settings (shell); model = em_folder_tree_model_new (); - em_folder_tree_model_set_backend (model, backend); - session = e_mail_backend_get_session (backend); + em_folder_tree_model_set_session (model, session); + list = camel_session_list_services (CAMEL_SESSION (session)); for (link = list; link != NULL; link = g_list_next (link)) { @@ -587,9 +588,9 @@ em_folder_utils_create_folder (GtkWindow *parent, continue; uid = camel_service_get_uid (service); - if (g_strcmp0 (uid, "local") == 0) + if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0) prop = "mail-enable-local-folders"; - else if (g_strcmp0 (uid, "vfolder") == 0) + else if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0) prop = "mail-enable-search-folders"; if (prop && !e_shell_settings_get_boolean (shell_settings, prop)) diff --git a/mail/em-utils.c b/mail/em-utils.c index c15f8b67b5..bfda4056be 100644 --- a/mail/em-utils.c +++ b/mail/em-utils.c @@ -71,7 +71,6 @@ #include "em-composer-utils.h" #include "em-format-quote.h" #include "e-mail-folder-utils.h" -#include "e-mail-local.h" #include "e-mail-session.h" /* XXX This is a dirty hack on a dirty hack. We really need @@ -84,8 +83,6 @@ extern const gchar *shell_builtin_backend; #define d(x) -static void free_account_sort_order_cache (void); - gboolean em_utils_ask_open_many (GtkWindow *parent, gint how_many) @@ -998,17 +995,18 @@ em_utils_folder_is_templates (CamelFolder *folder) g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE); + store = camel_folder_get_parent_store (folder); + session = camel_service_get_session (CAMEL_SERVICE (store)); + local_templates_folder = - e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_TEMPLATES); + e_mail_session_get_local_folder ( + E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_TEMPLATES); if (folder == local_templates_folder) return TRUE; folder_uri = e_mail_folder_uri_from_folder (folder); - store = camel_folder_get_parent_store (folder); - session = camel_service_get_session (CAMEL_SERVICE (store)); - account_list = e_get_account_list (); iterator = e_list_get_iterator (E_LIST (account_list)); @@ -1053,17 +1051,18 @@ em_utils_folder_is_drafts (CamelFolder *folder) g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE); + store = camel_folder_get_parent_store (folder); + session = camel_service_get_session (CAMEL_SERVICE (store)); + local_drafts_folder = - e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_DRAFTS); + e_mail_session_get_local_folder ( + E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_DRAFTS); if (folder == local_drafts_folder) return TRUE; folder_uri = e_mail_folder_uri_from_folder (folder); - store = camel_folder_get_parent_store (folder); - session = camel_service_get_session (CAMEL_SERVICE (store)); - account_list = e_get_account_list (); iterator = e_list_get_iterator (E_LIST (account_list)); @@ -1108,17 +1107,18 @@ em_utils_folder_is_sent (CamelFolder *folder) g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE); + store = camel_folder_get_parent_store (folder); + session = camel_service_get_session (CAMEL_SERVICE (store)); + local_sent_folder = - e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT); + e_mail_session_get_local_folder ( + E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_SENT); if (folder == local_sent_folder) return TRUE; folder_uri = e_mail_folder_uri_from_folder (folder); - store = camel_folder_get_parent_store (folder); - session = camel_service_get_session (CAMEL_SERVICE (store)); - account_list = e_get_account_list (); iterator = e_list_get_iterator (E_LIST (account_list)); @@ -1153,12 +1153,18 @@ em_utils_folder_is_sent (CamelFolder *folder) gboolean em_utils_folder_is_outbox (CamelFolder *folder) { + CamelStore *store; + CamelSession *session; CamelFolder *local_outbox_folder; g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE); + store = camel_folder_get_parent_store (folder); + session = camel_service_get_session (CAMEL_SERVICE (store)); + local_outbox_folder = - e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX); + e_mail_session_get_local_folder ( + E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_OUTBOX); return (folder == local_outbox_folder); } @@ -1911,8 +1917,6 @@ emu_free_mail_cache (void) photos_cache = NULL; G_UNLOCK (photos_cache); - - free_account_sort_order_cache (); } void @@ -2269,169 +2273,3 @@ em_utils_disconnect_service_sync (CamelService *service, return res; } -G_LOCK_DEFINE_STATIC (accounts_sort_order_cache); -static GHashTable *accounts_sort_order_cache = NULL; /* account_uid string to sort order uint */ - -static void -free_account_sort_order_cache (void) -{ - G_LOCK (accounts_sort_order_cache); - - if (accounts_sort_order_cache) { - g_hash_table_destroy (accounts_sort_order_cache); - accounts_sort_order_cache = NULL; - } - - G_UNLOCK (accounts_sort_order_cache); -} - -static void -fill_accounts_sort_order_cache (EMailBackend *backend, - gboolean force_reload) -{ - GSList *account_uids; - - G_LOCK (accounts_sort_order_cache); - - if (!force_reload && accounts_sort_order_cache) { - G_UNLOCK (accounts_sort_order_cache); - return; - } - - if (!accounts_sort_order_cache) - accounts_sort_order_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - else - g_hash_table_remove_all (accounts_sort_order_cache); - - account_uids = em_utils_load_accounts_sort_order (backend); - if (account_uids) { - GSList *iter; - guint index; - - for (index = 1, iter = account_uids; iter; index++, iter = iter->next) { - if (iter->data) - g_hash_table_insert (accounts_sort_order_cache, iter->data, GUINT_TO_POINTER (index)); - } - - /* items are stolen into the cache */ - /* g_slist_foreach (account_uids, (GFunc) g_free, NULL); */ - g_slist_free (account_uids); - } - - G_UNLOCK (accounts_sort_order_cache); -} - -static gchar * -emu_get_sort_order_filename (EMailBackend *backend) -{ - g_return_val_if_fail (backend != NULL, NULL); - - return g_build_filename ( - e_shell_backend_get_config_dir (E_SHELL_BACKEND (backend)), - "sortorder.ini", NULL); -} - -static GKeyFile * -emu_get_sort_order_key_file (EMailBackend *backend) -{ - gchar *filename; - GKeyFile *key_file; - - g_return_val_if_fail (backend != NULL, NULL); - - filename = emu_get_sort_order_filename (backend); - g_return_val_if_fail (filename != NULL, NULL); - - key_file = g_key_file_new (); - g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, NULL); - - g_free (filename); - - return key_file; -} - -void -em_utils_save_accounts_sort_order (EMailBackend *backend, - const GSList *account_uids) -{ - gchar *filename; - GKeyFile *key_file; - gint ii; - gchar key[32]; - gchar *content; - gsize length = 0; - - key_file = emu_get_sort_order_key_file (backend); - g_return_if_fail (key_file != NULL); - - filename = emu_get_sort_order_filename (backend); - g_return_if_fail (filename != NULL); - - g_key_file_remove_group (key_file, "accounts", NULL); - - for (ii = 0; account_uids; ii++, account_uids = account_uids->next) { - sprintf (key, "%d", ii); - - g_key_file_set_string (key_file, "accounts", key, account_uids->data); - } - - content = g_key_file_to_data (key_file, &length, NULL); - if (content) - g_file_set_contents (filename, content, length, NULL); - - g_free (content); - g_free (filename); - g_key_file_free (key_file); - - fill_accounts_sort_order_cache (backend, TRUE); - e_mail_backend_account_sort_order_changed (backend); -} - -GSList * -em_utils_load_accounts_sort_order (EMailBackend *backend) -{ - GKeyFile *key_file; - GSList *account_uids = NULL; - gchar key[32]; - gchar *value; - gint ii; - - key_file = emu_get_sort_order_key_file (backend); - g_return_val_if_fail (key_file != NULL, NULL); - - ii = 0; - do { - sprintf (key, "%d", ii); - ii++; - - value = g_key_file_get_string (key_file, "accounts", key, NULL); - if (!value) - break; - - account_uids = g_slist_prepend (account_uids, value); - } while (*key); - - g_key_file_free (key_file); - - return g_slist_reverse (account_uids); -} - -guint -em_utils_get_account_sort_order (EMailBackend *backend, - const gchar *account_uid) -{ - guint res; - - g_return_val_if_fail (backend != NULL, 0); - g_return_val_if_fail (account_uid != NULL, 0); - - fill_accounts_sort_order_cache (backend, FALSE); - - G_LOCK (accounts_sort_order_cache); - - res = GPOINTER_TO_UINT (g_hash_table_lookup (accounts_sort_order_cache, account_uid)); - - G_UNLOCK (accounts_sort_order_cache); - - return res; -} diff --git a/mail/em-utils.h b/mail/em-utils.h index b7e3ec6f49..0a27266d31 100644 --- a/mail/em-utils.h +++ b/mail/em-utils.h @@ -98,10 +98,6 @@ gboolean em_utils_is_local_delivery_mbox_file (CamelURL *url); gboolean em_utils_connect_service_sync (CamelService *service, GCancellable *cancellable, GError **error); gboolean em_utils_disconnect_service_sync (CamelService *service, gboolean clean, GCancellable *cancellable, GError **error); -void em_utils_save_accounts_sort_order (EMailBackend *backend, const GSList *account_uids); -GSList *em_utils_load_accounts_sort_order (EMailBackend *backend); -guint em_utils_get_account_sort_order (EMailBackend *backend, const gchar *account_uid); - G_END_DECLS #endif /* __EM_UTILS_H__ */ diff --git a/mail/em-vfolder-rule.c b/mail/em-vfolder-rule.c index 831059910c..3f0c2200aa 100644 --- a/mail/em-vfolder-rule.c +++ b/mail/em-vfolder-rule.c @@ -33,7 +33,6 @@ #include "em-vfolder-context.h" #include "em-vfolder-rule.h" #include "mail/e-mail-folder-utils.h" -#include "mail/e-mail-store.h" #include "mail/em-utils.h" #include "mail/em-folder-tree.h" #include "mail/em-folder-selector.h" diff --git a/mail/importers/evolution-mbox-importer.c b/mail/importers/evolution-mbox-importer.c index 3c97bd953b..b158d606a9 100644 --- a/mail/importers/evolution-mbox-importer.c +++ b/mail/importers/evolution-mbox-importer.c @@ -45,8 +45,6 @@ #include "shell/e-shell-sidebar.h" #include "mail/e-mail-backend.h" -#include "mail/e-mail-local.h" -#include "mail/e-mail-store.h" #include "mail/em-folder-selection-button.h" #include "mail/em-folder-tree-model.h" #include "mail/em-folder-tree.h" @@ -85,6 +83,8 @@ mbox_getwidget (EImport *ei, { EShell *shell; EShellBackend *shell_backend; + EMailBackend *backend; + EMailSession *session; GtkWindow *window; GtkWidget *hbox, *w; GtkLabel *label; @@ -96,6 +96,9 @@ mbox_getwidget (EImport *ei, shell = e_shell_get_default (); shell_backend = e_shell_get_backend_by_name (shell, "mail"); + backend = E_MAIL_BACKEND (shell_backend); + session = e_mail_backend_get_session (backend); + /* preselect the folder selected in a mail view */ window = e_shell_get_active_window (shell); if (E_IS_SHELL_WINDOW (window)) { @@ -129,7 +132,8 @@ mbox_getwidget (EImport *ei, if (!select_uri) { const gchar *uri; - uri = e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_INBOX); + uri = e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_INBOX); select_uri = g_strdup (uri); } diff --git a/mail/importers/mail-importer.c b/mail/importers/mail-importer.c index e28de37b3c..558359c636 100644 --- a/mail/importers/mail-importer.c +++ b/mail/importers/mail-importer.c @@ -41,7 +41,6 @@ #include "mail-mt.h" #include "mail-tools.h" -#include "e-mail-local.h" #include "e-mail-session.h" #include "mail-importer.h" @@ -124,7 +123,8 @@ import_mbox_exec (struct _import_mbox_msg *m, } if (m->uri == NULL || m->uri[0] == 0) - folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_INBOX); + folder = e_mail_session_get_local_folder ( + m->session, E_MAIL_LOCAL_FOLDER_INBOX); else folder = e_mail_session_uri_to_folder_sync ( m->session, m->uri, CAMEL_STORE_FOLDER_CREATE, diff --git a/mail/mail-config.c b/mail/mail-config.c index bbad256d2f..883612b346 100644 --- a/mail/mail-config.c +++ b/mail/mail-config.c @@ -34,7 +34,6 @@ #include "e-util/e-account-utils.h" #include "e-util/e-signature-utils.h" -#include "e-mail-local.h" #include "e-mail-folder-utils.h" #include "mail-config.h" #include "mail-tools.h" diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c index cab15c5e93..d9e3befa79 100644 --- a/mail/mail-folder-cache.c +++ b/mail/mail-folder-cache.c @@ -49,7 +49,6 @@ #include "em-utils.h" #include "e-mail-folder-utils.h" -#include "e-mail-local.h" #include "e-mail-session.h" #include "e-mail-store-utils.h" @@ -62,7 +61,12 @@ /* This code is a mess, there is no reason it should be so complicated. */ +typedef struct _StoreInfo StoreInfo; + struct _MailFolderCachePrivate { + gpointer session; /* weak pointer */ + EMailAccountStore *account_store; + /* source id for the ping timeout callback */ guint ping_id; /* Store to storeinfo table, active stores */ @@ -82,6 +86,11 @@ struct _MailFolderCachePrivate { }; enum { + PROP_0, + PROP_SESSION +}; + +enum { FOLDER_AVAILABLE, FOLDER_UNAVAILABLE, FOLDER_DELETED, @@ -94,7 +103,7 @@ enum { static guint signals[LAST_SIGNAL]; struct _folder_info { - struct _store_info *store_info; /* 'parent' link */ + StoreInfo *store_info; /* 'parent' link */ gchar *full_name; /* full name of folder/folderinfo */ @@ -124,14 +133,26 @@ struct _folder_update { gchar *msg_subject; /* ... and its subject. */ }; -struct _store_info { +struct _StoreInfo { GHashTable *folders; /* by full_name */ CamelStore *store; /* the store for these folders */ + gboolean first_update; /* TRUE initially, then FALSE forever */ + + /* Hold a reference to keep them alive. */ + CamelFolder *vjunk; + CamelFolder *vtrash; /* Outstanding folderinfo requests */ GQueue folderinfo_updates; }; +struct _update_data { + NoteDoneFunc done; + gpointer data; + MailFolderCache *cache; + GCancellable *cancellable; +}; + G_DEFINE_TYPE (MailFolderCache, mail_folder_cache, G_TYPE_OBJECT) static void @@ -147,6 +168,66 @@ free_update (struct _folder_update *up) g_free (up); } +static void +free_folder_info (struct _folder_info *mfi) +{ + g_free (mfi->full_name); + g_free (mfi); +} + +static StoreInfo * +store_info_new (CamelStore *store) +{ + StoreInfo *info; + GHashTable *folders; + + folders = g_hash_table_new_full ( + (GHashFunc) g_str_hash, + (GEqualFunc) g_str_equal, + (GDestroyNotify) NULL, + (GDestroyNotify) free_folder_info); + + info = g_slice_new0 (StoreInfo); + info->folders = folders; + info->store = g_object_ref (store); + info->first_update = TRUE; + + /* 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_VJUNK) + info->vjunk = camel_store_get_junk_folder_sync ( + store, NULL, NULL); + if (store->flags & CAMEL_STORE_VTRASH) + info->vtrash = camel_store_get_trash_folder_sync ( + store, NULL, NULL); + + g_queue_init (&info->folderinfo_updates); + + return info; +} + +static void +store_info_free (StoreInfo *info) +{ + struct _update_data *ud; + + while (!g_queue_is_empty (&info->folderinfo_updates)) { + ud = g_queue_pop_head (&info->folderinfo_updates); + g_cancellable_cancel (ud->cancellable); + } + + g_hash_table_destroy (info->folders); + g_object_unref (info->store); + + if (info->vjunk != NULL) + g_object_unref (info->vjunk); + + if (info->vtrash != NULL) + g_object_unref (info->vtrash); + + g_slice_free (StoreInfo, info); +} + static gboolean flush_updates_idle_cb (MailFolderCache *cache) { @@ -334,9 +415,10 @@ folder_changed_cb (CamelFolder *folder, CamelFolder *local_drafts; CamelFolder *local_outbox; CamelFolder *local_sent; + CamelSession *session; CamelStore *parent_store; CamelMessageInfo *info; - struct _store_info *si; + StoreInfo *si; struct _folder_info *mfi; const gchar *full_name; gint new = 0; @@ -346,6 +428,7 @@ folder_changed_cb (CamelFolder *folder, full_name = camel_folder_get_full_name (folder); parent_store = camel_folder_get_parent_store (folder); + session = camel_service_get_session (CAMEL_SERVICE (parent_store)); if (!last_newmail_per_folder) last_newmail_per_folder = g_hash_table_new (g_direct_hash, g_direct_equal); @@ -355,9 +438,12 @@ folder_changed_cb (CamelFolder *folder, g_hash_table_lookup (last_newmail_per_folder, folder)); new_latest_received = latest_received; - local_drafts = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_DRAFTS); - local_outbox = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX); - local_sent = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT); + local_drafts = e_mail_session_get_local_folder ( + E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_DRAFTS); + local_outbox = e_mail_session_get_local_folder ( + E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_OUTBOX); + local_sent = e_mail_session_get_local_folder ( + E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_SENT); if (!CAMEL_IS_VEE_FOLDER (folder) && folder != local_drafts @@ -451,16 +537,9 @@ unset_folder_info (MailFolderCache *cache, } static void -free_folder_info (struct _folder_info *mfi) -{ - g_free (mfi->full_name); - g_free (mfi); -} - -static void setup_folder (MailFolderCache *cache, CamelFolderInfo *fi, - struct _store_info *si) + StoreInfo *si) { struct _folder_info *mfi; struct _folder_update *up; @@ -493,7 +572,7 @@ setup_folder (MailFolderCache *cache, static void create_folders (MailFolderCache *cache, CamelFolderInfo *fi, - struct _store_info *si) + StoreInfo *si) { while (fi) { setup_folder (cache, fi, si); @@ -510,7 +589,7 @@ store_folder_subscribed_cb (CamelStore *store, CamelFolderInfo *info, MailFolderCache *cache) { - struct _store_info *si; + StoreInfo *si; g_mutex_lock (cache->priv->stores_mutex); si = g_hash_table_lookup (cache->priv->stores, store); @@ -543,7 +622,7 @@ store_folder_unsubscribed_cb (CamelStore *store, CamelFolderInfo *info, MailFolderCache *cache) { - struct _store_info *si; + StoreInfo *si; struct _folder_info *mfi; g_mutex_lock (cache->priv->stores_mutex); @@ -572,7 +651,7 @@ store_folder_deleted_cb (CamelStore *store, static void rename_folders (MailFolderCache *cache, - struct _store_info *si, + StoreInfo *si, const gchar *oldbase, const gchar *newbase, CamelFolderInfo *fi) @@ -678,7 +757,7 @@ store_folder_renamed_cb (CamelStore *store, CamelFolderInfo *info, MailFolderCache *cache) { - struct _store_info *si; + StoreInfo *si; g_mutex_lock (cache->priv->stores_mutex); si = g_hash_table_lookup (cache->priv->stores, store); @@ -703,13 +782,6 @@ store_folder_renamed_cb (CamelStore *store, g_mutex_unlock (cache->priv->stores_mutex); } -struct _update_data { - NoteDoneFunc done; - gpointer data; - MailFolderCache *cache; - GCancellable *cancellable; -}; - static void unset_folder_info_hash (gchar *path, struct _folder_info *mfi, @@ -720,11 +792,31 @@ unset_folder_info_hash (gchar *path, } static void -free_folder_info_hash (gchar *path, - struct _folder_info *mfi, - gpointer data) +mail_folder_cache_first_update (MailFolderCache *cache, + StoreInfo *info) { - free_folder_info (mfi); + EMailSession *session; + const gchar *uid; + + session = mail_folder_cache_get_session (cache); + uid = camel_service_get_uid (CAMEL_SERVICE (info->store)); + + if (info->vjunk != NULL) + mail_folder_cache_note_folder (cache, info->vjunk); + + if (info->vtrash != NULL) + mail_folder_cache_note_folder (cache, info->vtrash); + + /* Some extra work for the "On This Computer" store. */ + if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0) { + CamelFolder *folder; + gint ii; + + for (ii = 0; ii < E_MAIL_NUM_LOCAL_FOLDERS; ii++) { + folder = e_mail_session_get_local_folder (session, ii); + mail_folder_cache_note_folder (cache, folder); + } + } } static void @@ -733,7 +825,7 @@ update_folders (CamelStore *store, struct _update_data *ud) { CamelFolderInfo *fi; - struct _store_info *si; + StoreInfo *si; GError *error = NULL; fi = camel_store_get_folder_info_finish (store, result, &error); @@ -756,6 +848,12 @@ update_folders (CamelStore *store, } g_mutex_unlock (ud->cache->priv->stores_mutex); + /* Do some extra work for the first update. */ + if (si != NULL && si->first_update) { + mail_folder_cache_first_update (ud->cache, si); + si->first_update = FALSE; + } + if (fi != NULL) { gboolean free_fi = TRUE; @@ -913,7 +1011,7 @@ struct _find_info { static void storeinfo_find_folder_info (CamelStore *store, - struct _store_info *si, + StoreInfo *si, struct _find_info *fi) { gchar *folder_name; @@ -933,34 +1031,175 @@ storeinfo_find_folder_info (CamelStore *store, } static void +mail_folder_cache_service_added (EMailAccountStore *account_store, + CamelService *service, + MailFolderCache *cache) +{ + mail_folder_cache_note_store ( + cache, CAMEL_STORE (service), NULL, NULL, NULL); +} + +static void +mail_folder_cache_service_removed (EMailAccountStore *account_store, + CamelService *service, + MailFolderCache *cache) +{ + StoreInfo *si; + + if (cache->priv->stores == NULL) + return; + + g_mutex_lock (cache->priv->stores_mutex); + + si = g_hash_table_lookup (cache->priv->stores, service); + if (si != NULL) { + g_hash_table_remove (cache->priv->stores, service); + + g_signal_handlers_disconnect_matched ( + service, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, cache); + + g_hash_table_foreach ( + si->folders, (GHFunc) + unset_folder_info_hash, cache); + + store_info_free (si); + } + + g_mutex_unlock (cache->priv->stores_mutex); +} + +static void +mail_folder_cache_set_session (MailFolderCache *cache, + EMailSession *session) +{ + g_return_if_fail (E_IS_MAIL_SESSION (session)); + g_return_if_fail (cache->priv->session == NULL); + + cache->priv->session = session; + + g_object_add_weak_pointer ( + G_OBJECT (cache->priv->session), + &cache->priv->session); +} + +static void +mail_folder_cache_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SESSION: + mail_folder_cache_set_session ( + MAIL_FOLDER_CACHE (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_folder_cache_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SESSION: + g_value_set_object ( + value, + mail_folder_cache_get_session ( + MAIL_FOLDER_CACHE (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_folder_cache_dispose (GObject *object) +{ + MailFolderCachePrivate *priv; + + priv = MAIL_FOLDER_CACHE_GET_PRIVATE (object); + + if (priv->session != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->session), &priv->session); + priv->session = NULL; + } + + if (priv->account_store != NULL) { + g_signal_handlers_disconnect_matched ( + priv->account_store, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->account_store); + priv->account_store = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (mail_folder_cache_parent_class)->dispose (object); +} + +static void mail_folder_cache_finalize (GObject *object) { - MailFolderCache *cache = (MailFolderCache *) object; + MailFolderCachePrivate *priv; - g_hash_table_destroy (cache->priv->stores); - g_mutex_free (cache->priv->stores_mutex); + priv = MAIL_FOLDER_CACHE_GET_PRIVATE (object); - if (cache->priv->ping_id > 0) { - g_source_remove (cache->priv->ping_id); - cache->priv->ping_id = 0; + g_hash_table_destroy (priv->stores); + g_mutex_free (priv->stores_mutex); + + if (priv->ping_id > 0) { + g_source_remove (priv->ping_id); + priv->ping_id = 0; } - if (cache->priv->update_id > 0) { - g_source_remove (cache->priv->update_id); - cache->priv->update_id = 0; + if (priv->update_id > 0) { + g_source_remove (priv->update_id); + priv->update_id = 0; } - while (!g_queue_is_empty (&cache->priv->local_folder_uris)) - g_free (g_queue_pop_head (&cache->priv->local_folder_uris)); + while (!g_queue_is_empty (&priv->local_folder_uris)) + g_free (g_queue_pop_head (&priv->local_folder_uris)); - while (!g_queue_is_empty (&cache->priv->remote_folder_uris)) - g_free (g_queue_pop_head (&cache->priv->remote_folder_uris)); + while (!g_queue_is_empty (&priv->remote_folder_uris)) + g_free (g_queue_pop_head (&priv->remote_folder_uris)); /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (mail_folder_cache_parent_class)->finalize (object); } static void +mail_folder_cache_constructed (GObject *object) +{ + MailFolderCache *cache; + EMailSession *session; + EMailAccountStore *account_store; + + cache = MAIL_FOLDER_CACHE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (mail_folder_cache_parent_class)->constructed (object); + + session = mail_folder_cache_get_session (cache); + account_store = e_mail_session_get_account_store (session); + + cache->priv->account_store = g_object_ref (account_store); + + g_signal_connect ( + account_store, "service-added", + G_CALLBACK (mail_folder_cache_service_added), cache); + + g_signal_connect ( + account_store, "service-removed", + G_CALLBACK (mail_folder_cache_service_removed), cache); +} + +static void mail_folder_cache_folder_available (MailFolderCache *cache, CamelStore *store, const gchar *folder_name) @@ -1118,12 +1357,28 @@ mail_folder_cache_class_init (MailFolderCacheClass *class) g_type_class_add_private (class, sizeof (MailFolderCachePrivate)); object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_folder_cache_set_property; + object_class->get_property = mail_folder_cache_get_property; + object_class->dispose = mail_folder_cache_dispose; object_class->finalize = mail_folder_cache_finalize; + object_class->constructed = mail_folder_cache_constructed; class->folder_available = mail_folder_cache_folder_available; class->folder_unavailable = mail_folder_cache_folder_unavailable; class->folder_deleted = mail_folder_cache_folder_deleted; + g_object_class_install_property ( + object_class, + PROP_SESSION, + g_param_spec_object ( + "session", + "Session", + "Mail session", + E_TYPE_MAIL_SESSION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + /** * MailFolderCache::folder-available * @store: the #CamelStore containing the folder @@ -1274,9 +1529,21 @@ mail_folder_cache_init (MailFolderCache *cache) } MailFolderCache * -mail_folder_cache_new (void) +mail_folder_cache_new (EMailSession *session) { - return g_object_new (MAIL_TYPE_FOLDER_CACHE, NULL); + g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); + + return g_object_new ( + MAIL_TYPE_FOLDER_CACHE, + "session", session, NULL); +} + +EMailSession * +mail_folder_cache_get_session (MailFolderCache *cache) +{ + g_return_val_if_fail (MAIL_IS_FOLDER_CACHE (cache), NULL); + + return E_MAIL_SESSION (cache->priv->session); } /** @@ -1294,12 +1561,12 @@ mail_folder_cache_note_store (MailFolderCache *cache, gpointer data) { CamelSession *session; - struct _store_info *si; + StoreInfo *si; struct _update_data *ud; gint hook = 0; + g_return_if_fail (MAIL_IS_FOLDER_CACHE (cache)); g_return_if_fail (CAMEL_IS_STORE (store)); - g_return_if_fail (mail_in_main_thread ()); session = camel_service_get_session (CAMEL_SERVICE (store)); @@ -1307,11 +1574,8 @@ mail_folder_cache_note_store (MailFolderCache *cache, si = g_hash_table_lookup (cache->priv->stores, store); if (si == NULL) { - si = g_malloc0 (sizeof (*si)); - si->folders = g_hash_table_new (g_str_hash, g_str_equal); - si->store = g_object_ref (store); + si = store_info_new (store); g_hash_table_insert (cache->priv->stores, store, si); - g_queue_init (&si->folderinfo_updates); hook = TRUE; } @@ -1389,55 +1653,6 @@ mail_folder_cache_note_store (MailFolderCache *cache, } /** - * mail_folder_cache_note_store_remove: - * - * Notify the cache that the specified @store can be removed from the cache - */ -void -mail_folder_cache_note_store_remove (MailFolderCache *cache, - CamelStore *store) -{ - struct _store_info *si; - - g_return_if_fail (CAMEL_IS_STORE (store)); - - if (cache->priv->stores == NULL) - return; - - d(printf("store removed!!\n")); - g_mutex_lock (cache->priv->stores_mutex); - si = g_hash_table_lookup (cache->priv->stores, store); - if (si) { - GList *link; - - g_hash_table_remove (cache->priv->stores, store); - - g_signal_handlers_disconnect_matched ( - store, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, cache); - - g_hash_table_foreach ( - si->folders, (GHFunc) - unset_folder_info_hash, cache); - - link = g_queue_peek_head_link (&si->folderinfo_updates); - - while (link != NULL) { - struct _update_data *ud = link->data; - g_cancellable_cancel (ud->cancellable); - link = g_list_next (link); - } - - g_object_unref (si->store); - g_hash_table_foreach (si->folders, (GHFunc) free_folder_info_hash, NULL); - g_hash_table_destroy (si->folders); - g_free (si); - } - - g_mutex_unlock (cache->priv->stores_mutex); -} - -/** * mail_folder_cache_note_folder: * * When a folder has been opened, notify it for watching. The folder must have @@ -1449,10 +1664,13 @@ mail_folder_cache_note_folder (MailFolderCache *cache, CamelFolder *folder) { CamelStore *parent_store; - struct _store_info *si; + StoreInfo *si; struct _folder_info *mfi; const gchar *full_name; + g_return_if_fail (MAIL_IS_FOLDER_CACHE (cache)); + g_return_if_fail (CAMEL_IS_FOLDER (folder)); + full_name = camel_folder_get_full_name (folder); parent_store = camel_folder_get_parent_store (folder); diff --git a/mail/mail-folder-cache.h b/mail/mail-folder-cache.h index 146ead5012..78d5fd94de 100644 --- a/mail/mail-folder-cache.h +++ b/mail/mail-folder-cache.h @@ -49,6 +49,9 @@ G_BEGIN_DECLS +/* Avoid a circular dependency. */ +typedef struct _EMailSession EMailSession; + typedef struct _MailFolderCache MailFolderCache; typedef struct _MailFolderCacheClass MailFolderCacheClass; typedef struct _MailFolderCachePrivate MailFolderCachePrivate; @@ -107,34 +110,32 @@ struct _MailFolderCacheClass { GType mail_folder_cache_get_type (void) G_GNUC_CONST; MailFolderCache * - mail_folder_cache_new (void); -void mail_folder_cache_note_store (MailFolderCache *self, + mail_folder_cache_new (EMailSession *session); +EMailSession * mail_folder_cache_get_session (MailFolderCache *cache); +void mail_folder_cache_note_store (MailFolderCache *cache, CamelStore *store, GCancellable *cancellable, NoteDoneFunc done, gpointer data); -void mail_folder_cache_note_store_remove - (MailFolderCache *self, - CamelStore *store); -void mail_folder_cache_note_folder (MailFolderCache *self, +void mail_folder_cache_note_folder (MailFolderCache *cache, CamelFolder *folder); gboolean mail_folder_cache_get_folder_from_uri - (MailFolderCache *self, + (MailFolderCache *cache, const gchar *uri, CamelFolder **folderp); gboolean mail_folder_cache_get_folder_info_flags - (MailFolderCache *self, + (MailFolderCache *cache, CamelFolder *folder, CamelFolderInfoFlags *flags); gboolean mail_folder_cache_get_folder_has_children - (MailFolderCache *self, + (MailFolderCache *cache, CamelFolder *folder, gboolean *found); void mail_folder_cache_get_local_folder_uris - (MailFolderCache *self, + (MailFolderCache *cache, GQueue *out_queue); void mail_folder_cache_get_remote_folder_uris - (MailFolderCache *self, + (MailFolderCache *cache, GQueue *out_queue); G_END_DECLS diff --git a/mail/mail-ops.c b/mail/mail-ops.c index 24a494ddac..4ff12b3955 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -43,7 +43,6 @@ #include "mail-ops.h" #include "mail-tools.h" -#include "e-mail-local.h" #include "e-mail-session.h" #include "e-mail-session-utils.h" @@ -213,18 +212,23 @@ fetch_mail_exec (struct _fetch_mail_msg *m, { struct _filter_mail_msg *fm = (struct _filter_mail_msg *) m; CamelFolder *folder = NULL; + CamelService *service; + CamelSession *session; CamelURL *url; gboolean is_local_delivery; const gchar *uid; gint i; - fm->destination = e_mail_local_get_folder ( - E_MAIL_LOCAL_FOLDER_LOCAL_INBOX); + service = CAMEL_SERVICE (m->store); + session = camel_service_get_session (service); + + fm->destination = e_mail_session_get_local_folder ( + E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_LOCAL_INBOX); if (fm->destination == NULL) goto fail; g_object_ref (fm->destination); - url = camel_service_new_camel_url (CAMEL_SERVICE (m->store)); + url = camel_service_new_camel_url (service); is_local_delivery = em_utils_is_local_delivery_mbox_file (url); if (is_local_delivery) { @@ -250,7 +254,7 @@ fetch_mail_exec (struct _fetch_mail_msg *m, g_free (path); g_free (url_string); } else { - uid = camel_service_get_uid (CAMEL_SERVICE (m->store)); + uid = camel_service_get_uid (service); folder = fm->source_folder = e_mail_session_get_inbox_sync ( @@ -344,7 +348,7 @@ fail: * there is no need to keep the connection alive forever */ if (!is_local_delivery) em_utils_disconnect_service_sync ( - CAMEL_SERVICE (m->store), TRUE, cancellable, NULL); + service, TRUE, cancellable, NULL); } static void @@ -670,7 +674,8 @@ mail_send_message (struct _send_queue_msg *m, } if (!folder) { - folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT); + folder = e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_SENT); g_object_ref (folder); } @@ -683,7 +688,8 @@ mail_send_message (struct _send_queue_msg *m, if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; - sent_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT); + sent_folder = e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_SENT); if (folder != sent_folder) { const gchar *description; @@ -801,6 +807,7 @@ send_queue_exec (struct _send_queue_msg *m, GCancellable *cancellable, GError **error) { + EMailSession *session; CamelFolder *sent_folder; GPtrArray *uids, *send_uids = NULL; gint i, j; @@ -808,7 +815,11 @@ send_queue_exec (struct _send_queue_msg *m, d(printf("sending queue\n")); - sent_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT); + session = e_mail_backend_get_session (m->backend); + + sent_folder = + e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_SENT); if (!(uids = camel_folder_get_uids (m->queue))) return; @@ -1489,19 +1500,25 @@ expunge_folder_exec (struct _sync_folder_msg *m, GCancellable *cancellable, GError **error) { + EMailSession *session; CamelFolder *local_inbox; - CamelStore *local_store; CamelStore *parent_store; gboolean is_local_inbox_or_trash; + gboolean store_is_local; gboolean success = TRUE; + const gchar *uid; - local_inbox = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_INBOX); - is_local_inbox_or_trash = (m->folder == local_inbox); - - local_store = e_mail_local_get_store (); + session = e_mail_backend_get_session (m->backend); parent_store = camel_folder_get_parent_store (m->folder); + uid = camel_service_get_uid (CAMEL_SERVICE (parent_store)); + store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0); + + local_inbox = + e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_INBOX); + is_local_inbox_or_trash = (m->folder == local_inbox); - if (!is_local_inbox_or_trash && local_store == parent_store) { + if (store_is_local && !is_local_inbox_or_trash) { CamelFolder *trash; trash = camel_store_get_trash_folder_sync ( @@ -1591,7 +1608,7 @@ empty_trash_exec (struct _empty_trash_msg *m, return; /* do this before expunge, to know which messages will be expunged */ - if (g_strcmp0 (uid, "local") == 0) + if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0) success = expunge_pop3_stores ( trash, m->backend, cancellable, error); diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c index 44c5158631..36c717619b 100644 --- a/mail/mail-send-recv.c +++ b/mail/mail-send-recv.c @@ -36,7 +36,6 @@ #include "e-util/e-util.h" #include "e-mail-folder-utils.h" -#include "e-mail-local.h" #include "e-mail-session.h" #include "em-event.h" #include "em-filter-rule.h" @@ -164,10 +163,13 @@ free_send_info (struct _send_info *info) } static struct _send_data * -setup_send_data (void) +setup_send_data (EMailBackend *backend) { + EMailSession *session; struct _send_data *data; + session = e_mail_backend_get_session (backend); + if (send_data == NULL) { send_data = data = g_malloc0 (sizeof (*data)); data->lock = g_mutex_new (); @@ -175,8 +177,9 @@ setup_send_data (void) g_str_hash, g_str_equal, (GDestroyNotify) NULL, (GDestroyNotify) free_folder_info); - data->inbox = e_mail_local_get_folder ( - E_MAIL_LOCAL_FOLDER_LOCAL_INBOX); + data->inbox = + e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_LOCAL_INBOX); g_object_ref (data->inbox); data->active = g_hash_table_new_full ( g_str_hash, g_str_equal, @@ -520,7 +523,7 @@ build_dialog (GtkWindow *parent, gtk_widget_show (scrolled_window); /* must bet setup after send_recv_dialog as it may re-trigger send-recv button */ - data = setup_send_data (); + data = setup_send_data (backend); row = 0; iter = e_list_get_iterator ((EList *) accounts); @@ -810,8 +813,9 @@ receive_done (gpointer data) session = e_mail_backend_get_session (info->backend); - local_outbox = e_mail_local_get_folder ( - E_MAIL_LOCAL_FOLDER_OUTBOX); + local_outbox = + e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_OUTBOX); service = camel_session_get_service ( CAMEL_SESSION (session), @@ -1126,7 +1130,10 @@ send_receive (GtkWindow *parent, accounts = e_get_account_list (); - local_outbox = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX); + local_outbox = + e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_OUTBOX); + data = build_dialog ( parent, backend, accounts, local_outbox, account, allow_send); @@ -1280,11 +1287,12 @@ auto_account_changed (EAccountList *eal, EAccount *ea, gpointer dummy) { - struct _auto_data *info = g_object_get_data((GObject *)ea, "mail-autoreceive"); + struct _auto_data *info; - g_return_if_fail (info != NULL); + info = g_object_get_data (G_OBJECT (ea), "mail-autoreceive"); - auto_account_commit (info); + if (info != NULL) + auto_account_commit (info); } static void @@ -1394,7 +1402,7 @@ mail_receive_account (EMailBackend *backend, CamelURL *url; send_info_t type = SEND_INVALID; - data = setup_send_data (); + data = setup_send_data (backend); info = g_hash_table_lookup (data->active, account->uid); if (info != NULL) @@ -1450,8 +1458,9 @@ mail_receive_account (EMailBackend *backend, break; case SEND_SEND: /* todo, store the folder in info? */ - local_outbox = e_mail_local_get_folder ( - E_MAIL_LOCAL_FOLDER_OUTBOX); + local_outbox = + e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_OUTBOX); mail_send_queue ( info->backend, local_outbox, @@ -1487,7 +1496,7 @@ mail_send (EMailBackend *backend) if (account == NULL || account->transport->url == NULL) return; - data = setup_send_data (); + data = setup_send_data (backend); info = g_hash_table_lookup (data->active, SEND_URI_KEY); if (info != NULL) { info->again++; @@ -1525,11 +1534,13 @@ mail_send (EMailBackend *backend) g_hash_table_insert (data->active, (gpointer) SEND_URI_KEY, info); - /* todo, store the folder in info? */ - local_outbox = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX); - session = e_mail_backend_get_session (backend); + /* todo, store the folder in info? */ + local_outbox = + e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_OUTBOX); + service = camel_session_get_service ( CAMEL_SESSION (session), transport_uid); diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c index b37d042077..99caa6c0ec 100644 --- a/mail/mail-vfolder.c +++ b/mail/mail-vfolder.c @@ -49,11 +49,6 @@ #include "mail-tools.h" #include "mail-vfolder.h" -#include "e-mail-local.h" -#include "e-mail-store.h" - -#define VFOLDER_SERVICE_UID "vfolder" - #define d(x) /* (printf("%s:%s: ", G_STRLOC, G_STRFUNC), (x))*/ static EMVFolderContext *context; /* context remains open all time */ @@ -720,7 +715,7 @@ rule_changed (EFilterRule *rule, session = e_mail_backend_get_session (backend); service = camel_session_get_service ( - CAMEL_SESSION (session), VFOLDER_SERVICE_UID); + CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID); g_return_if_fail (CAMEL_IS_SERVICE (service)); /* if the folder has changed name, then add it, then remove the old manually */ @@ -820,7 +815,7 @@ context_rule_added (ERuleContext *ctx, session = e_mail_backend_get_session (backend); service = camel_session_get_service ( - CAMEL_SESSION (session), VFOLDER_SERVICE_UID); + CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID); g_return_if_fail (CAMEL_IS_SERVICE (service)); /* this always runs quickly */ @@ -853,7 +848,7 @@ context_rule_removed (ERuleContext *ctx, session = e_mail_backend_get_session (backend); service = camel_session_get_service ( - CAMEL_SESSION (session), VFOLDER_SERVICE_UID); + CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID); g_return_if_fail (CAMEL_IS_SERVICE (service)); /* TODO: remove from folder info cache? */ @@ -1008,8 +1003,7 @@ vfolder_load_storage (EMailBackend *backend) /* lock for loading storage, it is safe to call it more than once */ G_LOCK_DEFINE_STATIC (vfolder_hash); - CamelService *service; - const gchar *key; + CamelStore *vfolder_store; const gchar *config_dir; gchar *user; EFilterRule *rule; @@ -1034,27 +1028,14 @@ vfolder_load_storage (EMailBackend *backend) config_dir = mail_session_get_config_dir (); session = e_mail_backend_get_session (backend); - - /* first, create the vfolder store, and set it up */ - service = camel_session_add_service ( - CAMEL_SESSION (session), "vfolder", - "vfolder", CAMEL_PROVIDER_STORE, NULL); - if (service != NULL) { - camel_service_set_display_name (service, _("Search Folders")); - em_utils_connect_service_sync (service, NULL, NULL); - } else { - g_warning("Cannot open vfolder store - no vfolders available"); - return; - } - - g_return_if_fail (CAMEL_IS_STORE (service)); + vfolder_store = e_mail_session_get_vfolder_store (session); g_signal_connect ( - service, "folder-deleted", + vfolder_store, "folder-deleted", G_CALLBACK (store_folder_deleted_cb), backend); g_signal_connect ( - service, "folder-renamed", + vfolder_store, "folder-renamed", G_CALLBACK (store_folder_renamed_cb), NULL); /* load our rules */ @@ -1076,9 +1057,6 @@ vfolder_load_storage (EMailBackend *backend) context, "rule_removed", G_CALLBACK (context_rule_removed), context); - /* load store to mail component */ - e_mail_store_add (session, CAMEL_STORE (service)); - /* and setup the rules we have */ rule = NULL; while ((rule = e_rule_context_next_rule ((ERuleContext *) context, rule, NULL))) { @@ -1092,9 +1070,7 @@ vfolder_load_storage (EMailBackend *backend) /* reenable the feature if required */ settings = g_settings_new ("org.gnome.evolution.mail"); - key = "enable-vfolders"; - if (!g_settings_get_boolean (settings, key)) - g_settings_set_boolean (settings, key, TRUE); + g_settings_set_boolean (settings, "enable-vfolders", TRUE); g_object_unref (settings); folder_cache = e_mail_session_get_folder_cache (session); diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c index aba140b865..64817fad00 100644 --- a/modules/mail/e-mail-shell-backend.c +++ b/modules/mail/e-mail-shell-backend.c @@ -43,7 +43,6 @@ #include "e-mail-folder-utils.h" #include "e-mail-reader.h" #include "e-mail-session.h" -#include "e-mail-store.h" #include "em-account-editor.h" #include "em-account-prefs.h" #include "em-composer-prefs.h" @@ -220,18 +219,6 @@ mail_shell_backend_sync_store_done_cb (CamelStore *store, mail_shell_backend->priv->mail_sync_in_progress--; } -static void -mail_shell_backend_sync_store_cb (CamelStore *store, - EMailShellBackend *mail_shell_backend) -{ - mail_shell_backend->priv->mail_sync_in_progress++; - - mail_sync_store ( - store, FALSE, - mail_shell_backend_sync_store_done_cb, - mail_shell_backend); -} - static gboolean mail_shell_backend_mail_sync (EMailShellBackend *mail_shell_backend) { @@ -239,6 +226,7 @@ mail_shell_backend_mail_sync (EMailShellBackend *mail_shell_backend) EShellBackend *shell_backend; EMailBackend *backend; EMailSession *session; + GList *list, *link; shell_backend = E_SHELL_BACKEND (mail_shell_backend); shell = e_shell_backend_get_shell (shell_backend); @@ -254,10 +242,25 @@ mail_shell_backend_mail_sync (EMailShellBackend *mail_shell_backend) backend = E_MAIL_BACKEND (mail_shell_backend); session = e_mail_backend_get_session (backend); - e_mail_store_foreach ( - session, (GFunc) - mail_shell_backend_sync_store_cb, - mail_shell_backend); + list = camel_session_list_services (CAMEL_SESSION (session)); + + for (link = list; link != NULL; link = g_list_next (link)) { + CamelService *service; + + service = CAMEL_SERVICE (link->data); + + if (!CAMEL_IS_STORE (service)) + continue; + + mail_shell_backend->priv->mail_sync_in_progress++; + + mail_sync_store ( + CAMEL_STORE (service), FALSE, + mail_shell_backend_sync_store_done_cb, + mail_shell_backend); + } + + g_list_free (list); exit: return TRUE; @@ -309,8 +312,13 @@ mail_shell_backend_window_added_cb (GtkApplication *application, EShellBackend *shell_backend) { EShell *shell = E_SHELL (application); + EMailBackend *backend; + EMailSession *session; const gchar *backend_name; + backend = E_MAIL_BACKEND (shell_backend); + session = e_mail_backend_get_session (backend); + /* This applies to both the composer and signature editor. */ if (GTKHTML_IS_EDITOR (window)) { EShellSettings *shell_settings; @@ -339,7 +347,8 @@ mail_shell_backend_window_added_cb (GtkApplication *application, e_shell_backend_start (shell_backend); /* Integrate the new composer into the mail module. */ - em_configure_new_composer (E_MSG_COMPOSER (window)); + em_configure_new_composer ( + E_MSG_COMPOSER (window), session); return; } @@ -449,8 +458,9 @@ mail_shell_backend_start (EShellBackend *shell_backend) EShellSettings *shell_settings; EMailBackend *backend; EMailSession *session; + EMailAccountStore *account_store; gboolean enable_search_folders; - const gchar *data_dir; + GError *error = NULL; priv = E_MAIL_SHELL_BACKEND_GET_PRIVATE (shell_backend); @@ -459,15 +469,18 @@ mail_shell_backend_start (EShellBackend *shell_backend) backend = E_MAIL_BACKEND (shell_backend); session = e_mail_backend_get_session (backend); - data_dir = e_shell_backend_get_data_dir (shell_backend); - - e_mail_store_init (session, data_dir); + account_store = e_mail_session_get_account_store (session); enable_search_folders = e_shell_settings_get_boolean ( shell_settings, "mail-enable-search-folders"); if (enable_search_folders) vfolder_load_storage (backend); + if (!e_mail_account_store_load_sort_order (account_store, &error)) { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + } + mail_autoreceive_init (backend); if (g_getenv ("CAMEL_FLUSH_CHANGES") != NULL) diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c index abe3d2b6c5..5de727e7e7 100644 --- a/modules/mail/e-mail-shell-view-actions.c +++ b/modules/mail/e-mail-shell-view-actions.c @@ -84,45 +84,31 @@ action_mail_account_disable_cb (GtkAction *action, EMailShellSidebar *mail_shell_sidebar; EShellBackend *shell_backend; EShellView *shell_view; + EShellWindow *shell_window; EMailBackend *backend; EMailSession *session; + EMailAccountStore *account_store; EMFolderTree *folder_tree; - CamelService *service; CamelStore *store; - EAccountList *account_list; - EAccount *account; - const gchar *uid; mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; shell_view = E_SHELL_VIEW (mail_shell_view); shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); backend = E_MAIL_BACKEND (shell_backend); session = e_mail_backend_get_session (backend); + account_store = e_mail_session_get_account_store (session); folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); store = em_folder_tree_get_selected_store (folder_tree); g_return_if_fail (store != NULL); - service = CAMEL_SERVICE (store); - uid = camel_service_get_uid (service); - account = e_get_account_by_uid (uid); - g_return_if_fail (account != NULL); - - account_list = e_get_account_list (); - - if (e_account_list_account_has_proxies (account_list, account)) - e_account_list_remove_account_proxies (account_list, account); - - account->enabled = !account->enabled; - e_account_list_change (account_list, account); - e_mail_store_remove_by_account (session, account); - - if (account->parent_uid != NULL) - e_account_list_remove (account_list, account); - - e_account_list_save (account_list); + e_mail_account_store_disable_service ( + account_store, + GTK_WINDOW (shell_window), + CAMEL_SERVICE (store)); e_shell_view_update_actions (shell_view); } @@ -206,22 +192,6 @@ action_mail_download_finished_cb (CamelStore *store, } static void -action_mail_download_foreach_cb (CamelStore *store, - EMailReader *reader) -{ - EActivity *activity; - GCancellable *cancellable; - - activity = e_mail_reader_new_activity (reader); - cancellable = e_activity_get_cancellable (activity); - - e_mail_store_prepare_for_offline ( - store, G_PRIORITY_DEFAULT, - cancellable, (GAsyncReadyCallback) - action_mail_download_finished_cb, activity); -} - -static void action_mail_download_cb (GtkAction *action, EMailShellView *mail_shell_view) { @@ -230,6 +200,7 @@ action_mail_download_cb (GtkAction *action, EMailReader *reader; EMailBackend *backend; EMailSession *session; + GList *list, *link; mail_shell_content = mail_shell_view->priv->mail_shell_content; mail_view = e_mail_shell_content_get_mail_view (mail_shell_content); @@ -238,8 +209,28 @@ action_mail_download_cb (GtkAction *action, backend = e_mail_reader_get_backend (reader); session = e_mail_backend_get_session (backend); - e_mail_store_foreach ( - session, (GFunc) action_mail_download_foreach_cb, reader); + list = camel_session_list_services (CAMEL_SESSION (session)); + + for (link = list; link != NULL; link = g_list_next (link)) { + EActivity *activity; + CamelService *service; + GCancellable *cancellable; + + service = CAMEL_SERVICE (link->data); + + if (!CAMEL_IS_STORE (service)) + continue; + + activity = e_mail_reader_new_activity (reader); + cancellable = e_activity_get_cancellable (activity); + + e_mail_store_prepare_for_offline ( + CAMEL_STORE (service), G_PRIORITY_DEFAULT, + cancellable, (GAsyncReadyCallback) + action_mail_download_finished_cb, activity); + } + + g_list_free (list); } static void diff --git a/modules/mail/e-mail-shell-view-private.c b/modules/mail/e-mail-shell-view-private.c index ab669d3cb9..534a2583b6 100644 --- a/modules/mail/e-mail-shell-view-private.c +++ b/modules/mail/e-mail-shell-view-private.c @@ -937,13 +937,14 @@ e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view) EShellView *shell_view; EMailReader *reader; EMailView *mail_view; - CamelStore *local_store; CamelStore *parent_store; CamelFolder *folder; GPtrArray *uids; GString *buffer; + gboolean store_is_local; const gchar *display_name; const gchar *folder_name; + const gchar *uid; gchar *title; guint32 num_deleted; guint32 num_junked; @@ -962,8 +963,6 @@ e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view) reader = E_MAIL_READER (mail_view); folder = e_mail_reader_get_folder (reader); - local_store = e_mail_local_get_store (); - /* If no folder is selected, reset the sidebar banners * to their default values and stop. */ if (folder == NULL) { @@ -1058,9 +1057,12 @@ e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view) em_utils_uids_free (uids); + uid = camel_service_get_uid (CAMEL_SERVICE (parent_store)); + store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0); + /* Choose a suitable folder name for displaying. */ display_name = folder_name; - if (parent_store == local_store) { + if (store_is_local) { if (strcmp (folder_name, "Drafts") == 0) display_name = _("Drafts"); else if (strcmp (folder_name, "Inbox") == 0) diff --git a/modules/mail/e-mail-shell-view-private.h b/modules/mail/e-mail-shell-view-private.h index 5bc477dbcd..24b5e531bf 100644 --- a/modules/mail/e-mail-shell-view-private.h +++ b/modules/mail/e-mail-shell-view-private.h @@ -40,13 +40,11 @@ #include "e-mail-label-action.h" #include "e-mail-label-dialog.h" #include "e-mail-label-list-store.h" -#include "e-mail-local.h" #include "e-mail-reader.h" #include "e-mail-reader-utils.h" #include "e-mail-session.h" #include "e-mail-session-utils.h" #include "e-mail-sidebar.h" -#include "e-mail-store.h" #include "e-mail-store-utils.h" #include "em-composer-utils.h" #include "em-folder-properties.h" diff --git a/modules/mail/e-mail-shell-view.c b/modules/mail/e-mail-shell-view.c index 02a31c20de..45246e60e9 100644 --- a/modules/mail/e-mail-shell-view.c +++ b/modules/mail/e-mail-shell-view.c @@ -558,7 +558,7 @@ all_accounts: /* FIXME Complete lack of error checking here. */ service = camel_session_get_service ( - CAMEL_SESSION (session), "vfolder"); + CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID); em_utils_connect_service_sync (service, NULL, NULL); search_folder = (CamelVeeFolder *) camel_vee_folder_new ( @@ -719,7 +719,7 @@ current_account: /* FIXME Complete lack of error checking here. */ service = camel_session_get_service ( - CAMEL_SESSION (session), "vfolder"); + CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID); em_utils_connect_service_sync (service, NULL, NULL); search_folder = (CamelVeeFolder *) camel_vee_folder_new ( diff --git a/modules/mail/em-account-prefs.c b/modules/mail/em-account-prefs.c index ddf51d815e..9506e75d29 100644 --- a/modules/mail/em-account-prefs.c +++ b/modules/mail/em-account-prefs.c @@ -36,8 +36,6 @@ #include "e-util/e-account-utils.h" #include "e-mail-backend.h" -#include "e-mail-local.h" -#include "e-mail-store.h" #include "em-config.h" #include "em-account-editor.h" #include "em-utils.h" @@ -45,6 +43,10 @@ #include "shell/e-shell.h" #include "capplet/settings/mail-capplet-shell.h" +#define EM_ACCOUNT_PREFS_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefsPrivate)) + struct _EMAccountPrefsPrivate { EMailBackend *backend; gpointer assistant; /* weak pointer */ @@ -59,101 +61,23 @@ enum { G_DEFINE_TYPE ( EMAccountPrefs, em_account_prefs, - E_TYPE_ACCOUNT_MANAGER) - -static gboolean -account_prefs_toggle_enable_special (EMAccountPrefs *prefs, - EAccountTreeViewSelectedType type, - gboolean enabled) -{ - const gchar *prop = NULL; - EShell *shell; - EShellSettings *shell_settings; - - g_return_val_if_fail (prefs != NULL, FALSE); - g_return_val_if_fail (prefs->priv != NULL, FALSE); - - if (type == E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL) - prop = "mail-enable-local-folders"; - else if (type == E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER) - prop = "mail-enable-search-folders"; - - if (!prop) - return FALSE; - - shell = e_shell_backend_get_shell (E_SHELL_BACKEND (prefs->priv->backend)); - shell_settings = e_shell_get_shell_settings (shell); - - e_shell_settings_set_boolean (shell_settings, prop, enabled); - - /* make sure "Search Folders" are loaded when enabled */ - if (enabled && type == E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER) - vfolder_load_storage (prefs->priv->backend); - - return TRUE; -} + E_TYPE_MAIL_ACCOUNT_MANAGER) static void -account_prefs_enable_account_cb (EAccountTreeView *tree_view, - EMAccountPrefs *prefs) -{ - EAccount *account; - EMailSession *session; - - account = e_account_tree_view_get_selected (tree_view); - if (!account) { - if (account_prefs_toggle_enable_special (prefs, e_account_tree_view_get_selected_type (tree_view), TRUE)) - return; - } - - g_return_if_fail (account != NULL); - - session = e_mail_backend_get_session (prefs->priv->backend); - e_mail_store_add_by_account (session, account); -} - -static void -account_prefs_disable_account_cb (EAccountTreeView *tree_view, +account_prefs_service_enabled_cb (EMailAccountStore *store, + CamelService *service, EMAccountPrefs *prefs) { - EAccountList *account_list; - EAccount *account; - EMailSession *session; - gpointer parent; - gint response; - - account = e_account_tree_view_get_selected (tree_view); - if (!account) { - if (account_prefs_toggle_enable_special (prefs, e_account_tree_view_get_selected_type (tree_view), FALSE)) - return; - } - - g_return_if_fail (account != NULL); - - session = e_mail_backend_get_session (prefs->priv->backend); - - account_list = e_account_tree_view_get_account_list (tree_view); - g_return_if_fail (account_list != NULL); - - if (!e_account_list_account_has_proxies (account_list, account)) { - e_mail_store_remove_by_account (session, account); - return; - } - - parent = gtk_widget_get_toplevel (GTK_WIDGET (tree_view)); - parent = gtk_widget_is_toplevel (parent) ? parent : NULL; - - response = e_alert_run_dialog_for_args ( - parent, "mail:ask-delete-proxy-accounts", NULL); - - if (response != GTK_RESPONSE_YES) { - g_signal_stop_emission_by_name (tree_view, "disable-account"); - return; - } + EMailBackend *backend; + const gchar *uid; - e_account_list_remove_account_proxies (account_list, account); + uid = camel_service_get_uid (service); + backend = em_account_prefs_get_backend (prefs); - e_mail_store_remove_by_account (session, account); + /* FIXME Kind of a gross hack. EMailSession doesn't have + * access to EMailBackend so it can't do this itself. */ + if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0) + vfolder_load_storage (backend); } static void @@ -206,7 +130,7 @@ account_prefs_dispose (GObject *object) { EMAccountPrefsPrivate *priv; - priv = EM_ACCOUNT_PREFS (object)->priv; + priv = EM_ACCOUNT_PREFS_GET_PRIVATE (object); if (priv->backend != NULL) { g_object_unref (priv->backend); @@ -230,13 +154,30 @@ account_prefs_dispose (GObject *object) } static void -account_prefs_add_account (EAccountManager *manager) +account_prefs_constructed (GObject *object) +{ + EMailAccountManager *manager; + EMailAccountStore *store; + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (em_account_prefs_parent_class)->constructed (object); + + manager = E_MAIL_ACCOUNT_MANAGER (object); + store = e_mail_account_manager_get_store (manager); + + g_signal_connect ( + store, "service-enabled", + G_CALLBACK (account_prefs_service_enabled_cb), manager); +} + +static void +account_prefs_add_account (EMailAccountManager *manager) { EMAccountPrefsPrivate *priv; EMAccountEditor *emae; gpointer parent; - priv = EM_ACCOUNT_PREFS (manager)->priv; + priv = EM_ACCOUNT_PREFS_GET_PRIVATE (manager); if (priv->assistant != NULL) { gtk_window_present (GTK_WINDOW (priv->assistant)); @@ -275,25 +216,20 @@ account_prefs_add_account (EAccountManager *manager) } static void -account_prefs_edit_account (EAccountManager *manager) +account_prefs_edit_account (EMailAccountManager *manager, + EAccount *account) { EMAccountPrefsPrivate *priv; EMAccountEditor *emae; - EAccountTreeView *tree_view; - EAccount *account; gpointer parent; - priv = EM_ACCOUNT_PREFS (manager)->priv; + priv = EM_ACCOUNT_PREFS_GET_PRIVATE (manager); if (priv->editor != NULL) { gtk_window_present (GTK_WINDOW (priv->editor)); return; } - tree_view = e_account_manager_get_tree_view (manager); - account = e_account_tree_view_get_selected (tree_view); - g_return_if_fail (account != NULL); - parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); parent = gtk_widget_is_toplevel (parent) ? parent : NULL; @@ -320,64 +256,10 @@ account_prefs_edit_account (EAccountManager *manager) } static void -account_prefs_delete_account (EAccountManager *manager) -{ - EMAccountPrefsPrivate *priv; - EAccountTreeView *tree_view; - EAccountList *account_list; - EAccount *account; - EMailSession *session; - gboolean has_proxies; - gpointer parent; - gint response; - - priv = EM_ACCOUNT_PREFS (manager)->priv; - session = e_mail_backend_get_session (priv->backend); - - account_list = e_account_manager_get_account_list (manager); - tree_view = e_account_manager_get_tree_view (manager); - account = e_account_tree_view_get_selected (tree_view); - g_return_if_fail (account != NULL); - - /* Make sure we aren't editing anything... */ - if (priv->editor != NULL) - return; - - parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); - parent = gtk_widget_is_toplevel (parent) ? parent : NULL; - - has_proxies = - e_account_list_account_has_proxies (account_list, account); - - response = e_alert_run_dialog_for_args ( - parent, has_proxies ? - "mail:ask-delete-account-with-proxies" : - "mail:ask-delete-account", NULL); - - if (response != GTK_RESPONSE_YES) { - g_signal_stop_emission_by_name (manager, "delete-account"); - return; - } - - /* Remove the account from the folder tree. */ - if (account->enabled) - e_mail_store_remove_by_account (session, account); - - /* Remove all the proxies the account has created. */ - if (has_proxies) - e_account_list_remove_account_proxies (account_list, account); - - /* Remove it from the config file. */ - e_account_list_remove (account_list, account); - - e_account_list_save (account_list); -} - -static void em_account_prefs_class_init (EMAccountPrefsClass *class) { GObjectClass *object_class; - EAccountManagerClass *account_manager_class; + EMailAccountManagerClass *account_manager_class; g_type_class_add_private (class, sizeof (EMAccountPrefsPrivate)); @@ -385,11 +267,11 @@ em_account_prefs_class_init (EMAccountPrefsClass *class) object_class->set_property = account_prefs_set_property; object_class->get_property = account_prefs_get_property; object_class->dispose = account_prefs_dispose; + object_class->constructed = account_prefs_constructed; - account_manager_class = E_ACCOUNT_MANAGER_CLASS (class); + account_manager_class = E_MAIL_ACCOUNT_MANAGER_CLASS (class); account_manager_class->add_account = account_prefs_add_account; account_manager_class->edit_account = account_prefs_edit_account; - account_manager_class->delete_account = account_prefs_delete_account; g_object_class_install_property ( object_class, @@ -406,41 +288,7 @@ em_account_prefs_class_init (EMAccountPrefsClass *class) static void em_account_prefs_init (EMAccountPrefs *prefs) { - EAccountManager *manager; - EAccountTreeView *tree_view; - - prefs->priv = G_TYPE_INSTANCE_GET_PRIVATE ( - prefs, EM_TYPE_ACCOUNT_PREFS, EMAccountPrefsPrivate); - - manager = E_ACCOUNT_MANAGER (prefs); - tree_view = e_account_manager_get_tree_view (manager); - - g_signal_connect ( - tree_view, "enable-account", - G_CALLBACK (account_prefs_enable_account_cb), prefs); - - g_signal_connect ( - tree_view, "disable-account", - G_CALLBACK (account_prefs_disable_account_cb), prefs); -} - -static void -account_tree_view_sort_order_changed_cb (EAccountTreeView *tree_view, - EMailBackend *backend) -{ - GSList *account_uids; - - g_return_if_fail (tree_view != NULL); - g_return_if_fail (backend != NULL); - - account_uids = e_account_tree_view_get_sort_order (tree_view); - if (!account_uids) - return; - - em_utils_save_accounts_sort_order (backend, account_uids); - - g_slist_foreach (account_uids, (GFunc) g_free, NULL); - g_slist_free (account_uids); + prefs->priv = EM_ACCOUNT_PREFS_GET_PRIVATE (prefs); } GtkWidget * @@ -448,60 +296,20 @@ em_account_prefs_new (EPreferencesWindow *window) { EShell *shell; EShellBackend *shell_backend; - EAccountList *account_list; - EAccountTreeView *tree_view; + EMailAccountStore *account_store; EMailSession *session; - const gchar *data_dir; - GtkWidget *res; - GSList *account_uids; - - account_list = e_get_account_list (); - g_return_val_if_fail (E_IS_ACCOUNT_LIST (account_list), NULL); /* XXX Figure out a better way to get the mail backend. */ shell = e_preferences_window_get_shell (window); shell_backend = e_shell_get_backend_by_name (shell, "mail"); session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend)); - data_dir = e_shell_backend_get_data_dir (shell_backend); + account_store = e_mail_session_get_account_store (session); - /* Make sure the e-mail-local is initialized. */ - e_mail_local_init (session, data_dir); - - res = g_object_new ( + return g_object_new ( EM_TYPE_ACCOUNT_PREFS, - "account-list", account_list, + "store", account_store, "backend", shell_backend, NULL); - - tree_view = e_account_manager_get_tree_view (E_ACCOUNT_MANAGER (res)); - e_account_tree_view_set_express_mode (tree_view, e_shell_get_express_mode (shell)); - - g_object_bind_property ( - e_shell_get_shell_settings (shell), "mail-sort-accounts-alpha", - tree_view, "sort-alpha", - G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - e_shell_get_shell_settings (shell), "mail-enable-local-folders", - tree_view, "enable-local-folders", - G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); - - g_object_bind_property ( - e_shell_get_shell_settings (shell), "mail-enable-search-folders", - tree_view, "enable-search-folders", - G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); - - account_uids = em_utils_load_accounts_sort_order (E_MAIL_BACKEND (shell_backend)); - if (account_uids) { - e_account_tree_view_set_sort_order (tree_view, account_uids); - g_slist_foreach (account_uids, (GFunc) g_free, NULL); - g_slist_free (account_uids); - } - - g_signal_connect (tree_view, "sort-order-changed", - G_CALLBACK (account_tree_view_sort_order_changed_cb), shell_backend); - - return res; } EMailBackend * diff --git a/modules/mail/em-account-prefs.h b/modules/mail/em-account-prefs.h index 667b83f42f..b7ba5b0dde 100644 --- a/modules/mail/em-account-prefs.h +++ b/modules/mail/em-account-prefs.h @@ -26,7 +26,7 @@ #include <table/e-table.h> #include <libedataserver/e-account-list.h> #include <mail/e-mail-backend.h> -#include <misc/e-account-manager.h> +#include <mail/e-mail-account-manager.h> #include <widgets/misc/e-preferences-window.h> /* Standard GObject macros */ @@ -55,12 +55,12 @@ typedef struct _EMAccountPrefsClass EMAccountPrefsClass; typedef struct _EMAccountPrefsPrivate EMAccountPrefsPrivate; struct _EMAccountPrefs { - EAccountManager parent; + EMailAccountManager parent; EMAccountPrefsPrivate *priv; }; struct _EMAccountPrefsClass { - EAccountManagerClass parent_class; + EMailAccountManagerClass parent_class; }; GType em_account_prefs_get_type (void); diff --git a/modules/mdn/evolution-mdn.c b/modules/mdn/evolution-mdn.c index 4311ab73bf..6ce5dec555 100644 --- a/modules/mdn/evolution-mdn.c +++ b/modules/mdn/evolution-mdn.c @@ -26,7 +26,6 @@ #include <e-util/e-account-utils.h> #include <mail/em-utils.h> -#include <mail/e-mail-local.h> #include <mail/e-mail-reader.h> #include <mail/mail-send-recv.h> #include <mail/em-composer-utils.h> @@ -188,6 +187,7 @@ mdn_notify_sender (EAccount *account, CamelFolder *out_folder; CamelMessageInfo *receipt_info; EMailBackend *backend; + EMailSession *session; const gchar *message_id; const gchar *message_date; const gchar *message_subject; @@ -202,6 +202,7 @@ mdn_notify_sender (EAccount *account, gchar *ua; backend = e_mail_reader_get_backend (reader); + session = e_mail_backend_get_session (backend); /* Tag the message immediately even though we haven't actually sent * the read receipt yet. Not a big deal if we fail to send it, and @@ -361,7 +362,9 @@ mdn_notify_sender (EAccount *account, /* Send the receipt. */ receipt_info = camel_message_info_new (NULL); - out_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX); + out_folder = + e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_OUTBOX); camel_message_info_set_flags ( receipt_info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); diff --git a/modules/startup-wizard/evolution-startup-wizard.c b/modules/startup-wizard/evolution-startup-wizard.c index 54727df60a..de15b72609 100644 --- a/modules/startup-wizard/evolution-startup-wizard.c +++ b/modules/startup-wizard/evolution-startup-wizard.c @@ -29,7 +29,6 @@ #include <e-util/e-import.h> #include <mail/e-mail-backend.h> -#include <mail/e-mail-local.h> #include <mail/em-account-editor.h> #include <capplet/settings/mail-capplet-shell.h> #include <calendar/gui/calendar-config.h> @@ -433,22 +432,16 @@ startup_wizard_new_assistant (EStartupWizard *extension) EShell *shell; EShellBackend *shell_backend; EMailBackend *backend; - EMailSession *session; EMAccountEditor *emae; EConfig *config; EConfigItem *config_item; GtkWidget *widget; GSList *items = NULL; - const gchar *data_dir; shell = startup_wizard_get_shell (extension); shell_backend = e_shell_get_backend_by_name (shell, "mail"); backend = E_MAIL_BACKEND (shell_backend); - session = e_mail_backend_get_session (backend); - data_dir = e_shell_backend_get_data_dir (shell_backend); - - e_mail_local_init (session, data_dir); emae = em_account_editor_new ( NULL, EMAE_ASSISTANT, backend, diff --git a/plugins/dbx-import/dbx-importer.c b/plugins/dbx-import/dbx-importer.c index b838bdf953..f7bedc856f 100644 --- a/plugins/dbx-import/dbx-importer.c +++ b/plugins/dbx-import/dbx-importer.c @@ -65,7 +65,6 @@ #include <libedataserverui/e-source-selector-dialog.h> #include <mail/e-mail-backend.h> -#include <mail/e-mail-local.h> #include <mail/em-folder-selection-button.h> #include <mail/mail-mt.h> #include <mail/mail-tools.h> @@ -203,6 +202,8 @@ org_gnome_evolution_readdbx_getwidget (EImport *ei, { EShell *shell; EShellBackend *shell_backend; + EMailBackend *backend; + EMailSession *session; GtkWidget *hbox, *w; GtkLabel *label; gchar *select_uri = NULL; @@ -238,10 +239,18 @@ org_gnome_evolution_readdbx_getwidget (EImport *ei, } } #endif + + shell = e_shell_get_default (); + shell_backend = e_shell_get_backend_by_name (shell, "mail"); + + backend = E_MAIL_BACKEND (shell_backend); + session = e_mail_backend_get_session (backend); + if (!select_uri) { const gchar *local_inbox_uri; - local_inbox_uri = e_mail_local_get_folder_uri ( - E_MAIL_LOCAL_FOLDER_INBOX); + local_inbox_uri = + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_INBOX); select_uri = g_strdup (local_inbox_uri); } @@ -252,9 +261,6 @@ org_gnome_evolution_readdbx_getwidget (EImport *ei, label = GTK_LABEL (w); - shell = e_shell_get_default (); - shell_backend = e_shell_get_backend_by_name (shell, "mail"); - w = em_folder_selection_button_new ( E_MAIL_BACKEND (shell_backend), _("Select folder"), diff --git a/plugins/pst-import/pst-importer.c b/plugins/pst-import/pst-importer.c index 8ef601241f..c7d180151e 100644 --- a/plugins/pst-import/pst-importer.c +++ b/plugins/pst-import/pst-importer.c @@ -54,7 +54,6 @@ #include <libedataserverui/e-client-utils.h> #include <mail/e-mail-backend.h> -#include <mail/e-mail-local.h> #include <mail/em-folder-selection-button.h> #include <mail/mail-mt.h> #include <mail/mail-tools.h> @@ -228,6 +227,7 @@ get_suggested_foldername (EImportTargetURI *target) { EShell *shell; EShellBackend *shell_backend; + EMailBackend *backend; EMailSession *session; GtkWindow *window; const gchar *inbox; @@ -241,7 +241,9 @@ get_suggested_foldername (EImportTargetURI *target) * data, I don't see how else to get to it. */ shell = e_shell_get_default (); shell_backend = e_shell_get_backend_by_name (shell, "mail"); - session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend)); + + backend = E_MAIL_BACKEND (shell_backend); + session = e_mail_backend_get_session (backend); foldername = NULL; @@ -284,7 +286,9 @@ get_suggested_foldername (EImportTargetURI *target) if (!foldername) { /* Suggest a folder that is in the same mail storage as the users' inbox, * with a name derived from the .PST file */ - inbox = e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_INBOX); + inbox = + e_mail_session_get_local_folder_uri ( + session, E_MAIL_LOCAL_FOLDER_INBOX); delim = g_strrstr (inbox, "#"); if (delim != NULL) { diff --git a/plugins/templates/templates.c b/plugins/templates/templates.c index d8921bcb11..714a6f0e0b 100644 --- a/plugins/templates/templates.c +++ b/plugins/templates/templates.c @@ -33,7 +33,6 @@ #include <e-util/e-config.h> #include <mail/e-mail-folder-utils.h> -#include <mail/e-mail-local.h> #include <mail/e-mail-reader.h> #include <mail/e-mail-session.h> #include <mail/em-composer-utils.h> @@ -764,6 +763,7 @@ create_new_message (CamelFolder *folder, CamelDataWrapper *dw; struct _camel_header_raw *header; EMailBackend *backend; + EMailSession *session; EShell *shell; const gchar *message_uid; gint i; @@ -798,9 +798,11 @@ create_new_message (CamelFolder *folder, message_uid = context->message_uid; backend = e_mail_reader_get_backend (context->reader); + session = e_mail_backend_get_session (backend); shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend)); - folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_TEMPLATES); + folder = e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_TEMPLATES); new = camel_mime_message_new (); new_multipart = camel_multipart_new (); @@ -995,7 +997,8 @@ action_reply_with_template_cb (GtkAction *action, } static void -build_template_menus_recurse (GtkUIManager *ui_manager, +build_template_menus_recurse (CamelStore *local_store, + GtkUIManager *ui_manager, GtkActionGroup *action_group, const gchar *menu_path, guint *action_count, @@ -1003,10 +1006,9 @@ build_template_menus_recurse (GtkUIManager *ui_manager, CamelFolderInfo *folder_info, EShellView *shell_view) { - CamelStore *store; - EShellWindow *shell_window = e_shell_view_get_shell_window (shell_view); + EShellWindow *shell_window; - store = e_mail_local_get_store (); + shell_window = e_shell_view_get_shell_window (shell_view); while (folder_info != NULL) { CamelFolder *folder; @@ -1019,9 +1021,10 @@ build_template_menus_recurse (GtkUIManager *ui_manager, guint ii; display_name = folder_info->display_name; + /* FIXME Not passing a GCancellable or GError here. */ folder = camel_store_get_folder_sync ( - store, folder_info->full_name, 0, NULL, NULL); + local_store, folder_info->full_name, 0, NULL, NULL); action_name = g_strdup_printf ( "templates-menu-%d", *action_count); @@ -1044,9 +1047,12 @@ build_template_menus_recurse (GtkUIManager *ui_manager, /* Disconnect previous connection to avoid possible multiple calls because * folder is a persistent structure */ - g_signal_handlers_disconnect_by_func (folder, G_CALLBACK (templates_folder_msg_changed_cb), shell_window); - g_signal_connect (folder, "changed", - G_CALLBACK (templates_folder_msg_changed_cb), shell_window); + g_signal_handlers_disconnect_by_func ( + folder, G_CALLBACK (templates_folder_msg_changed_cb), shell_window); + g_signal_connect ( + folder, "changed", + G_CALLBACK (templates_folder_msg_changed_cb), + shell_window); path = g_strdup_printf ("%s/%s", menu_path, action_name); @@ -1056,6 +1062,7 @@ build_template_menus_recurse (GtkUIManager *ui_manager, /* Add submenus, if any. */ if (folder_info->child != NULL) build_template_menus_recurse ( + local_store, ui_manager, action_group, path, action_count, merge_id, folder_info->child, shell_view); @@ -1130,6 +1137,10 @@ static void got_message_draft_cb (EMsgComposer *composer, GAsyncResult *result) { + EShell *shell; + EShellBackend *shell_backend; + EMailBackend *backend; + EMailSession *session; CamelMimeMessage *message; CamelMessageInfo *info; CamelFolder *folder; @@ -1157,8 +1168,15 @@ got_message_draft_cb (EMsgComposer *composer, g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message)); + shell = e_shell_get_default (); + shell_backend = e_shell_get_backend_by_name (shell, "mail"); + + backend = E_MAIL_BACKEND (shell_backend); + session = e_mail_backend_get_session (backend); + /* Get the templates folder and all UIDs of the messages there. */ - folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_TEMPLATES); + folder = e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_TEMPLATES); info = camel_message_info_new (NULL); @@ -1201,8 +1219,11 @@ build_menu (EShellWindow *shell_window, GtkActionGroup *action_group) { EShellView *shell_view; + EShellBackend *shell_backend; + EMailBackend *backend; + EMailSession *session; CamelFolder *folder; - CamelStore *store; + CamelStore *local_store; CamelFolderInfo *folder_info; GtkUIManager *ui_manager; guint merge_id; @@ -1211,28 +1232,32 @@ build_menu (EShellWindow *shell_window, ui_manager = e_shell_window_get_ui_manager (shell_window); shell_view = e_shell_window_get_shell_view (shell_window, "mail"); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + backend = E_MAIL_BACKEND (shell_backend); + session = e_mail_backend_get_session (backend); + local_store = e_mail_session_get_local_store (session); merge_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (action_group), "merge-id")); /* Now recursively build template submenus in the pop-up menu. */ - store = e_mail_local_get_store (); - folder = e_mail_local_get_folder ( - E_MAIL_LOCAL_FOLDER_TEMPLATES); + folder = e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_TEMPLATES); full_name = camel_folder_get_full_name (folder); /* FIXME Not passing a GCancellable or GError here. */ folder_info = camel_store_get_folder_info_sync ( - store, full_name, + local_store, full_name, CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_FAST, NULL, NULL); build_template_menus_recurse ( - ui_manager, action_group, + local_store, ui_manager, action_group, "/mail-message-popup/mail-message-templates", &action_count, merge_id, folder_info, shell_view); - camel_store_free_folder_info (store, folder_info); + camel_store_free_folder_info (local_store, folder_info); } static void @@ -1325,32 +1350,49 @@ static void mail_shell_view_created_cb (EShellWindow *shell_window, EShellView *shell_view) { + EMailBackend *backend; + EMailSession *session; + EShellBackend *shell_backend; GtkUIManager *ui_manager; GtkActionGroup *action_group; CamelFolder *folder; - CamelStore *store; + CamelStore *local_store; guint merge_id; ui_manager = e_shell_window_get_ui_manager (shell_window); e_shell_window_add_action_group (shell_window, "templates"); action_group = e_lookup_action_group (ui_manager, "templates"); + merge_id = gtk_ui_manager_new_merge_id (ui_manager); - g_object_set_data (G_OBJECT (action_group), "merge-id", - GUINT_TO_POINTER (merge_id)); - folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_TEMPLATES); - store = e_mail_local_get_store (); + g_object_set_data ( + G_OBJECT (action_group), "merge-id", + GUINT_TO_POINTER (merge_id)); + + shell_backend = e_shell_view_get_shell_backend (shell_view); + + backend = E_MAIL_BACKEND (shell_backend); + session = e_mail_backend_get_session (backend); + local_store = e_mail_session_get_local_store (session); - g_signal_connect (folder, "changed", + folder = e_mail_session_get_local_folder ( + session, E_MAIL_LOCAL_FOLDER_TEMPLATES); + + g_signal_connect ( + folder, "changed", G_CALLBACK (templates_folder_msg_changed_cb), shell_window); - g_signal_connect (store, "folder-created", + g_signal_connect ( + local_store, "folder-created", G_CALLBACK (templates_folder_changed_cb), shell_window); - g_signal_connect (store, "folder-deleted", + g_signal_connect ( + local_store, "folder-deleted", G_CALLBACK (templates_folder_changed_cb), shell_window); - g_signal_connect (store, "folder-renamed", + g_signal_connect ( + local_store, "folder-renamed", G_CALLBACK (templates_folder_renamed_cb), shell_window); - g_signal_connect (shell_view, "update-actions", + g_signal_connect ( + shell_view, "update-actions", G_CALLBACK (update_actions_cb), action_group); } diff --git a/po/POTFILES.in b/po/POTFILES.in index 69b8498896..b257780c9b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -178,7 +178,8 @@ filter/e-rule-context.c filter/e-rule-editor.c filter/filter.error.xml [type: gettext/glade]filter/filter.ui -mail/em-account-editor.c +mail/e-mail-account-manager.c +mail/e-mail-account-tree-view.c mail/e-mail-attachment-bar.c mail/e-mail-browser.c mail/e-mail-display.c @@ -188,16 +189,15 @@ mail/e-mail-label-dialog.c mail/e-mail-label-list-store.c mail/e-mail-label-manager.c mail/e-mail-label-tree-view.c -mail/e-mail-local.c mail/e-mail-migrate.c mail/e-mail-notebook-view.c mail/e-mail-reader.c mail/e-mail-reader-utils.c mail/e-mail-session.c mail/e-mail-session-utils.c -mail/e-mail-store.c mail/e-mail-store-utils.c mail/e-mail-tag-editor.c +mail/em-account-editor.c mail/em-composer-utils.c mail/em-filter-editor.c mail/em-filter-folder-element.c @@ -424,8 +424,6 @@ widgets/menus/gal-view-instance-save-as-dialog.c widgets/menus/gal-view-new-dialog.c [type: gettext/glade]widgets/menus/gal-view-new-dialog.ui widgets/misc/ea-calendar-item.c -widgets/misc/e-account-manager.c -widgets/misc/e-account-tree-view.c widgets/misc/e-action-combo-box.c widgets/misc/e-activity-proxy.c widgets/misc/e-alert-bar.c diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am index 5235c1ca54..71194d17ad 100644 --- a/widgets/misc/Makefile.am +++ b/widgets/misc/Makefile.am @@ -6,8 +6,6 @@ ui_DATA = e-send-options.ui widgetsinclude_HEADERS = \ e-account-combo-box.h \ - e-account-manager.h \ - e-account-tree-view.h \ e-action-combo-box.h \ e-activity-bar.h \ e-activity-proxy.h \ @@ -91,8 +89,6 @@ libemiscwidgets_la_CPPFLAGS = \ libemiscwidgets_la_SOURCES = \ $(widgetsinclude_HEADERS) \ e-account-combo-box.c \ - e-account-manager.c \ - e-account-tree-view.c \ e-action-combo-box.c \ e-activity-bar.c \ e-activity-proxy.c \ diff --git a/widgets/misc/e-account-manager.c b/widgets/misc/e-account-manager.c deleted file mode 100644 index b2c0583b8b..0000000000 --- a/widgets/misc/e-account-manager.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * e-account-manager.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-account-manager.h" - -#include <glib/gi18n.h> -#include <gdk/gdkkeysyms.h> -#include "e-account-tree-view.h" - -struct _EAccountManagerPrivate { - EAccountList *account_list; - - GtkWidget *tree_view; - GtkWidget *add_button; - GtkWidget *edit_button; - GtkWidget *delete_button; - GtkWidget *default_button; - GtkWidget *sort_toggle; - GtkWidget *sort_up_button; - GtkWidget *sort_down_button; -}; - -enum { - PROP_0, - PROP_ACCOUNT_LIST -}; - -enum { - ADD_ACCOUNT, - EDIT_ACCOUNT, - DELETE_ACCOUNT, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -G_DEFINE_TYPE ( - EAccountManager, - e_account_manager, - GTK_TYPE_TABLE) - -static void -account_manager_default_clicked_cb (EAccountManager *manager) -{ - EAccountTreeView *tree_view; - EAccountList *account_list; - EAccount *account; - - tree_view = e_account_manager_get_tree_view (manager); - account_list = e_account_manager_get_account_list (manager); - account = e_account_tree_view_get_selected (tree_view); - g_return_if_fail (account != NULL); - - e_account_list_set_default (account_list, account); - - /* This signals the tree view to refresh. */ - e_account_list_change (account_list, account); -} - -static gboolean -account_manager_key_press_event_cb (EAccountManager *manager, - GdkEventKey *event) -{ - if (event->keyval == GDK_KEY_Delete) { - e_account_manager_delete_account (manager); - return TRUE; - } - - return FALSE; -} - -static void -account_manager_selection_changed_cb (EAccountManager *manager, - GtkTreeSelection *selection) -{ - EAccountTreeView *tree_view; - EAccountList *account_list; - EAccount *default_account; - EAccount *account; - GtkTreeModel *model = NULL; - GtkTreeIter iter1, iter2; - GtkWidget *add_button; - GtkWidget *edit_button; - GtkWidget *delete_button; - GtkWidget *default_button; - GtkWidget *sort_up_button; - GtkWidget *sort_down_button; - gboolean sensitive; - - add_button = manager->priv->add_button; - edit_button = manager->priv->edit_button; - delete_button = manager->priv->delete_button; - default_button = manager->priv->default_button; - sort_up_button = manager->priv->sort_up_button; - sort_down_button = manager->priv->sort_down_button; - - tree_view = e_account_manager_get_tree_view (manager); - account = e_account_tree_view_get_selected (tree_view); - account_list = e_account_tree_view_get_account_list (tree_view); - - if (account == NULL) - gtk_widget_grab_focus (add_button); - - /* XXX EAccountList misuses const */ - default_account = (EAccount *) - e_account_list_get_default (account_list); - - sensitive = (account != NULL); - gtk_widget_set_sensitive (edit_button, sensitive); - - sensitive = (account != NULL); - gtk_widget_set_sensitive (delete_button, sensitive); - - sensitive = (account != NULL && account != default_account); - gtk_widget_set_sensitive (default_button, sensitive); - - sensitive = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (manager->priv->sort_toggle)) && - gtk_tree_selection_get_selected (selection, &model, &iter1); - iter2 = iter1; - gtk_widget_set_sensitive (sort_up_button, sensitive && gtk_tree_model_iter_previous (model, &iter1)); - gtk_widget_set_sensitive (sort_down_button, sensitive && gtk_tree_model_iter_next (model, &iter2)); -} - -static void -account_manager_sort_toggled_cb (EAccountManager *manager) -{ - GtkTreeView *tree_view; - GtkTreeSelection *selection; - - tree_view = GTK_TREE_VIEW (e_account_manager_get_tree_view (manager)); - selection = gtk_tree_view_get_selection (tree_view); - - account_manager_selection_changed_cb (manager, selection); -} - -static void -account_manager_sort_up_cb (EAccountManager *manager) -{ - GtkTreeView *tree_view; - GtkTreeSelection *selection; - - tree_view = GTK_TREE_VIEW (e_account_manager_get_tree_view (manager)); - selection = gtk_tree_view_get_selection (tree_view); - - e_account_tree_view_move_up (e_account_manager_get_tree_view (manager)); - account_manager_selection_changed_cb (manager, selection); -} - -static void -account_manager_sort_down_cb (EAccountManager *manager) -{ - GtkTreeView *tree_view; - GtkTreeSelection *selection; - - tree_view = GTK_TREE_VIEW (e_account_manager_get_tree_view (manager)); - selection = gtk_tree_view_get_selection (tree_view); - - e_account_tree_view_move_down (e_account_manager_get_tree_view (manager)); - account_manager_selection_changed_cb (manager, selection); -} - -static void -account_manager_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_ACCOUNT_LIST: - e_account_manager_set_account_list ( - E_ACCOUNT_MANAGER (object), - g_value_get_object (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -account_manager_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_ACCOUNT_LIST: - g_value_set_object ( - value, - e_account_manager_get_account_list ( - E_ACCOUNT_MANAGER (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -account_manager_dispose (GObject *object) -{ - EAccountManagerPrivate *priv; - - priv = E_ACCOUNT_MANAGER (object)->priv; - - if (priv->account_list != NULL) { - g_object_unref (priv->account_list); - priv->account_list = NULL; - } - - if (priv->tree_view != NULL) { - g_object_unref (priv->tree_view); - priv->tree_view = NULL; - } - - if (priv->add_button != NULL) { - g_object_unref (priv->add_button); - priv->add_button = NULL; - } - - if (priv->edit_button != NULL) { - g_object_unref (priv->edit_button); - priv->edit_button = NULL; - } - - if (priv->delete_button != NULL) { - g_object_unref (priv->delete_button); - priv->delete_button = NULL; - } - - if (priv->sort_toggle != NULL) { - g_object_unref (priv->sort_toggle); - priv->sort_toggle = NULL; - } - - if (priv->sort_up_button != NULL) { - g_object_unref (priv->sort_up_button); - priv->sort_up_button = NULL; - } - - if (priv->sort_down_button != NULL) { - g_object_unref (priv->sort_down_button); - priv->sort_down_button = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (e_account_manager_parent_class)->dispose (object); -} - -static void -e_account_manager_class_init (EAccountManagerClass *class) -{ - GObjectClass *object_class; - - g_type_class_add_private (class, sizeof (EAccountManagerPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = account_manager_set_property; - object_class->get_property = account_manager_get_property; - object_class->dispose = account_manager_dispose; - - /* XXX If we moved the account editor to /widgets/misc we - * could handle adding and editing accounts directly. */ - - g_object_class_install_property ( - object_class, - PROP_ACCOUNT_LIST, - g_param_spec_object ( - "account-list", - "Account List", - NULL, - E_TYPE_ACCOUNT_LIST, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - signals[ADD_ACCOUNT] = g_signal_new ( - "add-account", - G_OBJECT_CLASS_TYPE (class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (EAccountManagerClass, add_account), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[EDIT_ACCOUNT] = g_signal_new ( - "edit-account", - G_OBJECT_CLASS_TYPE (class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (EAccountManagerClass, edit_account), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[DELETE_ACCOUNT] = g_signal_new ( - "delete-account", - G_OBJECT_CLASS_TYPE (class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (EAccountManagerClass, delete_account), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -static void -e_account_manager_init (EAccountManager *manager) -{ - GtkTreeSelection *selection; - GtkWidget *container; - GtkWidget *widget; - - manager->priv = G_TYPE_INSTANCE_GET_PRIVATE ( - manager, E_TYPE_ACCOUNT_MANAGER, EAccountManagerPrivate); - - gtk_table_resize (GTK_TABLE (manager), 1, 2); - gtk_table_set_col_spacings (GTK_TABLE (manager), 6); - gtk_table_set_row_spacings (GTK_TABLE (manager), 12); - - container = GTK_WIDGET (manager); - - 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_table_attach ( - GTK_TABLE (container), widget, 0, 1, 0, 1, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_show (widget); - - container = widget; - - widget = e_account_tree_view_new (); - gtk_container_add (GTK_CONTAINER (container), widget); - manager->priv->tree_view = g_object_ref (widget); - gtk_widget_show (widget); - - g_object_bind_property ( - manager, "account-list", - widget, "account-list", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - g_signal_connect_swapped ( - widget, "key-press-event", - G_CALLBACK (account_manager_key_press_event_cb), - manager); - - g_signal_connect_swapped ( - widget, "row-activated", - G_CALLBACK (e_account_manager_edit_account), - manager); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)); - - g_signal_connect_swapped ( - selection, "changed", - G_CALLBACK (account_manager_selection_changed_cb), - manager); - - container = GTK_WIDGET (manager); - - widget = gtk_check_button_new_with_mnemonic (_("Use default Evolution _sort order for accounts")); - manager->priv->sort_toggle = g_object_ref (widget); - gtk_widget_show (widget); - gtk_table_attach ( - GTK_TABLE (container), widget, 0, 1, 1, 2, - GTK_EXPAND | GTK_FILL, 0, 4, 0); - - g_object_bind_property ( - manager->priv->tree_view, "sort-alpha", - widget, "active", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - g_signal_connect_swapped ( - widget, "toggled", - G_CALLBACK (account_manager_sort_toggled_cb), manager); - - widget = gtk_vbutton_box_new (); - gtk_button_box_set_layout ( - GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START); - gtk_box_set_spacing (GTK_BOX (widget), 6); - gtk_table_attach ( - GTK_TABLE (container), widget, - 1, 2, 0, 2, 0, GTK_FILL, 0, 0); - gtk_widget_show (widget); - - container = widget; - - widget = gtk_button_new_from_stock (GTK_STOCK_ADD); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - manager->priv->add_button = g_object_ref (widget); - gtk_widget_show (widget); - - g_signal_connect_swapped ( - widget, "clicked", - G_CALLBACK (e_account_manager_add_account), manager); - - widget = gtk_button_new_from_stock (GTK_STOCK_EDIT); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - manager->priv->edit_button = g_object_ref (widget); - gtk_widget_show (widget); - - g_signal_connect_swapped ( - widget, "clicked", - G_CALLBACK (e_account_manager_edit_account), manager); - - widget = gtk_button_new_from_stock (GTK_STOCK_DELETE); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - manager->priv->delete_button = g_object_ref (widget); - gtk_widget_show (widget); - - g_signal_connect_swapped ( - widget, "clicked", - G_CALLBACK (e_account_manager_delete_account), manager); - - widget = gtk_button_new_with_mnemonic (_("De_fault")); - gtk_button_set_image ( - GTK_BUTTON (widget), gtk_image_new_from_icon_name ( - "emblem-default", GTK_ICON_SIZE_BUTTON)); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - manager->priv->default_button = g_object_ref (widget); - gtk_widget_show (widget); - - g_signal_connect_swapped ( - widget, "clicked", - G_CALLBACK (account_manager_default_clicked_cb), manager); - - widget = gtk_button_new_from_stock (GTK_STOCK_GO_UP); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - manager->priv->sort_up_button = g_object_ref (widget); - gtk_widget_show (widget); - - g_signal_connect_swapped ( - widget, "clicked", - G_CALLBACK (account_manager_sort_up_cb), manager); - - widget = gtk_button_new_from_stock (GTK_STOCK_GO_DOWN); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - manager->priv->sort_down_button = g_object_ref (widget); - gtk_widget_show (widget); - - g_signal_connect_swapped ( - widget, "clicked", - G_CALLBACK (account_manager_sort_down_cb), manager); -} - -GtkWidget * -e_account_manager_new (EAccountList *account_list) -{ - g_return_val_if_fail (E_IS_ACCOUNT_LIST (account_list), NULL); - - return g_object_new ( - E_TYPE_ACCOUNT_MANAGER, - "account-list", account_list, NULL); -} - -void -e_account_manager_add_account (EAccountManager *manager) -{ - g_return_if_fail (E_IS_ACCOUNT_MANAGER (manager)); - - g_signal_emit (manager, signals[ADD_ACCOUNT], 0); -} - -void -e_account_manager_edit_account (EAccountManager *manager) -{ - g_return_if_fail (E_IS_ACCOUNT_MANAGER (manager)); - - g_signal_emit (manager, signals[EDIT_ACCOUNT], 0); -} - -void -e_account_manager_delete_account (EAccountManager *manager) -{ - g_return_if_fail (E_IS_ACCOUNT_MANAGER (manager)); - - g_signal_emit (manager, signals[DELETE_ACCOUNT], 0); -} - -EAccountList * -e_account_manager_get_account_list (EAccountManager *manager) -{ - g_return_val_if_fail (E_IS_ACCOUNT_MANAGER (manager), NULL); - - return manager->priv->account_list; -} - -void -e_account_manager_set_account_list (EAccountManager *manager, - EAccountList *account_list) -{ - g_return_if_fail (E_IS_ACCOUNT_MANAGER (manager)); - - if (account_list != NULL) { - g_return_if_fail (E_IS_ACCOUNT_LIST (account_list)); - g_object_ref (account_list); - } - - if (manager->priv->account_list != NULL) - g_object_unref (manager->priv->account_list); - - manager->priv->account_list = account_list; - - g_object_notify (G_OBJECT (manager), "account-list"); -} - -EAccountTreeView * -e_account_manager_get_tree_view (EAccountManager *manager) -{ - g_return_val_if_fail (E_IS_ACCOUNT_MANAGER (manager), NULL); - - return E_ACCOUNT_TREE_VIEW (manager->priv->tree_view); -} diff --git a/widgets/misc/e-account-manager.h b/widgets/misc/e-account-manager.h deleted file mode 100644 index 0dc5892b2e..0000000000 --- a/widgets/misc/e-account-manager.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * e-account-manager.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_ACCOUNT_MANAGER_H -#define E_ACCOUNT_MANAGER_H - -#include <gtk/gtk.h> -#include <libedataserver/e-account-list.h> -#include <misc/e-account-tree-view.h> - -/* Standard GObject macros */ -#define E_TYPE_ACCOUNT_MANAGER \ - (e_account_manager_get_type ()) -#define E_ACCOUNT_MANAGER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_ACCOUNT_MANAGER, EAccountManager)) -#define E_ACCOUNT_MANAGER_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_ACCOUNT_MANAGER, EAccountManagerClass)) -#define E_IS_ACCOUNT_MANAGER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_ACCOUNT_MANAGER)) -#define E_IS_ACCOUNT_MANAGER_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_ACCOUNT_MANAGER)) -#define E_ACCOUNT_MANAGER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_ACCOUNT_MANAGER, EAccountManagerClass)) - -G_BEGIN_DECLS - -typedef struct _EAccountManager EAccountManager; -typedef struct _EAccountManagerClass EAccountManagerClass; -typedef struct _EAccountManagerPrivate EAccountManagerPrivate; - -struct _EAccountManager { - GtkTable parent; - EAccountManagerPrivate *priv; -}; - -struct _EAccountManagerClass { - GtkTableClass parent_class; - - void (*add_account) (EAccountManager *manager); - void (*edit_account) (EAccountManager *manager); - void (*delete_account) (EAccountManager *manager); -}; - -GType e_account_manager_get_type (void); -GtkWidget * e_account_manager_new (EAccountList *account_list); -void e_account_manager_add_account (EAccountManager *manager); -void e_account_manager_edit_account (EAccountManager *manager); -void e_account_manager_delete_account - (EAccountManager *manager); -EAccountList * e_account_manager_get_account_list - (EAccountManager *manager); -void e_account_manager_set_account_list - (EAccountManager *manager, - EAccountList *account_list); -EAccountTreeView * - e_account_manager_get_tree_view (EAccountManager *manager); - -G_END_DECLS - -#endif /* E_ACCOUNT_MANAGER_H */ diff --git a/widgets/misc/e-account-tree-view.c b/widgets/misc/e-account-tree-view.c deleted file mode 100644 index bd21668e2f..0000000000 --- a/widgets/misc/e-account-tree-view.c +++ /dev/null @@ -1,1401 +0,0 @@ -/* - * e-account-tree-view.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-account-tree-view.h" - -#include <glib/gi18n.h> -#include <camel/camel.h> - -enum { - COLUMN_ACCOUNT, - COLUMN_DEFAULT, - COLUMN_ENABLED, - COLUMN_NAME, - COLUMN_PROTOCOL, - COLUMN_SORTORDER -}; - -enum { - PROP_0, - PROP_ACCOUNT_LIST, - PROP_SELECTED, - PROP_SORT_ALPHA, - PROP_EXPRESS_MODE, - PROP_ENABLE_LOCAL_FOLDERS, - PROP_ENABLE_SEARCH_FOLDERS -}; - -enum { - ENABLE_ACCOUNT, - DISABLE_ACCOUNT, - REFRESHED, - SORT_ORDER_CHANGED, - LAST_SIGNAL -}; - -struct _EAccountTreeViewPrivate { - EAccountList *account_list; - GHashTable *index; - gboolean sort_alpha; - gboolean express_mode; - gboolean enable_local_folders; - gboolean enable_search_folders; -}; - -static guint signals[LAST_SIGNAL]; - -G_DEFINE_TYPE ( - EAccountTreeView, - e_account_tree_view, - GTK_TYPE_TREE_VIEW) - -static gint -account_tree_view_sort (GtkTreeModel *model, - GtkTreeIter *a, - GtkTreeIter *b, - gpointer user_data) -{ - gint rv = -2; - gchar *aname = NULL, *bname = NULL; - EAccount *aaccount = NULL, *baccount = NULL; - guint asortorder = 0, bsortorder = 0; - - gtk_tree_model_get (model, a, - COLUMN_ACCOUNT, &aaccount, - COLUMN_NAME, &aname, - COLUMN_SORTORDER, &asortorder, - -1); - - gtk_tree_model_get (model, b, - COLUMN_ACCOUNT, &baccount, - COLUMN_NAME, &bname, - COLUMN_SORTORDER, &bsortorder, - -1); - - if ((!aaccount || !baccount || !e_account_tree_view_get_sort_alpha (user_data)) && aname && bname) { - if (e_account_tree_view_get_sort_alpha (user_data)) { - const gchar *on_this_computer = _("On This Computer"); - const gchar *search_folders = _("Search Folders"); - - if (e_account_tree_view_get_express_mode (user_data)) { - if (g_str_equal (aname, on_this_computer) && - g_str_equal (bname, search_folders)) - rv = -1; - else if (g_str_equal (bname, on_this_computer) && - g_str_equal (aname, search_folders)) - rv = 1; - else if (g_str_equal (aname, on_this_computer)) - rv = 1; - else if (g_str_equal (bname, on_this_computer)) - rv = -1; - else if (g_str_equal (aname, search_folders)) - rv = 1; - else if (g_str_equal (bname, search_folders)) - rv = -1; - } else { - if (g_str_equal (aname, on_this_computer)) - rv = -1; - else if (g_str_equal (bname, on_this_computer)) - rv = 1; - else if (g_str_equal (aname, search_folders)) - rv = 1; - else if (g_str_equal (bname, search_folders)) - rv = -1; - } - } else { - if (asortorder < bsortorder) - rv = -1; - else if (asortorder > bsortorder) - rv = 1; - else - rv = 0; - } - } - - if (rv == -2) { - if (aname == NULL) { - if (bname == NULL) - rv = 0; - else - rv = -1; - } else if (bname == NULL) - rv = 1; - - if (rv == -2) - rv = g_utf8_collate (aname, bname); - } - - g_free (aname); - g_free (bname); - - if (aaccount) - g_object_unref (aaccount); - if (baccount) - g_object_unref (baccount); - - return rv; -} - -static void -account_tree_view_normalize_sortorder_column (EAccountTreeView *tree_view) -{ - GtkListStore *list_store; - GtkTreeModel *model; - GtkTreeIter iter; - guint index; - - g_return_if_fail (tree_view != NULL); - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); - if (!model || !gtk_tree_model_get_iter_first (model, &iter)) - return; - - list_store = GTK_LIST_STORE (model); - g_return_if_fail (list_store != NULL); - - index = 1; - do { - gtk_list_store_set (list_store, &iter, COLUMN_SORTORDER, index, -1); - - index++; - } while (gtk_tree_model_iter_next (model, &iter)); -} - -static gboolean -account_tree_view_refresh_timeout_cb (gpointer ptree_view) -{ - EAccountTreeView *tree_view; - EAccountTreeViewSelectedType selected; - EAccountList *account_list; - EAccount *account; - GtkListStore *store; - GtkTreeModel *model; - GtkTreeIter tree_iter; - EIterator *account_iter; - EAccount *default_account; - GHashTable *index; - GSList *sort_order; - GList *list = NULL; - GList *iter; - - tree_view = ptree_view; - account_list = e_account_tree_view_get_account_list (tree_view); - sort_order = e_account_tree_view_get_sort_order (tree_view); - - store = gtk_list_store_new ( - 6, E_TYPE_ACCOUNT, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); - model = GTK_TREE_MODEL (store); - index = tree_view->priv->index; - - gtk_tree_sortable_set_default_sort_func ( - GTK_TREE_SORTABLE (model), - account_tree_view_sort, tree_view, NULL); - gtk_tree_sortable_set_sort_column_id ( - GTK_TREE_SORTABLE (model), - GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, - GTK_SORT_ASCENDING); - - g_hash_table_remove_all (index); - - if (account_list == NULL) - goto skip; - - /* XXX EAccountList misuses const. */ - default_account = (EAccount *) - e_account_list_get_default (account_list); - - /* Build a list of EAccounts to display. */ - account_iter = e_list_get_iterator (E_LIST (account_list)); - while (e_iterator_is_valid (account_iter)) { - /* XXX EIterator misuses const. */ - account = (EAccount *) e_iterator_get (account_iter); - list = g_list_prepend (list, account); - e_iterator_next (account_iter); - } - g_object_unref (account_iter); - - list = g_list_reverse (list); - - /* Populate the list store and index. */ - for (iter = list; iter != NULL; iter = iter->next) { - GtkTreeRowReference *reference; - GtkTreePath *path; - CamelURL *url = NULL; - gboolean is_default; - const gchar *protocol; - - account = iter->data; - - /* Skip proxy accounts. */ - if (account->parent_uid != NULL) - continue; - - is_default = (account == default_account); - - if (account->source != NULL && account->source->url != NULL) - url = camel_url_new (account->source->url, NULL); - - if (url != NULL && url->protocol != NULL) - protocol = url->protocol; - else - protocol = C_("mail-receiving", "None"); - - gtk_list_store_append (store, &tree_iter); - gtk_list_store_set ( - store, &tree_iter, - COLUMN_ACCOUNT, account, - COLUMN_DEFAULT, is_default, - COLUMN_ENABLED, account->enabled, - COLUMN_NAME, account->name, - COLUMN_PROTOCOL, protocol, -1); - - path = gtk_tree_model_get_path (model, &tree_iter); - reference = gtk_tree_row_reference_new (model, path); - g_hash_table_insert (index, account, reference); - gtk_tree_path_free (path); - - if (url != NULL) - camel_url_free (url); - } - - gtk_list_store_append (store, &tree_iter); - gtk_list_store_set ( - store, &tree_iter, - COLUMN_ACCOUNT, NULL, - COLUMN_DEFAULT, FALSE, - COLUMN_ENABLED, tree_view->priv->enable_local_folders, - COLUMN_NAME, _("On This Computer"), - COLUMN_PROTOCOL, NULL, - -1); - - gtk_list_store_append (store, &tree_iter); - gtk_list_store_set ( - store, &tree_iter, - COLUMN_ACCOUNT, NULL, - COLUMN_DEFAULT, FALSE, - COLUMN_ENABLED, tree_view->priv->enable_search_folders, - COLUMN_NAME, _("Search Folders"), - COLUMN_PROTOCOL, NULL, - -1); - - g_list_free (list); - - skip: - /* Restore the previously selected account. */ - selected = e_account_tree_view_get_selected_type (tree_view); - account = e_account_tree_view_get_selected (tree_view); - if (account != NULL) - g_object_ref (account); - gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), model); - e_account_tree_view_set_selected (tree_view, account); - if (account != NULL) - g_object_unref (account); - else if (selected == E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL || - selected == E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER) - e_account_tree_view_set_selected_type (tree_view, selected); - - e_account_tree_view_set_sort_order (tree_view, sort_order); - g_slist_foreach (sort_order, (GFunc) g_free, NULL); - g_slist_free (sort_order); - - g_signal_emit (tree_view, signals[REFRESHED], 0); - - return FALSE; -} - -static void -account_tree_view_refresh_cb (EAccountList *account_list, - EAccount *account, - EAccountTreeView *tree_view) -{ - g_timeout_add (10, account_tree_view_refresh_timeout_cb, tree_view); -} - -static void -account_tree_view_enabled_toggled_cb (EAccountTreeView *tree_view, - gchar *path_string, - GtkCellRendererToggle *renderer) -{ - GtkTreeSelection *selection; - GtkTreePath *path; - - /* Change the selection first so we enable or disable the - * correct account. */ - path = gtk_tree_path_new_from_string (path_string); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); - gtk_tree_selection_select_path (selection, path); - gtk_tree_path_free (path); - - if (gtk_cell_renderer_toggle_get_active (renderer)) - e_account_tree_view_disable_account (tree_view); - else - e_account_tree_view_enable_account (tree_view); -} - -static void -account_tree_view_selection_changed_cb (EAccountTreeView *tree_view) -{ - g_object_notify (G_OBJECT (tree_view), "selected"); -} - -static GObject * -account_tree_view_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_properties) -{ - GObject *object; - GObjectClass *parent_class; - GtkTreeView *tree_view; - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - - /* Chain up to parent's constructor() method. */ - parent_class = G_OBJECT_CLASS (e_account_tree_view_parent_class); - object = parent_class->constructor ( - type, n_construct_properties, construct_properties); - - tree_view = GTK_TREE_VIEW (object); - gtk_tree_view_set_headers_visible (tree_view, TRUE); - - /* Column: Enabled */ - - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_expand (column, FALSE); - gtk_tree_view_column_set_title (column, _("Enabled")); - - renderer = gtk_cell_renderer_toggle_new (); - gtk_tree_view_column_pack_start (column, renderer, TRUE); - - g_signal_connect_swapped ( - renderer, "toggled", - G_CALLBACK (account_tree_view_enabled_toggled_cb), - tree_view); - - gtk_tree_view_column_add_attribute ( - column, renderer, "active", COLUMN_ENABLED); - - gtk_tree_view_append_column (tree_view, column); - - /* Column: Account Name */ - - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_column_set_title (column, _("Account Name")); - - renderer = gtk_cell_renderer_text_new (); - g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); - gtk_tree_view_column_pack_start (column, renderer, TRUE); - - gtk_tree_view_column_add_attribute ( - column, renderer, "text", COLUMN_NAME); - - renderer = gtk_cell_renderer_text_new (); - g_object_set (renderer, "text", _("Default"), NULL); - gtk_tree_view_column_pack_end (column, renderer, FALSE); - - gtk_tree_view_column_add_attribute ( - column, renderer, "visible", COLUMN_DEFAULT); - - renderer = gtk_cell_renderer_pixbuf_new (); - g_object_set ( - renderer, "icon-name", "emblem-default", - "stock-size", GTK_ICON_SIZE_MENU, NULL); - gtk_tree_view_column_pack_end (column, renderer, FALSE); - - gtk_tree_view_column_add_attribute ( - column, renderer, "visible", COLUMN_DEFAULT); - - gtk_tree_view_append_column (tree_view, column); - - /* Column: Protocol */ - - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_expand (column, FALSE); - gtk_tree_view_column_set_title (column, _("Protocol")); - - renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_column_pack_start (column, renderer, TRUE); - - gtk_tree_view_column_add_attribute ( - column, renderer, "text", COLUMN_PROTOCOL); - - gtk_tree_view_append_column (tree_view, column); - - return object; -} - -static void -account_tree_view_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_ACCOUNT_LIST: - e_account_tree_view_set_account_list ( - E_ACCOUNT_TREE_VIEW (object), - g_value_get_object (value)); - return; - - case PROP_SELECTED: - e_account_tree_view_set_selected ( - E_ACCOUNT_TREE_VIEW (object), - g_value_get_object (value)); - return; - case PROP_SORT_ALPHA: - e_account_tree_view_set_sort_alpha ( - E_ACCOUNT_TREE_VIEW (object), - g_value_get_boolean (value)); - return; - case PROP_EXPRESS_MODE: - e_account_tree_view_set_express_mode ( - E_ACCOUNT_TREE_VIEW (object), - g_value_get_boolean (value)); - return; - case PROP_ENABLE_LOCAL_FOLDERS: - e_account_tree_view_set_enable_local_folders ( - E_ACCOUNT_TREE_VIEW (object), - g_value_get_boolean (value)); - return; - case PROP_ENABLE_SEARCH_FOLDERS: - e_account_tree_view_set_enable_search_folders ( - E_ACCOUNT_TREE_VIEW (object), - g_value_get_boolean (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -account_tree_view_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_ACCOUNT_LIST: - g_value_set_object ( - value, - e_account_tree_view_get_account_list ( - E_ACCOUNT_TREE_VIEW (object))); - return; - - case PROP_SELECTED: - g_value_set_object ( - value, - e_account_tree_view_get_selected ( - E_ACCOUNT_TREE_VIEW (object))); - return; - case PROP_SORT_ALPHA: - g_value_set_boolean ( - value, - e_account_tree_view_get_sort_alpha ( - E_ACCOUNT_TREE_VIEW (object))); - return; - case PROP_EXPRESS_MODE: - g_value_set_boolean ( - value, - e_account_tree_view_get_express_mode ( - E_ACCOUNT_TREE_VIEW (object))); - return; - case PROP_ENABLE_LOCAL_FOLDERS: - g_value_set_boolean ( - value, - e_account_tree_view_get_enable_local_folders ( - E_ACCOUNT_TREE_VIEW (object))); - return; - case PROP_ENABLE_SEARCH_FOLDERS: - g_value_set_boolean ( - value, - e_account_tree_view_get_enable_search_folders ( - E_ACCOUNT_TREE_VIEW (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -account_tree_view_dispose (GObject *object) -{ - EAccountTreeViewPrivate *priv; - - priv = E_ACCOUNT_TREE_VIEW (object)->priv; - - if (priv->account_list != NULL) { - g_signal_handlers_disconnect_by_func ( - priv->account_list, - account_tree_view_refresh_cb, object); - g_object_unref (priv->account_list); - priv->account_list = NULL; - } - - g_hash_table_remove_all (priv->index); - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (e_account_tree_view_parent_class)->dispose (object); -} - -static void -account_tree_view_finalize (GObject *object) -{ - EAccountTreeViewPrivate *priv; - - priv = E_ACCOUNT_TREE_VIEW (object)->priv; - - g_hash_table_destroy (priv->index); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (e_account_tree_view_parent_class)->finalize (object); -} - -static void -account_tree_view_enable_account (EAccountTreeView *tree_view) -{ - EAccountList *account_list; - EAccount *account; - - account = e_account_tree_view_get_selected (tree_view); - if (account == NULL || account->enabled) - return; - - account_list = e_account_tree_view_get_account_list (tree_view); - g_return_if_fail (account_list != NULL); - - account->enabled = TRUE; - e_account_list_change (account_list, account); - - e_account_list_save (account_list); -} - -static void -account_tree_view_disable_account (EAccountTreeView *tree_view) -{ - EAccountList *account_list; - EAccount *account; - - account = e_account_tree_view_get_selected (tree_view); - if (account == NULL || !account->enabled) - return; - - account_list = e_account_tree_view_get_account_list (tree_view); - g_return_if_fail (account_list != NULL); - - account->enabled = FALSE; - e_account_list_change (account_list, account); - - e_account_list_save (account_list); -} - -static void -e_account_tree_view_class_init (EAccountTreeViewClass *class) -{ - GObjectClass *object_class; - - g_type_class_add_private (class, sizeof (EAccountTreeViewPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->constructor = account_tree_view_constructor; - object_class->set_property = account_tree_view_set_property; - object_class->get_property = account_tree_view_get_property; - object_class->dispose = account_tree_view_dispose; - object_class->finalize = account_tree_view_finalize; - - class->enable_account = account_tree_view_enable_account; - class->disable_account = account_tree_view_disable_account; - - g_object_class_install_property ( - object_class, - PROP_SELECTED, - g_param_spec_object ( - "selected", - "Selected Account", - NULL, - E_TYPE_ACCOUNT, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_ACCOUNT_LIST, - g_param_spec_object ( - "account-list", - "Account List", - NULL, - E_TYPE_ACCOUNT_LIST, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_SORT_ALPHA, - g_param_spec_boolean ( - "sort-alpha", - "Sort alphabetically", - NULL, - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_EXPRESS_MODE, - g_param_spec_boolean ( - "express-mode", - "Express Mode sorting", - NULL, - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_ENABLE_LOCAL_FOLDERS, - g_param_spec_boolean ( - "enable-local-folders", - "Enable Local Folders", - NULL, - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_ENABLE_SEARCH_FOLDERS, - g_param_spec_boolean ( - "enable-search-folders", - "Enable Search Folders", - NULL, - TRUE, - G_PARAM_READWRITE)); - - signals[ENABLE_ACCOUNT] = g_signal_new ( - "enable-account", - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EAccountTreeViewClass, enable_account), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[DISABLE_ACCOUNT] = g_signal_new ( - "disable-account", - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EAccountTreeViewClass, disable_account), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[REFRESHED] = g_signal_new ( - "refreshed", - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EAccountTreeViewClass, refreshed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[SORT_ORDER_CHANGED] = g_signal_new ( - "sort-order-changed", - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EAccountTreeViewClass, sort_order_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -static void -e_account_tree_view_init (EAccountTreeView *tree_view) -{ - GHashTable *index; - GtkTreeSelection *selection; - - /* Reverse-lookup index */ - index = g_hash_table_new_full ( - g_direct_hash, g_direct_equal, - (GDestroyNotify) g_object_unref, - (GDestroyNotify) gtk_tree_row_reference_free); - - tree_view->priv = G_TYPE_INSTANCE_GET_PRIVATE ( - tree_view, E_TYPE_ACCOUNT_TREE_VIEW, EAccountTreeViewPrivate); - tree_view->priv->index = index; - tree_view->priv->sort_alpha = TRUE; - tree_view->priv->express_mode = FALSE; - tree_view->priv->enable_local_folders = TRUE; - tree_view->priv->enable_search_folders = TRUE; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); - - g_signal_connect_swapped ( - selection, "changed", - G_CALLBACK (account_tree_view_selection_changed_cb), - tree_view); -} - -GtkWidget * -e_account_tree_view_new (void) -{ - return g_object_new (E_TYPE_ACCOUNT_TREE_VIEW, NULL); -} - -void -e_account_tree_view_enable_account (EAccountTreeView *tree_view) -{ - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - - g_signal_emit (tree_view, signals[ENABLE_ACCOUNT], 0); -} - -void -e_account_tree_view_disable_account (EAccountTreeView *tree_view) -{ - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - - g_signal_emit (tree_view, signals[DISABLE_ACCOUNT], 0); -} - -EAccountList * -e_account_tree_view_get_account_list (EAccountTreeView *tree_view) -{ - g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), NULL); - - return tree_view->priv->account_list; -} - -void -e_account_tree_view_set_account_list (EAccountTreeView *tree_view, - EAccountList *account_list) -{ - EAccountTreeViewPrivate *priv; - - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - - if (account_list != NULL) - g_return_if_fail (E_IS_ACCOUNT_LIST (account_list)); - - priv = tree_view->priv; - - if (priv->account_list != NULL) { - g_signal_handlers_disconnect_by_func ( - priv->account_list, - account_tree_view_refresh_cb, tree_view); - g_object_unref (priv->account_list); - priv->account_list = NULL; - } - - if (account_list != NULL) { - priv->account_list = g_object_ref (account_list); - - /* Listen for changes to the account list. */ - g_signal_connect ( - priv->account_list, "account-added", - G_CALLBACK (account_tree_view_refresh_cb), - tree_view); - g_signal_connect ( - priv->account_list, "account-changed", - G_CALLBACK (account_tree_view_refresh_cb), - tree_view); - g_signal_connect ( - priv->account_list, "account-removed", - G_CALLBACK (account_tree_view_refresh_cb), - tree_view); - } - - account_tree_view_refresh_timeout_cb (tree_view); - - g_object_notify (G_OBJECT (tree_view), "account-list"); -} - -EAccount * -e_account_tree_view_get_selected (EAccountTreeView *tree_view) -{ - EAccount *account; - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - - g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), NULL); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - return NULL; - - gtk_tree_model_get (model, &iter, COLUMN_ACCOUNT, &account, -1); - - return account; -} - -gboolean -e_account_tree_view_set_selected (EAccountTreeView *tree_view, - EAccount *account) -{ - GtkTreeRowReference *reference; - GtkTreeSelection *selection; - GtkTreePath *path; - - g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), FALSE); - - if (account != NULL) - g_return_val_if_fail (E_IS_ACCOUNT (account), FALSE); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); - - /* NULL means clear the selection. */ - if (account == NULL) { - gtk_tree_selection_unselect_all (selection); - return TRUE; - } - - /* Lookup the tree row reference for the account. */ - reference = g_hash_table_lookup (tree_view->priv->index, account); - if (reference == NULL) - return FALSE; - - /* Select the referenced path. */ - path = gtk_tree_row_reference_get_path (reference); - gtk_tree_selection_select_path (selection, path); - gtk_tree_path_free (path); - - g_object_notify (G_OBJECT (tree_view), "selected"); - - return TRUE; -} - -/** - * e_account_tree_view_get_selected_type: - * @tree_view: an #EAccountTreeView - * - * Returns: What node type is selected. This is useful for virtual - * nodes "On This Computer" and "Search Folders", which doesn't have - * their #EAccount representations. if the function returns - * #E_ACCOUNT_TREE_VIEW_SELECTED_ACCOUNT, then the selected account - * can be obtained with e_account_tree_view_get_selected(). - * - * Since: 3.4 - **/ -EAccountTreeViewSelectedType -e_account_tree_view_get_selected_type (EAccountTreeView *tree_view) -{ - EAccountTreeViewSelectedType res = E_ACCOUNT_TREE_VIEW_SELECTED_NONE; - EAccount *account = NULL; - gchar *name = NULL; - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - - g_return_val_if_fail (tree_view != NULL, E_ACCOUNT_TREE_VIEW_SELECTED_NONE); - g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), E_ACCOUNT_TREE_VIEW_SELECTED_NONE); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - return E_ACCOUNT_TREE_VIEW_SELECTED_NONE; - - gtk_tree_model_get (model, &iter, - COLUMN_ACCOUNT, &account, - COLUMN_NAME, &name, - -1); - - if (account) { - res = E_ACCOUNT_TREE_VIEW_SELECTED_ACCOUNT; - g_object_unref (account); - } else if (name) { - if (g_str_equal (name, _("On This Computer"))) - res = E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL; - else if (g_str_equal (name, _("Search Folders"))) - res = E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER; - } - - g_free (name); - - return res; -} - -/** - * e_account_tree_view_set_selected_type: - * @tree_view: an #EAccountTreeView - * @select: what to select; see below what can be used here - * - * Selects special nodes in a view. Can be only either #E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL - * or #E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER. - * - * Since: 3.4 - **/ -void -e_account_tree_view_set_selected_type (EAccountTreeView *tree_view, - EAccountTreeViewSelectedType select) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - gboolean found; - - g_return_if_fail (tree_view != NULL); - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); - model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); - - if (!model || !gtk_tree_model_get_iter_first (model, &iter)) - return; - - if (select != E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL && - select != E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER) - return; - - found = FALSE; - do { - gchar *name = NULL; - EAccount *account = NULL; - - gtk_tree_model_get (model, &iter, - COLUMN_ACCOUNT, &account, - COLUMN_NAME, &name, - -1); - - if (account) { - g_object_unref (account); - } else { - switch (select) { - case E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL: - found = g_strcmp0 (name, _("On This Computer")) == 0; - break; - case E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER: - found = g_strcmp0 (name, _("Search Folders")) == 0; - break; - default: - break; - } - } - - g_free (name); - } while (!found && gtk_tree_model_iter_next (model, &iter)); - - if (found) - gtk_tree_selection_select_iter (selection, &iter); -} - -static guint -account_tree_view_get_slist_index (const GSList *account_uids, - const gchar *uid) -{ - guint res = 0; - - while (account_uids) { - if (g_strcmp0 (uid, account_uids->data) == 0) - return res; - - account_uids = account_uids->next; - res++; - } - - return -1; -} - -/** - * e_account_tree_view_set_sort_order: - * @tree_view: an #EAccountTreeView - * @account_uids: a #GSList of account uids as string - * - * Sets user sort order for accounts based on the order - * in @account_uids. This is used only when sort - * alphabetically is set to #FALSE. - * - * Since: 3.4 - **/ -void -e_account_tree_view_set_sort_order (EAccountTreeView *tree_view, - const GSList *account_uids) -{ - GtkTreeModel *model; - GtkTreeIter iter; - - g_return_if_fail (tree_view != NULL); - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); - - if (!model || !gtk_tree_model_get_iter_first (model, &iter)) - return; - - do { - gchar *name = NULL; - EAccount *account = NULL; - guint sort_order = 0; - - gtk_tree_model_get (model, &iter, - COLUMN_ACCOUNT, &account, - COLUMN_NAME, &name, - -1); - - if (account) { - sort_order = account_tree_view_get_slist_index (account_uids, account->uid) + 1; - g_object_unref (account); - } else if (g_strcmp0 (name, _("On This Computer")) == 0) { - sort_order = account_tree_view_get_slist_index (account_uids, "local") + 1; - } else if (g_strcmp0 (name, _("Search Folders")) == 0) { - sort_order = account_tree_view_get_slist_index (account_uids, "vfolder") + 1; - } else { - g_warn_if_reached (); - } - - gtk_list_store_set (GTK_LIST_STORE (model), &iter, COLUMN_SORTORDER, sort_order, -1); - g_free (name); - } while (gtk_tree_model_iter_next (model, &iter)); - - account_tree_view_normalize_sortorder_column (tree_view); - e_account_tree_view_sort_changed (tree_view); -} - -static gint -eval_order_by_sort_hash_cb (gconstpointer a, - gconstpointer b, - gpointer user_data) -{ - guint asortorder = GPOINTER_TO_UINT (g_hash_table_lookup (user_data, a)); - guint bsortorder = GPOINTER_TO_UINT (g_hash_table_lookup (user_data, b)); - - if (asortorder < bsortorder) - return -1; - if (asortorder > bsortorder) - return 1; - - return 0; -} - -/** - * e_account_tree_view_get_sort_order: - * @tree_view: an #EAccountTreeView - * - * Returns: Newly allocated #GSList of newly allocated strings - * containing account UIDs in order as user wish to see them. - * Each item of the returned list should be freed with g_free() - * and the list itself should be freed with g_slist_free(), when - * no longer needed. - * - * Since: 3.4 - **/ -GSList * -e_account_tree_view_get_sort_order (EAccountTreeView *tree_view) -{ - GtkTreeModel *model; - GtkTreeIter iter; - GHashTable *hash; - GSList *res = NULL; - - g_return_val_if_fail (tree_view != NULL, NULL); - g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), NULL); - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); - - if (!model || !gtk_tree_model_get_iter_first (model, &iter)) - return NULL; - - hash = g_hash_table_new (g_direct_hash, g_direct_equal); - - do { - gchar *toadd = NULL; - gchar *name = NULL; - EAccount *account = NULL; - guint sort_order = 0; - - gtk_tree_model_get (model, &iter, - COLUMN_ACCOUNT, &account, - COLUMN_NAME, &name, - COLUMN_SORTORDER, &sort_order, - -1); - - if (account) { - toadd = g_strdup (account->uid); - g_object_unref (account); - } else if (g_strcmp0 (name, _("On This Computer")) == 0) { - toadd = g_strdup ("local"); - } else if (g_strcmp0 (name, _("Search Folders")) == 0) { - toadd = g_strdup ("vfolder"); - } else { - g_warn_if_reached (); - } - - if (toadd) { - g_hash_table_insert (hash, toadd, GUINT_TO_POINTER (sort_order)); - res = g_slist_prepend (res, toadd); - } - - g_free (name); - } while (gtk_tree_model_iter_next (model, &iter)); - - res = g_slist_sort_with_data (res, eval_order_by_sort_hash_cb, hash); - - g_hash_table_destroy (hash); - - return res; -} - -/** - * e_account_tree_view_sort_changed: - * @tree_view: an #EAccountTreeView - * - * Notifies @tree_view about sort order change, thus it resorts - * items in a view. - * - * Since: 3.4 - **/ -void -e_account_tree_view_sort_changed (EAccountTreeView *tree_view) -{ - GtkTreeModel *model; - - g_return_if_fail (tree_view != NULL); - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); - if (!model) - return; - - /* this invokes also sort on a GtkListStore */ - gtk_tree_sortable_set_default_sort_func ( - GTK_TREE_SORTABLE (model), - account_tree_view_sort, tree_view, NULL); -} - -static void -account_tree_view_swap_sort_order (EAccountTreeView *tree_view, - gint direction) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter1, iter2; - guint sortorder1, sortorder2; - - g_return_if_fail (tree_view != NULL); - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - g_return_if_fail (direction != 0); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); - if (!gtk_tree_selection_get_selected (selection, &model, &iter1)) - return; - - iter2 = iter1; - if ((direction < 0 && !gtk_tree_model_iter_previous (model, &iter2)) || - (direction > 0 && !gtk_tree_model_iter_next (model, &iter2))) - return; - - gtk_tree_model_get (model, &iter1, COLUMN_SORTORDER, &sortorder1, -1); - gtk_tree_model_get (model, &iter2, COLUMN_SORTORDER, &sortorder2, -1); - - gtk_list_store_set (GTK_LIST_STORE (model), &iter1, COLUMN_SORTORDER, sortorder2, -1); - gtk_list_store_set (GTK_LIST_STORE (model), &iter2, COLUMN_SORTORDER, sortorder1, -1); - - e_account_tree_view_sort_changed (tree_view); - - g_signal_emit (tree_view, signals[SORT_ORDER_CHANGED], 0); -} - -/** - * e_account_tree_view_move_up: - * @tree_view: an #EAccountTreeView - * - * Moves currently selected node up within user's sort order. - * - * Since: 3.4 - **/ -void -e_account_tree_view_move_up (EAccountTreeView *tree_view) -{ - g_return_if_fail (tree_view != NULL); - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - - account_tree_view_swap_sort_order (tree_view, -1); -} - -/** - * e_account_tree_view_move_down: - * @tree_view: an #EAccountTreeView - * - * Moves currently selected node down within user's sort order. - * - * Since: 3.4 - **/ -void -e_account_tree_view_move_down (EAccountTreeView *tree_view) -{ - g_return_if_fail (tree_view != NULL); - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - - account_tree_view_swap_sort_order (tree_view, +1); -} - -void -e_account_tree_view_set_sort_alpha (EAccountTreeView *tree_view, - gboolean sort_alpha) -{ - g_return_if_fail (tree_view != NULL); - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - g_return_if_fail (tree_view->priv != NULL); - - if ((tree_view->priv->sort_alpha ? 1 : 0) == (sort_alpha ? 1 : 0)) - return; - - tree_view->priv->sort_alpha = sort_alpha; - - g_object_notify (G_OBJECT (tree_view), "sort-alpha"); - e_account_tree_view_sort_changed (tree_view); -} - -gboolean -e_account_tree_view_get_sort_alpha (EAccountTreeView *tree_view) -{ - g_return_val_if_fail (tree_view != NULL, FALSE); - g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), FALSE); - g_return_val_if_fail (tree_view->priv != NULL, FALSE); - - return tree_view->priv->sort_alpha; -} - -void -e_account_tree_view_set_express_mode (EAccountTreeView *tree_view, - gboolean express_mode) -{ - g_return_if_fail (tree_view != NULL); - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - g_return_if_fail (tree_view->priv != NULL); - - if ((tree_view->priv->express_mode ? 1 : 0) == (express_mode ? 1 : 0)) - return; - - tree_view->priv->express_mode = express_mode; - - g_object_notify (G_OBJECT (tree_view), "express-mode"); - e_account_tree_view_sort_changed (tree_view); -} - -gboolean -e_account_tree_view_get_express_mode (EAccountTreeView *tree_view) -{ - g_return_val_if_fail (tree_view != NULL, FALSE); - g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), FALSE); - g_return_val_if_fail (tree_view->priv != NULL, FALSE); - - return tree_view->priv->express_mode; -} - -static void -update_special_enable_state (EAccountTreeView *tree_view, - const gchar *display_name, - gboolean enabled) -{ - GtkTreeModel *model; - GtkTreeIter iter; - GtkListStore *list_store; - - g_return_if_fail (tree_view != NULL); - g_return_if_fail (display_name != NULL); - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); - if (!model) - return; - - list_store = GTK_LIST_STORE (model); - g_return_if_fail (list_store != NULL); - - if (!gtk_tree_model_get_iter_first (model, &iter)) - return; - - do { - gchar *name = NULL; - EAccount *account = NULL; - - gtk_tree_model_get (model, &iter, - COLUMN_ACCOUNT, &account, - COLUMN_NAME, &name, - -1); - - if (account) { - g_object_unref (account); - } else if (g_strcmp0 (name, display_name) == 0) { - gtk_list_store_set (list_store, &iter, COLUMN_ENABLED, enabled, -1); - g_free (name); - break; - } - - g_free (name); - } while (gtk_tree_model_iter_next (model, &iter)); -} - -void -e_account_tree_view_set_enable_local_folders (EAccountTreeView *tree_view, - gboolean enabled) -{ - g_return_if_fail (tree_view != NULL); - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - g_return_if_fail (tree_view->priv != NULL); - - if ((tree_view->priv->enable_local_folders ? 1 : 0) == (enabled ? 1 : 0)) - return; - - tree_view->priv->enable_local_folders = enabled; - - g_object_notify (G_OBJECT (tree_view), "enable-local-folders"); - - update_special_enable_state (tree_view, _("On This Computer"), enabled); -} - -gboolean -e_account_tree_view_get_enable_local_folders (EAccountTreeView *tree_view) -{ - g_return_val_if_fail (tree_view != NULL, FALSE); - g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), FALSE); - g_return_val_if_fail (tree_view->priv != NULL, FALSE); - - return tree_view->priv->enable_local_folders; -} - -void -e_account_tree_view_set_enable_search_folders (EAccountTreeView *tree_view, - gboolean enabled) -{ - g_return_if_fail (tree_view != NULL); - g_return_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view)); - g_return_if_fail (tree_view->priv != NULL); - - if ((tree_view->priv->enable_search_folders ? 1 : 0) == (enabled ? 1 : 0)) - return; - - tree_view->priv->enable_search_folders = enabled; - - g_object_notify (G_OBJECT (tree_view), "enable-search-folders"); - - update_special_enable_state (tree_view, _("Search Folders"), enabled); -} - -gboolean -e_account_tree_view_get_enable_search_folders (EAccountTreeView *tree_view) -{ - g_return_val_if_fail (tree_view != NULL, FALSE); - g_return_val_if_fail (E_IS_ACCOUNT_TREE_VIEW (tree_view), FALSE); - g_return_val_if_fail (tree_view->priv != NULL, FALSE); - - return tree_view->priv->enable_search_folders; -} diff --git a/widgets/misc/e-account-tree-view.h b/widgets/misc/e-account-tree-view.h deleted file mode 100644 index d62d040bbd..0000000000 --- a/widgets/misc/e-account-tree-view.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * e-account-tree-view.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_ACCOUNT_TREE_VIEW_H -#define E_ACCOUNT_TREE_VIEW_H - -#include <gtk/gtk.h> -#include <libedataserver/e-account.h> -#include <libedataserver/e-account-list.h> - -/* Standard GObject macros */ -#define E_TYPE_ACCOUNT_TREE_VIEW \ - (e_account_tree_view_get_type ()) -#define E_ACCOUNT_TREE_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_ACCOUNT_TREE_VIEW, EAccountTreeView)) -#define E_ACCOUNT_TREE_VIEW_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_ACCOUNT_TREE_VIEW, EAccountTreeViewClass)) -#define E_IS_ACCOUNT_TREE_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_ACCOUNT_TREE_VIEW)) -#define E_IS_ACCOUNT_TREE_VIEW_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_ACCOUNT_TREE_VIEW)) -#define E_ACCOUNT_TREE_VIEW_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_ACCOUNT_TREE_VIEW, EAccountTreeViewClass)) - -G_BEGIN_DECLS - -typedef enum -{ - E_ACCOUNT_TREE_VIEW_SELECTED_NONE, - E_ACCOUNT_TREE_VIEW_SELECTED_ACCOUNT, - E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL, - E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER -} EAccountTreeViewSelectedType; - -typedef struct _EAccountTreeView EAccountTreeView; -typedef struct _EAccountTreeViewClass EAccountTreeViewClass; -typedef struct _EAccountTreeViewPrivate EAccountTreeViewPrivate; - -struct _EAccountTreeView { - GtkTreeView parent; - EAccountTreeViewPrivate *priv; -}; - -struct _EAccountTreeViewClass { - GtkTreeViewClass parent_class; - - void (*enable_account) (EAccountTreeView *tree_view); - void (*disable_account) (EAccountTreeView *tree_view); - void (*refreshed) (EAccountTreeView *tree_view); - void (*sort_order_changed) (EAccountTreeView *tree_view); -}; - -GType e_account_tree_view_get_type (void); -GtkWidget * e_account_tree_view_new (void); -void e_account_tree_view_enable_account - (EAccountTreeView *tree_view); -void e_account_tree_view_disable_account - (EAccountTreeView *tree_view); -EAccountList * e_account_tree_view_get_account_list - (EAccountTreeView *tree_view); -void e_account_tree_view_set_account_list - (EAccountTreeView *tree_view, - EAccountList *account_list); -EAccount * e_account_tree_view_get_selected - (EAccountTreeView *tree_view); -gboolean e_account_tree_view_set_selected - (EAccountTreeView *tree_view, - EAccount *account); -EAccountTreeViewSelectedType - e_account_tree_view_get_selected_type - (EAccountTreeView *tree_view); -void e_account_tree_view_set_selected_type - (EAccountTreeView *tree_view, - EAccountTreeViewSelectedType select); - -void e_account_tree_view_set_sort_order - (EAccountTreeView *tree_view, - const GSList *account_uids); - -GSList * e_account_tree_view_get_sort_order - (EAccountTreeView *tree_view); - -void e_account_tree_view_sort_changed - (EAccountTreeView *tree_view); -void e_account_tree_view_move_up (EAccountTreeView *tree_view); -void e_account_tree_view_move_down (EAccountTreeView *tree_view); - -void e_account_tree_view_set_sort_alpha - (EAccountTreeView *tree_view, - gboolean sort_alpha); -gboolean e_account_tree_view_get_sort_alpha - (EAccountTreeView *tree_view); -void e_account_tree_view_set_express_mode - (EAccountTreeView *tree_view, - gboolean express_mode); -gboolean e_account_tree_view_get_express_mode - (EAccountTreeView *tree_view); -void e_account_tree_view_set_enable_local_folders - (EAccountTreeView *tree_view, gboolean enabled); -gboolean e_account_tree_view_get_enable_local_folders - (EAccountTreeView *tree_view); -void e_account_tree_view_set_enable_search_folders - (EAccountTreeView *tree_view, gboolean enabled); -gboolean e_account_tree_view_get_enable_search_folders - (EAccountTreeView *tree_view); - -G_END_DECLS - -#endif /* E_ACCOUNT_TREE_VIEW_H */ |