diff options
author | Milan Crha <mcrha@redhat.com> | 2011-09-26 17:45:59 +0800 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2011-09-26 17:45:59 +0800 |
commit | e0548d25707ad8c4713e2e74c622a92bf4988545 (patch) | |
tree | be2dd1051fa169b90b959cd80b9729a1416d0393 /mail | |
parent | 4046d1944855274c8a6c406392ee734943142f90 (diff) | |
download | gsoc2013-evolution-e0548d25707ad8c4713e2e74c622a92bf4988545.tar.gz gsoc2013-evolution-e0548d25707ad8c4713e2e74c622a92bf4988545.tar.zst gsoc2013-evolution-e0548d25707ad8c4713e2e74c622a92bf4988545.zip |
Bug #351025 - Make the order of the mail accounts configurable
Diffstat (limited to 'mail')
-rw-r--r-- | mail/e-mail-backend.c | 35 | ||||
-rw-r--r-- | mail/e-mail-backend.h | 7 | ||||
-rw-r--r-- | mail/e-mail-reader.c | 6 | ||||
-rw-r--r-- | mail/e-mail-sidebar.c | 2 | ||||
-rw-r--r-- | mail/e-mail-store.c | 36 | ||||
-rw-r--r-- | mail/em-composer-utils.c | 2 | ||||
-rw-r--r-- | mail/em-folder-selection-button.c | 4 | ||||
-rw-r--r-- | mail/em-folder-tree-model.c | 367 | ||||
-rw-r--r-- | mail/em-folder-tree-model.h | 11 | ||||
-rw-r--r-- | mail/em-folder-tree.c | 2 | ||||
-rw-r--r-- | mail/em-folder-utils.c | 19 | ||||
-rw-r--r-- | mail/em-subscription-editor.c | 2 | ||||
-rw-r--r-- | mail/em-utils.c | 168 | ||||
-rw-r--r-- | mail/em-utils.h | 4 | ||||
-rw-r--r-- | mail/em-vfolder-rule.c | 2 | ||||
-rw-r--r-- | mail/evolution-mail.schemas.in | 35 | ||||
-rw-r--r-- | mail/message-list.c | 2 |
17 files changed, 606 insertions, 98 deletions
diff --git a/mail/e-mail-backend.c b/mail/e-mail-backend.c index c9ee133bb0..ff37b7a93a 100644 --- a/mail/e-mail-backend.c +++ b/mail/e-mail-backend.c @@ -71,9 +71,16 @@ 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, @@ -538,7 +545,7 @@ mail_backend_folder_changed_cb (MailFolderCache *folder_cache, const gchar *msg_uid, const gchar *msg_sender, const gchar *msg_subject, - EShell *shell) + EMailBackend *mail_backend) { CamelFolder *folder = NULL; EMEvent *event = em_event_peek (); @@ -565,12 +572,12 @@ mail_backend_folder_changed_cb (MailFolderCache *folder_cache, folder_type = (flags & CAMEL_FOLDER_TYPE_MASK); target->is_inbox = (folder_type == CAMEL_FOLDER_TYPE_INBOX); - model = em_folder_tree_model_get_default (); + model = em_folder_tree_model_get_default (mail_backend); target->display_name = em_folder_tree_model_get_folder_name ( model, store, folder_name); if (target->new > 0) - e_shell_event (shell, "mail-icon", (gpointer) "mail-unread"); + e_shell_event (e_shell_backend_get_shell (E_SHELL_BACKEND (mail_backend)), "mail-icon", (gpointer) "mail-unread"); /** @Event: folder.changed * @Title: Folder changed @@ -766,7 +773,7 @@ mail_backend_constructed (GObject *object) 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 (); + folder_tree_model = em_folder_tree_model_get_default (E_MAIL_BACKEND (shell_backend)); em_folder_tree_model_set_session (folder_tree_model, priv->session); g_signal_connect ( @@ -801,7 +808,7 @@ mail_backend_constructed (GObject *object) g_signal_connect ( folder_cache, "folder-changed", - G_CALLBACK (mail_backend_folder_changed_cb), shell); + G_CALLBACK (mail_backend_folder_changed_cb), shell_backend); mail_config_init (priv->session); mail_msg_init (); @@ -838,6 +845,15 @@ 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 @@ -934,3 +950,12 @@ e_mail_backend_submit_alert (EMailBackend *backend, e_alert_submit_valist (E_ALERT_SINK (shell_content), tag, va); 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 6d425197f3..4d3cc10799 100644 --- a/mail/e-mail-backend.h +++ b/mail/e-mail-backend.h @@ -67,6 +67,10 @@ 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); @@ -79,6 +83,9 @@ 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-reader.c b/mail/e-mail-reader.c index 430f71dc4f..a8e3899ace 100644 --- a/mail/e-mail-reader.c +++ b/mail/e-mail-reader.c @@ -300,7 +300,7 @@ action_mail_copy_cb (GtkAction *action, window = e_mail_reader_get_window (reader); uids = e_mail_reader_get_selected_uids (reader); - model = em_folder_tree_model_get_default (); + model = em_folder_tree_model_get_default (backend); dialog = em_folder_selector_new ( window, backend, model, @@ -732,7 +732,7 @@ action_mail_mark_unread_cb (GtkAction *action, /* Notify the tree model that the user has marked messages as * unread so it doesn't mistake the event as new mail arriving. */ - model = em_folder_tree_model_get_default (); + model = em_folder_tree_model_get_default (e_mail_reader_get_backend (reader)); folder = e_mail_reader_get_folder (reader); em_folder_tree_model_user_marked_unread (model, folder, n_marked); } @@ -806,7 +806,7 @@ action_mail_move_cb (GtkAction *action, uids = e_mail_reader_get_selected_uids (reader); window = e_mail_reader_get_window (reader); - model = em_folder_tree_model_get_default (); + model = em_folder_tree_model_get_default (backend); dialog = em_folder_selector_new ( window, backend, model, diff --git a/mail/e-mail-sidebar.c b/mail/e-mail-sidebar.c index 35048f8293..6a971ea51f 100644 --- a/mail/e-mail-sidebar.c +++ b/mail/e-mail-sidebar.c @@ -471,7 +471,7 @@ e_mail_sidebar_new (EMailBackend *backend, g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL); g_return_val_if_fail (E_IS_ALERT_SINK (alert_sink), NULL); - model = em_folder_tree_model_get_default (); + model = em_folder_tree_model_get_default (backend); return g_object_new ( E_TYPE_MAIL_SIDEBAR, diff --git a/mail/e-mail-store.c b/mail/e-mail-store.c index ea44e4238b..7b7774399d 100644 --- a/mail/e-mail-store.c +++ b/mail/e-mail-store.c @@ -39,6 +39,9 @@ #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, @@ -152,6 +155,32 @@ mail_store_note_store_cb (MailFolderCache *folder_cache, 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, @@ -165,7 +194,7 @@ mail_store_add (EMailSession *session, g_return_if_fail (store != NULL); g_return_if_fail (CAMEL_IS_STORE (store)); - default_model = em_folder_tree_model_get_default (); + default_model = em_folder_tree_model_get_default (NULL); folder_cache = e_mail_session_get_folder_cache (session); store_info = store_info_new (store); @@ -173,7 +202,8 @@ mail_store_add (EMailSession *session, g_hash_table_insert (store_table, store, store_info); - em_folder_tree_model_add_store (default_model, store); + if (special_mail_store_is_enabled (store)) + em_folder_tree_model_add_store (default_model, store); mail_folder_cache_note_store ( folder_cache, CAMEL_SESSION (session), store, NULL, @@ -387,7 +417,7 @@ e_mail_store_remove (EMailSession *session, 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 (); + default_model = em_folder_tree_model_get_default (NULL); em_folder_tree_model_remove_store (default_model, store); mail_disconnect_store (store); diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c index 8c98040ada..e42559ab3b 100644 --- a/mail/em-composer-utils.c +++ b/mail/em-composer-utils.c @@ -2989,7 +2989,7 @@ post_header_clicked_cb (EComposerPostHeader *header, 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 (); + model = em_folder_tree_model_get_default (E_MAIL_BACKEND (shell_backend)); dialog = em_folder_selector_new ( GTK_WINDOW (composer), diff --git a/mail/em-folder-selection-button.c b/mail/em-folder-selection-button.c index 3f05147078..26a3c9c2b0 100644 --- a/mail/em-folder-selection-button.c +++ b/mail/em-folder-selection-button.c @@ -272,13 +272,13 @@ folder_selection_button_clicked (GtkButton *button) session = e_mail_backend_get_session (priv->backend); - model = em_folder_tree_model_new (); + model = em_folder_tree_model_new (priv->backend); em_folder_tree_model_set_session (model, session); em_folder_tree_model_add_store (model, priv->store); } if (model == NULL) - model = g_object_ref (em_folder_tree_model_get_default ()); + model = g_object_ref (em_folder_tree_model_get_default (priv->backend)); dialog = em_folder_selector_new ( parent, priv->backend, model, diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c index eb26ad5fff..2116faf854 100644 --- a/mail/em-folder-tree-model.c +++ b/mail/em-folder-tree-model.c @@ -69,6 +69,7 @@ struct _EMFolderTreeModelPrivate { EAccountList *accounts; EMailSession *session; + EMailBackend *backend; /* CamelStore -> EMFolderTreeStoreInfo */ GHashTable *store_index; @@ -84,7 +85,8 @@ struct _EMFolderTreeModelPrivate { enum { PROP_0, PROP_SELECTION, - PROP_SESSION + PROP_SESSION, + PROP_BACKEND }; enum { @@ -124,55 +126,69 @@ folder_tree_model_sort (GtkTreeModel *model, GtkTreeIter *b, gpointer user_data) { - EShell *shell; + EShell *shell = user_data; gchar *aname, *bname; CamelStore *store; gboolean is_store; guint32 aflags, bflags; + guint asortorder, bsortorder; gint rv = -2; - /* XXX Pass the EShell in as user_data. */ - shell = e_shell_get_default (); - gtk_tree_model_get ( model, a, COL_BOOL_IS_STORE, &is_store, COL_POINTER_CAMEL_STORE, &store, COL_STRING_DISPLAY_NAME, &aname, - COL_UINT_FLAGS, &aflags, -1); + COL_UINT_FLAGS, &aflags, + COL_UINT_SORTORDER, &asortorder, + -1); gtk_tree_model_get ( model, b, COL_STRING_DISPLAY_NAME, &bname, - COL_UINT_FLAGS, &bflags, -1); + COL_UINT_FLAGS, &bflags, + COL_UINT_SORTORDER, &bsortorder, + -1); if (is_store) { - /* On This Computer is always first, and Search Folders - * is always last. */ - if (e_shell_get_express_mode (shell)) { - if (!strcmp (aname, _("On This Computer")) && - !strcmp (bname, _("Search Folders"))) - rv = -1; - else if (!strcmp (bname, _("On This Computer")) && - !strcmp (aname, _("Search Folders"))) - rv = 1; - else if (!strcmp (aname, _("On This Computer"))) - rv = 1; - else if (!strcmp (bname, _("On This Computer"))) - rv = -1; - else if (!strcmp (aname, _("Search Folders"))) - rv = 1; - else if (!strcmp (bname, _("Search Folders"))) - rv = -1; - } else { - if (!strcmp (aname, _("On This Computer"))) + if (e_shell_settings_get_boolean (e_shell_get_shell_settings (shell), "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 (!strcmp (bname, _("On This Computer"))) - rv = 1; - else if (!strcmp (aname, _("Search Folders"))) + else if (asortorder > bsortorder) rv = 1; - else if (!strcmp (bname, _("Search Folders"))) - rv = -1; + else + rv = 0; } } else if (store == vfolder_store) { /* UNMATCHED is always last. */ @@ -191,6 +207,8 @@ folder_tree_model_sort (GtkTreeModel *model, if (aname == NULL) { if (bname == NULL) rv = 0; + else + rv = -1; } else if (bname == NULL) rv = 1; @@ -260,6 +278,106 @@ account_added_cb (EAccountList *accounts, } static void +folder_tree_model_sort_changed (EMFolderTreeModel *tree_model) +{ + GtkTreeModel *model; + EShellBackend *shell_backend; + + 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; + + shell_backend = E_SHELL_BACKEND (em_folder_tree_model_get_backend (tree_model)); + + /* this invokes also sort on a GtkTreeStore */ + gtk_tree_sortable_set_default_sort_func ( + GTK_TREE_SORTABLE (model), + folder_tree_model_sort, e_shell_backend_get_shell (shell_backend), 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) +{ + EMailSession *session; + CamelService *service; + + session = em_folder_tree_model_get_session (model); + + 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; @@ -285,6 +403,11 @@ folder_tree_model_set_property (GObject *object, EM_FOLDER_TREE_MODEL (object), g_value_get_object (value)); return; + case PROP_BACKEND: + em_folder_tree_model_set_backend ( + EM_FOLDER_TREE_MODEL (object), + g_value_get_object (value)); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -310,11 +433,74 @@ folder_tree_model_get_property (GObject *object, em_folder_tree_model_get_session ( EM_FOLDER_TREE_MODEL (object))); return; + case PROP_BACKEND: + g_value_set_object ( + value, + em_folder_tree_model_get_backend ( + EM_FOLDER_TREE_MODEL (object))); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } + +static void +folder_tree_model_constructed (GObject *object) +{ + EShell *shell; + EShellSettings *shell_settings; + EMFolderTreeModel *model; + + GType col_types[] = { + G_TYPE_STRING, /* display name */ + G_TYPE_POINTER, /* store object */ + G_TYPE_STRING, /* full name */ + G_TYPE_STRING, /* icon name */ + G_TYPE_STRING, /* uri */ + G_TYPE_UINT, /* unread count */ + G_TYPE_UINT, /* flags */ + G_TYPE_BOOLEAN, /* is a store node */ + G_TYPE_BOOLEAN, /* is a folder node */ + G_TYPE_BOOLEAN, /* has not-yet-loaded subfolders */ + G_TYPE_UINT, /* last known unread count */ + G_TYPE_BOOLEAN, /* folder is a draft folder */ + G_TYPE_UINT /* user's sortorder */ + }; + + model = EM_FOLDER_TREE_MODEL (object); + shell = e_shell_backend_get_shell (E_SHELL_BACKEND (model->priv->backend)); + shell_settings = e_shell_get_shell_settings (shell); + + gtk_tree_store_set_column_types ( + GTK_TREE_STORE (model), NUM_COLUMNS, col_types); + gtk_tree_sortable_set_default_sort_func ( + GTK_TREE_SORTABLE (model), + folder_tree_model_sort, shell, NULL); + gtk_tree_sortable_set_sort_column_id ( + GTK_TREE_SORTABLE (model), + GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, + GTK_SORT_ASCENDING); + + model->priv->accounts = e_get_account_list (); + model->priv->account_changed_id = g_signal_connect ( + model->priv->accounts, "account-changed", + G_CALLBACK (account_changed_cb), model); + model->priv->account_removed_id = g_signal_connect ( + model->priv->accounts, "account-removed", + G_CALLBACK (account_removed_cb), model); + model->priv->account_added_id = g_signal_connect ( + model->priv->accounts, "account-added", + G_CALLBACK (account_added_cb), model); + + g_signal_connect_swapped (model->priv->backend, "account-sort-order-changed", G_CALLBACK (account_sort_order_changed_cb), model); + 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_OBJECT_CLASS (parent_class)->constructed (object); +} + static void folder_tree_model_dispose (GObject *object) { @@ -334,6 +520,24 @@ folder_tree_model_dispose (GObject *object) priv->session = NULL; } + if (priv->backend) { + EShell *shell; + EShellSettings *shell_settings; + EMFolderTreeModel *model; + + model = EM_FOLDER_TREE_MODEL (object); + shell = e_shell_backend_get_shell (E_SHELL_BACKEND (priv->backend)); + shell_settings = e_shell_get_shell_settings (shell); + + g_signal_handlers_disconnect_by_func (priv->backend, G_CALLBACK (account_sort_order_changed_cb), model); + g_signal_handlers_disconnect_by_func (shell_settings, G_CALLBACK (account_sort_order_changed_cb), model); + g_signal_handlers_disconnect_by_func (shell_settings, G_CALLBACK (enable_local_folders_changed_cb), model); + g_signal_handlers_disconnect_by_func (shell_settings, G_CALLBACK (enable_search_folders_changed_cb), model); + + g_object_unref (priv->backend); + priv->backend = NULL; + } + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -370,6 +574,7 @@ em_folder_tree_model_class_init (EMFolderTreeModelClass *class) object_class = G_OBJECT_CLASS (class); object_class->set_property = folder_tree_model_set_property; object_class->get_property = folder_tree_model_get_property; + object_class->constructed = folder_tree_model_constructed; object_class->dispose = folder_tree_model_dispose; object_class->finalize = folder_tree_model_finalize; @@ -393,6 +598,16 @@ em_folder_tree_model_class_init (EMFolderTreeModelClass *class) E_TYPE_MAIL_SESSION, G_PARAM_READWRITE)); + g_object_class_install_property ( + object_class, + PROP_BACKEND, + g_param_spec_object ( + "backend", + NULL, + NULL, + E_TYPE_MAIL_BACKEND, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + signals[LOADING_ROW] = g_signal_new ( "loading-row", G_OBJECT_CLASS_TYPE (object_class), @@ -477,21 +692,6 @@ em_folder_tree_model_init (EMFolderTreeModel *model) GHashTable *store_index; GHashTable *uri_index; - GType col_types[] = { - G_TYPE_STRING, /* display name */ - G_TYPE_POINTER, /* store object */ - G_TYPE_STRING, /* full name */ - G_TYPE_STRING, /* icon name */ - G_TYPE_STRING, /* uri */ - G_TYPE_UINT, /* unread count */ - G_TYPE_UINT, /* flags */ - G_TYPE_BOOLEAN, /* is a store node */ - G_TYPE_BOOLEAN, /* is a folder node */ - G_TYPE_BOOLEAN, /* has not-yet-loaded subfolders */ - G_TYPE_UINT, /* last known unread count */ - G_TYPE_BOOLEAN /* folder is a draft folder */ - }; - store_index = g_hash_table_new_full ( g_direct_hash, g_direct_equal, (GDestroyNotify) NULL, @@ -505,42 +705,29 @@ em_folder_tree_model_init (EMFolderTreeModel *model) model->priv = EM_FOLDER_TREE_MODEL_GET_PRIVATE (model); model->priv->store_index = store_index; model->priv->uri_index = uri_index; - - gtk_tree_store_set_column_types ( - GTK_TREE_STORE (model), NUM_COLUMNS, col_types); - gtk_tree_sortable_set_default_sort_func ( - GTK_TREE_SORTABLE (model), - folder_tree_model_sort, NULL, NULL); - gtk_tree_sortable_set_sort_column_id ( - GTK_TREE_SORTABLE (model), - GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, - GTK_SORT_ASCENDING); - - model->priv->accounts = e_get_account_list (); - model->priv->account_changed_id = g_signal_connect ( - model->priv->accounts, "account-changed", - G_CALLBACK (account_changed_cb), model); - model->priv->account_removed_id = g_signal_connect ( - model->priv->accounts, "account-removed", - G_CALLBACK (account_removed_cb), model); - model->priv->account_added_id = g_signal_connect ( - model->priv->accounts, "account-added", - G_CALLBACK (account_added_cb), model); } EMFolderTreeModel * -em_folder_tree_model_new (void) +em_folder_tree_model_new (EMailBackend *mail_backend) { - return g_object_new (EM_TYPE_FOLDER_TREE_MODEL, NULL); + return g_object_new (EM_TYPE_FOLDER_TREE_MODEL, "backend", mail_backend, NULL); } EMFolderTreeModel * -em_folder_tree_model_get_default (void) +em_folder_tree_model_get_default (EMailBackend *mail_backend) { static EMFolderTreeModel *default_folder_tree_model; - if (G_UNLIKELY (default_folder_tree_model == NULL)) - default_folder_tree_model = em_folder_tree_model_new (); + if (G_UNLIKELY (default_folder_tree_model == NULL)) { + if (!mail_backend) { + EShell *shell; + + shell = e_shell_get_default (); + mail_backend = E_MAIL_BACKEND (e_shell_get_backend_by_name (shell, "mail")); + } + + default_folder_tree_model = em_folder_tree_model_new (mail_backend); + } return default_folder_tree_model; } @@ -620,6 +807,33 @@ em_folder_tree_model_set_session (EMFolderTreeModel *model, g_object_notify (G_OBJECT (model), "session"); } +EMailBackend * +em_folder_tree_model_get_backend (EMFolderTreeModel *model) +{ + g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), NULL); + + return model->priv->backend; +} + +void +em_folder_tree_model_set_backend (EMFolderTreeModel *model, + EMailBackend *backend) +{ + 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 (model->priv->backend != NULL) + g_object_unref (model->priv->backend); + + model->priv->backend = backend; + + g_object_notify (G_OBJECT (model), "backend"); +} + void em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *iter, @@ -1002,6 +1216,7 @@ void em_folder_tree_model_add_store (EMFolderTreeModel *model, CamelStore *store) { + EMailBackend *mail_backend; EMFolderTreeModelStoreInfo *si; GtkTreeRowReference *reference; GtkTreeStore *tree_store; @@ -1011,6 +1226,7 @@ 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)); @@ -1022,6 +1238,7 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model, provider = camel_service_get_provider (service); service_url = camel_service_get_camel_url (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. */ @@ -1040,6 +1257,8 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model, uri = camel_url_to_string (service_url, CAMEL_URL_HIDE_ALL); + 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 ( @@ -1049,7 +1268,9 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model, COL_STRING_FULL_NAME, NULL, COL_BOOL_LOAD_SUBDIRS, TRUE, COL_BOOL_IS_STORE, TRUE, - COL_STRING_URI, uri, -1); + 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); reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (model), path); diff --git a/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h index 1bf5483367..3765cfea11 100644 --- a/mail/em-folder-tree-model.h +++ b/mail/em-folder-tree-model.h @@ -26,6 +26,7 @@ #include <gtk/gtk.h> #include <camel/camel.h> +#include <mail/e-mail-backend.h> #include <mail/e-mail-session.h> /* Standard GObject macros */ @@ -72,6 +73,7 @@ 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 }; @@ -109,9 +111,9 @@ struct _EMFolderTreeModelClass { GType em_folder_tree_model_get_type (void); EMFolderTreeModel * - em_folder_tree_model_new (void); + em_folder_tree_model_new (EMailBackend *mail_backend); EMFolderTreeModel * - em_folder_tree_model_get_default (void); + em_folder_tree_model_get_default (EMailBackend *mail_backend); GtkTreeSelection * em_folder_tree_model_get_selection (EMFolderTreeModel *model); @@ -123,6 +125,11 @@ EMailSession * em_folder_tree_model_get_session void em_folder_tree_model_set_session (EMFolderTreeModel *model, EMailSession *session); +EMailBackend * em_folder_tree_model_get_backend + (EMFolderTreeModel *model); +void em_folder_tree_model_set_backend + (EMFolderTreeModel *model, + EMailBackend *backend); 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 061c3540f7..6212f8a8ca 100644 --- a/mail/em-folder-tree.c +++ b/mail/em-folder-tree.c @@ -1770,7 +1770,7 @@ em_folder_tree_new (EMailBackend *backend, g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL); g_return_val_if_fail (E_IS_ALERT_SINK (alert_sink), NULL); - model = em_folder_tree_model_get_default (); + model = em_folder_tree_model_get_default (backend); return em_folder_tree_new_with_model (backend, alert_sink, model); } diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c index 775dfbb663..54586ad763 100644 --- a/mail/em-folder-utils.c +++ b/mail/em-folder-utils.c @@ -487,7 +487,7 @@ em_folder_utils_copy_folder (GtkWindow *parent, label = delete ? _("_Move") : _("C_opy"); title = delete ? _("Move Folder To") : _("Copy Folder To"); - model = em_folder_tree_model_get_default (); + model = em_folder_tree_model_get_default (backend); dialog = em_folder_selector_new ( parent, backend, model, @@ -547,6 +547,8 @@ em_folder_utils_create_folder (GtkWindow *parent, EMFolderTree *emft, const gchar *initial_uri) { + EShell *shell; + EShellSettings *shell_settings; EMailSession *session; EMFolderSelector *selector; EMFolderTree *folder_tree; @@ -560,7 +562,10 @@ em_folder_utils_create_folder (GtkWindow *parent, g_return_if_fail (GTK_IS_WINDOW (parent)); g_return_if_fail (E_IS_MAIL_BACKEND (backend)); - model = em_folder_tree_model_new (); + shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend)); + shell_settings = e_shell_get_shell_settings (shell); + + model = em_folder_tree_model_new (backend); session = e_mail_backend_get_session (backend); em_folder_tree_model_set_session (model, session); @@ -569,6 +574,7 @@ em_folder_utils_create_folder (GtkWindow *parent, for (link = list; link != NULL; link = g_list_next (link)) { CamelService *service; CamelStore *store; + const gchar *uid, *prop = NULL; service = CAMEL_SERVICE (link->data); @@ -580,6 +586,15 @@ em_folder_utils_create_folder (GtkWindow *parent, if ((store->flags & CAMEL_STORE_CAN_EDIT_FOLDERS) == 0) continue; + 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 && !e_shell_settings_get_boolean (shell_settings, prop)) + continue; + em_folder_tree_model_add_store (model, store); } diff --git a/mail/em-subscription-editor.c b/mail/em-subscription-editor.c index e2452d70bf..2dca93b51a 100644 --- a/mail/em-subscription-editor.c +++ b/mail/em-subscription-editor.c @@ -1077,7 +1077,7 @@ subscription_editor_realize (GtkWidget *widget) /* Find stores to display, and watch for the initial store. */ - model = em_folder_tree_model_get_default (); + model = em_folder_tree_model_get_default (NULL); list = em_folder_tree_model_list_stores (model); for (link = list; link != NULL; link = g_list_next (link)) { diff --git a/mail/em-utils.c b/mail/em-utils.c index 968165385a..5ff93887a2 100644 --- a/mail/em-utils.c +++ b/mail/em-utils.c @@ -84,6 +84,8 @@ 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) @@ -2014,6 +2016,8 @@ emu_free_mail_cache (void) photos_cache = NULL; G_UNLOCK (photos_cache); + + free_account_sort_order_cache (); } void @@ -2369,3 +2373,167 @@ 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 e8ffd190d6..e6ebe8ca4b 100644 --- a/mail/em-utils.h +++ b/mail/em-utils.h @@ -99,6 +99,10 @@ 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 be18f2c248..fbb711738f 100644 --- a/mail/em-vfolder-rule.c +++ b/mail/em-vfolder-rule.c @@ -610,7 +610,7 @@ source_add (GtkWidget *widget, backend = em_vfolder_rule_get_backend (data->vr); - model = em_folder_tree_model_get_default (); + model = em_folder_tree_model_get_default (backend); dialog = em_folder_selector_new ( parent, backend, model, diff --git a/mail/evolution-mail.schemas.in b/mail/evolution-mail.schemas.in index f1dcd73ea6..82be1319c8 100644 --- a/mail/evolution-mail.schemas.in +++ b/mail/evolution-mail.schemas.in @@ -678,6 +678,20 @@ </schema> <schema> + <key>/schemas/apps/evolution/mail/display/enable_local</key> + <applyto>/apps/evolution/mail/display/enable_local</applyto> + <owner>evolution-mail</owner> + <type>bool</type> + <default>true</default> + <locale name="C"> + <short>Enable local folders</short> + <long> + Whether to show local folders (On This Computer) in a folder tree. + </long> + </locale> + </schema> + + <schema> <key>/schemas/apps/evolution/mail/display/safe_list</key> <applyto>/apps/evolution/mail/display/safe_list</applyto> <owner>evolution-mail</owner> @@ -885,7 +899,7 @@ </long> </locale> </schema> - + <schema> <key>/schemas/apps/evolution/mail/display/paned_view_headers_state</key> <applyto>/apps/evolution/mail/display/paned_view_headers_state</applyto> @@ -901,7 +915,24 @@ </long> </locale> </schema> - + + <schema> + <key>/schemas/apps/evolution/mail/display/sort_accounts_alpha</key> + <applyto>/apps/evolution/mail/display/sort_accounts_alpha</applyto> + <owner>evolution-mail</owner> + <type>bool</type> + <default>true</default> + <locale name="C"> + <short>Sort accounts alphabetically in a folder tree</short> + <long> + Tells how to sort accounts in a folder tree used in a Mail view. + When set to true accounts are sorted alphabetically, with an exception + of On This Computer and Search folders, otherwise accounts are + sorted based on an order given by a user. + </long> + </locale> + </schema> + <!-- Mail Browser --> <schema> diff --git a/mail/message-list.c b/mail/message-list.c index d98f860f8c..cd44b9506a 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -4191,7 +4191,7 @@ on_click (ETree *tree, if (col == COL_MESSAGE_STATUS && (flags & CAMEL_MESSAGE_SEEN)) { EMFolderTreeModel *model; - model = em_folder_tree_model_get_default (); + model = em_folder_tree_model_get_default (list->priv->backend); em_folder_tree_model_user_marked_unread ( model, list->folder, 1); } |