1 /* Copyright (c) 2007, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <glib/gi18n.h>
35 #include <tny-error.h>
36 #include <modest-tny-local-folders-account.h>
37 #include <modest-tny-outbox-account.h>
38 #include <modest-tny-folder.h>
39 #include <tny-camel-folder.h>
40 #include <tny-merge-folder.h>
41 #include <tny-simple-list.h>
43 G_DEFINE_TYPE (ModestTnyLocalFoldersAccount,
44 modest_tny_local_folders_account,
45 TNY_TYPE_CAMEL_STORE_ACCOUNT);
47 #define TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE(o) \
48 (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, ModestTnyLocalFoldersAccountPrivate))
50 typedef struct _ModestTnyLocalFoldersAccountPrivate ModestTnyLocalFoldersAccountPrivate;
52 struct _ModestTnyLocalFoldersAccountPrivate
54 GSList *list_extra_folders;
57 static void get_folders (TnyFolderStore *self,
59 TnyFolderStoreQuery *query,
62 static TnyFolder* create_folder (TnyFolderStore *self,
67 modest_tny_local_folders_account_dispose (GObject *object)
69 if (G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->dispose)
70 G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->dispose (object);
75 modest_tny_local_folders_account_remove_all_extra_folders (ModestTnyLocalFoldersAccount *store)
77 ModestTnyLocalFoldersAccountPrivate *priv =
78 TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (store);
80 GSList *iter = priv->list_extra_folders;
83 TnyFolder *folder = (TnyFolder*)iter->data;
85 g_object_unref (folder);
89 iter = g_slist_next (iter);
92 g_slist_free (priv->list_extra_folders);
93 priv->list_extra_folders = NULL;
97 modest_tny_local_folders_account_finalize (GObject *object)
99 G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->finalize (object);
101 ModestTnyLocalFoldersAccount *self =
102 MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (object);
104 modest_tny_local_folders_account_remove_all_extra_folders (self);
108 modest_tny_local_folders_account_class_init (ModestTnyLocalFoldersAccountClass *klass)
110 GObjectClass *object_class = G_OBJECT_CLASS (klass);
112 g_type_class_add_private (klass, sizeof (ModestTnyLocalFoldersAccountPrivate));
114 object_class->dispose = modest_tny_local_folders_account_dispose;
115 object_class->finalize = modest_tny_local_folders_account_finalize;
117 /* Override virtual functions from the parent class: */
118 TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->get_folders_func = get_folders;
119 TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->create_folder_func = create_folder;
123 modest_tny_local_folders_account_init (ModestTnyLocalFoldersAccount *self)
127 ModestTnyLocalFoldersAccount*
128 modest_tny_local_folders_account_new (void)
130 return g_object_new (MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, NULL);
134 modest_tny_local_folders_account_add_extra_folder (ModestTnyLocalFoldersAccount *store,
137 ModestTnyLocalFoldersAccountPrivate *priv =
138 TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (store);
140 /* Check that it isn't already in the list: */
141 GSList *exists = g_slist_find (priv->list_extra_folders, folder);
146 /* The reference is released in finalize: */
147 priv->list_extra_folders = g_slist_append (priv->list_extra_folders, folder);
148 g_object_ref (folder);
152 modest_tny_local_folders_account_query_passes (TnyFolderStoreQuery *query, TnyFolder *folder)
154 gboolean retval = FALSE;
156 if (query && (tny_list_get_length (tny_folder_store_query_get_items (query)) > 0))
158 TnyList *items = tny_folder_store_query_get_items (query);
159 TnyIterator *iterator;
160 iterator = tny_list_create_iterator (items);
162 while (!tny_iterator_is_done (iterator))
164 TnyFolderStoreQueryItem *item = (TnyFolderStoreQueryItem*) tny_iterator_get_current (iterator);
166 TnyFolderStoreQueryOption options = tny_folder_store_query_item_get_options (item);
167 regex_t *regex = tny_folder_store_query_item_get_regex (item);
169 if ((options & TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED) &&
170 tny_folder_is_subscribed (folder))
173 if ((options & TNY_FOLDER_STORE_QUERY_OPTION_UNSUBSCRIBED) &&
174 !(tny_folder_is_subscribed (folder)))
177 if (regex && options & TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_NAME)
178 if (regexec (regex, tny_folder_get_name (folder), 0, NULL, 0) == 0)
181 if (regex && options & TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_ID)
182 if (regexec (regex, tny_folder_get_id (folder), 0, NULL, 0) == 0)
185 g_object_unref (G_OBJECT (item));
188 tny_iterator_next (iterator);
191 g_object_unref (G_OBJECT (iterator));
192 g_object_unref (G_OBJECT (items));
201 get_folders (TnyFolderStore *self, TnyList *list, TnyFolderStoreQuery *query, GError **err)
203 ModestTnyLocalFoldersAccountPrivate *priv =
204 TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
206 /* Call the base class implementation: */
207 TnyCamelStoreAccountClass *parent_class = g_type_class_peek_parent (
208 MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self));
209 parent_class->get_folders_func (self, list, query, err);
211 /* Add our extra folders only if it passes the query */
212 GSList *iter = priv->list_extra_folders;
214 TnyFolder *folder = TNY_FOLDER (iter->data);
216 if (folder && modest_tny_local_folders_account_query_passes (query, folder))
217 tny_list_prepend (list, G_OBJECT (folder));
219 iter = g_slist_next (iter);
224 add_account_folders_to_merged_folder (TnyAccount *account, TnyMergeFolder* merge_folder)
226 const gchar* account_id = tny_account_get_id (account);
227 const gboolean is_actual_local_folders_account = account_id &&
228 (strcmp (account_id, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0);
230 TnyList *list_outbox_folders = tny_simple_list_new ();
231 tny_folder_store_get_folders (TNY_FOLDER_STORE (account),
232 list_outbox_folders, NULL, NULL);
234 TnyIterator* iter = tny_list_create_iterator (list_outbox_folders);
235 while (!tny_iterator_is_done (iter))
237 TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (iter));
241 /* TODO: Do not add outboxes that are inside local-folders/,
242 * because these are just left-over from earlier Modest versions
243 * that put the outbox there: */
244 if (is_actual_local_folders_account) {
245 const TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
246 if (type == TNY_FOLDER_TYPE_OUTBOX) {
252 tny_merge_folder_add_folder (merge_folder, folder);
254 g_object_unref (folder);
257 tny_iterator_next (iter);
260 g_object_unref (list_outbox_folders);
264 modest_tny_local_folders_account_add_merged_outbox_folders (ModestTnyLocalFoldersAccount *self,
267 TnyMergeFolder *merged_outbox = NULL;
268 TnyIterator *iter = NULL;
270 modest_tny_local_folders_account_remove_all_extra_folders (self);
272 /* All per-account outbox folders are merged into one folders
273 * so that they appear as one outbox to the user: */
274 merged_outbox = TNY_MERGE_FOLDER (tny_merge_folder_new(_("mcen_me_folder_outbox")));
276 /* Set type to outbox */
277 tny_merge_folder_set_folder_type (merged_outbox, TNY_FOLDER_TYPE_OUTBOX);
279 iter = tny_list_create_iterator (accounts);
280 while (!tny_iterator_is_done (iter)){
282 TnyAccount *account = TNY_ACCOUNT (tny_iterator_get_current (iter));
284 /* Add both outbox account and local-folders account folders
285 * to our one combined account:
287 if (MODEST_IS_TNY_OUTBOX_ACCOUNT (account)) {
288 /* Add the folder to the merged folder.
289 * We will add it later to the virtual local-folders store: */
290 add_account_folders_to_merged_folder (account, merged_outbox);
292 g_object_unref (account);
293 tny_iterator_next (iter);
295 g_object_unref (iter);
297 /* Add the merged outbox folder to the virtual local-folders store: */
298 modest_tny_local_folders_account_add_extra_folder (self, TNY_FOLDER(merged_outbox));
299 g_object_unref (merged_outbox);
303 modest_tny_local_folders_account_extra_folder_exists (ModestTnyLocalFoldersAccount *self,
306 ModestTnyLocalFoldersAccountPrivate *priv;
311 /* Check that we're not trying to create/rename any folder
312 with the same name that our extra folders */
313 priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
314 iter = priv->list_extra_folders;
316 down_name = g_utf8_strdown (name, strlen (name));
317 while (iter && !found) {
318 TnyFolder *folder = TNY_FOLDER (iter->data);
319 const gchar *type_name;
321 type_name = modest_local_folder_info_get_type_name (tny_folder_get_folder_type (folder));
322 if (!strcmp (type_name, down_name))
325 iter = g_slist_next (iter);
333 create_folder (TnyFolderStore *self,
337 TnyCamelStoreAccountClass *parent_class;
339 parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self));
341 /* If the folder name is been used by our extra folders */
342 if (modest_tny_local_folders_account_extra_folder_exists (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (self), name)) {
343 g_set_error (err, TNY_FOLDER_STORE_ERROR,
344 TNY_FOLDER_STORE_ERROR_CREATE_FOLDER,
345 "Folder name already in use");
349 /* Call the base class implementation: */
350 return parent_class->create_folder_func (self, name, err);