[evolution/email-factory-3-4: 32/38] Reorder accounts by drag-and-drop.
- From: Srinivasa Ragavan <sragavan src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/email-factory-3-4: 32/38] Reorder accounts by drag-and-drop.
- Date: Fri, 16 Dec 2011 11:57:09 +0000 (UTC)
commit 1a08f6e9ef651594e7f581c5ebbc565da85aa4d7
Author: Srinivasa Ragavan <sragavan gnome org>
Date: Fri Dec 16 15:48:11 2011 +0530
Reorder accounts by drag-and-drop.
This implements
https://bugzilla.gnome.org/show_bug.cgi?id=663527#c3. by Matthew
Barnes.
libemail-engine/e-mail-session-utils.c | 5 +-
libemail-engine/e-mail-session.c | 367 ++++++++++++++++++++++++++-
libemail-engine/e-mail-session.h | 13 +
libemail-engine/mail-config.c | 1 -
libemail-engine/mail-folder-cache.c | 403 ++++++++++++++++++++++--------
libemail-engine/mail-folder-cache.h | 28 ++-
libemail-engine/mail-ops.c | 50 +++--
libemail-utils/e-marshal.list | 1 +
mail/e-mail-account-store.c | 12 +
mail/e-mail-ui-session.c | 259 +++++++++++++++++++-
mail/e-mail-ui-session.h | 7 +
mail/em-account-editor.c | 3 +-
mail/em-folder-tree-model.c | 3 +-
mail/mail-vfolder.c | 3 +-
modules/mail/e-mail-shell-backend.c | 3 +-
modules/mail/e-mail-shell-view-actions.c | 2 +-
modules/mail/e-mail-shell-view-private.h | 10 +-
modules/mail/em-account-prefs.c | 3 +-
18 files changed, 1011 insertions(+), 162 deletions(-)
---
diff --git a/libemail-engine/e-mail-session-utils.c b/libemail-engine/e-mail-session-utils.c
index 09fc2d5..404b9d9 100644
--- a/libemail-engine/e-mail-session-utils.c
+++ b/libemail-engine/e-mail-session-utils.c
@@ -27,7 +27,6 @@
#include <glib/gi18n-lib.h>
#include "mail-tools.h"
-#include "e-mail-local.h"
#include "e-mail-folder-utils.h"
#include <libemail-utils/e-account-utils.h>
@@ -510,7 +509,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/libemail-engine/e-mail-session.c b/libemail-engine/e-mail-session.c
index 6029b79..d0cda25 100644
--- a/libemail-engine/e-mail-session.c
+++ b/libemail-engine/e-mail-session.c
@@ -66,13 +66,23 @@
((obj), E_TYPE_MAIL_SESSION, EMailSessionPrivate))
typedef struct _AsyncContext AsyncContext;
+typedef struct _SourceContext SourceContext;
struct _EMailSessionPrivate {
MailFolderCache *folder_cache;
+ EAccountList *account_list;
+ gulong account_added_handler_id;
+
+ CamelStore *local_store;
+
FILE *filter_logfile;
GHashTable *junk_filters;
EProxy *proxy;
+
+ /* Local folder cache. */
+ GPtrArray *local_folders;
+ GPtrArray *local_folder_uris;
};
struct _AsyncContext {
@@ -85,10 +95,25 @@ struct _AsyncContext {
CamelFolder *folder;
};
+struct _SourceContext {
+ EMailSession *session;
+ CamelService *service;
+};
+
enum {
PROP_0,
PROP_FOLDER_CACHE,
- PROP_JUNK_FILTER_NAME
+ PROP_JUNK_FILTER_NAME,
+ PROP_LOCAL_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 */
};
enum {
@@ -316,6 +341,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)
@@ -406,6 +443,184 @@ 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_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_set_property (GObject *object,
guint property_id,
const GValue *value,
@@ -442,6 +657,13 @@ 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;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -459,6 +681,23 @@ mail_session_dispose (GObject *object)
priv->folder_cache = NULL;
}
+ if (priv->account_list != NULL) {
+ g_signal_handler_disconnect (
+ priv->account_list,
+ priv->account_added_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;
+ }
+
+
+ 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);
}
@@ -473,6 +712,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);
@@ -495,17 +737,53 @@ mail_session_notify (GObject *object,
static void
mail_session_constructed (GObject *object)
{
- EMailSessionPrivate *priv;
+ 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);
+
+ /* This must be created after the account store. */
+ session->priv->folder_cache = mail_folder_cache_new (session);
+
+
+ /* Add built-in CamelStores. */
+ mail_session_add_local_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);
+
+ mail_session_add_by_account (session, account);
+
+ e_iterator_next (iter);
+ }
+
+ g_object_unref (iter);
+
+ /* 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;
+
extensible = E_EXTENSIBLE (object);
e_extensible_load_extensions (extensible);
@@ -514,11 +792,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)) {
@@ -546,17 +824,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);
}
@@ -926,7 +1208,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);
@@ -1154,6 +1437,17 @@ e_mail_session_class_init (EMailSessionClass *class)
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));
+
/**
* EMailSession::flush-outbox
* @session: the email session
@@ -1213,11 +1507,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);
@@ -1253,6 +1553,7 @@ e_mail_session_new (void)
NULL);
}
+
MailFolderCache *
e_mail_session_get_folder_cache (EMailSession *session)
{
@@ -1261,6 +1562,50 @@ 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;
+}
+
+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/libemail-engine/e-mail-session.h b/libemail-engine/e-mail-session.h
index b82c6e9..b22f3f7 100644
--- a/libemail-engine/e-mail-session.h
+++ b/libemail-engine/e-mail-session.h
@@ -47,8 +47,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;
@@ -66,6 +73,12 @@ GType e_mail_session_get_type (void);
EMailSession * e_mail_session_new (void);
MailFolderCache *
e_mail_session_get_folder_cache (EMailSession *session);
+CamelStore * e_mail_session_get_local_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/libemail-engine/mail-config.c b/libemail-engine/mail-config.c
index 0c0d1cc..57ec1b5 100644
--- a/libemail-engine/mail-config.c
+++ b/libemail-engine/mail-config.c
@@ -35,7 +35,6 @@
#include "libemail-utils/e-signature-utils.h"
#include "libemail-engine/e-mail-folder-utils.h"
-#include "e-mail-local.h"
#include "mail-config.h"
#include "mail-tools.h"
diff --git a/libemail-engine/mail-folder-cache.c b/libemail-engine/mail-folder-cache.c
index 11edb5c..05f151f 100644
--- a/libemail-engine/mail-folder-cache.c
+++ b/libemail-engine/mail-folder-cache.c
@@ -47,7 +47,6 @@
#include "mail-tools.h"
#include "e-mail-utils.h"
#include "e-mail-folder-utils.h"
-#include "e-mail-local.h"
#include "e-mail-store-utils.h"
#include "mail-config.h"
@@ -56,7 +55,11 @@
/* This code is a mess, there is no reason it should be so complicated. */
+typedef struct _StoreInfo StoreInfo;
+
struct _MailFolderCachePrivate {
+ gpointer session; /* weak pointer */
+
/* source id for the ping timeout callback */
guint ping_id;
/* Store to storeinfo table, active stores */
@@ -76,6 +79,11 @@ struct _MailFolderCachePrivate {
};
enum {
+ PROP_0,
+ PROP_SESSION
+};
+
+enum {
FOLDER_AVAILABLE,
FOLDER_UNAVAILABLE,
FOLDER_DELETED,
@@ -88,7 +96,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 */
@@ -119,14 +127,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
@@ -142,6 +162,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 *self)
{
@@ -343,9 +423,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;
@@ -356,6 +437,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);
@@ -365,9 +447,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
@@ -477,17 +562,9 @@ unset_folder_info (MailFolderCache *self,
}
static void
-free_folder_info (struct _folder_info *mfi)
-{
- g_free (mfi->full_name);
- g_source_remove (mfi->timeout);
- g_free (mfi);
-}
-
-static void
setup_folder (MailFolderCache *self,
CamelFolderInfo *fi,
- struct _store_info *si)
+ StoreInfo *si)
{
struct _folder_info *mfi;
struct _folder_update *up;
@@ -520,7 +597,7 @@ setup_folder (MailFolderCache *self,
static void
create_folders (MailFolderCache *self,
CamelFolderInfo *fi,
- struct _store_info *si)
+ StoreInfo *si)
{
while (fi) {
setup_folder (self, fi, si);
@@ -537,7 +614,7 @@ store_folder_subscribed_cb (CamelStore *store,
CamelFolderInfo *info,
MailFolderCache *self)
{
- struct _store_info *si;
+ StoreInfo *si;
g_mutex_lock (self->priv->stores_mutex);
si = g_hash_table_lookup (self->priv->stores, store);
@@ -570,7 +647,7 @@ store_folder_unsubscribed_cb (CamelStore *store,
CamelFolderInfo *info,
MailFolderCache *self)
{
- struct _store_info *si;
+ StoreInfo *si;
struct _folder_info *mfi;
g_mutex_lock (self->priv->stores_mutex);
@@ -599,7 +676,7 @@ store_folder_deleted_cb (CamelStore *store,
static void
rename_folders (MailFolderCache *self,
- struct _store_info *si,
+ StoreInfo *si,
const gchar *oldbase,
const gchar *newbase,
CamelFolderInfo *fi)
@@ -705,7 +782,7 @@ store_folder_renamed_cb (CamelStore *store,
CamelFolderInfo *info,
MailFolderCache *self)
{
- struct _store_info *si;
+ StoreInfo *si;
g_mutex_lock (self->priv->stores_mutex);
si = g_hash_table_lookup (self->priv->stores, store);
@@ -730,13 +807,6 @@ store_folder_renamed_cb (CamelStore *store,
g_mutex_unlock (self->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,
@@ -747,11 +817,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
@@ -760,7 +850,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);
@@ -783,6 +873,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;
@@ -940,7 +1036,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;
@@ -959,35 +1055,154 @@ storeinfo_find_folder_info (CamelStore *store,
}
}
+void
+mail_folder_cache_service_added (MailFolderCache *cache,
+ CamelService *service)
+{
+ mail_folder_cache_note_store (
+ cache, CAMEL_STORE (service), NULL, NULL, NULL);
+}
+
+void
+mail_folder_cache_service_removed (MailFolderCache *cache
+ CamelService *service)
+{
+ 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;
+ }
+
+ /* 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;
+
+ priv = MAIL_FOLDER_CACHE_GET_PRIVATE (object);
- g_hash_table_destroy (cache->priv->stores);
- g_mutex_free (cache->priv->stores_mutex);
+ g_hash_table_destroy (priv->stores);
+ g_mutex_free (priv->stores_mutex);
- if (cache->priv->ping_id > 0) {
- g_source_remove (cache->priv->ping_id);
- cache->priv->ping_id = 0;
+ 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;
+
+ 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);
+}
+
+static void
mail_folder_cache_folder_available (MailFolderCache *cache,
CamelStore *store,
const gchar *folder_name)
@@ -1145,12 +1360,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
@@ -1302,9 +1533,21 @@ mail_folder_cache_init (MailFolderCache *self)
}
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);
}
/**
@@ -1322,12 +1565,12 @@ mail_folder_cache_note_store (MailFolderCache *self,
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));
@@ -1336,11 +1579,8 @@ mail_folder_cache_note_store (MailFolderCache *self,
printf("Loading: %s %s\n", camel_service_get_display_name ((CamelService *) store), camel_service_get_uid ((CamelService *) store));
si = g_hash_table_lookup (self->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 (self->priv->stores, store, si);
- g_queue_init (&si->folderinfo_updates);
hook = TRUE;
}
@@ -1417,54 +1657,6 @@ mail_folder_cache_note_store (MailFolderCache *self,
}
}
-/**
- * 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 *self,
- CamelStore *store)
-{
- struct _store_info *si;
-
- g_return_if_fail (CAMEL_IS_STORE (store));
-
- if (self->priv->stores == NULL)
- return;
-
- d(printf("store removed!!\n"));
- g_mutex_lock (self->priv->stores_mutex);
- si = g_hash_table_lookup (self->priv->stores, store);
- if (si) {
- GList *link;
-
- g_hash_table_remove (self->priv->stores, store);
-
- g_signal_handlers_disconnect_matched (
- store, G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, self);
-
- g_hash_table_foreach (
- si->folders, (GHFunc)
- unset_folder_info_hash, self);
-
- 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 (self->priv->stores_mutex);
-}
/**
* mail_folder_cache_note_folder:
@@ -1478,10 +1670,13 @@ mail_folder_cache_note_folder (MailFolderCache *self,
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/libemail-engine/mail-folder-cache.h b/libemail-engine/mail-folder-cache.h
index 146ead5..ac56575 100644
--- a/libemail-engine/mail-folder-cache.h
+++ b/libemail-engine/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,35 +110,38 @@ 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);
+void mail_folder_cache_service_added (MailFolderCache *cache,
+ CamelService *service);
+void mail_folder_cache_service_removed
+ (MailFolderCache *cache
+ CamelService *service);
G_END_DECLS
diff --git a/libemail-engine/mail-ops.c b/libemail-engine/mail-ops.c
index 8cf7dac..8620c56 100644
--- a/libemail-engine/mail-ops.c
+++ b/libemail-engine/mail-ops.c
@@ -42,7 +42,6 @@
#include "mail-ops.h"
#include "mail-tools.h"
#include "e-mail-session-utils.h"
-#include "e-mail-local.h"
#define w(x)
#define d(x)
@@ -210,18 +209,24 @@ 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 = FALSE;
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) {
@@ -247,7 +252,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 (
@@ -341,7 +346,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
@@ -667,7 +672,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);
}
@@ -680,7 +686,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;
@@ -798,6 +805,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;
@@ -805,7 +813,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;
@@ -1479,19 +1491,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 (
@@ -1581,7 +1599,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->session, cancellable, error);
diff --git a/libemail-utils/e-marshal.list b/libemail-utils/e-marshal.list
index 884886c..6d3c1fc 100644
--- a/libemail-utils/e-marshal.list
+++ b/libemail-utils/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/e-mail-account-store.c b/mail/e-mail-account-store.c
index ccfbe3b..02c8bb4 100644
--- a/mail/e-mail-account-store.c
+++ b/mail/e-mail-account-store.c
@@ -1027,10 +1027,15 @@ e_mail_account_store_add_service (EMailAccountStore *store,
const gchar *uid;
gboolean builtin;
gboolean enabled;
+ MailFolderCache *cache;
+ EMailSession *session;
g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store));
g_return_if_fail (CAMEL_IS_SERVICE (service));
+ session = e_mail_account_store_get_session (store);
+ cache = e_mail_session_get_folder_cache (session);
+
/* Avoid duplicate services in the account store. */
if (mail_account_store_get_iter (store, service, &iter))
g_return_if_reached ();
@@ -1087,6 +1092,7 @@ e_mail_account_store_add_service (EMailAccountStore *store,
/* This populates the rest of the columns. */
mail_account_store_update_row (store, service, &iter);
+ mail_folder_cache_service_added (cache, service);
g_signal_emit (store, signals[SERVICE_ADDED], 0, service);
if (enabled)
@@ -1107,10 +1113,15 @@ e_mail_account_store_remove_service (EMailAccountStore *store,
{
GtkTreeIter iter;
gboolean proceed;
+ MailFolderCache *cache;
+ EMailSession *session;
g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store));
g_return_if_fail (CAMEL_IS_SERVICE (service));
+ session = e_mail_account_store_get_session (store);
+ cache = e_mail_session_get_folder_cache (session);
+
if (!mail_account_store_get_iter (store, service, &iter))
g_return_if_reached ();
@@ -1126,6 +1137,7 @@ e_mail_account_store_remove_service (EMailAccountStore *store,
mail_account_store_clean_index (store);
+ mail_folder_cache_service_removed (cache, service);
g_signal_emit (store, signals[SERVICE_REMOVED], 0, service);
g_object_unref (service);
diff --git a/mail/e-mail-ui-session.c b/mail/e-mail-ui-session.c
index 6cc46f2..2ecbef7 100644
--- a/mail/e-mail-ui-session.c
+++ b/mail/e-mail-ui-session.c
@@ -48,6 +48,8 @@
#include <libebackend/e-extensible.h>
#include <libedataserverui/e-passwords.h>
+#include "e-mail-account-store.h"
+
#include "e-util/e-util.h"
#include "libemail-utils/e-account-utils.h"
#include "e-util/e-alert-dialog.h"
@@ -55,7 +57,6 @@
#include "libemail-engine/e-mail-folder-utils.h"
#include "libemail-engine/e-mail-junk-filter.h"
-#include "libemail-engine/e-mail-local.h"
#include "libemail-engine/e-mail-session.h"
#include "e-mail-ui-session.h"
#include "em-composer-utils.h"
@@ -74,6 +75,17 @@
struct _EMailUISessionPrivate {
FILE *filter_logfile;
+ CamelStore *vfolder_store;
+ EMailAccountStore *account_store;
+
+ EAccountList *account_list;
+ gulong account_changed_handler_id;
+};
+
+enum {
+ PROP_0,
+ PROP_ACCOUNT_STORE,
+ PROP_VFOLDER_STORE
};
G_DEFINE_TYPE_WITH_CODE (
@@ -384,6 +396,25 @@ mail_ui_session_dispose (GObject *object)
priv = E_MAIL_UI_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->vfolder_store != NULL) {
+ g_object_unref (priv->vfolder_store);
+ priv->vfolder_store = NULL;
+ }
+
+ if (priv->account_list != NULL) {
+ g_signal_handler_disconnect (
+ priv->account_list,
+ priv->account_changed_handler_id);
+ g_object_unref (priv->account_list);
+ priv->account_list = NULL;
+ }
+
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (e_mail_ui_session_parent_class)->dispose (object);
}
@@ -399,16 +430,134 @@ mail_ui_session_finalize (GObject *object)
G_OBJECT_CLASS (e_mail_ui_session_parent_class)->finalize (object);
}
+static void
+mail_session_add_vfolder_store (EMailUISession *uisession)
+{
+ 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_ui_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 void
mail_ui_session_constructed (GObject *object)
{
EMailUISessionPrivate *priv;
-
+ EMFolderTreeModel *folder_tree_model;
+ EMailSession *session;
+ EMailUISession *session;
+ EAccount *account;
+ EAccountList *account_list;
+ gulong handler_id;
+
+ session = E_MAIL_SESSION (object);
+ uisession = E_MAIL_UI_SESSION(object);
priv = E_MAIL_UI_SESSION_GET_PRIVATE (object);
+ priv->account_store = e_mail_account_store_new (session);
+
+ account_list = e_get_account_list ();
+ session->priv->account_list = g_object_ref (account_list);
+
+ /* 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);
+
/* Chain up to parent's constructed() method. */
G_OBJECT_CLASS (e_mail_ui_session_parent_class)->constructed (object);
+
+ mail_session_add_vfolder_store (session);
+
+ /* 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 (
+ priv->account_store, service);
+ }
+
+ handler_id = g_signal_connect (
+ account_list, "account-changed",
+ G_CALLBACK (mail_ui_session_account_changed_cb), session);
+ priv->account_changed_handler_id = handler_id;
+
}
static gint
@@ -463,6 +612,81 @@ mail_ui_session_get_filter_driver (CamelSession *session,
}
static void
+mail_ui_session_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_session_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ACCOUNT_STORE:
+ g_value_set_object (
+ value,
+ e_mail_ui_session_get_account_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);
+}
+
+static gboolean
+mail_ui_session_add_service_cb (SourceContext *context)
+{
+ EMailAccountStore *store;
+
+ store = e_mail_ui_session_get_account_store (context->session);
+ e_mail_account_store_add_service (store, context->service);
+
+ return FALSE;
+}
+
+static CamelService *
+mail_session_add_service (CamelSession *session,
+ const gchar *uid,
+ const gchar *protocol,
+ CamelProviderType type,
+ GError **error)
+{
+ CamelService *service;
+
+ /* Chain up to parent's constructed() method. */
+ service = G_OBJECT_CLASS (e_mail_ui_session_parent_class)->add_service (object);
+
+ /* 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);
+ }
+
+}
+
+static void
e_mail_ui_session_class_init (EMailUISessionClass *class)
{
GObjectClass *object_class;
@@ -471,6 +695,8 @@ e_mail_ui_session_class_init (EMailUISessionClass *class)
g_type_class_add_private (class, sizeof (EMailUISessionPrivate));
object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mail_ui_session_set_property;
+ object_class->get_property = mail_ui_session_get_property;
object_class->dispose = mail_ui_session_dispose;
object_class->finalize = mail_ui_session_finalize;
object_class->constructed = mail_ui_session_constructed;
@@ -478,6 +704,19 @@ e_mail_ui_session_class_init (EMailUISessionClass *class)
session_class = CAMEL_SESSION_CLASS (class);
session_class->alert_user = mail_ui_session_alert_user;
session_class->get_filter_driver = mail_ui_session_get_filter_driver;
+ session_class->add_service = mail_ui_session_add_service;
+
+ 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
@@ -502,3 +741,19 @@ e_mail_ui_session_new (void)
NULL);
}
+
+EMailAccountStore *
+e_mail_ui_session_get_account_store (EMailUISession *session)
+{
+ g_return_val_if_fail (E_IS_MAIL_UI_SESSION (session), NULL);
+
+ return session->priv->account_store;
+}
+
+CamelStore *
+e_mail_ui_session_get_vfolder_store (EMailUISession *session)
+{
+ g_return_val_if_fail (E_IS_MAIL_UI_SESSION (session), NULL);
+
+ return session->priv->vfolder_store;
+}
diff --git a/mail/e-mail-ui-session.h b/mail/e-mail-ui-session.h
index 44ca178..d6cb565 100644
--- a/mail/e-mail-ui-session.h
+++ b/mail/e-mail-ui-session.h
@@ -30,6 +30,8 @@
#include <camel/camel.h>
#include <libemail-engine/e-mail-session.h>
#include <libemail-engine/mail-folder-cache.h>
+#include <mail/e-mail-enums.h>
+#include <mail/e-mail-account-store.h>
/* Standard GObject macros */
#define E_TYPE_MAIL_UI_SESSION \
@@ -67,6 +69,11 @@ struct _EMailUISessionClass {
GType e_mail_ui_session_get_type (void);
EMailSession * e_mail_ui_session_new (void);
+CamelStore * e_mail_ui_session_get_vfolder_store
+ (EMailSession *session);
+EMailAccountStore *
+ e_mail_ui_session_get_account_store
+ (EMailSession *session);
G_END_DECLS
diff --git a/mail/em-account-editor.c b/mail/em-account-editor.c
index 9ec4d05..b7128f3 100644
--- a/mail/em-account-editor.c
+++ b/mail/em-account-editor.c
@@ -68,6 +68,7 @@
#include "mail-guess-servers.h"
#include "libemail-engine/mail-ops.h"
#include "libemail-utils/mail-mt.h"
+#include "e-mail-ui-session.h"
#if defined (HAVE_NSS) && defined (ENABLE_SMIME)
#include "smime/gui/e-cert-selector.h"
@@ -5218,7 +5219,7 @@ emae_commit (EConfig *ec,
service = camel_session_get_service (
CAMEL_SESSION (session), account->uid);
- store = e_mail_session_get_account_store (session);
+ store = e_mail_ui_session_get_account_store (session);
e_mail_account_store_set_default_service (store, service);
}
diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c
index 07cfbab..6ae8f28 100644
--- a/mail/em-folder-tree-model.c
+++ b/mail/em-folder-tree-model.c
@@ -49,6 +49,7 @@
#include "em-utils.h"
#include "em-folder-utils.h"
#include "em-event.h"
+#include "e-mail-ui-session.h"
#include "libemail-engine/e-mail-folder-utils.h"
#include "libemail-engine/e-mail-utils.h"
@@ -574,7 +575,7 @@ em_folder_tree_model_set_session (EMFolderTreeModel *model,
MailFolderCache *folder_cache;
folder_cache = e_mail_session_get_folder_cache (session);
- account_store = e_mail_session_get_account_store (session);
+ account_store = e_mail_ui_session_get_account_store (session);
/* Keep our own reference since we connect to its signals. */
g_warn_if_fail (model->priv->account_store == NULL);
diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c
index 49c6251..7e33d6b 100644
--- a/mail/mail-vfolder.c
+++ b/mail/mail-vfolder.c
@@ -49,6 +49,7 @@
#include "libemail-engine/mail-ops.h"
#include "libemail-engine/mail-tools.h"
#include "mail-vfolder.h"
+#include "e-mail-ui-session.h"
#define d(x) /* (printf("%s:%s: ", G_STRLOC, G_STRFUNC), (x))*/
@@ -1029,7 +1030,7 @@ vfolder_load_storage (EMailBackend *backend)
config_dir = mail_session_get_config_dir ();
session = e_mail_backend_get_session (backend);
- vfolder_store = e_mail_session_get_vfolder_store (session);
+ vfolder_store = e_mail_ui_session_get_vfolder_store (E_MAIL_UI_SESSION(session));
g_signal_connect (
vfolder_store, "folder-deleted",
diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c
index c84320f..0a2731e 100644
--- a/modules/mail/e-mail-shell-backend.c
+++ b/modules/mail/e-mail-shell-backend.c
@@ -58,6 +58,7 @@
#include "mail-send-recv.h"
#include "mail-vfolder.h"
#include "importers/mail-importer.h"
+#include "e-mail-ui-session.h"
#define E_MAIL_SHELL_BACKEND_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -469,7 +470,7 @@ mail_shell_backend_start (EShellBackend *shell_backend)
backend = E_MAIL_BACKEND (shell_backend);
session = e_mail_backend_get_session (backend);
- account_store = e_mail_session_get_account_store (session);
+ account_store = e_mail_ui_session_get_account_store (session);
enable_search_folders = e_shell_settings_get_boolean (
shell_settings, "mail-enable-search-folders");
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index 5de727e..c81f53b 100644
--- a/modules/mail/e-mail-shell-view-actions.c
+++ b/modules/mail/e-mail-shell-view-actions.c
@@ -99,7 +99,7 @@ action_mail_account_disable_cb (GtkAction *action,
backend = E_MAIL_BACKEND (shell_backend);
session = e_mail_backend_get_session (backend);
- account_store = e_mail_session_get_account_store (session);
+ account_store = e_mail_ui_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);
diff --git a/modules/mail/e-mail-shell-view-private.h b/modules/mail/e-mail-shell-view-private.h
index 97084e7..58892fa 100644
--- a/modules/mail/e-mail-shell-view-private.h
+++ b/modules/mail/e-mail-shell-view-private.h
@@ -40,21 +40,12 @@
#include "e-mail-label-action.h"
#include "e-mail-label-dialog.h"
#include "e-mail-label-list-store.h"
-<<<<<<< HEAD
-=======
-#include "libemail-engine/e-mail-local.h"
->>>>>>> Port Evolution to EDS's new mail library.
#include "e-mail-reader.h"
#include "e-mail-reader-utils.h"
#include "libemail-engine/e-mail-session.h"
#include "libemail-engine/e-mail-session-utils.h"
#include "e-mail-sidebar.h"
-<<<<<<< HEAD
-#include "e-mail-store-utils.h"
-=======
-#include "libemail-engine/e-mail-store.h"
#include "libemail-engine/e-mail-store-utils.h"
->>>>>>> Port Evolution to EDS's new mail library.
#include "em-composer-utils.h"
#include "em-folder-properties.h"
#include "em-folder-selector.h"
@@ -69,6 +60,7 @@
#include "libemail-engine/mail-tools.h"
#include "mail-vfolder.h"
#include "message-list.h"
+#include "e-mail-ui-session.h"
#include "e-mail-shell-backend.h"
#include "e-mail-shell-content.h"
diff --git a/modules/mail/em-account-prefs.c b/modules/mail/em-account-prefs.c
index 49d616f..befdeab 100644
--- a/modules/mail/em-account-prefs.c
+++ b/modules/mail/em-account-prefs.c
@@ -42,6 +42,7 @@
#include "mail-vfolder.h"
#include "shell/e-shell.h"
#include "capplet/settings/mail-capplet-shell.h"
+#include "e-mail-ui-session.h"
#define EM_ACCOUNT_PREFS_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -422,7 +423,7 @@ em_account_prefs_new (EPreferencesWindow *window)
shell_backend = e_shell_get_backend_by_name (shell, "mail");
session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend));
- account_store = e_mail_session_get_account_store (session);
+ account_store = e_mail_ui_session_get_account_store (session);
return g_object_new (
EM_TYPE_ACCOUNT_PREFS,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]