mail-notification

Fork of Jean-Yves Lefort's mail-notification, a tray icon to notify of new mail
git clone https://code.djc.id.au/git/mail-notification/

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 }