X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fmodest-tny-local-folders-account.c;h=3410305464cfb19200620dfca1c07f9e3a446fb0;hp=1ef8ef0e28fc5187d14ae57d3aa3dacd4f599bf9;hb=12a672c559d983c4e49a7e4054ee14c0177ecb1c;hpb=b994012b9333d384da0ea9af77713cd1852b5b85 diff --git a/src/modest-tny-local-folders-account.c b/src/modest-tny-local-folders-account.c index 1ef8ef0..3410305 100644 --- a/src/modest-tny-local-folders-account.c +++ b/src/modest-tny-local-folders-account.c @@ -28,17 +28,18 @@ */ +#include +#include #include #include - +#include #include #include #include +#include #include #include - -#include -#include +#include G_DEFINE_TYPE (ModestTnyLocalFoldersAccount, modest_tny_local_folders_account, @@ -51,74 +52,70 @@ typedef struct _ModestTnyLocalFoldersAccountPrivate ModestTnyLocalFoldersAccount struct _ModestTnyLocalFoldersAccountPrivate { - GSList *list_extra_folders; + TnyMergeFolder *outbox_folder; }; -static void -modest_tny_local_folders_account_dispose (GObject *object) -{ - if (G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->dispose) - G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->dispose (object); -} +static void get_folders (TnyFolderStore *self, + TnyList *list, + TnyFolderStoreQuery *query, + gboolean refresh, + GError **err); +static TnyFolder* create_folder (TnyFolderStore *self, + const gchar *name, + GError **err); -static void -modest_tny_local_folders_account_remove_all_extra_folders (ModestTnyLocalFoldersAccount *store) -{ - ModestTnyLocalFoldersAccountPrivate *priv = - TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (store); - - GSList *iter = priv->list_extra_folders; - while (iter) - { - TnyFolder *folder = (TnyFolder*)iter->data; - if (folder) { - g_object_unref (folder); - iter->data = NULL; - } - - iter = g_slist_next (iter); - } - - g_slist_free (priv->list_extra_folders); - priv->list_extra_folders = NULL; -} +enum { + OUTBOX_DELETED_SIGNAL, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; static void modest_tny_local_folders_account_finalize (GObject *object) { - G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->finalize (object); - - ModestTnyLocalFoldersAccount *self = - MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (object); - - modest_tny_local_folders_account_remove_all_extra_folders (self); -} - -static void -get_folders (TnyFolderStore *self, TnyList *list, TnyFolderStoreQuery *query, GError **err); + ModestTnyLocalFoldersAccountPrivate *priv; -static void -get_folders_async (TnyFolderStore *self, TnyList *list, TnyGetFoldersCallback callback, TnyFolderStoreQuery *query, TnyStatusCallback status_callback, gpointer user_data); + priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (object); + if (priv->outbox_folder) { + g_object_unref (priv->outbox_folder); + priv->outbox_folder = NULL; + } + G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->finalize (object); +} static void modest_tny_local_folders_account_class_init (ModestTnyLocalFoldersAccountClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - + g_type_class_add_private (klass, sizeof (ModestTnyLocalFoldersAccountPrivate)); - - object_class->dispose = modest_tny_local_folders_account_dispose; + object_class->finalize = modest_tny_local_folders_account_finalize; - + + /* Signals */ + + /* Note that this signal is removed before unsetting my own + reference to outbox, this means that by the time of this + call, modest_tny_local_folders_account_get_merged_outbox is + still valid. The reason is that the listeners of the signal + might want to do something with the outbox instance */ + signals[OUTBOX_DELETED_SIGNAL] = g_signal_new + ("outbox-deleted", MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET + (ModestTnyLocalFoldersAccountClass, outbox_deleted), NULL, + NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /* Override virtual functions from the parent class: */ - TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->get_folders_func = get_folders; - TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->get_folders_async_func = get_folders_async; + TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->get_folders = get_folders; + TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->create_folder = create_folder; } static void modest_tny_local_folders_account_init (ModestTnyLocalFoldersAccount *self) { + /* Do nothing */ } ModestTnyLocalFoldersAccount* @@ -127,128 +124,200 @@ modest_tny_local_folders_account_new (void) return g_object_new (MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, NULL); } -void -modest_tny_local_folders_account_add_extra_folder (ModestTnyLocalFoldersAccount *store, - TnyFolder *folder) +/**********************************************************/ +/* TnyCamelStoreAccount functions redefinitions */ +/**********************************************************/ +static gboolean +modest_tny_local_folders_account_query_passes (TnyFolderStoreQuery *query, TnyFolder *folder) { - ModestTnyLocalFoldersAccountPrivate *priv = - TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (store); - - /* Check that it isn't already in the list: */ - GSList *exists = g_slist_find (priv->list_extra_folders, folder); - if (exists) - return; - - /* Add it: */ - /* The reference is released in finalize: */ - priv->list_extra_folders = g_slist_append (priv->list_extra_folders, folder); - g_object_ref (folder); + gboolean retval = FALSE; + + if (query && (tny_list_get_length (tny_folder_store_query_get_items (query)) > 0)) { + TnyList *items = tny_folder_store_query_get_items (query); + TnyIterator *iterator; + iterator = tny_list_create_iterator (items); + + while (!tny_iterator_is_done (iterator)) + { + TnyFolderStoreQueryItem *item = (TnyFolderStoreQueryItem*) tny_iterator_get_current (iterator); + if (item) { + TnyFolderStoreQueryOption options = tny_folder_store_query_item_get_options (item); + const regex_t *regex = tny_folder_store_query_item_get_regex (item); + + if ((options & TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED) && + tny_folder_is_subscribed (folder)) + retval = TRUE; + + if ((options & TNY_FOLDER_STORE_QUERY_OPTION_UNSUBSCRIBED) && + !(tny_folder_is_subscribed (folder))) + retval = TRUE; + + if (regex && options & TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_NAME) + if (regexec (regex, tny_folder_get_name (folder), 0, NULL, 0) == 0) + retval = TRUE; + + if (regex && options & TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_ID) + if (regexec (regex, tny_folder_get_id (folder), 0, NULL, 0) == 0) + retval = TRUE; + + g_object_unref (G_OBJECT (item)); + } + + tny_iterator_next (iterator); + } + + g_object_unref (G_OBJECT (iterator)); + g_object_unref (G_OBJECT (items)); + } else + retval = TRUE; + + return retval; } static void -get_folders (TnyFolderStore *self, TnyList *list, TnyFolderStoreQuery *query, GError **err) +get_folders (TnyFolderStore *self, + TnyList *list, + TnyFolderStoreQuery *query, + gboolean refresh, + GError **err) { - ModestTnyLocalFoldersAccountPrivate *priv = - TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self); - + TnyCamelStoreAccountClass *parent_class; + ModestTnyLocalFoldersAccountPrivate *priv; + /* Call the base class implementation: */ - TnyCamelStoreAccountClass *parent_class = g_type_class_peek_parent ( - MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self)); - parent_class->get_folders_func (self, list, query, err); + parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self)); + parent_class->get_folders (self, list, query, refresh, err); - /* Add our extra folders: */ - GSList *iter = priv->list_extra_folders; - while (iter) - { - TnyFolder *folder = TNY_FOLDER (iter->data); - if (folder) - tny_list_append (list, G_OBJECT (folder)); - - iter = g_slist_next (iter); - } + /* Add our extra folder only if it passes the query */ + priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self); + + if (priv->outbox_folder && + modest_tny_local_folders_account_query_passes (query, TNY_FOLDER (priv->outbox_folder))) + tny_list_prepend (list, G_OBJECT (priv->outbox_folder)); } -static void -get_folders_async (TnyFolderStore *self, TnyList *list, TnyGetFoldersCallback callback, TnyFolderStoreQuery *query, TnyStatusCallback status_callback, gpointer user_data) +static TnyFolder* +create_folder (TnyFolderStore *self, + const gchar *name, + GError **err) { + TnyCamelStoreAccountClass *parent_class; + + parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self)); + + /* If the folder name is been used by our extra folders */ + if (modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (self), name)) { + g_set_error (err, TNY_ERROR_DOMAIN, + TNY_SERVICE_ERROR_FOLDER_CREATE, + "Folder name already in use"); + return NULL; + } + /* Call the base class implementation: */ - TnyCamelStoreAccountClass *parent_class = g_type_class_peek_parent ( - MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self)); - parent_class->get_folders_async_func (self, list, callback, query, status_callback, user_data); + return parent_class->create_folder (self, name, err); } -static void -add_account_folders_to_merged_folder (TnyAccount *account, TnyMergeFolder* merge_folder) +/*****************************/ +/* Public methods */ +/*****************************/ +gboolean +modest_tny_local_folders_account_folder_name_in_use (ModestTnyLocalFoldersAccount *self, + const gchar *name) { - const gchar* account_id = tny_account_get_id (account); - const gboolean is_actual_local_folders_account = account_id && - (strcmp (account_id, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0); - - TnyList *list_outbox_folders = tny_simple_list_new (); - tny_folder_store_get_folders (TNY_FOLDER_STORE (account), - list_outbox_folders, NULL, NULL); - - TnyIterator* iter = tny_list_create_iterator (list_outbox_folders); - while (!tny_iterator_is_done (iter)) - { - TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (iter)); - - if (folder) { - gboolean add = TRUE; - /* TODO: Do not add outboxes that are inside local-folders/, - * because these are just left-over from earlier Modest versions - * that put the outbox there: */ - if (is_actual_local_folders_account) { - const TnyFolderType type = modest_tny_folder_get_local_folder_type (folder); - if (type == TNY_FOLDER_TYPE_OUTBOX) { - add = FALSE; - } + ModestTnyLocalFoldersAccountPrivate *priv; + gchar *down_name; + const gchar *type_name; + gboolean retval; + + /* Check that we're not trying to create/rename any folder + with the same name that our OUTBOX, DRAFT, SENT */ + priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self); + down_name = g_utf8_strdown (name, strlen (name)); + + type_name = modest_local_folder_info_get_type_name (TNY_FOLDER_TYPE_OUTBOX); + if (!strcmp (type_name, down_name)) { + retval = TRUE; + } else { + type_name = modest_local_folder_info_get_type_name (TNY_FOLDER_TYPE_DRAFTS); + if (!strcmp (type_name, down_name)) { + retval = TRUE; + } else { + type_name = modest_local_folder_info_get_type_name (TNY_FOLDER_TYPE_SENT); + if (!strcmp (type_name, down_name)) { + retval = TRUE; + } else { + retval = FALSE; } - - if (add) - tny_merge_folder_add_folder (merge_folder, folder); - - g_object_unref (folder); } - - tny_iterator_next (iter); } - - g_object_unref (list_outbox_folders); + g_free (down_name); + + return retval; } -void modest_tny_local_folders_account_add_merged_outbox_folders (ModestTnyLocalFoldersAccount *self, - GSList *accounts) +void +modest_tny_local_folders_account_add_folder_to_outbox (ModestTnyLocalFoldersAccount *self, + TnyFolder *per_account_outbox) { - modest_tny_local_folders_account_remove_all_extra_folders (self); - - /* All per-account outbox folders are merged into one folders - * so that they appear as one outbox to the user: */ - TnyMergeFolder *merged_outbox = TNY_MERGE_FOLDER (tny_merge_folder_new()); - - GSList *iter = accounts; - while (iter) - { - TnyAccount *account = TNY_ACCOUNT (iter->data); - if (account) { - /* Add both outbox account and local-folders account folders - * to our one combined account: - */ - if (MODEST_IS_TNY_OUTBOX_ACCOUNT (account)) { - /* Add the folder to the merged folder. - * We will add it later to the virtual local-folders store: */ - add_account_folders_to_merged_folder (account, merged_outbox); - } - } - - iter = g_slist_next (iter); + ModestTnyLocalFoldersAccountPrivate *priv; + + g_return_if_fail (MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self)); + g_return_if_fail (TNY_IS_FOLDER (per_account_outbox)); + + priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self); + + /* Create on-demand */ + if (!priv->outbox_folder) { + priv->outbox_folder = (TnyMergeFolder *) + tny_merge_folder_new_with_ui_locker (_("mcen_me_folder_outbox"), + tny_gtk_lockable_new ()); + /* Set type to outbox */ + tny_merge_folder_set_folder_type (priv->outbox_folder, + TNY_FOLDER_TYPE_OUTBOX); } - - /* Add the merged outbox folder to the virtual local-folders store: */ - printf ("Debug: %s: adding merged outbox.\n", __FUNCTION__); - modest_tny_local_folders_account_add_extra_folder (self, TNY_FOLDER(merged_outbox)); - g_object_unref (merged_outbox); - merged_outbox = NULL; + + /* Add outbox to the global OUTBOX folder */ + tny_merge_folder_add_folder (priv->outbox_folder, per_account_outbox); +} + +void +modest_tny_local_folders_account_remove_folder_from_outbox (ModestTnyLocalFoldersAccount *self, + TnyFolder *per_account_outbox) +{ + ModestTnyLocalFoldersAccountPrivate *priv; + TnyList *merged_folders = NULL; + + g_return_if_fail (MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self)); + g_return_if_fail (TNY_IS_FOLDER (per_account_outbox)); + + priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self); + + /* Remove outbox from the global OUTBOX folder */ + tny_merge_folder_remove_folder (priv->outbox_folder, per_account_outbox); + + /* If there is no folder in the outbox the delete it */ + merged_folders = tny_simple_list_new (); + tny_merge_folder_get_folders (priv->outbox_folder, merged_folders); + if (tny_list_get_length (merged_folders) == 0) { + /* Emit signal */ + g_signal_emit ((GObject *)self, signals[OUTBOX_DELETED_SIGNAL], 0); + + /* Unref my own reference */ + g_object_unref (priv->outbox_folder); + priv->outbox_folder = NULL; + } + g_object_unref (merged_folders); } +TnyFolder * +modest_tny_local_folders_account_get_merged_outbox (ModestTnyLocalFoldersAccount *self) +{ + ModestTnyLocalFoldersAccountPrivate *priv; + g_return_val_if_fail (MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self), NULL); + priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self); + if (priv->outbox_folder) + return g_object_ref (priv->outbox_folder); + else + return NULL; +}