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>
42 #include <tny-gtk-lockable.h>
44 G_DEFINE_TYPE (ModestTnyLocalFoldersAccount,
45 modest_tny_local_folders_account,
46 TNY_TYPE_CAMEL_STORE_ACCOUNT);
48 #define TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE(o) \
49 (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, ModestTnyLocalFoldersAccountPrivate))
51 typedef struct _ModestTnyLocalFoldersAccountPrivate ModestTnyLocalFoldersAccountPrivate;
53 struct _ModestTnyLocalFoldersAccountPrivate
55 TnyMergeFolder *outbox_folder;
58 static void get_folders (TnyFolderStore *self,
60 TnyFolderStoreQuery *query,
64 static TnyFolder* create_folder (TnyFolderStore *self,
69 OUTBOX_DELETED_SIGNAL,
73 static guint signals[LAST_SIGNAL] = {0};
76 modest_tny_local_folders_account_finalize (GObject *object)
78 ModestTnyLocalFoldersAccountPrivate *priv;
80 priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (object);
81 if (priv->outbox_folder) {
82 g_object_unref (priv->outbox_folder);
83 priv->outbox_folder = NULL;
85 G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->finalize (object);
89 modest_tny_local_folders_account_class_init (ModestTnyLocalFoldersAccountClass *klass)
91 GObjectClass *object_class = G_OBJECT_CLASS (klass);
93 g_type_class_add_private (klass, sizeof (ModestTnyLocalFoldersAccountPrivate));
95 object_class->finalize = modest_tny_local_folders_account_finalize;
99 /* Note that this signal is removed before unsetting my own
100 reference to outbox, this means that by the time of this
101 call, modest_tny_local_folders_account_get_merged_outbox is
102 still valid. The reason is that the listeners of the signal
103 might want to do something with the outbox instance */
104 signals[OUTBOX_DELETED_SIGNAL] = g_signal_new
105 ("outbox-deleted", MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT,
106 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET
107 (ModestTnyLocalFoldersAccountClass, outbox_deleted), NULL,
108 NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
110 /* Override virtual functions from the parent class: */
111 TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->get_folders = get_folders;
112 TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->create_folder = create_folder;
116 modest_tny_local_folders_account_init (ModestTnyLocalFoldersAccount *self)
121 ModestTnyLocalFoldersAccount*
122 modest_tny_local_folders_account_new (void)
124 return g_object_new (MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, NULL);
127 /**********************************************************/
128 /* TnyCamelStoreAccount functions redefinitions */
129 /**********************************************************/
131 modest_tny_local_folders_account_query_passes (TnyFolderStoreQuery *query, TnyFolder *folder)
133 gboolean retval = FALSE;
135 if (query && (tny_list_get_length (tny_folder_store_query_get_items (query)) > 0)) {
136 TnyList *items = tny_folder_store_query_get_items (query);
137 TnyIterator *iterator;
138 iterator = tny_list_create_iterator (items);
140 while (!tny_iterator_is_done (iterator))
142 TnyFolderStoreQueryItem *item = (TnyFolderStoreQueryItem*) tny_iterator_get_current (iterator);
144 TnyFolderStoreQueryOption options = tny_folder_store_query_item_get_options (item);
145 const regex_t *regex = tny_folder_store_query_item_get_regex (item);
147 if ((options & TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED) &&
148 tny_folder_is_subscribed (folder))
151 if ((options & TNY_FOLDER_STORE_QUERY_OPTION_UNSUBSCRIBED) &&
152 !(tny_folder_is_subscribed (folder)))
155 if (regex && options & TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_NAME)
156 if (regexec (regex, tny_folder_get_name (folder), 0, NULL, 0) == 0)
159 if (regex && options & TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_ID)
160 if (regexec (regex, tny_folder_get_id (folder), 0, NULL, 0) == 0)
163 g_object_unref (G_OBJECT (item));
166 tny_iterator_next (iterator);
169 g_object_unref (G_OBJECT (iterator));
170 g_object_unref (G_OBJECT (items));
178 get_folders (TnyFolderStore *self,
180 TnyFolderStoreQuery *query,
184 TnyCamelStoreAccountClass *parent_class;
185 ModestTnyLocalFoldersAccountPrivate *priv;
187 /* Call the base class implementation: */
188 parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self));
189 parent_class->get_folders (self, list, query, refresh, err);
191 /* Add our extra folder only if it passes the query */
192 priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
194 if (priv->outbox_folder &&
195 modest_tny_local_folders_account_query_passes (query, TNY_FOLDER (priv->outbox_folder)))
196 tny_list_prepend (list, G_OBJECT (priv->outbox_folder));
200 create_folder (TnyFolderStore *self,
204 TnyCamelStoreAccountClass *parent_class;
206 parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self));
208 /* If the folder name is been used by our extra folders */
209 if (modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (self), name)) {
210 g_set_error (err, TNY_ERROR_DOMAIN,
211 TNY_SERVICE_ERROR_FOLDER_CREATE,
212 "Folder name already in use");
216 /* Call the base class implementation: */
217 return parent_class->create_folder (self, name, err);
220 /*****************************/
222 /*****************************/
224 modest_tny_local_folders_account_folder_name_in_use (ModestTnyLocalFoldersAccount *self,
227 ModestTnyLocalFoldersAccountPrivate *priv;
229 const gchar *type_name;
232 /* Check that we're not trying to create/rename any folder
233 with the same name that our OUTBOX, DRAFT, SENT */
234 priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
235 down_name = g_utf8_strdown (name, strlen (name));
237 type_name = modest_local_folder_info_get_type_name (TNY_FOLDER_TYPE_OUTBOX);
238 if (!strcmp (type_name, down_name)) {
241 type_name = modest_local_folder_info_get_type_name (TNY_FOLDER_TYPE_DRAFTS);
242 if (!strcmp (type_name, down_name)) {
245 type_name = modest_local_folder_info_get_type_name (TNY_FOLDER_TYPE_SENT);
246 if (!strcmp (type_name, down_name)) {
259 modest_tny_local_folders_account_add_folder_to_outbox (ModestTnyLocalFoldersAccount *self,
260 TnyFolder *per_account_outbox)
262 ModestTnyLocalFoldersAccountPrivate *priv;
264 g_return_if_fail (MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self));
265 g_return_if_fail (TNY_IS_FOLDER (per_account_outbox));
267 priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
269 /* Create on-demand */
270 if (!priv->outbox_folder) {
271 priv->outbox_folder = (TnyMergeFolder *)
272 tny_merge_folder_new_with_ui_locker (_("mcen_me_folder_outbox"),
273 tny_gtk_lockable_new ());
274 /* Set type to outbox */
275 tny_merge_folder_set_folder_type (priv->outbox_folder,
276 TNY_FOLDER_TYPE_OUTBOX);
279 /* Add outbox to the global OUTBOX folder */
280 tny_merge_folder_add_folder (priv->outbox_folder, per_account_outbox);
284 modest_tny_local_folders_account_remove_folder_from_outbox (ModestTnyLocalFoldersAccount *self,
285 TnyFolder *per_account_outbox)
287 ModestTnyLocalFoldersAccountPrivate *priv;
288 TnyList *merged_folders = NULL;
290 g_return_if_fail (MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self));
291 g_return_if_fail (TNY_IS_FOLDER (per_account_outbox));
293 priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
295 /* Remove outbox from the global OUTBOX folder */
296 tny_merge_folder_remove_folder (priv->outbox_folder, per_account_outbox);
298 /* If there is no folder in the outbox the delete it */
299 merged_folders = tny_simple_list_new ();
300 tny_merge_folder_get_folders (priv->outbox_folder, merged_folders);
301 if (tny_list_get_length (merged_folders) == 0) {
303 g_signal_emit ((GObject *)self, signals[OUTBOX_DELETED_SIGNAL], 0);
305 /* Unref my own reference */
306 g_object_unref (priv->outbox_folder);
307 priv->outbox_folder = NULL;
309 g_object_unref (merged_folders);
313 modest_tny_local_folders_account_get_merged_outbox (ModestTnyLocalFoldersAccount *self)
315 ModestTnyLocalFoldersAccountPrivate *priv;
316 g_return_val_if_fail (MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self), NULL);
318 priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
319 if (priv->outbox_folder)
320 return g_object_ref (priv->outbox_folder);