mh_gtk.c (13372B)
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 27 #include "utils.h" 28 #include "folder.h" 29 #include "folder_item_prefs.h" 30 #include "folderview.h" 31 #include "menu.h" 32 #include "account.h" 33 #include "alertpanel.h" 34 #include "inputdialog.h" 35 #include "mh.h" 36 #include "foldersel.h" 37 #include "prefs_common.h" 38 #include "prefs_actions.h" 39 40 static void new_folder_cb(GtkAction *action, gpointer data); 41 static void delete_folder_cb(GtkAction *action, gpointer data); 42 static void rename_folder_cb(GtkAction *action, gpointer data); 43 static void move_folder_cb(GtkAction *action, gpointer data); 44 static void copy_folder_cb(GtkAction *action, gpointer data); 45 static void update_tree_cb(GtkAction *action, gpointer data); 46 static void remove_mailbox_cb(GtkAction *action, gpointer data); 47 48 static GtkActionEntry mh_popup_entries[] = 49 { 50 {"FolderViewPopup/CreateNewFolder", NULL, N_("Create _new folder..."), NULL, NULL, G_CALLBACK(new_folder_cb) }, 51 {"FolderViewPopup/RenameFolder", NULL, N_("_Rename folder..."), NULL, NULL, G_CALLBACK(rename_folder_cb) }, 52 {"FolderViewPopup/MoveFolder", NULL, N_("M_ove folder..."), NULL, NULL, G_CALLBACK(move_folder_cb) }, 53 {"FolderViewPopup/CopyFolder", NULL, N_("Cop_y folder..."), NULL, NULL, G_CALLBACK(copy_folder_cb) }, 54 {"FolderViewPopup/DeleteFolder", NULL, N_("_Delete folder..."), NULL, NULL, G_CALLBACK(delete_folder_cb) }, 55 {"FolderViewPopup/CheckNewMessages", NULL, N_("_Check for new messages"), NULL, NULL, G_CALLBACK(update_tree_cb) }, /*0*/ 56 {"FolderViewPopup/CheckNewFolders", NULL, N_("C_heck for new folders"), NULL, NULL, G_CALLBACK(update_tree_cb) }, /*1*/ 57 {"FolderViewPopup/RebuildTree", NULL, N_("R_ebuild folder tree"), NULL, NULL, G_CALLBACK(update_tree_cb) }, /*2*/ 58 {"FolderViewPopup/RemoveMailbox", NULL, N_("Remove _mailbox..."), NULL, NULL, G_CALLBACK(remove_mailbox_cb) }, 59 }; 60 static void set_sensitivity(GtkUIManager *ui_manager, FolderItem *item); 61 static void add_menuitems(GtkUIManager *ui_manager, FolderItem *item); 62 63 static FolderViewPopup mh_popup = 64 { 65 "mh", 66 "<MHFolder>", 67 mh_popup_entries, 68 G_N_ELEMENTS(mh_popup_entries), 69 NULL, 0, 70 NULL, 0, 0, NULL, 71 add_menuitems, 72 set_sensitivity 73 }; 74 75 void mh_gtk_init(void) 76 { } 77 78 static void add_menuitems(GtkUIManager *ui_manager, FolderItem *item) 79 { 80 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CreateNewFolder", "FolderViewPopup/CreateNewFolder", GTK_UI_MANAGER_MENUITEM) 81 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMH1", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR) 82 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RenameFolder", "FolderViewPopup/RenameFolder", GTK_UI_MANAGER_MENUITEM) 83 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "MoveFolder", "FolderViewPopup/MoveFolder", GTK_UI_MANAGER_MENUITEM) 84 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CopyFolder", "FolderViewPopup/CopyFolder", GTK_UI_MANAGER_MENUITEM) 85 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMH2", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR) 86 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "DeleteFolder", "FolderViewPopup/DeleteFolder", GTK_UI_MANAGER_MENUITEM) 87 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMH3", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR) 88 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CheckNewMessages", "FolderViewPopup/CheckNewMessages", GTK_UI_MANAGER_MENUITEM) 89 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CheckNewFolders", "FolderViewPopup/CheckNewFolders", GTK_UI_MANAGER_MENUITEM) 90 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RebuildTree", "FolderViewPopup/RebuildTree", GTK_UI_MANAGER_MENUITEM) 91 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMH4", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR) 92 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RemoveMailbox", "FolderViewPopup/RemoveMailbox", GTK_UI_MANAGER_MENUITEM) 93 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMH5", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR) 94 } 95 96 static void set_sensitivity(GtkUIManager *ui_manager, FolderItem *item) 97 { 98 gboolean folder_is_normal = 99 item != NULL && 100 item->stype == F_NORMAL && 101 !folder_has_parent_of_type(item, F_OUTBOX) && 102 !folder_has_parent_of_type(item, F_DRAFT) && 103 !folder_has_parent_of_type(item, F_QUEUE) && 104 !folder_has_parent_of_type(item, F_TRASH); 105 #define SET_SENS(name, sens) \ 106 cm_menu_set_sensitive_full(ui_manager, "Popup/"name, sens) 107 108 SET_SENS("FolderViewPopup/CreateNewFolder", TRUE); 109 SET_SENS("FolderViewPopup/RenameFolder", item && item->stype == F_NORMAL && folder_item_parent(item) != NULL); 110 SET_SENS("FolderViewPopup/MoveFolder", folder_is_normal && folder_item_parent(item) != NULL); 111 SET_SENS("FolderViewPopup/DeleteFolder", item && item->stype == F_NORMAL && folder_item_parent(item) != NULL); 112 113 SET_SENS("FolderViewPopup/CheckNewMessages", folder_item_parent(item) == NULL); 114 SET_SENS("FolderViewPopup/CheckNewFolders", folder_item_parent(item) == NULL); 115 SET_SENS("FolderViewPopup/RebuildTree", folder_item_parent(item) == NULL); 116 117 SET_SENS("FolderViewPopup/RemoveMailbox", folder_item_parent(item) == NULL); 118 119 #undef SET_SENS 120 } 121 122 static void new_folder_cb(GtkAction *action, gpointer data) 123 { 124 FolderView *folderview = (FolderView *)data; 125 FolderItem *item; 126 FolderItem *new_item; 127 gchar *new_folder; 128 gchar *name; 129 gchar *p; 130 131 if (!folderview_get_selected_item(folderview)) return; 132 133 item = folderview_get_selected_item(folderview); 134 cm_return_if_fail(item != NULL); 135 cm_return_if_fail(item->folder != NULL); 136 137 new_folder = input_dialog_with_checkbtn(_("New folder"), 138 _("Input the name of new folder:"), 139 _("NewFolder"), 140 _("Inherit properties and processing rules from parent folder"), 141 &(prefs_common.inherit_folder_props)); 142 if (!new_folder) return; 143 AUTORELEASE_STR(new_folder, {g_free(new_folder); return;}); 144 145 p = strchr(new_folder, G_DIR_SEPARATOR); 146 if (p) { 147 alertpanel_error(_("'%c' can't be included in folder name."), 148 G_DIR_SEPARATOR); 149 return; 150 } 151 152 if (!folder_local_name_ok(new_folder)) 153 return; 154 155 name = trim_string(new_folder, 32); 156 AUTORELEASE_STR(name, {g_free(name); return;}); 157 158 /* find whether the directory already exists */ 159 if (folder_find_child_item_by_name(item, new_folder)) { 160 alertpanel_error(_("The folder '%s' already exists."), name); 161 return; 162 } 163 164 new_item = folder_create_folder(item, new_folder); 165 if (!new_item) { 166 alertpanel_error(_("Can't create the folder '%s'."), name); 167 return; 168 } 169 170 if (prefs_common.inherit_folder_props) { 171 folder_item_prefs_copy_prefs(item, new_item); 172 } 173 174 folder_write_list(); 175 } 176 177 static void delete_folder_cb(GtkAction *action, gpointer data) 178 { 179 FolderView *folderview = (FolderView *)data; 180 FolderItem *item, *opened; 181 gchar *message, *name; 182 AlertValue avalue; 183 gchar *old_id; 184 gint ret; 185 186 item = folderview_get_selected_item(folderview); 187 opened = folderview_get_opened_item(folderview); 188 189 cm_return_if_fail(item != NULL); 190 cm_return_if_fail(item->path != NULL); 191 cm_return_if_fail(item->folder != NULL); 192 193 name = trim_string(item->name, 32); 194 AUTORELEASE_STR(name, {g_free(name); return;}); 195 message = g_markup_printf_escaped 196 (_("All folders and messages under '%s' will be permanently deleted.\n" 197 "Recovery will not be possible.\n\n" 198 "Do you really want to delete?"), name); 199 avalue = alertpanel_full(_("Delete folder"), message, 200 NULL, _("_Cancel"), "edit-delete-symbolic", _("D_elete"), 201 NULL, NULL, ALERTFOCUS_FIRST, FALSE, 202 NULL, ALERT_WARNING); 203 g_free(message); 204 if (avalue != G_ALERTALTERNATE) return; 205 206 old_id = folder_item_get_identifier(item); 207 208 if (item == opened || 209 folder_is_child_of(item, opened)) { 210 summary_clear_all(folderview->summaryview); 211 folderview_close_opened(folderview, TRUE); 212 } 213 214 if ((ret = item->folder->klass->remove_folder(item->folder, item)) < 0) { 215 folder_item_scan(item); 216 alertpanel_error(_("Can't remove the folder '%s'\n\n%s."), 217 name, g_strerror(-ret)); 218 g_free(old_id); 219 return; 220 } 221 222 folder_write_list(); 223 224 g_free(old_id); 225 226 } 227 228 static void rename_folder_cb(GtkAction *action, gpointer data) 229 { 230 FolderView *folderview = (FolderView *)data; 231 FolderItem *item; 232 gchar *new_folder; 233 gchar *name; 234 gchar *message; 235 gchar *old_id; 236 gchar *new_id; 237 gchar *base; 238 239 item = folderview_get_selected_item(folderview); 240 cm_return_if_fail(item != NULL); 241 cm_return_if_fail(item->path != NULL); 242 cm_return_if_fail(item->folder != NULL); 243 244 name = trim_string(item->name, 32); 245 message = g_strdup_printf(_("Input new name for '%s':"), name); 246 base = g_path_get_basename(item->path); 247 new_folder = input_dialog(_("Rename folder"), message, base); 248 g_free(message); 249 g_free(name); 250 g_free(base); 251 if (!new_folder) return; 252 AUTORELEASE_STR(new_folder, {g_free(new_folder); return;}); 253 254 if (strchr(new_folder, G_DIR_SEPARATOR) != NULL) { 255 alertpanel_error(_("'%c' can't be included in folder name."), 256 G_DIR_SEPARATOR); 257 return; 258 } 259 260 if (!folder_local_name_ok(new_folder)) 261 return; 262 263 if (folder_find_child_item_by_name(folder_item_parent(item), new_folder)) { 264 name = trim_string(new_folder, 32); 265 alertpanel_error(_("The folder '%s' already exists."), name); 266 g_free(name); 267 return; 268 } 269 270 old_id = folder_item_get_identifier(item); 271 272 if (folder_item_rename(item, new_folder) < 0) { 273 alertpanel_error(_("The folder could not be renamed.\n" 274 "The new folder name is not allowed.")); 275 g_free(old_id); 276 return; 277 } 278 279 new_id = folder_item_get_identifier(item); 280 account_rename_path(old_id, new_id); 281 prefs_actions_rename_path(old_id, new_id); 282 g_free(old_id); 283 g_free(new_id); 284 285 folder_item_prefs_save_config_recursive(item); 286 folder_write_list(); 287 } 288 289 static void move_folder_cb(GtkAction *action, gpointer data) 290 { 291 FolderView *folderview = (FolderView *)data; 292 FolderItem *from_folder = NULL, *to_folder = NULL; 293 gchar *msg; 294 295 from_folder = folderview_get_selected_item(folderview); 296 if (!from_folder || from_folder->folder->klass != mh_get_class()) 297 return; 298 299 msg = g_strdup_printf(_("Select folder to move folder '%s' to"), 300 from_folder->name); 301 to_folder = foldersel_folder_sel(NULL, FOLDER_SEL_MOVE, NULL, TRUE, msg); 302 g_free(msg); 303 if (!to_folder) 304 return; 305 306 folderview_move_folder(folderview, from_folder, to_folder, 0); 307 } 308 309 static void copy_folder_cb(GtkAction *action, gpointer data) 310 { 311 FolderView *folderview = (FolderView *)data; 312 FolderItem *from_folder = NULL, *to_folder = NULL; 313 gchar *msg; 314 315 from_folder = folderview_get_selected_item(folderview); 316 if (!from_folder || from_folder->folder->klass != mh_get_class()) 317 return; 318 319 msg = g_strdup_printf(_("Select folder to copy folder '%s' to"), 320 from_folder->name); 321 to_folder = foldersel_folder_sel(NULL, FOLDER_SEL_MOVE, NULL, TRUE, msg); 322 g_free(msg); 323 if (!to_folder) 324 return; 325 326 folderview_move_folder(folderview, from_folder, to_folder, 1); 327 } 328 329 #define DO_ACTION(name, act) { if (!strcmp(a_name, name)) act; } 330 331 static void update_tree_cb(GtkAction *action, gpointer data) 332 { 333 FolderView *folderview = (FolderView *)data; 334 FolderItem *item; 335 const gchar *a_name = gtk_action_get_name(action); 336 337 item = folderview_get_selected_item(folderview); 338 cm_return_if_fail(item != NULL); 339 340 summary_show(folderview->summaryview, NULL, FALSE); 341 342 cm_return_if_fail(item->folder != NULL); 343 344 DO_ACTION("FolderViewPopup/CheckNewMessages", folderview_check_new(item->folder)); 345 DO_ACTION("FolderViewPopup/CheckNewFolders", folderview_rescan_tree(item->folder, FALSE)); 346 DO_ACTION("FolderViewPopup/RebuildTree", folderview_rescan_tree(item->folder, TRUE)); 347 } 348 349 static void remove_mailbox_cb(GtkAction *action, gpointer data) 350 { 351 FolderView *folderview = (FolderView *)data; 352 FolderItem *item; 353 gchar *name; 354 gchar *message; 355 AlertValue avalue; 356 357 item = folderview_get_selected_item(folderview); 358 cm_return_if_fail(item != NULL); 359 cm_return_if_fail(item->folder != NULL); 360 if (folder_item_parent(item)) return; 361 362 name = trim_string(item->folder->name, 32); 363 message = g_markup_printf_escaped 364 (_("Really remove the mailbox '%s'?\n" 365 "(The messages are NOT deleted from the disk)"), name); 366 avalue = alertpanel_full(_("Remove mailbox"), message, 367 NULL, _("_Cancel"), "list-remove-symbolic", _("_Remove"), 368 NULL, NULL, ALERTFOCUS_FIRST, FALSE, 369 NULL, ALERT_WARNING); 370 371 g_free(message); 372 g_free(name); 373 if (avalue != G_ALERTALTERNATE) return; 374 375 folderview_unselect(folderview); 376 summary_clear_all(folderview->summaryview); 377 378 folder_destroy(item->folder); 379 } 380