aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
Diffstat (limited to 'mail')
-rw-r--r--mail/e-mail-backend.c35
-rw-r--r--mail/e-mail-backend.h7
-rw-r--r--mail/e-mail-reader.c6
-rw-r--r--mail/e-mail-sidebar.c2
-rw-r--r--mail/e-mail-store.c36
-rw-r--r--mail/em-composer-utils.c2
-rw-r--r--mail/em-folder-selection-button.c4
-rw-r--r--mail/em-folder-tree-model.c367
-rw-r--r--mail/em-folder-tree-model.h11
-rw-r--r--mail/em-folder-tree.c2
-rw-r--r--mail/em-folder-utils.c19
-rw-r--r--mail/em-subscription-editor.c2
-rw-r--r--mail/em-utils.c168
-rw-r--r--mail/em-utils.h4
-rw-r--r--mail/em-vfolder-rule.c2
-rw-r--r--mail/evolution-mail.schemas.in35
-rw-r--r--mail/message-list.c2
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);
}