b3f88860f32e15d0c9cced4d7378f3a75ecefda4
[claws.git] / src / mh_gtk.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2007 Hiroyuki Yamamoto & the Claws Mail Team
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
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  * 
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "defs.h"
25
26 #include <glib.h>
27 #include <glib/gi18n.h>
28
29 #include <gtk/gtk.h>
30
31 #include "utils.h"
32 #include "folder.h"
33 #include "folderview.h"
34 #include "menu.h"
35 #include "account.h"
36 #include "alertpanel.h"
37 #include "inputdialog.h"
38 #include "mh.h"
39 #include "foldersel.h"
40
41 static void new_folder_cb(FolderView *folderview, guint action, GtkWidget *widget);
42 static void delete_folder_cb(FolderView *folderview, guint action, GtkWidget *widget);
43 static void rename_folder_cb(FolderView *folderview, guint action, GtkWidget *widget);
44 static void move_folder_cb(FolderView *folderview, guint action, GtkWidget *widget);
45 static void update_tree_cb(FolderView *folderview, guint action, GtkWidget *widget);
46 static void remove_mailbox_cb(FolderView *folderview, guint action, GtkWidget *widget);
47
48 static GtkItemFactoryEntry mh_popup_entries[] =
49 {
50         {N_("/Create _new folder..."),   NULL, new_folder_cb,     0, NULL},
51         {"/---",                         NULL, NULL,             0, "<Separator>"},
52         {N_("/_Rename folder..."),       NULL, rename_folder_cb,  0, NULL},
53         {N_("/M_ove folder..."),         NULL, move_folder_cb,    0, NULL},
54         {N_("/Cop_y folder..."),         NULL, move_folder_cb,    1, NULL},
55         {"/---",                         NULL, NULL,             0, "<Separator>"},
56         {N_("/_Delete folder..."),       NULL, delete_folder_cb,  0, NULL},
57         {"/---",                         NULL, NULL,              0, "<Separator>"},
58         {N_("/_Check for new messages"), NULL, update_tree_cb,    0, NULL},
59         {N_("/C_heck for new folders"),  NULL, update_tree_cb,    1, NULL},
60         {N_("/R_ebuild folder tree"),    NULL, update_tree_cb,    2, NULL},
61         {"/---",                         NULL, NULL,              0, "<Separator>"},
62         {N_("/Remove _mailbox..."),      NULL, remove_mailbox_cb, 0, NULL},
63         {"/---",                         NULL, NULL,              0, "<Separator>"},
64 };
65
66 static void set_sensitivity(GtkItemFactory *factory, FolderItem *item);
67
68 static FolderViewPopup mh_popup =
69 {
70         "mh",
71         "<MHFolder>",
72         NULL,
73         set_sensitivity
74 };
75
76 void mh_gtk_init(void)
77 {
78         guint i, n_entries;
79
80         n_entries = sizeof(mh_popup_entries) /
81                 sizeof(mh_popup_entries[0]);
82         for (i = 0; i < n_entries; i++)
83                 mh_popup.entries = g_slist_append(mh_popup.entries, &mh_popup_entries[i]);
84
85         folderview_register_popup(&mh_popup);
86 }
87
88 static void set_sensitivity(GtkItemFactory *factory, FolderItem *item)
89 {
90         gboolean folder_is_normal = 
91                         item != NULL &&
92                         item->stype == F_NORMAL &&
93                         !folder_has_parent_of_type(item, F_OUTBOX) &&
94                         !folder_has_parent_of_type(item, F_DRAFT) &&
95                         !folder_has_parent_of_type(item, F_QUEUE) &&
96                         !folder_has_parent_of_type(item, F_TRASH);
97 #define SET_SENS(name, sens) \
98         menu_set_sensitive(factory, name, sens)
99
100         SET_SENS("/Create new folder...",   TRUE);
101         SET_SENS("/Rename folder...",       item->stype == F_NORMAL && folder_item_parent(item) != NULL);
102         SET_SENS("/Move folder...",         folder_is_normal && folder_item_parent(item) != NULL);
103         SET_SENS("/Delete folder...",       item->stype == F_NORMAL && folder_item_parent(item) != NULL);
104
105         SET_SENS("/Check for new messages", folder_item_parent(item) == NULL);
106         SET_SENS("/Check for new folders",  folder_item_parent(item) == NULL);
107         SET_SENS("/Rebuild folder tree",    folder_item_parent(item) == NULL);
108
109         SET_SENS("/Remove mailbox...",         folder_item_parent(item) == NULL);
110
111 #undef SET_SENS
112 }
113
114 static void new_folder_cb(FolderView *folderview, guint action,
115                           GtkWidget *widget)
116 {
117         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
118         FolderItem *item;
119         FolderItem *new_item;
120         gchar *new_folder;
121         gchar *name;
122         gchar *p;
123
124         if (!folderview->selected) return;
125
126         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
127         g_return_if_fail(item != NULL);
128         g_return_if_fail(item->folder != NULL);
129
130         new_folder = input_dialog(_("New folder"),
131                                   _("Input the name of new folder:"),
132                                   _("NewFolder"));
133         if (!new_folder) return;
134         AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});
135
136         p = strchr(new_folder, G_DIR_SEPARATOR);
137         if (p) {
138                 alertpanel_error(_("'%c' can't be included in folder name."),
139                                  G_DIR_SEPARATOR);
140                 return;
141         }
142
143         name = trim_string(new_folder, 32);
144         AUTORELEASE_STR(name, {g_free(name); return;});
145
146         /* find whether the directory already exists */
147         if (folder_find_child_item_by_name(item, new_folder)) {
148                 alertpanel_error(_("The folder '%s' already exists."), name);
149                 return;
150         }
151
152         new_item = folder_create_folder(item, new_folder);
153         if (!new_item) {
154                 alertpanel_error(_("Can't create the folder '%s'."), name);
155                 return;
156         }
157
158         folder_write_list();
159 }
160
161 static void delete_folder_cb(FolderView *folderview, guint action,
162                              GtkWidget *widget)
163 {
164         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
165         FolderItem *item;
166         gchar *message, *name;
167         AlertValue avalue;
168         gchar *old_path;
169         gchar *old_id;
170
171         item = folderview_get_selected_item(folderview);
172         g_return_if_fail(item != NULL);
173         g_return_if_fail(item->path != NULL);
174         g_return_if_fail(item->folder != NULL);
175
176         name = trim_string(item->name, 32);
177         AUTORELEASE_STR(name, {g_free(name); return;});
178         message = g_markup_printf_escaped
179                 (_("All folders and messages under '%s' will be permanently deleted. "
180                    "Recovery will not be possible.\n\n"
181                    "Do you really want to delete?"), name);
182         avalue = alertpanel_full(_("Delete folder"), message,
183                                  GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, FALSE,
184                                  NULL, ALERT_WARNING, G_ALERTDEFAULT);
185         g_free(message);
186         if (avalue != G_ALERTALTERNATE) return;
187
188         Xstrdup_a(old_path, item->path, return);
189         old_id = folder_item_get_identifier(item);
190
191         if (folderview->opened == folderview->selected ||
192             gtk_ctree_is_ancestor(ctree,
193                                   folderview->selected,
194                                   folderview->opened)) {
195                 summary_clear_all(folderview->summaryview);
196                 folderview->opened = NULL;
197         }
198
199         if (item->folder->klass->remove_folder(item->folder, item) < 0) {
200                 folder_item_scan(item);
201                 alertpanel_error(_("Can't remove the folder '%s'."), name);
202                 g_free(old_id);
203                 return;
204         }
205
206         folder_write_list();
207
208         prefs_filtering_delete_path(old_id);
209         g_free(old_id);
210
211 }
212
213 static void rename_folder_cb(FolderView *folderview, guint action,
214                              GtkWidget *widget)
215 {
216         FolderItem *item;
217         gchar *new_folder;
218         gchar *name;
219         gchar *message;
220         gchar *old_path;
221         gchar *old_id;
222         gchar *new_id;
223         gchar *base;
224
225         item = folderview_get_selected_item(folderview);
226         g_return_if_fail(item != NULL);
227         g_return_if_fail(item->path != NULL);
228         g_return_if_fail(item->folder != NULL);
229
230         name = trim_string(item->name, 32);
231         message = g_strdup_printf(_("Input new name for '%s':"), name);
232         base = g_path_get_basename(item->path);
233         new_folder = input_dialog(_("Rename folder"), message, base);
234         g_free(message);
235         g_free(name);
236         g_free(base);
237         if (!new_folder) return;
238         AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});
239
240         if (strchr(new_folder, G_DIR_SEPARATOR) != NULL) {
241                 alertpanel_error(_("'%c' can't be included in folder name."),
242                                  G_DIR_SEPARATOR);
243                 return;
244         }
245
246         if (folder_find_child_item_by_name(folder_item_parent(item), new_folder)) {
247                 name = trim_string(new_folder, 32);
248                 alertpanel_error(_("The folder '%s' already exists."), name);
249                 g_free(name);
250                 return;
251         }
252
253         Xstrdup_a(old_path, item->path, {g_free(new_folder); return;});
254
255         old_id = folder_item_get_identifier(item);
256         
257         if (folder_item_rename(item, new_folder) < 0) {
258                 alertpanel_error(_("The folder could not be renamed.\n"
259                                    "The new folder name is not allowed."));
260                 g_free(old_id);
261                 return;
262         }
263
264         new_id = folder_item_get_identifier(item);
265         prefs_filtering_rename_path(old_id, new_id);
266         account_rename_path(old_id, new_id);
267         g_free(old_id);
268         g_free(new_id);
269
270         folder_item_prefs_save_config_recursive(item);
271         folder_write_list();
272 }
273
274 static void move_folder_cb(FolderView *folderview, guint action, GtkWidget *widget)
275 {
276         FolderItem *from_folder = NULL, *to_folder = NULL;
277
278         from_folder = folderview_get_selected_item(folderview);
279         if (!from_folder || from_folder->folder->klass != mh_get_class())
280                 return;
281
282         to_folder = foldersel_folder_sel(from_folder->folder, FOLDER_SEL_MOVE, NULL, TRUE);
283         if (!to_folder)
284                 return;
285         
286         folderview_move_folder(folderview, from_folder, to_folder, action);
287 }
288
289 static void update_tree_cb(FolderView *folderview, guint action,
290                            GtkWidget *widget)
291 {
292         FolderItem *item;
293
294         item = folderview_get_selected_item(folderview);
295         g_return_if_fail(item != NULL);
296
297         summary_show(folderview->summaryview, NULL);
298
299         g_return_if_fail(item->folder != NULL);
300
301         if (action == 0)
302                 folderview_check_new(item->folder);
303         else if (action == 1)
304                 folderview_rescan_tree(item->folder, FALSE);
305         else if (action == 2)
306                 folderview_rescan_tree(item->folder, TRUE);
307 }
308
309 static void remove_mailbox_cb(FolderView *folderview, guint action,
310                               GtkWidget *widget)
311 {
312         FolderItem *item;
313         gchar *name;
314         gchar *message;
315         AlertValue avalue;
316
317         item = folderview_get_selected_item(folderview);
318         g_return_if_fail(item != NULL);
319         g_return_if_fail(item->folder != NULL);
320         if (folder_item_parent(item)) return;
321
322         name = trim_string(item->folder->name, 32);
323         message = g_markup_printf_escaped
324                 (_("Really remove the mailbox '%s' ?\n"
325                    "(The messages are NOT deleted from the disk)"), name);
326         avalue = alertpanel_full(_("Remove mailbox"), message,
327                                  GTK_STOCK_CANCEL, _("_Remove"), NULL, FALSE,
328                                  NULL, ALERT_WARNING, G_ALERTDEFAULT);
329                             
330         g_free(message);
331         g_free(name);
332         if (avalue != G_ALERTALTERNATE) return;
333
334         folderview_unselect(folderview);
335         summary_clear_all(folderview->summaryview);
336
337         folder_destroy(item->folder);
338 }
339