[evolution-data-server] Bug 725320 - [Camel] Let the store preconfigure settings the first time



commit 1be0d6f2127802c093c4f089b675ab283d4cd3d3
Author: Milan Crha <mcrha redhat com>
Date:   Fri Jan 22 17:10:03 2016 +0100

    Bug 725320 - [Camel] Let the store preconfigure settings the first time

 camel/camel-enums.h                       |    3 +-
 camel/camel-offline-store.c               |    2 +-
 camel/camel-store.c                       |  185 +++++++++++++++++++++++++
 camel/camel-store.h                       |   46 ++++++-
 camel/providers/imapx/camel-imapx-store.c |  210 ++++++++++++++++++++++++++++-
 docs/reference/camel/camel-sections.txt   |    3 +
 docs/reference/eds/eds-sections.txt       |    2 +
 libedataserver/e-source-mail-account.c    |   71 ++++++++++-
 libedataserver/e-source-mail-account.h    |    5 +
 9 files changed, 522 insertions(+), 5 deletions(-)
---
diff --git a/camel/camel-enums.h b/camel/camel-enums.h
index 022a482..5ca476f 100644
--- a/camel/camel-enums.h
+++ b/camel/camel-enums.h
@@ -410,7 +410,8 @@ typedef enum { /*< flags >*/
        CAMEL_STORE_REAL_JUNK_FOLDER = 1 << 4,
        CAMEL_STORE_CAN_EDIT_FOLDERS = 1 << 5,
        CAMEL_STORE_USE_CACHE_DIR = 1 << 6,
-       CAMEL_STORE_CAN_DELETE_FOLDERS_AT_ONCE = 1 << 7
+       CAMEL_STORE_CAN_DELETE_FOLDERS_AT_ONCE = 1 << 7,
+       CAMEL_STORE_SUPPORTS_INITIAL_SETUP = 1 << 8
 } CamelStoreFlags;
 
 /**
diff --git a/camel/camel-offline-store.c b/camel/camel-offline-store.c
index edec1ab..0965c76 100644
--- a/camel/camel-offline-store.c
+++ b/camel/camel-offline-store.c
@@ -180,7 +180,7 @@ camel_offline_store_set_online_sync (CamelOfflineStore *store,
 
        g_return_val_if_fail (CAMEL_IS_OFFLINE_STORE (store), FALSE);
 
-       if (store->priv->online == online)
+       if (camel_offline_store_get_online (store) == online)
                return TRUE;
 
        service = CAMEL_SERVICE (store);
diff --git a/camel/camel-store.c b/camel/camel-store.c
index 1912081..fe42ad9 100644
--- a/camel/camel-store.c
+++ b/camel/camel-store.c
@@ -63,6 +63,7 @@ struct _AsyncContext {
        gchar *folder_name_2;
        gboolean expunge;
        guint32 flags;
+       GHashTable *save_setup;
 };
 
 struct _SignalClosure {
@@ -95,6 +96,11 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (
 static void
 async_context_free (AsyncContext *async_context)
 {
+       if (async_context->save_setup) {
+               g_hash_table_destroy (async_context->save_setup);
+               async_context->save_setup = NULL;
+       }
+
        g_free (async_context->folder_name_1);
        g_free (async_context->folder_name_2);
 
@@ -510,6 +516,15 @@ store_synchronize_sync (CamelStore *store,
 }
 
 static gboolean
+store_initial_setup_sync (CamelStore *store,
+                         GHashTable *out_save_setup,
+                         GCancellable *cancellable,
+                         GError **error)
+{
+       return TRUE;
+}
+
+static gboolean
 store_initable_init (GInitable *initable,
                      GCancellable *cancellable,
                      GError **error)
@@ -579,6 +594,7 @@ camel_store_class_init (CamelStoreClass *class)
        class->get_junk_folder_sync = store_get_junk_folder_sync;
        class->get_trash_folder_sync = store_get_trash_folder_sync;
        class->synchronize_sync = store_synchronize_sync;
+       class->initial_setup_sync = store_initial_setup_sync;
 
        signals[FOLDER_CREATED] = g_signal_new (
                "folder-created",
@@ -2919,6 +2935,175 @@ camel_store_synchronize_finish (CamelStore *store,
 }
 
 /**
+ * camel_store_initial_setup_sync:
+ * @store: a #CamelStore
+ * @out_save_setup: (out) (transfer container) (element-type utf8 utf8): setup values to save
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Runs initial setup for the @store. It's meant to preset some
+ * values the first time the account connects to the server after
+ * it had been created. The function should return %TRUE even if
+ * it didn't populate anything. The default implementation does
+ * just that.
+ *
+ * The save_setup result, if not %NULL, should be freed using
+ * g_hash_table_destroy(). It's not an error to have it %NULL,
+ * it only means the @store doesn't have anything to save.
+ * Both the key and the value in the hash are newly allocated
+ * UTF-8 strings, owned by the hash table.
+ *
+ * The @store advertises support of this function by including
+ * CAMEL_STORE_SUPPORTS_INITIAL_SETUP in CamelStore::flags.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 3.20
+ **/
+gboolean
+camel_store_initial_setup_sync (CamelStore *store,
+                               GHashTable **out_save_setup,
+                               GCancellable *cancellable,
+                               GError **error)
+{
+       GHashTable *save_setup;
+       CamelStoreClass *class;
+       gboolean success;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (out_save_setup != NULL, FALSE);
+
+       *out_save_setup = NULL;
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->initial_setup_sync != NULL, FALSE);
+
+       save_setup = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+       success = class->initial_setup_sync (store, save_setup, cancellable, error);
+
+       if (!success || !g_hash_table_size (save_setup)) {
+               g_hash_table_destroy (save_setup);
+               save_setup = NULL;
+       }
+
+       CAMEL_CHECK_GERROR (store, initial_setup_sync, success, error);
+
+       *out_save_setup = save_setup;
+
+       return success;
+}
+
+static void
+store_initial_setup_thread (GTask *task,
+                           gpointer source_object,
+                           gpointer task_data,
+                           GCancellable *cancellable)
+{
+       gboolean success;
+       AsyncContext *async_context;
+       GError *local_error = NULL;
+
+       async_context = (AsyncContext *) task_data;
+
+       success = camel_store_initial_setup_sync (
+               CAMEL_STORE (source_object),
+               &async_context->save_setup,
+               cancellable, &local_error);
+
+       if (local_error != NULL) {
+               g_task_return_error (task, local_error);
+       } else {
+               g_task_return_boolean (task, success);
+       }
+}
+
+/**
+ * camel_store_initial_setup:
+ * @store: a #CamelStore
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Runs initial setup for the @store asynchronously.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call camel_store_initial_setup_finish() to get the result of the operation.
+ *
+ * The @store advertises support of this function by including
+ * CAMEL_STORE_SUPPORTS_INITIAL_SETUP in CamelStore::flags.
+ *
+ * Since: 3.20
+ **/
+void
+camel_store_initial_setup (CamelStore *store,
+                          gint io_priority,
+                          GCancellable *cancellable,
+                          GAsyncReadyCallback callback,
+                          gpointer user_data)
+{
+       GTask *task;
+       AsyncContext *async_context;
+
+       g_return_if_fail (CAMEL_IS_STORE (store));
+
+       async_context = g_slice_new0 (AsyncContext);
+
+       task = g_task_new (store, cancellable, callback, user_data);
+       g_task_set_source_tag (task, camel_store_initial_setup);
+       g_task_set_priority (task, io_priority);
+
+       g_task_set_task_data (
+               task, async_context,
+               (GDestroyNotify) async_context_free);
+
+       g_task_run_in_thread (task, store_initial_setup_thread);
+
+       g_object_unref (task);
+}
+
+/**
+ * camel_store_initial_setup_finish:
+ * @store: a #CamelStore
+ * @result: a #GAsyncResult
+ * @out_save_setup: (out) (transfer container) (element-type utf8 utf8): setup values to save
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_store_initial_setup().
+ *
+ * The save_setup result, if not %NULL, should be freed using
+ * g_hash_table_destroy(). It's not an error to have it %NULL,
+ * it only means the @store doesn't have anything to save.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 3.20
+ **/
+gboolean
+camel_store_initial_setup_finish (CamelStore *store,
+                                 GAsyncResult *result,
+                                 GHashTable **out_save_setup,
+                                 GError **error)
+{
+       AsyncContext *async_context;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (out_save_setup != NULL, FALSE);
+       g_return_val_if_fail (g_task_is_valid (result, store), FALSE);
+
+       g_return_val_if_fail (
+               g_async_result_is_tagged (
+               result, camel_store_initial_setup), FALSE);
+
+       async_context = g_task_get_task_data (G_TASK (result));
+       *out_save_setup = async_context->save_setup;
+       async_context->save_setup = NULL;
+
+       return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+/**
  * camel_store_maybe_run_db_maintenance:
  * @store: a #CamelStore instance
  * @error: (allow-none): return location for a #GError, or %NULL
diff --git a/camel/camel-store.h b/camel/camel-store.h
index 028ce28..570f08c 100644
--- a/camel/camel-store.h
+++ b/camel/camel-store.h
@@ -61,6 +61,32 @@
 #define CAMEL_STORE_ERROR \
        (camel_store_error_quark ())
 
+/**
+ * @CAMEL_STORE_SETUP_ARCHIVE_FOLDER: Name of an Archive folder key
+ * @CAMEL_STORE_SETUP_DRAFTS_FOLDER: Name of a Drafts folder key
+ * @CAMEL_STORE_SETUP_SENT_FOLDER: Name of a Sent folder key
+ * @CAMEL_STORE_SETUP_TEMPLATES_FOLDER: Name of a Templates folder key
+ *
+ * Key names to a hash table with values to preset for the account used
+ * as in the camel_store_initial_setup_sync() function.
+ *
+ * The key name consists of up to four parts: Source:Extension:Property[:Type]
+ * Source can be 'Collection', 'Account', 'Submission', 'Transport', 'Backend'.
+ * Extension is any extension name; it's up to the key creator to make sure
+ * the extension belongs to that particular Source.
+ * Property is a property name in the Extension.
+ * Type is an optional letter describing the type of the value; if not set, then
+ * string is used. Available values are: 'b' for boolean, 'i' for integer,
+ * 's' for string, 'f' for folder full path.
+ * All the part values are case sensitive.
+ *
+ * Since: 3.20
+ **/
+#define CAMEL_STORE_SETUP_ARCHIVE_FOLDER       "Account:Mail Account:archive-folder:f"
+#define CAMEL_STORE_SETUP_DRAFTS_FOLDER                "Submission:Mail Composition:drafts-folder:f"
+#define CAMEL_STORE_SETUP_SENT_FOLDER          "Submission:Mail Submission:sent-folder:f"
+#define CAMEL_STORE_SETUP_TEMPLATES_FOLDER     "Submission:Mail Composition:templates-folder:f"
+
 G_BEGIN_DECLS
 
 /**
@@ -176,9 +202,13 @@ struct _CamelStoreClass {
                                                 gboolean expunge,
                                                 GCancellable *cancellable,
                                                 GError **error);
+       gboolean        (*initial_setup_sync)   (CamelStore *store,
+                                                GHashTable *save_setup,
+                                                GCancellable *cancellable,
+                                                GError **error);
 
        /* Reserved slots for methods. */
-       gpointer reserved_for_methods[21];
+       gpointer reserved_for_methods[20];
 
        /* Signals */
        void            (*folder_created)       (CamelStore *store,
@@ -355,6 +385,20 @@ void               camel_store_synchronize         (CamelStore *store,
 gboolean       camel_store_synchronize_finish  (CamelStore *store,
                                                 GAsyncResult *result,
                                                 GError **error);
+gboolean       camel_store_initial_setup_sync  (CamelStore *store,
+                                                GHashTable **out_save_setup,
+                                                GCancellable *cancellable,
+                                                GError **error);
+void           camel_store_initial_setup       (CamelStore *store,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_store_initial_setup_finish
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GHashTable **out_save_setup,
+                                                GError **error);
 gboolean       camel_store_maybe_run_db_maintenance
                                                (CamelStore *store,
                                                 GError **error);
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index 148d53b..28d1a75 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -2230,6 +2230,213 @@ exit:
        return success;
 }
 
+static gchar *
+imapx_find_folder_for_initial_setup (CamelFolderInfo *root,
+                                    const gchar *path)
+{
+       CamelFolderInfo *finfo, *next;
+       gchar *folder_fullname = NULL;
+       gchar **path_parts;
+       gint ii;
+
+       if (!root || !path)
+               return NULL;
+
+       path_parts = g_strsplit (path, "/", -1);
+       if (!path_parts)
+               return NULL;
+
+       finfo = root;
+
+       for (ii = 0; path_parts[ii] && finfo; ii++) {
+               gchar *folded_path;
+
+               folded_path = g_utf8_casefold (path_parts[ii], -1);
+               if (!folded_path)
+                       break;
+
+               for (next = NULL; finfo; finfo = finfo->next) {
+                       gchar *folded_display_name;
+                       gint cmp;
+
+                       if ((finfo->flags & (CAMEL_FOLDER_NOSELECT | CAMEL_FOLDER_VIRTUAL)) != 0)
+                               continue;
+
+                       folded_display_name = g_utf8_casefold (finfo->display_name, -1);
+                       if (!folded_display_name)
+                               continue;
+
+                       cmp = g_utf8_collate (folded_path, folded_display_name);
+
+                       g_free (folded_display_name);
+
+                       if (cmp == 0) {
+                               next = finfo;
+                               break;
+                       }
+               }
+
+               g_free (folded_path);
+
+               finfo = next;
+               if (finfo) {
+                       if (path_parts[ii + 1])
+                               finfo = finfo->child;
+                       else
+                               folder_fullname = g_strdup (finfo->full_name);
+               }
+       }
+
+       g_strfreev (path_parts);
+
+       return folder_fullname;
+}
+
+static void
+imapx_check_initial_setup_group (CamelFolderInfo *finfo,
+                                GHashTable *save_setup,
+                                const gchar *main_key,
+                                const gchar *additional_key,
+                                const gchar *additional_key_value,
+                                const gchar **names,
+                                guint n_names)
+{
+       gchar *folder_fullname = NULL;
+       gint ii;
+
+       g_return_if_fail (finfo != NULL);
+       g_return_if_fail (save_setup != NULL);
+       g_return_if_fail (main_key != NULL);
+       g_return_if_fail (names != NULL);
+       g_return_if_fail (n_names > 0);
+
+       /* First check the folder names in the user's locale */
+       for (ii = 0; ii < n_names && !folder_fullname; ii++) {
+               gchar *name;
+
+               /* In the same level as the Inbox */
+               folder_fullname = imapx_find_folder_for_initial_setup (finfo, g_dpgettext2 (GETTEXT_PACKAGE, 
"IMAPDefaults", names[ii]));
+
+               if (folder_fullname)
+                       break;
+
+               /* as a subfolder of the Inbox */
+               name = g_strconcat ("INBOX/", g_dpgettext2 (GETTEXT_PACKAGE, "IMAPDefaults", names[ii]), 
NULL);
+               folder_fullname = imapx_find_folder_for_initial_setup (finfo, name);
+               g_free (name);
+       }
+
+       /* Then repeat with the english name (as written in the code) */
+       for (ii = 0; ii < n_names && !folder_fullname; ii++) {
+               gchar *name;
+
+               /* Do not try the same folder name twice */
+               if (g_strcmp0 (g_dpgettext2 (GETTEXT_PACKAGE, "IMAPDefaults", names[ii]), names[ii]) == 0)
+                       continue;
+
+               folder_fullname = imapx_find_folder_for_initial_setup (finfo, names[ii]);
+
+               if (folder_fullname)
+                       break;
+
+               name = g_strconcat ("INBOX/", names[ii], NULL);
+               folder_fullname = imapx_find_folder_for_initial_setup (finfo, name);
+               g_free (name);
+       }
+
+       if (folder_fullname) {
+               g_hash_table_insert (save_setup,
+                       g_strdup (main_key),
+                       g_strdup (folder_fullname));
+
+               if (additional_key) {
+                       g_hash_table_insert (save_setup,
+                               g_strdup (additional_key),
+                               g_strdup (additional_key_value));
+               }
+
+               g_free (folder_fullname);
+       }
+}
+
+static gboolean
+imapx_initial_setup_sync (CamelStore *store,
+                         GHashTable *save_setup,
+                         GCancellable *cancellable,
+                         GError **error)
+{
+       /* Translators: The strings in "IMAPDefaults" context are folder names as can be presented
+          by the server; There's checked for the localized version of it and for the non-localized
+          version as well. It's always the folder name (eventually path) as provided by the server,
+          when returned in given localization. it can be checked semi-easily in the case of
+          the GMail variants, by changing the GMail interface language in the GMail Preferences. */
+       const gchar *draft_names[] = {
+               NC_("IMAPDefaults", "[Gmail]/Drafts"),
+               NC_("IMAPDefaults", "Drafts"),
+               NC_("IMAPDefaults", "Draft")
+       };
+       const gchar *sent_names[] = {
+               NC_("IMAPDefaults", "[Gmail]/Sent Mail"),
+               NC_("IMAPDefaults", "Sent"),
+               NC_("IMAPDefaults", "Sent Items")
+       };
+       const gchar *junk_names[] = {
+               NC_("IMAPDefaults", "[Gmail]/Spam"),
+               NC_("IMAPDefaults", "Junk"),
+               NC_("IMAPDefaults", "Junk E-mail"),
+               NC_("IMAPDefaults", "Junk Email"),
+               NC_("IMAPDefaults", "Spam"),
+               NC_("IMAPDefaults", "Bulk Mail")
+       };
+       const gchar *trash_names[] = {
+               NC_("IMAPDefaults", "[Gmail]/Trash"),
+               NC_("IMAPDefaults", "Trash"),
+               NC_("IMAPDefaults", "Deleted Items")
+       };
+       CamelFolderInfo *finfo;
+       GError *local_error = NULL;
+
+       g_return_val_if_fail (CAMEL_IS_IMAPX_STORE (store), FALSE);
+       g_return_val_if_fail (save_setup != NULL, FALSE);
+
+       finfo = camel_store_get_folder_info_sync (store, NULL,
+               CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL,
+               cancellable, &local_error);
+
+       if (!finfo) {
+               if (local_error) {
+                       g_propagate_error (error, local_error);
+                       return FALSE;
+               }
+
+               return TRUE;
+       }
+
+       imapx_check_initial_setup_group (finfo, save_setup,
+               CAMEL_STORE_SETUP_DRAFTS_FOLDER, NULL, NULL,
+               draft_names, G_N_ELEMENTS (draft_names));
+
+       imapx_check_initial_setup_group (finfo, save_setup,
+               CAMEL_STORE_SETUP_SENT_FOLDER, NULL, NULL,
+               sent_names, G_N_ELEMENTS (sent_names));
+
+       /* It's a folder path inside the account, thus not use the 'f' type, but the 's' type. */
+       imapx_check_initial_setup_group (finfo, save_setup,
+               "Backend:Imapx Backend:real-junk-path:s",
+               "Backend:Imapx Backend:use-real-junk-path:b", "true",
+               junk_names, G_N_ELEMENTS (junk_names));
+
+       /* It's a folder path inside the account, thus not use the 'f' type, but the 's' type. */
+       imapx_check_initial_setup_group (finfo, save_setup,
+               "Backend:Imapx Backend:real-trash-path:s",
+               "Backend:Imapx Backend:use-real-trash-path:b", "true",
+               trash_names, G_N_ELEMENTS (trash_names));
+
+       camel_folder_info_free (finfo);
+
+       return TRUE;
+}
+
 static void
 imapx_migrate_to_user_cache_dir (CamelService *service)
 {
@@ -2273,7 +2480,7 @@ imapx_store_initable_init (GInitable *initable,
        store = CAMEL_STORE (initable);
        service = CAMEL_SERVICE (initable);
 
-       store->flags |= CAMEL_STORE_USE_CACHE_DIR;
+       store->flags |= CAMEL_STORE_USE_CACHE_DIR | CAMEL_STORE_SUPPORTS_INITIAL_SETUP;
        imapx_migrate_to_user_cache_dir (service);
 
        /* Chain up to parent interface's init() method. */
@@ -2580,6 +2787,7 @@ camel_imapx_store_class_init (CamelIMAPXStoreClass *class)
        store_class->create_folder_sync = imapx_store_create_folder_sync;
        store_class->delete_folder_sync = imapx_store_delete_folder_sync;
        store_class->rename_folder_sync = imapx_store_rename_folder_sync;
+       store_class->initial_setup_sync = imapx_initial_setup_sync;
 
        class->mailbox_created = imapx_store_mailbox_created;
        class->mailbox_renamed = imapx_store_mailbox_renamed;
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index 7125a8f..e663a3a 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -2133,6 +2133,9 @@ camel_store_rename_folder_finish
 camel_store_synchronize_sync
 camel_store_synchronize
 camel_store_synchronize_finish
+camel_store_initial_setup_sync
+camel_store_initial_setup
+camel_store_initial_setup_finish
 camel_store_maybe_run_db_maintenance
 <SUBSECTION Standard>
 CAMEL_STORE
diff --git a/docs/reference/eds/eds-sections.txt b/docs/reference/eds/eds-sections.txt
index 7e5d611..1733133 100644
--- a/docs/reference/eds/eds-sections.txt
+++ b/docs/reference/eds/eds-sections.txt
@@ -3416,6 +3416,8 @@ e_source_mail_account_set_identity_uid
 e_source_mail_account_dup_archive_folder
 e_source_mail_account_get_archive_folder
 e_source_mail_account_set_archive_folder
+e_source_mail_account_get_needs_initial_setup
+e_source_mail_account_set_needs_initial_setup
 <SUBSECTION Standard>
 ESourceMailAccountPrivate
 E_IS_SOURCE_MAIL_ACCOUNT
diff --git a/libedataserver/e-source-mail-account.c b/libedataserver/e-source-mail-account.c
index 1e0dce7..7679043 100644
--- a/libedataserver/e-source-mail-account.c
+++ b/libedataserver/e-source-mail-account.c
@@ -47,12 +47,14 @@
 struct _ESourceMailAccountPrivate {
        gchar *identity_uid;
        gchar *archive_folder;
+       gboolean needs_initial_setup;
 };
 
 enum {
        PROP_0,
        PROP_IDENTITY_UID,
-       PROP_ARCHIVE_FOLDER
+       PROP_ARCHIVE_FOLDER,
+       PROP_NEEDS_INITIAL_SETUP
 };
 
 G_DEFINE_TYPE (
@@ -78,6 +80,12 @@ source_mail_account_set_property (GObject *object,
                                E_SOURCE_MAIL_ACCOUNT (object),
                                g_value_get_string (value));
                        return;
+
+               case PROP_NEEDS_INITIAL_SETUP:
+                       e_source_mail_account_set_needs_initial_setup (
+                               E_SOURCE_MAIL_ACCOUNT (object),
+                               g_value_get_boolean (value));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -103,6 +111,13 @@ source_mail_account_get_property (GObject *object,
                                e_source_mail_account_dup_archive_folder (
                                E_SOURCE_MAIL_ACCOUNT (object)));
                        return;
+
+               case PROP_NEEDS_INITIAL_SETUP:
+                       g_value_set_boolean (
+                               value,
+                               e_source_mail_account_get_needs_initial_setup (
+                               E_SOURCE_MAIL_ACCOUNT (object)));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -163,6 +178,19 @@ e_source_mail_account_class_init (ESourceMailAccountClass *class)
                        G_PARAM_CONSTRUCT |
                        G_PARAM_STATIC_STRINGS |
                        E_SOURCE_PARAM_SETTING));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_NEEDS_INITIAL_SETUP,
+               g_param_spec_boolean (
+                       "needs-initial-setup",
+                       "Needs Initial Setup",
+                       "Whether the account needs to do an initial setup",
+                       TRUE,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_STATIC_STRINGS |
+                       E_SOURCE_PARAM_SETTING));
 }
 
 static void
@@ -336,3 +364,44 @@ e_source_mail_account_set_archive_folder (ESourceMailAccount *extension,
 
        g_object_notify (G_OBJECT (extension), "archive-folder");
 }
+
+/**
+ * e_source_mail_account_get_needs_initial_setup:
+ * @extension: an #ESourceMailAccount
+ *
+ * Check whether the mail account needs to do its initial setup.
+ *
+ * Returns: %TRUE, when the account needs to run its initial setup
+ *
+ * Since: 3.20
+ **/
+gboolean
+e_source_mail_account_get_needs_initial_setup (ESourceMailAccount *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_MAIL_ACCOUNT (extension), FALSE);
+
+       return extension->priv->needs_initial_setup;
+}
+
+/**
+ * e_source_mail_account_set_needs_initial_setup:
+ * @extension: an #ESourceMailAccount
+ * @needs_initial_setup: value to set
+ *
+ * Sets whether the account needs to run its initial setup.
+ *
+ * Since: 3.20
+ **/
+void
+e_source_mail_account_set_needs_initial_setup (ESourceMailAccount *extension,
+                                              gboolean needs_initial_setup)
+{
+       g_return_if_fail (E_IS_SOURCE_MAIL_ACCOUNT (extension));
+
+       if ((extension->priv->needs_initial_setup ? 1 : 0) == (needs_initial_setup ? 1 : 0))
+               return;
+
+       extension->priv->needs_initial_setup = needs_initial_setup;
+
+       g_object_notify (G_OBJECT (extension), "needs-initial-setup");
+}
diff --git a/libedataserver/e-source-mail-account.h b/libedataserver/e-source-mail-account.h
index 4095b28..e89e467 100644
--- a/libedataserver/e-source-mail-account.h
+++ b/libedataserver/e-source-mail-account.h
@@ -92,6 +92,11 @@ gchar *              e_source_mail_account_dup_archive_folder
 void           e_source_mail_account_set_archive_folder
                                        (ESourceMailAccount *extension,
                                         const gchar *archive_folder);
+gboolean       e_source_mail_account_get_needs_initial_setup
+                                       (ESourceMailAccount *extension);
+void           e_source_mail_account_set_needs_initial_setup
+                                       (ESourceMailAccount *extension,
+                                        gboolean needs_initial_setup);
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]