1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Authors: Jeffrey Stedfast <fejj@ximian.com>
4 * Michael Zucchi <notzed@ximian.com>
6 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU Lesser General Public
10 * License as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
30 #include <glib/gi18n-lib.h>
33 #include "camel-mime-message.h"
34 #include "camel-store.h"
35 #include "camel-vee-store.h"
36 #include "camel-vtrash-folder.h"
37 #include "camel-string-utils.h"
40 const gchar *full_name;
45 const gchar *error_copy;
48 { CAMEL_VTRASH_NAME, N_("Trash"), "(match-all (system-flag \"Deleted\"))", CAMEL_MESSAGE_DELETED, CAMEL_FOLDER_IS_TRASH,
49 N_("Cannot copy messages to the Trash folder"), "deleted" },
50 { CAMEL_VJUNK_NAME, N_("Junk"), "(match-all (system-flag \"Junk\"))", CAMEL_MESSAGE_JUNK, CAMEL_FOLDER_IS_JUNK,
51 N_("Cannot copy messages to the Junk folder"), "junk" },
54 struct _transfer_data {
55 GCancellable *cancellable;
61 CamelFolder *source_folder;
62 GPtrArray *source_uids;
66 G_DEFINE_TYPE (CamelVTrashFolder, camel_vtrash_folder, CAMEL_TYPE_VEE_FOLDER)
69 transfer_messages (CamelFolder *folder,
70 struct _transfer_data *md,
75 camel_folder_transfer_messages_to_sync (
76 md->folder, md->uids, md->dest,
77 md->delete, NULL, md->cancellable, error);
79 if (md->cancellable != NULL)
80 g_object_unref (md->cancellable);
82 /* set the bit back */
83 for (i = 0; i < md->source_uids->len; i++) {
84 CamelMessageInfo *mi = camel_folder_get_message_info (md->source_folder, md->source_uids->pdata[i]);
86 camel_message_info_set_flags (mi, md->sbit, md->sbit);
87 camel_folder_free_message_info (md->source_folder, mi);
91 camel_folder_thaw (md->folder);
93 for (i = 0; i < md->uids->len; i++)
94 g_free (md->uids->pdata[i]);
96 g_ptr_array_free (md->uids, TRUE);
97 g_ptr_array_free (md->source_uids, TRUE);
98 g_object_unref (md->folder);
103 vtrash_folder_append_message_sync (CamelFolder *folder,
104 CamelMimeMessage *message,
105 CamelMessageInfo *info,
106 gchar **appended_uid,
107 GCancellable *cancellable,
111 error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, "%s",
112 _(vdata[((CamelVTrashFolder *) folder)->type].error_copy));
118 vtrash_folder_transfer_messages_to_sync (CamelFolder *source,
121 gboolean delete_originals,
122 GPtrArray **transferred_uids,
123 GCancellable *cancellable,
126 CamelVeeMessageInfo *mi;
128 GHashTable *batch = NULL;
130 struct _transfer_data *md;
131 guint32 sbit = ((CamelVTrashFolder *) source)->bit;
133 /* This is a special case of transfer_messages_to: Either the
134 * source or the destination is a vtrash folder (but not both
135 * since a store should never have more than one).
138 if (transferred_uids)
139 *transferred_uids = NULL;
141 if (CAMEL_IS_VTRASH_FOLDER (dest)) {
142 /* Copy to trash is meaningless. */
143 if (!delete_originals) {
145 error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, "%s",
146 _(vdata[((CamelVTrashFolder *) dest)->type].error_copy));
150 /* Move to trash is the same as setting the message flag */
151 for (i = 0; i < uids->len; i++)
152 camel_folder_set_message_flags (
153 source, uids->pdata[i],
154 ((CamelVTrashFolder *) dest)->bit, ~0);
158 /* Moving/Copying from the trash to the original folder = undelete.
159 * Moving/Copying from the trash to a different folder = move/copy.
161 * Need to check this uid by uid, but we batch up the copies.
164 camel_folder_freeze (source);
165 camel_folder_freeze (dest);
167 for (i = 0; i < uids->len; i++) {
168 mi = (CamelVeeMessageInfo *) camel_folder_get_message_info (source, uids->pdata[i]);
170 g_warning ("Cannot find uid %s in source folder during transfer", (gchar *) uids->pdata[i]);
174 if (dest == camel_folder_summary_get_folder (mi->orig_summary)) {
175 /* Just unset the flag on the original message */
176 camel_folder_set_message_flags (
177 source, uids->pdata[i], sbit, 0);
180 batch = g_hash_table_new (NULL, NULL);
181 md = g_hash_table_lookup (batch, camel_folder_summary_get_folder (mi->orig_summary));
183 md = g_malloc0 (sizeof (*md));
184 md->cancellable = cancellable;
185 md->folder = g_object_ref (camel_folder_summary_get_folder (mi->orig_summary));
186 md->uids = g_ptr_array_new ();
188 md->delete = delete_originals;
189 md->source_folder = source;
190 md->source_uids = g_ptr_array_new ();
192 if (cancellable != NULL)
193 g_object_ref (cancellable);
194 camel_folder_freeze (md->folder);
195 g_hash_table_insert (batch, camel_folder_summary_get_folder (mi->orig_summary), md);
198 /* unset the bit temporarily */
199 camel_message_info_set_flags ((CamelMessageInfo *) mi, sbit, 0);
201 tuid = uids->pdata[i];
202 if (strlen (tuid) > 8)
204 g_ptr_array_add (md->uids, g_strdup (tuid));
205 g_ptr_array_add (md->source_uids, uids->pdata[i]);
207 camel_folder_free_message_info (source, (CamelMessageInfo *) mi);
211 g_hash_table_foreach (batch, (GHFunc) transfer_messages, error);
212 g_hash_table_destroy (batch);
215 camel_folder_thaw (dest);
216 camel_folder_thaw (source);
222 camel_vtrash_folder_class_init (CamelVTrashFolderClass *class)
224 CamelFolderClass *folder_class;
226 folder_class = CAMEL_FOLDER_CLASS (class);
227 folder_class->append_message_sync = vtrash_folder_append_message_sync;
228 folder_class->transfer_messages_to_sync = vtrash_folder_transfer_messages_to_sync;
232 camel_vtrash_folder_init (CamelVTrashFolder *vtrash_folder)
237 * camel_vtrash_folder_new:
238 * @parent_store: the parent #CamelVeeStore object
239 * @type: type of vfolder, #CAMEL_VTRASH_FOLDER_TRASH or
240 * #CAMEL_VTRASH_FOLDER_JUNK currently.
242 * Create a new CamelVTrashFolder object.
244 * Returns: a new #CamelVTrashFolder object
247 camel_vtrash_folder_new (CamelStore *parent_store,
248 camel_vtrash_folder_t type)
250 CamelVTrashFolder *vtrash;
252 g_assert (type < CAMEL_VTRASH_FOLDER_LAST);
254 vtrash = g_object_new (
255 CAMEL_TYPE_VTRASH_FOLDER,
256 "full-name", vdata[type].full_name,
257 "display-name", gettext (vdata[type].name),
258 "parent-store", parent_store, NULL);
260 camel_vee_folder_construct (
261 CAMEL_VEE_FOLDER (vtrash),
262 CAMEL_STORE_FOLDER_PRIVATE |
263 CAMEL_STORE_FOLDER_CREATE);
265 ((CamelFolder *) vtrash)->folder_flags |= vdata[type].flags;
266 camel_vee_folder_set_expression ((CamelVeeFolder *) vtrash, vdata[type].expr);
267 vtrash->bit = vdata[type].bit;
270 return (CamelFolder *) vtrash;