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