* src/modest-text-utils.c:
[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 <string.h>
32 #include <stdio.h>
33 #include <config.h>
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>
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         TnyMergeFolder *outbox_folder;
55 };
56
57 static void         get_folders    (TnyFolderStore *self, 
58                                     TnyList *list, 
59                                     TnyFolderStoreQuery *query, 
60                                     GError **err);
61
62 static TnyFolder*   create_folder  (TnyFolderStore *self, 
63                                     const gchar *name, 
64                                     GError **err);
65
66 static void
67 modest_tny_local_folders_account_finalize (GObject *object)
68 {
69         G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->finalize (object);
70 }
71
72 static void
73 modest_tny_local_folders_account_class_init (ModestTnyLocalFoldersAccountClass *klass)
74 {
75         GObjectClass *object_class = G_OBJECT_CLASS (klass);
76         
77         g_type_class_add_private (klass, sizeof (ModestTnyLocalFoldersAccountPrivate));
78         
79         object_class->finalize = modest_tny_local_folders_account_finalize;
80           
81         /* Override virtual functions from the parent class: */
82         TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->get_folders_func = get_folders;
83         TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->create_folder_func = create_folder;
84 }
85
86 static void
87 modest_tny_local_folders_account_init (ModestTnyLocalFoldersAccount *self)
88 {
89         /* Do nothing */
90 }
91
92 ModestTnyLocalFoldersAccount*
93 modest_tny_local_folders_account_new (void)
94 {
95   return g_object_new (MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, NULL);
96 }
97
98 /**********************************************************/
99 /*          TnyCamelStoreAccount functions redefinitions  */
100 /**********************************************************/
101 static gboolean 
102 modest_tny_local_folders_account_query_passes (TnyFolderStoreQuery *query, TnyFolder *folder)
103 {
104         gboolean retval = FALSE;
105
106         if (query && (tny_list_get_length (tny_folder_store_query_get_items (query)) > 0))
107         {
108                 TnyList *items = tny_folder_store_query_get_items (query);
109                 TnyIterator *iterator;
110                 iterator = tny_list_create_iterator (items);
111
112                 while (!tny_iterator_is_done (iterator))
113                 {
114                         TnyFolderStoreQueryItem *item = (TnyFolderStoreQueryItem*) tny_iterator_get_current (iterator);
115                         if (item) {
116                                 TnyFolderStoreQueryOption options = tny_folder_store_query_item_get_options (item);
117                                 regex_t *regex = tny_folder_store_query_item_get_regex (item);
118
119                                 if ((options & TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED) &&
120                                    tny_folder_is_subscribed (folder))
121                                         retval = TRUE;
122
123                                 if ((options & TNY_FOLDER_STORE_QUERY_OPTION_UNSUBSCRIBED) &&
124                                     !(tny_folder_is_subscribed (folder)))
125                                         retval = TRUE;
126
127                                 if (regex && options & TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_NAME)
128                                    if (regexec (regex, tny_folder_get_name (folder), 0, NULL, 0) == 0)
129                                         retval = TRUE;
130
131                                 if (regex && options & TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_ID)
132                                   if (regexec (regex, tny_folder_get_id (folder), 0, NULL, 0) == 0)
133                                         retval = TRUE;
134
135                                 g_object_unref (G_OBJECT (item));
136                         }
137
138                         tny_iterator_next (iterator);
139                 }
140                  
141                 g_object_unref (G_OBJECT (iterator));    
142                 g_object_unref (G_OBJECT (items));
143         } else
144                 retval = TRUE;
145
146         return retval;
147 }
148
149 static void
150 get_folders (TnyFolderStore *self, TnyList *list, TnyFolderStoreQuery *query, GError **err)
151 {
152         TnyCamelStoreAccountClass *parent_class;
153         ModestTnyLocalFoldersAccountPrivate *priv;
154
155         /* Call the base class implementation: */
156         parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self));
157         parent_class->get_folders_func (self, list, query, err);
158         
159         /* Add our extra folder only if it passes the query */
160         priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
161                 
162         if (priv->outbox_folder && 
163             modest_tny_local_folders_account_query_passes (query, TNY_FOLDER (priv->outbox_folder)))
164                 tny_list_prepend (list, G_OBJECT (priv->outbox_folder));
165 }
166
167 static TnyFolder*
168 create_folder (TnyFolderStore *self, 
169                const gchar *name, 
170                GError **err)
171 {
172         TnyCamelStoreAccountClass *parent_class;
173
174         parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self));
175
176         /* If the folder name is been used by our extra folders */
177         if (modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (self), name)) {
178                 g_set_error (err, TNY_FOLDER_STORE_ERROR, 
179                              TNY_FOLDER_STORE_ERROR_CREATE_FOLDER,
180                              "Folder name already in use");
181                 return NULL;
182         }
183
184         /* Call the base class implementation: */
185         return parent_class->create_folder_func (self, name, err);
186 }
187
188 /*****************************/
189 /*      Public methods       */ 
190 /*****************************/
191 gboolean
192 modest_tny_local_folders_account_folder_name_in_use (ModestTnyLocalFoldersAccount *self,
193                                                      const gchar *name)
194 {
195         ModestTnyLocalFoldersAccountPrivate *priv;
196         gchar *down_name;
197         const gchar *type_name;
198         gboolean retval;
199         
200         /* Check that we're not trying to create/rename any folder
201            with the same name that our OUTBOX */
202         priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
203         down_name = g_utf8_strdown (name, strlen (name));
204
205         type_name = modest_local_folder_info_get_type_name (TNY_FOLDER_TYPE_OUTBOX);
206         if (!strcmp (type_name, down_name))
207                 retval = TRUE;
208         else
209                 retval = FALSE;
210
211         g_free (down_name);
212
213         return retval;
214 }
215
216 void
217 modest_tny_local_folders_account_add_folder_to_outbox (ModestTnyLocalFoldersAccount *self, 
218                                                        TnyFolder *per_account_outbox)
219 {
220         ModestTnyLocalFoldersAccountPrivate *priv;
221
222         g_return_if_fail (MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self));
223         g_return_if_fail (TNY_IS_FOLDER (per_account_outbox));
224
225         /* We can not test it yet, because there is no API to set the
226            type of a folder */
227 /*      g_return_if_fail (tny_folder_get_folder_type (per_account_outbox) == TNY_FOLDER_TYPE_OUTBOX); */
228
229         priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
230
231         /* Create on-demand */
232         if (!priv->outbox_folder) {
233                 priv->outbox_folder = TNY_MERGE_FOLDER (tny_merge_folder_new (_("mcen_me_folder_outbox")));
234         
235                 /* Set type to outbox */
236                 tny_merge_folder_set_folder_type (priv->outbox_folder, TNY_FOLDER_TYPE_OUTBOX);
237         }
238
239         /* Add outbox to the global OUTBOX folder */
240         tny_merge_folder_add_folder (priv->outbox_folder, per_account_outbox);
241 }