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 }