talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

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