1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2012 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 #include "claws-features.h"
23 #endif
24 
25 #include "defs.h"
26 
27 #include <glib.h>
28 #include <glib/gi18n.h>
29 
30 #include <gtk/gtk.h>
31 #include <time.h>
32 
33 #include "utils.h"
34 #include "folder.h"
35 #include "folder_item_prefs.h"
36 #include "folderview.h"
37 #include "menu.h"
38 #include "account.h"
39 #include "alertpanel.h"
40 #include "foldersel.h"
41 #include "inputdialog.h"
42 #include "imap.h"
43 #include "inc.h"
44 #include "prefs_common.h"
45 #include "statusbar.h"
46 #include "summaryview.h"
47 #include "prefs_actions.h"
48 
49 static void new_folder_cb(GtkAction *action, gpointer data);
50 static void rename_folder_cb(GtkAction *action, gpointer data);
51 static void move_folder_cb(GtkAction *action, gpointer data);
52 static void copy_folder_cb(GtkAction *action, gpointer data);
53 static void delete_folder_cb(GtkAction *action, gpointer data);
54 static void update_tree_cb(GtkAction *action, gpointer data);
55 static void download_cb(GtkAction *action, gpointer data);
56 static void sync_cb(GtkAction *action, gpointer data);
57 static void subscribed_cb(GtkAction *action, gpointer data);
58 static void subscribe_cb(GtkAction *action, gpointer data);
59 static void unsubscribe_cb(GtkAction *action, gpointer data);
60 
61 static GtkActionEntry imap_popup_entries[] =
62 {
63 	{"FolderViewPopup/CreateNewFolder",	NULL, N_("Create _new folder..."), NULL, NULL, G_CALLBACK(new_folder_cb) },
64 
65 	{"FolderViewPopup/RenameFolder",	NULL, N_("_Rename folder..."), NULL, NULL, G_CALLBACK(rename_folder_cb) },
66 	{"FolderViewPopup/MoveFolder",		NULL, N_("M_ove folder..."), NULL, NULL, G_CALLBACK(move_folder_cb) },
67 	{"FolderViewPopup/CopyFolder",		NULL, N_("Cop_y folder..."), NULL, NULL, G_CALLBACK(copy_folder_cb) },
68 
69 	{"FolderViewPopup/DeleteFolder",	NULL, N_("_Delete folder..."), NULL, NULL, G_CALLBACK(delete_folder_cb) },
70 
71 	{"FolderViewPopup/Synchronise",		NULL, N_("Synchronise"), NULL, NULL, G_CALLBACK(sync_cb) },
72 	{"FolderViewPopup/DownloadMessages",	NULL, N_("Down_load messages"), NULL, NULL, G_CALLBACK(download_cb) },
73 
74 
75 	{"FolderViewPopup/Subscriptions",	NULL, N_("S_ubscriptions"), NULL, NULL, NULL },
76 	{"FolderViewPopup/Subscriptions/---",	NULL, "---", NULL, NULL, NULL },
77 	{"FolderViewPopup/Subscriptions/Subscribe",	NULL, N_("_Subscribe..."), NULL, NULL, G_CALLBACK(subscribe_cb) },
78 	{"FolderViewPopup/Subscriptions/Unsubscribe",	NULL, N_("_Unsubscribe..."), NULL, NULL, G_CALLBACK(unsubscribe_cb) },
79 
80 	{"FolderViewPopup/CheckNewMessages",	NULL, N_("_Check for new messages"), NULL, NULL, G_CALLBACK(update_tree_cb) }, /*0*/
81 	{"FolderViewPopup/CheckNewFolders",	NULL, N_("C_heck for new folders"), NULL, NULL, G_CALLBACK(update_tree_cb) }, /*1*/
82 	{"FolderViewPopup/RebuildTree",		NULL, N_("R_ebuild folder tree"), NULL, NULL, G_CALLBACK(update_tree_cb) }, /*2*/
83 };
84 
85 static GtkToggleActionEntry imap_toggle_popup_entries[] =
86 {
87 	{"FolderViewPopup/Subscriptions/ShowOnlySubs",	NULL, N_("Show only subscribed _folders"), NULL, NULL, G_CALLBACK(subscribed_cb), FALSE },
88 };
89 
90 static void set_sensitivity(GtkUIManager *ui_manager, FolderItem *item);
91 static void add_menuitems(GtkUIManager *ui_manager, FolderItem *item);
92 
93 static FolderViewPopup imap_popup =
94 {
95 	"imap",
96 	"<IMAPFolder>",
97 	imap_popup_entries,
98 	G_N_ELEMENTS(imap_popup_entries),
99 	imap_toggle_popup_entries,
100 	G_N_ELEMENTS(imap_toggle_popup_entries),
101 	NULL, 0, 0, NULL,
102 	add_menuitems,
103 	set_sensitivity
104 };
105 
imap_gtk_init(void)106 void imap_gtk_init(void)
107 {
108 	folderview_register_popup(&imap_popup);
109 }
110 
add_menuitems(GtkUIManager * ui_manager,FolderItem * item)111 static void add_menuitems(GtkUIManager *ui_manager, FolderItem *item)
112 {
113 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CreateNewFolder", "FolderViewPopup/CreateNewFolder", GTK_UI_MANAGER_MENUITEM)
114 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorIMAP1", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
115 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RenameFolder", "FolderViewPopup/RenameFolder", GTK_UI_MANAGER_MENUITEM)
116 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "MoveFolder", "FolderViewPopup/MoveFolder", GTK_UI_MANAGER_MENUITEM)
117 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CopyFolder", "FolderViewPopup/CopyFolder", GTK_UI_MANAGER_MENUITEM)
118 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorIMAP2", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
119 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "DeleteFolder", "FolderViewPopup/DeleteFolder", GTK_UI_MANAGER_MENUITEM)
120 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorIMAP3", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
121 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "Synchronise", "FolderViewPopup/Synchronise", GTK_UI_MANAGER_MENUITEM)
122 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "DownloadMessages", "FolderViewPopup/DownloadMessages", GTK_UI_MANAGER_MENUITEM)
123 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorIMAP4", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
124 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "Subscriptions", "FolderViewPopup/Subscriptions", GTK_UI_MANAGER_MENU)
125 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup/Subscriptions", "ShowOnlySubs", "FolderViewPopup/Subscriptions/ShowOnlySubs", GTK_UI_MANAGER_MENUITEM)
126 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup/Subscriptions", "SeparatorIMAP5", "FolderViewPopup/Subscriptions/---", GTK_UI_MANAGER_SEPARATOR)
127 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup/Subscriptions", "Subscribe", "FolderViewPopup/Subscriptions/Subscribe", GTK_UI_MANAGER_MENUITEM)
128 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup/Subscriptions", "Unsubscribe", "FolderViewPopup/Subscriptions/Unsubscribe", GTK_UI_MANAGER_MENUITEM)
129 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CheckNewMessages", "FolderViewPopup/CheckNewMessages", GTK_UI_MANAGER_MENUITEM)
130 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CheckNewFolders", "FolderViewPopup/CheckNewFolders", GTK_UI_MANAGER_MENUITEM)
131 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RebuildTree", "FolderViewPopup/RebuildTree", GTK_UI_MANAGER_MENUITEM)
132 	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorIMAP6", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
133 }
134 
set_sensitivity(GtkUIManager * ui_manager,FolderItem * item)135 static void set_sensitivity(GtkUIManager *ui_manager, FolderItem *item)
136 {
137 	gboolean folder_is_normal =
138 			item != NULL &&
139 			item->stype == F_NORMAL &&
140 			!folder_has_parent_of_type(item, F_OUTBOX) &&
141 			!folder_has_parent_of_type(item, F_DRAFT) &&
142 			!folder_has_parent_of_type(item, F_QUEUE) &&
143 			!folder_has_parent_of_type(item, F_TRASH);
144 
145 #define SET_SENS(name, sens) \
146 	cm_menu_set_sensitive_full(ui_manager, "Popup/"name, sens)
147 
148 	SET_SENS("FolderViewPopup/CreateNewFolder",   item && item->no_sub == FALSE);
149 	SET_SENS("FolderViewPopup/RenameFolder",       item && item->stype == F_NORMAL && folder_item_parent(item) != NULL);
150 	SET_SENS("FolderViewPopup/MoveFolder", 	    item && folder_is_normal && folder_item_parent(item) != NULL);
151 	SET_SENS("FolderViewPopup/DeleteFolder", 	    item && item->stype == F_NORMAL && folder_item_parent(item) != NULL);
152 
153 	SET_SENS("FolderViewPopup/CheckNewMessages", folder_item_parent(item) == NULL);
154 	SET_SENS("FolderViewPopup/CheckNewFolders",  folder_item_parent(item) == NULL);
155 	SET_SENS("FolderViewPopup/RebuildTree",    folder_item_parent(item) == NULL);
156 
157 	SET_SENS("FolderViewPopup/Synchronise",
158 			item ? (folder_item_parent(item) != NULL
159 			&& folder_want_synchronise(item->folder))
160 			: FALSE);
161 	SET_SENS("FolderViewPopup/DownloadMessages", item && !item->no_select);
162 
163 	SET_SENS("FolderViewPopup/CheckNewMessages", folder_item_parent(item) == NULL);
164 	SET_SENS("FolderViewPopup/CheckNewFolders",  folder_item_parent(item) == NULL);
165 	SET_SENS("FolderViewPopup/RebuildTree",    folder_item_parent(item) == NULL);
166 
167 	SET_SENS("FolderViewPopup/Subscriptions/Unsubscribe",    item && item->stype == F_NORMAL && folder_item_parent(item) != NULL);
168 	SET_SENS("FolderViewPopup/Subscriptions/Subscribe",    TRUE);
169 	if (item && item->folder && item->folder->account)
170 		cm_toggle_menu_set_active_full(ui_manager, "Popup/FolderViewPopup/Subscriptions/ShowOnlySubs",
171 			item->folder->account->imap_subsonly);
172 
173 #undef SET_SENS
174 }
175 
new_folder_cb(GtkAction * action,gpointer data)176 static void new_folder_cb(GtkAction *action, gpointer data)
177 {
178 	FolderView *folderview = (FolderView *)data;
179 	FolderItem *item;
180 	FolderItem *new_item;
181 	gchar *new_folder;
182 	gchar *name;
183 	gchar *p;
184 	gchar separator = '/';
185 
186 	if ((item = folderview_get_selected_item(folderview)) == NULL) return;
187 
188 	cm_return_if_fail(item != NULL);
189 	cm_return_if_fail(item->folder != NULL);
190 	cm_return_if_fail(item->folder->account != NULL);
191 
192 	new_folder = input_dialog_with_checkbtn
193 		(_("New folder"),
194 		 _("Input the name of new folder:\n"
195 		   "(if you want to create a folder to store subfolders\n"
196 		   "only and no mail, append '/' to the folder name)"),
197 		 _("NewFolder"),
198 		 _("Inherit properties and processing rules from parent folder"),
199 		 &(prefs_common.inherit_folder_props));
200 
201 	if (!new_folder) return;
202 	AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});
203 
204 	separator = imap_get_path_separator_for_item(item);
205 
206 	p = strchr(new_folder, separator);
207 	if (p && *(p + 1) != '\0') {
208 		alertpanel_error(_("'%c' can't be included in folder name."),
209 				 separator);
210 		return;
211 	}
212 	p = strchr(new_folder, '/');
213 	if (p && *(p + 1) != '\0') {
214 		alertpanel_error(_("'%c' can't be included in folder name."),
215 				 '/');
216 		return;
217 	}
218 
219 	name = trim_string(new_folder, 32);
220 	AUTORELEASE_STR(name, {g_free(name); return;});
221 
222 	/* find whether the directory already exists */
223 	if (folder_find_child_item_by_name(item, new_folder)) {
224 		alertpanel_error(_("The folder '%s' already exists."), name);
225 		return;
226 	}
227 
228 	new_item = folder_create_folder(item, new_folder);
229 	if (!new_item) {
230 		alertpanel_error(_("Can't create the folder '%s'."), name);
231 		return;
232 	}
233 
234 	if (prefs_common.inherit_folder_props) {
235 		folder_item_prefs_copy_prefs(item, new_item);
236 	}
237 
238 	folder_write_list();
239 }
240 
rename_folder_cb(GtkAction * action,gpointer data)241 static void rename_folder_cb(GtkAction *action, gpointer data)
242 {
243 	FolderView *folderview = (FolderView *)data;
244 	FolderItem *item;
245 	gchar *new_folder;
246 	gchar *name;
247 	gchar *message;
248 	gchar *old_id;
249 	gchar *new_id;
250 	gchar *base;
251 	gchar separator = '/';
252 
253 	item = folderview_get_selected_item(folderview);
254 	cm_return_if_fail(item != NULL);
255 	cm_return_if_fail(item->path != NULL);
256 	cm_return_if_fail(item->folder != NULL);
257 
258 	name = trim_string(item->name, 32);
259 	message = g_strdup_printf(_("Input new name for '%s':"), name);
260 	base = g_path_get_basename(item->path);
261 	new_folder = input_dialog(_("Rename folder"), message, base);
262 	g_free(base);
263 	g_free(message);
264 	g_free(name);
265 	if (!new_folder) return;
266 	AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});
267 
268 	separator = imap_get_path_separator_for_item(item);
269 	if (strchr(new_folder, separator) != NULL) {
270 		alertpanel_error(_("'%c' can't be included in folder name."),
271 				 separator);
272 		return;
273 	}
274 	if (strchr(new_folder, '/') != NULL) {
275 		alertpanel_error(_("'%c' can't be included in folder name."),
276 				 '/');
277 		return;
278 	}
279 
280 	if (folder_find_child_item_by_name(folder_item_parent(item), new_folder)) {
281 		name = trim_string(new_folder, 32);
282 		alertpanel_error(_("The folder '%s' already exists."), name);
283 		g_free(name);
284 		return;
285 	}
286 
287 	old_id = folder_item_get_identifier(item);
288 
289 	if (folder_item_rename(item, new_folder) < 0) {
290 		alertpanel_error(_("The folder could not be renamed.\n"
291 				   "The new folder name is not allowed."));
292 		g_free(old_id);
293 		return;
294 	}
295 
296 	new_id = folder_item_get_identifier(item);
297 	prefs_filtering_rename_path(old_id, new_id);
298 	account_rename_path(old_id, new_id);
299 	prefs_actions_rename_path(old_id, new_id);
300 	g_free(old_id);
301 	g_free(new_id);
302 
303 	folder_item_prefs_save_config_recursive(item);
304 	folder_write_list();
305 }
306 
move_folder_cb(GtkAction * action,gpointer data)307 static void move_folder_cb(GtkAction *action, gpointer data)
308 {
309 	FolderView *folderview = (FolderView *)data;
310 	FolderItem *from_folder = NULL, *to_folder = NULL;
311 	gchar *msg;
312 
313 	from_folder = folderview_get_selected_item(folderview);
314 	if (!from_folder || from_folder->folder->klass != imap_get_class())
315 		return;
316 
317 	msg = g_strdup_printf(_("Select folder to move folder '%s' to"),
318 		from_folder->name);
319 	to_folder = foldersel_folder_sel(NULL, FOLDER_SEL_MOVE, NULL, TRUE, msg);
320 	g_free(msg);
321 	if (!to_folder)
322 		return;
323 
324 	folderview_move_folder(folderview, from_folder, to_folder, 0);
325 }
326 
copy_folder_cb(GtkAction * action,gpointer data)327 static void copy_folder_cb(GtkAction *action, gpointer data)
328 {
329 	FolderView *folderview = (FolderView *)data;
330 	FolderItem *from_folder = NULL, *to_folder = NULL;
331 	gchar *msg;
332 
333 	from_folder = folderview_get_selected_item(folderview);
334 	if (!from_folder || from_folder->folder->klass != imap_get_class())
335 		return;
336 
337 	msg = g_strdup_printf(_("Select folder to copy folder '%s' to"),
338 		from_folder->name);
339 	to_folder = foldersel_folder_sel(NULL, FOLDER_SEL_MOVE, NULL, TRUE, msg);
340 	g_free(msg);
341 	if (!to_folder)
342 		return;
343 
344 	folderview_move_folder(folderview, from_folder, to_folder, 1);
345 }
346 
delete_folder_cb(GtkAction * action,gpointer data)347 static void delete_folder_cb(GtkAction *action, gpointer data)
348 {
349 	FolderView *folderview = (FolderView *)data;
350 	FolderItem *item, *opened;
351 	gchar *message, *name;
352 	AlertValue avalue;
353 	gchar *old_id;
354 
355 	if ((item = folderview_get_selected_item(folderview)) == NULL) return;
356 	opened = folderview_get_opened_item(folderview);
357 
358 	cm_return_if_fail(item != NULL);
359 	cm_return_if_fail(item->path != NULL);
360 	cm_return_if_fail(item->folder != NULL);
361 
362 	name = trim_string(item->name, 32);
363 	AUTORELEASE_STR(name, {g_free(name); return;});
364 	message = g_markup_printf_escaped
365 		(_("All folders and messages under '%s' will be permanently deleted. "
366 		   "Recovery will not be possible.\n\n"
367 		   "Do you really want to delete?"), name);
368 	avalue = alertpanel_full(_("Delete folder"), message,
369 		 		 GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, ALERTFOCUS_FIRST, FALSE,
370 				 NULL, ALERT_WARNING);
371 	g_free(message);
372 	if (avalue != G_ALERTALTERNATE) return;
373 
374 	old_id = folder_item_get_identifier(item);
375 
376 	if (item == opened ||
377 			folder_is_child_of(item, opened)) {
378 		summary_clear_all(folderview->summaryview);
379 		folderview_close_opened(folderview, TRUE);
380 	}
381 
382 	if (item->folder->klass->remove_folder(item->folder, item) < 0) {
383 		folder_item_scan(item);
384 		alertpanel_error(_("Can't remove the folder '%s'."), name);
385 		g_free(old_id);
386 		return;
387 	}
388 
389 	folder_write_list();
390 
391 	prefs_filtering_delete_path(old_id);
392 	g_free(old_id);
393 
394 }
395 
396 #define DO_ACTION(name, act)	{ if (!strcmp(a_name, name)) act; }
397 
update_tree_cb(GtkAction * action,gpointer data)398 static void update_tree_cb(GtkAction *action, gpointer data)
399 {
400 	FolderView *folderview = (FolderView *)data;
401 	FolderItem *item;
402 	const gchar *a_name = gtk_action_get_name(action);
403 
404 	item = folderview_get_selected_item(folderview);
405 	cm_return_if_fail(item != NULL);
406 
407 	summary_show(folderview->summaryview, NULL, FALSE);
408 
409 	cm_return_if_fail(item->folder != NULL);
410 
411 	DO_ACTION("FolderViewPopup/CheckNewMessages", folderview_check_new(item->folder));
412 	DO_ACTION("FolderViewPopup/CheckNewFolders", folderview_rescan_tree(item->folder, FALSE));
413 	DO_ACTION("FolderViewPopup/RebuildTree", folderview_rescan_tree(item->folder, TRUE));
414 }
415 
sync_cb(GtkAction * action,gpointer data)416 static void sync_cb(GtkAction *action, gpointer data)
417 {
418 	FolderView *folderview = (FolderView *)data;
419 	FolderItem *item;
420 
421 	item = folderview_get_selected_item(folderview);
422 	cm_return_if_fail(item != NULL);
423 	folder_synchronise(item->folder);
424 }
425 
imap_gtk_synchronise(FolderItem * item,gint days)426 void imap_gtk_synchronise(FolderItem *item, gint days)
427 {
428 	MainWindow *mainwin = mainwindow_get_mainwindow();
429 	FolderView *folderview = mainwin->folderview;
430 
431 	cm_return_if_fail(item != NULL);
432 	cm_return_if_fail(item->folder != NULL);
433 
434 	main_window_cursor_wait(mainwin);
435 	inc_lock();
436 	main_window_lock(mainwin);
437 	gtk_widget_set_sensitive(folderview->ctree, FALSE);
438 	main_window_progress_on(mainwin);
439 	GTK_EVENTS_FLUSH();
440 	if (item->no_select == FALSE) {
441 		GSList *mlist;
442 		GSList *cur;
443 		gint num = 0;
444 		gint total = item->total_msgs;
445 		time_t t = time(NULL);
446 
447 		mlist = folder_item_get_msg_list(item);
448 		for (cur = mlist; cur != NULL; cur = cur->next) {
449 			MsgInfo *msginfo = (MsgInfo *)cur->data;
450 			gint age = (t - msginfo->date_t) / (60*60*24);
451 			if (days == 0 || age <= days)
452 				imap_cache_msg(msginfo->folder, msginfo->msgnum);
453 			statusbar_progress_all(num++,total, 100);
454 			if (num % 100 == 0)
455 				GTK_EVENTS_FLUSH();
456 		}
457 
458 		statusbar_progress_all(0,0,0);
459 		procmsg_msg_list_free(mlist);
460 	}
461 
462 	folder_set_ui_func(item->folder, NULL, NULL);
463 	main_window_progress_off(mainwin);
464 	gtk_widget_set_sensitive(folderview->ctree, TRUE);
465 	main_window_unlock(mainwin);
466 	inc_unlock();
467 	main_window_cursor_normal(mainwin);
468 }
469 
chk_update_val(GtkWidget * widget,gpointer data)470 static void chk_update_val(GtkWidget *widget, gpointer data)
471 {
472         gboolean *val = (gboolean *)data;
473 	*val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
474 }
475 
imap_gtk_subscribe_func(GNode * node,gpointer data)476 static gboolean imap_gtk_subscribe_func(GNode *node, gpointer data)
477 {
478 	FolderItem *item = node->data;
479 	gboolean action = GPOINTER_TO_INT(data);
480 
481 	if (item->path)
482 		imap_subscribe(item->folder, item, NULL, action);
483 
484 	return FALSE;
485 }
486 
subscribe_cb_full(FolderView * folderview,guint action)487 static void subscribe_cb_full(FolderView *folderview, guint action)
488 {
489 	FolderItem *item;
490 	gchar *message, *name;
491 	AlertValue avalue;
492 	GtkWidget *rec_chk;
493 	gboolean recurse = FALSE;
494 
495 	if ((item = folderview_get_selected_item(folderview)) == NULL) return;
496 	cm_return_if_fail(item->folder != NULL);
497 
498 	name = trim_string(item->name, 32);
499 	AUTORELEASE_STR(name, {g_free(name); return;});
500 
501 	if (action && item->folder->account->imap_subsonly) {
502 		GList *child_list = NULL;
503 		GList *transc_list = NULL;
504 
505 		message = g_markup_printf_escaped
506 			(_("Do you want to search for unsubscribed subfolders of '%s'?"),
507 			 name);
508 
509 		rec_chk = gtk_check_button_new_with_label(_("Search recursively"));
510 
511 		g_signal_connect(G_OBJECT(rec_chk), "toggled",
512 				G_CALLBACK(chk_update_val), &recurse);
513 
514 		avalue = alertpanel_full(_("Subscriptions"), message,
515 		 			 GTK_STOCK_CANCEL, _("_Search"), NULL, ALERTFOCUS_SECOND,
516 					 FALSE, rec_chk, ALERT_QUESTION);
517 		g_free(message);
518 		if (avalue != G_ALERTALTERNATE) return;
519 
520 		child_list = imap_scan_subtree(item->folder, item, TRUE, recurse);
521 
522 		if (child_list) {
523 			GList *cur;
524 			int r = -1;
525 			gchar *msg = g_strdup_printf(_("Choose a subfolder of %s to subscribe to: "),
526 					item->name);
527 			gchar *child_folder = NULL;
528 
529 			for (cur = child_list; cur; cur = cur->next) {
530 				transc_list = g_list_append(transc_list,
531 					imap_modified_utf7_to_utf8(cur->data, FALSE));
532 			}
533 
534 			transc_list = g_list_sort(transc_list, g_str_equal);
535 
536 			child_folder = input_dialog_combo(_("Subscribe"),
537 					msg,
538 					transc_list->next?_("All of them"):transc_list->data, transc_list);
539 			g_free(msg);
540 			if (child_folder && strcmp(child_folder, _("All of them"))) {
541 				gchar *transc_folder = imap_utf8_to_modified_utf7(child_folder, FALSE);
542 				r = imap_subscribe(item->folder, NULL, transc_folder, TRUE);
543 				g_free(transc_folder);
544 			} else if (child_folder) {
545 				for (cur = child_list; cur; cur = cur->next)
546 					r = imap_subscribe(item->folder, NULL, (gchar *)cur->data, TRUE);
547 			}
548 			g_free(child_folder);
549 			for (cur = child_list; cur; cur = cur->next)
550 				g_free((gchar *)cur->data);
551 			for (cur = transc_list; cur; cur = cur->next)
552 				g_free((gchar *)cur->data);
553 			if (r == 0)
554 				folderview_rescan_tree(item->folder, FALSE);
555 		} else {
556 			alertpanel_notice(_("This folder is already subscribed and "
557 				  "has no unsubscribed subfolders.\n\nIf there are new folders, "
558 				  "created and subscribed to from another client, use \"Check "
559 				  "for new folders\" at the mailbox's root folder."));
560 		}
561 		g_list_free(child_list);
562 		return;
563 	}
564 	message = g_markup_printf_escaped
565 		(_("Do you want to %s the '%s' folder?"),
566 		   action?_("subscribe"):_("unsubscribe"), name);
567 
568 	rec_chk = gtk_check_button_new_with_label(_("Apply to subfolders"));
569 
570 	g_signal_connect(G_OBJECT(rec_chk), "toggled",
571 			G_CALLBACK(chk_update_val), &recurse);
572 
573 	avalue = alertpanel_full(_("Subscriptions"), message,
574 		 		 GTK_STOCK_CANCEL, action?_("_Subscribe"):_("_Unsubscribe"), NULL,
575 				 ALERTFOCUS_SECOND, FALSE, rec_chk, ALERT_QUESTION);
576 	g_free(message);
577 	if (avalue != G_ALERTALTERNATE) return;
578 
579 	FolderItem *opened = folderview_get_opened_item(folderview);
580 	FolderItem *selected = folderview_get_selected_item(folderview);
581 	if (!action) {
582 		if (opened == selected ||
583 				folder_is_child_of(selected, opened)) {
584 			summary_clear_all(folderview->summaryview);
585 			folderview_close_opened(folderview, TRUE);
586 		}
587 	}
588 
589 	if (recurse) {
590 		g_node_traverse(item->node, G_PRE_ORDER,
591 			G_TRAVERSE_ALL, -1, imap_gtk_subscribe_func, GINT_TO_POINTER(action));
592 	} else {
593 		imap_subscribe(item->folder, item, NULL, action);
594 	}
595 
596 	if (!action && item->folder->account->imap_subsonly)
597 		folderview_rescan_tree(item->folder, FALSE);
598 }
599 
subscribe_cb(GtkAction * action,gpointer data)600 static void subscribe_cb(GtkAction *action, gpointer data)
601 {
602 	subscribe_cb_full((FolderView *)data, 1);
603 }
604 
unsubscribe_cb(GtkAction * action,gpointer data)605 static void unsubscribe_cb(GtkAction *action, gpointer data)
606 {
607 	subscribe_cb_full((FolderView *)data, 0);
608 }
609 
subscribed_cb(GtkAction * action,gpointer data)610 static void subscribed_cb(GtkAction *action, gpointer data)
611 {
612 	FolderView *folderview = (FolderView *)data;
613 	FolderItem *item = folderview_get_selected_item(folderview);
614 	FolderItem *opened = folderview_get_opened_item(folderview);
615 
616 	if (!item || !item->folder || !item->folder->account)
617 		return;
618 	if (item->folder->account->imap_subsonly == gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
619 		return;
620 
621 	if (opened == item ||
622 			folder_is_child_of(item, opened)) {
623 		summary_clear_all(folderview->summaryview);
624 		folderview_close_opened(folderview, TRUE);
625 	}
626 
627 	item->folder->account->imap_subsonly = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
628 	folderview_rescan_tree(item->folder, FALSE);
629 }
630 
download_cb(GtkAction * action,gpointer data)631 static void download_cb(GtkAction *action, gpointer data)
632 {
633 	FolderView *folderview = (FolderView *)data;
634 	FolderItem *item;
635 
636 	if ((item = folderview_get_selected_item(folderview)) == NULL)
637 		return;
638 	imap_gtk_synchronise(item, 0);
639 }
640