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);
165 TnyFolderStoreQueryOption options = tny_folder_store_query_item_get_options (item);
166 regex_t *regex = tny_folder_store_query_item_get_regex (item);
168 if ((options & TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED) &&
169 tny_folder_is_subscribed (folder))
172 if ((options & TNY_FOLDER_STORE_QUERY_OPTION_UNSUBSCRIBED) &&
173 !(tny_folder_is_subscribed (folder)))
176 if (regex && options & TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_NAME)
177 if (regexec (regex, tny_folder_get_name (folder), 0, NULL, 0) == 0)
180 if (regex && options & TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_ID)
181 if (regexec (regex, tny_folder_get_id (folder), 0, NULL, 0) == 0)
184 g_object_unref (G_OBJECT (item));
185 tny_iterator_next (iterator);
188 g_object_unref (G_OBJECT (iterator));
189 g_object_unref (G_OBJECT (items));
198 get_folders (TnyFolderStore *self, TnyList *list, TnyFolderStoreQuery *query, GError **err)
200 ModestTnyLocalFoldersAccountPrivate *priv =
201 TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
203 /* Call the base class implementation: */
204 TnyCamelStoreAccountClass *parent_class = g_type_class_peek_parent (
205 MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self));
206 parent_class->get_folders_func (self, list, query, err);
208 /* Add our extra folders only if it passes the query */
209 GSList *iter = priv->list_extra_folders;
211 TnyFolder *folder = TNY_FOLDER (iter->data);
213 if (folder && modest_tny_local_folders_account_query_passes (query, folder))
214 tny_list_prepend (list, G_OBJECT (folder));
216 iter = g_slist_next (iter);
221 add_account_folders_to_merged_folder (TnyAccount *account, TnyMergeFolder* merge_folder)
223 const gchar* account_id = tny_account_get_id (account);
224 const gboolean is_actual_local_folders_account = account_id &&
225 (strcmp (account_id, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0);
227 TnyList *list_outbox_folders = tny_simple_list_new ();
228 tny_folder_store_get_folders (TNY_FOLDER_STORE (account),
229 list_outbox_folders, NULL, NULL);
231 TnyIterator* iter = tny_list_create_iterator (list_outbox_folders);
232 while (!tny_iterator_is_done (iter))
234 TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (iter));
238 /* TODO: Do not add outboxes that are inside local-folders/,
239 * because these are just left-over from earlier Modest versions
240 * that put the outbox there: */
241 if (is_actual_local_folders_account) {
242 const TnyFolderType type = modest_tny_folder_get_local_folder_type (folder);
243 if (type == TNY_FOLDER_TYPE_OUTBOX) {
249 tny_merge_folder_add_folder (merge_folder, folder);
251 g_object_unref (folder);
254 tny_iterator_next (iter);
257 g_object_unref (list_outbox_folders);
260 void modest_tny_local_folders_account_add_merged_outbox_folders (ModestTnyLocalFoldersAccount *self,
263 modest_tny_local_folders_account_remove_all_extra_folders (self);
265 /* All per-account outbox folders are merged into one folders
266 * so that they appear as one outbox to the user: */
267 TnyMergeFolder *merged_outbox = TNY_MERGE_FOLDER (tny_merge_folder_new(_("mcen_me_folder_outbox")));
269 /* Set type to outbox (NB#61580) */
270 tny_merge_folder_set_folder_type (merged_outbox, TNY_FOLDER_TYPE_OUTBOX);
272 GSList *iter = accounts;
275 TnyAccount *account = TNY_ACCOUNT (iter->data);
277 /* Add both outbox account and local-folders account folders
278 * to our one combined account:
280 if (MODEST_IS_TNY_OUTBOX_ACCOUNT (account)) {
281 /* Add the folder to the merged folder.
282 * We will add it later to the virtual local-folders store: */
283 add_account_folders_to_merged_folder (account, merged_outbox);
287 iter = g_slist_next (iter);
290 /* Add the merged outbox folder to the virtual local-folders store: */
291 /* printf ("Debug: %s: adding merged outbox.\n", __FUNCTION__); */
292 modest_tny_local_folders_account_add_extra_folder (self, TNY_FOLDER(merged_outbox));
293 g_object_unref (merged_outbox);
294 merged_outbox = NULL;
298 modest_tny_local_folders_account_extra_folder_exists (ModestTnyLocalFoldersAccount *self,
301 ModestTnyLocalFoldersAccountPrivate *priv;
306 /* Check that we're not trying to create/rename any folder
307 with the same name that our extra folders */
308 priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
309 iter = priv->list_extra_folders;
311 down_name = g_utf8_strdown (name, strlen (name));
312 while (iter && !found) {
313 TnyFolder *folder = TNY_FOLDER (iter->data);
314 const gchar *type_name;
316 type_name = modest_local_folder_info_get_type_name (tny_folder_get_folder_type (folder));
317 if (!strcmp (type_name, down_name))
320 iter = g_slist_next (iter);
328 create_folder (TnyFolderStore *self,
332 TnyCamelStoreAccountClass *parent_class;
334 parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self));
336 /* If the folder name is been used by our extra folders */
337 if (modest_tny_local_folders_account_extra_folder_exists (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (self), name)) {
338 g_set_error (err, TNY_FOLDER_STORE_ERROR,
339 TNY_FOLDER_STORE_ERROR_CREATE_FOLDER,
340 "Folder name already in use");
344 /* Call the base class implementation: */
345 return parent_class->create_folder_func (self, name, err);