a884c423fddc80bbe0caea8f4ad38498bea0b68a
[modest] / src / modest-tny-local-folders-account.c
1 /* Copyright (c) 2007, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
16  *
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.
28  */
29
30
31 #include <config.h>
32 #include <glib/gi18n.h>
33
34 #include <modest-tny-local-folders-account.h>
35 #include <modest-tny-outbox-account.h>
36 #include <modest-tny-folder.h>
37 #include <tny-merge-folder.h>
38 #include <tny-simple-list.h>
39
40 #include <string.h>
41 #include <stdio.h>
42
43 G_DEFINE_TYPE (ModestTnyLocalFoldersAccount, 
44         modest_tny_local_folders_account, 
45         TNY_TYPE_CAMEL_STORE_ACCOUNT);
46
47 #define TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE(o) \
48   (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, ModestTnyLocalFoldersAccountPrivate))
49
50 typedef struct _ModestTnyLocalFoldersAccountPrivate ModestTnyLocalFoldersAccountPrivate;
51
52 struct _ModestTnyLocalFoldersAccountPrivate
53 {
54         GSList *list_extra_folders;
55 };
56
57 static void
58 modest_tny_local_folders_account_dispose (GObject *object)
59 {
60   if (G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->dispose)
61     G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->dispose (object);
62 }
63
64
65 static void
66 modest_tny_local_folders_account_remove_all_extra_folders (ModestTnyLocalFoldersAccount *store)
67 {
68         ModestTnyLocalFoldersAccountPrivate *priv = 
69                 TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (store);
70                 
71         GSList *iter = priv->list_extra_folders;
72         while (iter)
73         {
74                 TnyFolder *folder = (TnyFolder*)iter->data;
75                 if (folder) {
76                         g_object_unref (folder);
77                         iter->data = NULL;
78                 }
79                         
80                 iter = g_slist_next (iter);
81         }
82         
83         g_slist_free (priv->list_extra_folders);
84         priv->list_extra_folders = NULL;
85 }
86
87 static void
88 modest_tny_local_folders_account_finalize (GObject *object)
89 {
90         G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->finalize (object);
91   
92         ModestTnyLocalFoldersAccount *self = 
93                 MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (object);
94                 
95         modest_tny_local_folders_account_remove_all_extra_folders (self);
96 }
97
98 static void
99 get_folders (TnyFolderStore *self, TnyList *list, TnyFolderStoreQuery *query, GError **err);
100
101 static void 
102 get_folders_async (TnyFolderStore *self, TnyList *list, TnyGetFoldersCallback callback, TnyFolderStoreQuery *query, TnyStatusCallback status_callback, gpointer user_data);
103
104 static void
105 modest_tny_local_folders_account_class_init (ModestTnyLocalFoldersAccountClass *klass)
106 {
107         GObjectClass *object_class = G_OBJECT_CLASS (klass);
108         
109         g_type_class_add_private (klass, sizeof (ModestTnyLocalFoldersAccountPrivate));
110         
111         object_class->dispose = modest_tny_local_folders_account_dispose;
112         object_class->finalize = modest_tny_local_folders_account_finalize;
113           
114         /* Override virtual functions from the parent class: */
115         TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->get_folders_func = get_folders;
116         TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->get_folders_async_func = get_folders_async;
117 }
118
119 static void
120 modest_tny_local_folders_account_init (ModestTnyLocalFoldersAccount *self)
121 {
122 }
123
124 ModestTnyLocalFoldersAccount*
125 modest_tny_local_folders_account_new (void)
126 {
127   return g_object_new (MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, NULL);
128 }
129
130 void
131 modest_tny_local_folders_account_add_extra_folder (ModestTnyLocalFoldersAccount *store, 
132         TnyFolder *folder)
133 {
134         ModestTnyLocalFoldersAccountPrivate *priv = 
135                 TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (store);
136                 
137         /* Check that it isn't already in the list: */
138         GSList *exists = g_slist_find (priv->list_extra_folders, folder);
139         if (exists)
140                 return;
141                 
142         /* Add it: */
143         /* The reference is released in finalize: */
144         priv->list_extra_folders = g_slist_append (priv->list_extra_folders, folder);
145         g_object_ref (folder);
146 }
147
148 static void
149 get_folders (TnyFolderStore *self, TnyList *list, TnyFolderStoreQuery *query, GError **err)
150 {
151         ModestTnyLocalFoldersAccountPrivate *priv = 
152                 TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
153                 
154         /* Call the base class implementation: */
155         TnyCamelStoreAccountClass *parent_class = g_type_class_peek_parent (
156                 MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self));
157         parent_class->get_folders_func (self, list, query, err);
158         
159         /* Add our extra folders: */
160         GSList *iter = priv->list_extra_folders;
161         while (iter)
162         {
163                 TnyFolder *folder = TNY_FOLDER (iter->data);
164
165                 if (folder)
166                         tny_list_append (list, G_OBJECT (folder));
167                         
168                 iter = g_slist_next (iter);
169         }
170 }
171
172 static void 
173 get_folders_async (TnyFolderStore *self, TnyList *list, TnyGetFoldersCallback callback, TnyFolderStoreQuery *query, TnyStatusCallback status_callback, gpointer user_data)
174 {
175         /* Call the base class implementation: */
176         TnyCamelStoreAccountClass *parent_class = g_type_class_peek_parent (
177                 MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self));
178         parent_class->get_folders_async_func (self, list, callback, query, status_callback, user_data);
179 }
180
181 static void
182 add_account_folders_to_merged_folder (TnyAccount *account, TnyMergeFolder* merge_folder)
183 {
184         const gchar* account_id = tny_account_get_id (account);
185         const gboolean is_actual_local_folders_account = account_id && 
186                 (strcmp (account_id, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0);
187                 
188         TnyList *list_outbox_folders = tny_simple_list_new ();
189         tny_folder_store_get_folders (TNY_FOLDER_STORE (account), 
190                 list_outbox_folders, NULL, NULL);
191                 
192         TnyIterator*  iter =  tny_list_create_iterator (list_outbox_folders);
193         while (!tny_iterator_is_done (iter))
194         {
195                 TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (iter));
196                 
197                 if (folder) {
198                         gboolean add = TRUE;
199                         /* TODO: Do not add outboxes that are inside local-folders/, 
200                          * because these are just left-over from earlier Modest versions 
201                          * that put the outbox there: */
202                         if (is_actual_local_folders_account) {
203                                 const TnyFolderType type = modest_tny_folder_get_local_folder_type (folder);
204                                 if (type == TNY_FOLDER_TYPE_OUTBOX) {
205                                         add = FALSE;
206                                 }
207                         }
208                         
209                         if (add)
210                                 tny_merge_folder_add_folder (merge_folder, folder);
211                                 
212                         g_object_unref (folder);        
213                 }
214                 
215                 tny_iterator_next (iter);
216         }
217         
218         g_object_unref (list_outbox_folders);
219 }
220
221 void modest_tny_local_folders_account_add_merged_outbox_folders (ModestTnyLocalFoldersAccount *self, 
222         GSList *accounts)
223 {
224         modest_tny_local_folders_account_remove_all_extra_folders (self);
225         
226         /* All per-account outbox folders are merged into one folders
227          * so that they appear as one outbox to the user: */
228         TnyMergeFolder *merged_outbox = TNY_MERGE_FOLDER (tny_merge_folder_new());
229         
230         GSList *iter = accounts;
231         while (iter)
232         {
233                 TnyAccount *account = TNY_ACCOUNT (iter->data);
234                 if (account) {
235                         /* Add both outbox account and local-folders account folders
236                          * to our one combined account:
237                          */
238                         if (MODEST_IS_TNY_OUTBOX_ACCOUNT (account)) {
239                                 /* Add the folder to the merged folder.
240                                  * We will add it later to the virtual local-folders store: */
241                                 add_account_folders_to_merged_folder (account, merged_outbox);
242                         }
243                 }
244            
245                 iter = g_slist_next (iter);
246         }
247         
248         /* Add the merged outbox folder to the virtual local-folders store: */
249         /* printf ("Debug: %s: adding merged outbox.\n", __FUNCTION__); */
250         modest_tny_local_folders_account_add_extra_folder (self, TNY_FOLDER(merged_outbox));
251         g_object_unref (merged_outbox);
252         merged_outbox = NULL;
253 }
254
255