src/mn-maildir-message.gob (7051B) - raw
1 /*
2 * Mail Notification
3 * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 %headertop{
21 #include "mn-vfs-message.h"
22 %}
23
24 %privateheader{
25 #include <gtk/gtk.h>
26 %}
27
28 %{
29 #include <glib/gi18n.h>
30 #include "mn-vfs-mailbox.h"
31 #include "mn-vfs.h"
32 #include "mn-util.h"
33 #include "mn-message-private.h"
34 #include "mn-shell.h"
35
36 #define DELETE_DIALOG_MESSAGE "mn-maildir-message-delete-dialog-message"
37 %}
38
39 class MN:Maildir:Message from MN:VFS:Message
40 {
41 private int
42 flags_sort_cb (const void *a, const void *b)
43 {
44 char ca = *((char *) a);
45 char cb = *((char *) b);
46
47 /* sort flags using ASCII order, see http://cr.yp.to/proto/maildir.html */
48
49 return ca - cb;
50 }
51
52 override (MN:Message) void
53 builtin_mark_as_read (MNMessage *message, MNMessageActionRequest *request)
54 {
55 mn_message_perform_action_in_thread(request, self_builtin_mark_as_read_cb, NULL);
56 }
57
58 private GError *
59 builtin_mark_as_read_cb (MNMessage *message, gpointer data)
60 {
61 MNVFSMessage *vmessage = MN_VFS_MESSAGE(message);
62 char *old_flags;
63 char *old_filename;
64 char *new_filename;
65 GnomeVFSURI *dir_uri;
66 GnomeVFSURI *new_uri;
67 GError *err = NULL;
68
69 /* http://cr.yp.to/proto/maildir.html */
70
71 old_filename = gnome_vfs_uri_extract_short_name(vmessage->vfs_uri);
72
73 old_flags = strrchr(old_filename, ',');
74 if (old_flags)
75 {
76 char *new_flags;
77 int old_len;
78 char *base_filename;
79
80 /* append the S (seen) flag */
81
82 old_flags++;
83 g_assert(strchr(old_flags, 'S') == NULL);
84
85 old_len = strlen(old_flags);
86 new_flags = g_new(char, old_len + 2); /* + space for S and nul */
87 memcpy(new_flags, old_flags, old_len);
88 new_flags[old_len] = 'S';
89 new_flags[old_len + 1] = 0;
90 qsort(new_flags, old_len + 1, sizeof(char), self_flags_sort_cb);
91
92 base_filename = g_strndup(old_filename, old_flags - old_filename - 1);
93 new_filename = g_strdup_printf("%s,%s", base_filename, new_flags);
94 g_free(base_filename);
95 g_free(new_flags);
96 }
97 else
98 new_filename = g_strconcat(old_filename, ":2,S", NULL);
99
100 g_free(old_filename);
101
102 dir_uri = gnome_vfs_uri_append_path(MN_VFS_MAILBOX(message->mailbox)->vfs_uri, "cur");
103 new_uri = gnome_vfs_uri_append_file_name(dir_uri, new_filename);
104 gnome_vfs_uri_unref(dir_uri);
105 g_free(new_filename);
106
107 mn_vfs_result_to_g_error(gnome_vfs_move_uri(vmessage->vfs_uri, new_uri, TRUE), &err);
108 gnome_vfs_uri_unref(new_uri);
109
110 return err;
111 }
112
113 /* returns NULL if not supported for the volume where the file resides */
114 private GnomeVFSURI *
115 get_trash_uri (self)
116 {
117 MNVFSMessage *vmessage = MN_VFS_MESSAGE(self);
118 GnomeVFSURI *trash_uri;
119
120 /*
121 * Do what is advised in the gnome_vfs_find_directory()
122 * documentation: first pass find_if_needed, then create_if_needed.
123 */
124
125 if (gnome_vfs_find_directory(vmessage->vfs_uri,
126 GNOME_VFS_DIRECTORY_KIND_TRASH,
127 &trash_uri,
128 FALSE,
129 TRUE,
130 0) == GNOME_VFS_OK)
131 return trash_uri;
132
133 if (gnome_vfs_find_directory(vmessage->vfs_uri,
134 GNOME_VFS_DIRECTORY_KIND_TRASH,
135 &trash_uri,
136 TRUE,
137 FALSE,
138 S_IRUSR | S_IWUSR | S_IXUSR) == GNOME_VFS_OK)
139 return trash_uri;
140
141 return NULL;
142 }
143
144 private GError *
145 delete_with_prompt (self, const char *format (check null), ...)
146 attr {G_GNUC_PRINTF(2, 3)}
147 {
148 GtkWidget *dialog;
149 char *prompt;
150 int response;
151
152 MN_STRDUP_VPRINTF(prompt, format);
153
154 GDK_THREADS_ENTER();
155
156 dialog = mn_alert_dialog_new(NULL,
157 GTK_MESSAGE_WARNING,
158 0,
159 _("Delete message?"),
160 prompt);
161 g_free(prompt);
162
163 gtk_dialog_add_buttons(GTK_DIALOG(dialog),
164 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
165 GTK_STOCK_DELETE, GTK_RESPONSE_OK,
166 NULL);
167
168 g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_MESSAGE, self);
169
170 mn_g_object_connect(dialog, mn_shell->mailboxes,
171 "signal::messages-changed", self_delete_messages_changed_h, dialog,
172 NULL);
173
174 response = mn_dialog_run_nonmodal(GTK_DIALOG(dialog));
175 gtk_widget_destroy(dialog);
176
177 gdk_flush();
178 GDK_THREADS_LEAVE();
179
180 if (response == GTK_RESPONSE_OK)
181 {
182 GError *err = NULL;
183
184 mn_vfs_result_to_g_error(gnome_vfs_unlink_from_uri(MN_VFS_MESSAGE(self)->vfs_uri), &err);
185
186 return err;
187 }
188 else
189 return g_error_new(MN_MESSAGE_ACTION_ERROR, MN_MESSAGE_ACTION_ERROR_CANCELLED, "cancelled");
190 }
191
192 private void
193 delete_messages_changed_h (MNMailboxes *mailboxes,
194 gboolean has_new,
195 gpointer user_data)
196 {
197 GtkWidget *dialog = user_data;
198 Self *self;
199
200 self = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_MESSAGE);
201
202 /* if the message was removed, close the dialog */
203 if (! g_hash_table_lookup(mn_shell->mailboxes->messages_hash_table, MN_MESSAGE(self)->id))
204 gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
205 }
206
207 override (MN:Message) void
208 builtin_delete (MNMessage *message, MNMessageActionRequest *request)
209 {
210 mn_message_perform_action_in_thread(request, self_builtin_delete_cb, NULL);
211 }
212
213 private GError *
214 builtin_delete_cb (MNMessage *message, gpointer data)
215 {
216 Self *self = SELF(message);
217 MNVFSMessage *vmessage = MN_VFS_MESSAGE(message);
218 GnomeVFSURI *trash_uri;
219 char *filename;
220 GnomeVFSURI *dest_uri;
221 GnomeVFSResult result;
222
223 trash_uri = self_get_trash_uri(self);
224 if (! trash_uri)
225 return self_delete_with_prompt(self, _("The message cannot be moved to the trash. Permanently delete it?"));
226
227 filename = gnome_vfs_uri_extract_short_name(vmessage->vfs_uri);
228 dest_uri = gnome_vfs_uri_append_file_name(trash_uri, filename);
229 gnome_vfs_uri_unref(trash_uri);
230 g_free(filename);
231
232 /*
233 * Use gnome_vfs_xfer_uri() rather than gnome_vfs_move_uri(), in
234 * case the trash resides on a different file system than the
235 * message.
236 */
237 result = gnome_vfs_xfer_uri(vmessage->vfs_uri,
238 dest_uri,
239 GNOME_VFS_XFER_REMOVESOURCE
240 | GNOME_VFS_XFER_FOLLOW_LINKS,
241 GNOME_VFS_XFER_ERROR_MODE_ABORT,
242 GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
243 NULL,
244 NULL);
245 gnome_vfs_uri_unref(dest_uri);
246
247 if (result == GNOME_VFS_OK)
248 return NULL;
249 else
250 return self_delete_with_prompt(self, _("The message could not be moved to the trash (%s). Permanently delete it?"), gnome_vfs_result_to_string(result));
251 }
252 }