4 /* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */
7 * Virtual folder plugin for claws-mail
9 * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32 #include "mainwindow.h"
33 #include "inputdialog.h"
35 #include "folderview.h"
36 #include "alertpanel.h"
39 #include "summaryview.h"
45 #include "vfolder_gtk.h"
47 #include "vfolder_prop.h"
49 #define CONFIG_GROUP "VFolder"
51 static guint folder_hook_id
;
52 static guint item_hook_id
;
53 static guint msginfo_hook_id
;
54 static GSList
* widgets
= NULL
;
67 static char* vfolder_popup_menu_labels
[] = {
68 N_("_Refresh folder"),
69 N_("Refresh _all folders"),
70 N_("Folder pr_operties..."),
72 N_("_Create new folder..."),
73 N_("_Delete folder..."),
77 static GtkActionEntry vfolder_popup_entries
[] = {
78 {"FolderViewPopup/RefreshFolder", NULL
, NULL
, NULL
, NULL
, NULL
/*G_CALLBACK(vfolder_refresh_cb)*/ },
79 {"FolderViewPopup/RefreshAllFolders", NULL
, NULL
, NULL
, NULL
, NULL
/*G_CALLBACK(vfolder_refresh_cb)*/ },
81 {"FolderViewPopup/FolderProperties", NULL
, NULL
, NULL
, NULL
, G_CALLBACK(vfolder_properties_cb
) },
83 {"FolderViewPopup/RenameFolder", NULL
, NULL
, NULL
, NULL
, NULL
/*G_CALLBACK(vfolder_refresh_cb)*/ },
85 {"FolderViewPopup/NewFolder", NULL
, NULL
, NULL
, NULL
, G_CALLBACK(vfolder_new_folder_cb
) },
86 {"FolderViewPopup/RemoveFolder", NULL
, NULL
, NULL
, NULL
, G_CALLBACK(vfolder_remove_folder_cb
) },
89 static void vfolder_add_menuitems(GtkUIManager
*ui_manager
, FolderItem
*item
) {
90 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popup/FolderViewPopup", "RefreshFolder", "FolderViewPopup/RefreshFolder", GTK_UI_MANAGER_MENUITEM
)
91 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popup/FolderViewPopup", "RefreshAllFolders", "FolderViewPopup/RefreshAllFolders", GTK_UI_MANAGER_MENUITEM
)
92 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popup/FolderViewPopup", "SeparatorVF1", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR
)
93 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popup/FolderViewPopup", "FolderProperties", "FolderViewPopup/FolderProperties", GTK_UI_MANAGER_MENUITEM
)
94 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popup/FolderViewPopup", "SeparatorVF2", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR
)
95 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popup/FolderViewPopup", "RenameFolder", "FolderViewPopup/RenameFolder", GTK_UI_MANAGER_MENUITEM
)
96 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popup/FolderViewPopup", "SeparatorVF3", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR
)
97 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popup/FolderViewPopup", "NewFolder", "FolderViewPopup/NewFolder", GTK_UI_MANAGER_MENUITEM
)
98 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popup/FolderViewPopup", "RemoveFolder", "FolderViewPopup/RemoveFolder", GTK_UI_MANAGER_MENUITEM
)
99 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popup/FolderViewPopup", "SeparatorVF4", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR
)
102 static void vfolder_set_sensitivity(GtkUIManager
*ui_manager
, FolderItem
*item
) {
103 #define SET_SENS(name, sens) \
104 cm_menu_set_sensitive_full(ui_manager, "Popup/"name, sens)
106 VFolderItem
*ritem
= (VFolderItem
*)item
;
107 SET_SENS("FolderViewPopup/RefreshFolder", folder_item_parent(item
) != NULL
&& ! ritem
->frozen
);
108 SET_SENS("FolderViewPopup/RefreshAllFolders", folder_item_parent(item
) == NULL
&& ! ritem
->frozen
);
109 SET_SENS("FolderViewPopup/FolderProperties", folder_item_parent(item
) != NULL
);
110 SET_SENS("FolderViewPopup/RenameFolder", folder_item_parent(item
) != NULL
);
111 SET_SENS("FolderViewPopup/NewFolder", TRUE
);
112 SET_SENS("FolderViewPopup/RemoveFolder", folder_item_parent(item
) != NULL
);
117 static FolderViewPopup vfolder_popup
= {
120 vfolder_popup_entries
,
121 G_N_ELEMENTS(vfolder_popup_entries
),
124 vfolder_add_menuitems
,
125 vfolder_set_sensitivity
128 static void vfolder_fill_popup_menu_labels(void) {
131 for (i
= 0; vfolder_popup_menu_labels
[i
] != NULL
; i
++) {
132 (vfolder_popup_entries
[i
]).label
= _(vfolder_popup_menu_labels
[i
]);
136 static void gslist_menu_item_free(GSList
** menu_list
) {
139 if (! menu_list
|| ! *menu_list
)
142 for (list
= *menu_list
; list
; list
= g_slist_next(list
)) {
143 MenuItem
* menu
= (MenuItem
*) list
->data
;
147 g_slist_free(*menu_list
);
151 static MsgBridge
* vfolder_split_file_id(gchar
* id
) {
152 MsgBridge
* resp
= NULL
;
157 gchar
** tokens
= g_strsplit(id
, ":", 0);
158 if (g_strv_length(tokens
) != 2)
161 resp
= g_new0(MsgBridge
, 1);
162 resp
->my_num
= to_number(tokens
[0]);
163 resp
->claws_num
= to_number(tokens
[1]);
170 static gboolean
get_menu_widgets() {
171 MainWindow
* mainwindow
;
172 MenuItem
* menuitem
= NULL
;
175 mainwindow
= mainwindow_get_mainwindow();
176 if (mainwindow
&& mainwindow
->ui_manager
) {
177 widget
= gtk_ui_manager_get_widget(
178 mainwindow
->ui_manager
, "/Menus/SummaryViewPopup/Move/");
180 menuitem
= g_new0(MenuItem
, 1);
181 menuitem
->widget
= widget
;
182 menuitem
->action
= gtk_ui_manager_get_action(
183 mainwindow
->ui_manager
, "/Menus/SummaryViewPopup/Move/");
184 widgets
= g_slist_prepend(widgets
, menuitem
);
189 widget
= gtk_ui_manager_get_widget(
190 mainwindow
->ui_manager
, "/Menus/SummaryViewPopup/Trash/");
192 menuitem
= g_new0(MenuItem
, 1);
193 menuitem
->widget
= widget
;
194 menuitem
->action
= gtk_ui_manager_get_action(
195 mainwindow
->ui_manager
, "/Menus/SummaryViewPopup/Trash/");
196 widgets
= g_slist_prepend(widgets
, menuitem
);
199 gslist_menu_item_free(&widgets
);
203 widget
= gtk_ui_manager_get_widget(
204 mainwindow
->ui_manager
, "/Menus/SummaryViewPopup/Delete/");
206 menuitem
= g_new0(MenuItem
, 1);
207 menuitem
->widget
= widget
;
208 menuitem
->action
= gtk_ui_manager_get_action(
209 mainwindow
->ui_manager
, "/Menus/SummaryViewPopup/Delete/");
210 widgets
= g_slist_prepend(widgets
, menuitem
);
213 gslist_menu_item_free(&widgets
);
217 widget
= gtk_ui_manager_get_widget(
218 mainwindow
->ui_manager
, "/Menu/Message/Move/");
220 menuitem
= g_new0(MenuItem
, 1);
221 menuitem
->widget
= widget
;
222 menuitem
->action
= gtk_ui_manager_get_action(
223 mainwindow
->ui_manager
, "/Menu/Message/Move/");
224 widgets
= g_slist_prepend(widgets
, menuitem
);
227 gslist_menu_item_free(&widgets
);
231 widget
= gtk_ui_manager_get_widget(
232 mainwindow
->ui_manager
, "/Menu/Message/Trash/");
234 menuitem
= g_new0(MenuItem
, 1);
235 menuitem
->widget
= widget
;
236 menuitem
->action
= gtk_ui_manager_get_action(
237 mainwindow
->ui_manager
, "/Menu/Message/Trash/");
238 widgets
= g_slist_prepend(widgets
, menuitem
);
241 gslist_menu_item_free(&widgets
);
245 widget
= gtk_ui_manager_get_widget(
246 mainwindow
->ui_manager
, "/Menu/Message/Delete/");
248 menuitem
= g_new0(MenuItem
, 1);
249 menuitem
->widget
= widget
;
250 menuitem
->action
= gtk_ui_manager_get_action(
251 mainwindow
->ui_manager
, "/Menu/Message/Delete/");
252 widgets
= g_slist_prepend(widgets
, menuitem
);
255 gslist_menu_item_free(&widgets
);
266 static gboolean vfolder_widgets_is_visible() {
267 gboolean visible = TRUE;
269 if (widgets && widgets->data) {
270 MenuItem* menu = (MenuItem *) widgets->data;
271 visible = gtk_widget_get_visible(menu->widget);
277 static gboolean vfolder_hide_widgets(VFolderItem* item) {
279 MainWindow* mainwindow;
281 // if (! item->deep_copy) {
282 for (list = widgets; list; list = g_slist_next(list)) {
283 MenuItem* menu = (MenuItem *) list->data;
284 gtk_widget_hide(menu->widget);
285 gtk_action_block_activate(menu->action);
288 mainwindow = mainwindow_get_mainwindow();
289 if (mainwindow && mainwindow->toolbar) {
290 if (mainwindow->toolbar->trash_btn)
291 gtk_widget_hide(mainwindow->toolbar->trash_btn);
292 if (mainwindow->toolbar->delete_btn)
293 gtk_widget_hide(mainwindow->toolbar->delete_btn);
299 static gboolean
vfolder_show_widgets(VFolderItem
* item
) {
301 MainWindow
* mainwindow
;
303 // if (! item->deep_copy) {
304 for (list
= widgets
; list
; list
= g_slist_next(list
)) {
305 MenuItem
* menu
= (MenuItem
*) list
->data
;
306 gtk_widget_show(menu
->widget
);
307 gtk_action_unblock_activate(menu
->action
);
310 mainwindow
= mainwindow_get_mainwindow();
311 if (mainwindow
&& mainwindow
->toolbar
) {
312 if (mainwindow
->toolbar
->trash_btn
)
313 gtk_widget_show(mainwindow
->toolbar
->trash_btn
);
314 if (mainwindow
->toolbar
->delete_btn
)
315 gtk_widget_show(mainwindow
->toolbar
->delete_btn
);
321 static gchar* vfolder_get_message_file_path(VFolderItem* item, MsgInfo* msg) {
323 GSList* list = NULL, *cur;
328 if (item->deep_copy) {
329 path = procmsg_get_message_file_path(msg);
332 gchar* root = folder_item_get_path(msg->to_folder);
333 folder = msg->to_folder->folder;
334 guint num = folder->klass->get_num_list(folder, msg->to_folder, &list, &old_uid);
336 for (cur = list, last = 0; cur; cur = g_slist_next(cur)) {
337 guint tmp = GPOINTER_TO_UINT(cur->data);
344 path = g_strdup_printf("%s%s%u", root, G_DIR_SEPARATOR_S, last + 1);
352 static void vfolder_item_update(AddMsgData* msgdata) {
355 MsgFileInfo fileinfo;
357 if (!msgdata->item || !msgdata->list->data)
360 for (cur = msgdata->list; cur; cur = g_slist_next(cur)) {
361 MsgInfo* msg = (MsgInfo *) cur->data;
362 if (MSG_IS_DELETED(msg->flags)) {
363 folder_item_remove_msg(FOLDER_ITEM(msgdata->item), msg->msgnum);
366 fileinfo.msginfo = msg;
367 fileinfo.flags = &msg->flags;
368 fileinfo.file = msgdata->file;
369 update.data = &fileinfo;
371 folder_item_scan(msg->folder);
372 gint n = folder_item_add_msgs(FOLDER_ITEM(msgdata->item), &update, FALSE);
373 gchar* p = strrchr(fileinfo.file, G_DIR_SEPARATOR);
375 guint num = to_number((const gchar *) p);
376 vfolder_replace_key_in_bridge(msgdata->item, msg->msgnum, num);
377 FOLDER_ITEM(msgdata->item)->last_num = n;
381 //procmsg_message_file_list_free(list);
382 //item->msginfos = folder_item_get_msg_list(FOLDER_ITEM(item));
386 static void add_msg_data_free(AddMsgData** rec) {
388 AddMsgData* data = *rec;
389 g_slist_free(data->list);
397 static void vfolder_update_affected_folder_items(MsgInfo* msginfo) {
398 GList *vfolders, *cur;
407 if (MSG_IS_NEW(msginfo->flags) ||
408 MSG_IS_MOVE(msginfo->flags) ||
409 MSG_IS_COPY(msginfo->flags) ||
410 MSG_IS_DELETED(msginfo->flags)) {
411 vfolders = vfolder_get_vfolder_items();
412 for (cur = vfolders; cur; cur = g_list_next(cur)) {
413 data = g_new0(AddMsgData, 1);
414 VFolderItem* vitem = VFOLDER_ITEM(cur->data);
415 if (MSG_IS_MOVE(msginfo->flags) || MSG_IS_COPY(msginfo->flags))
416 src = folder_item_get_identifier(msginfo->to_folder);
418 src = folder_item_get_identifier(msginfo->folder);
419 gchar* shadow = folder_item_get_identifier(vitem->source);
420 debug_print("cmp %s : %s\n", src, shadow);
421 if (src && shadow && strcmp(src, shadow) == 0) {
422 if (MSG_IS_DELETED(msginfo->flags)) {
423 msg = vfolder_find_msg_from_claws_num(vitem, msginfo->msgnum);
425 data->list = g_slist_append(data->list, msg);
427 add_msg_data_free(&data);
428 g_slist_free(add_msg_data);
436 data->list = g_slist_append(data->list, msginfo);
438 data->file = vfolder_get_message_file_path(vitem, msginfo);
439 add_msg_data = g_slist_prepend(add_msg_data, data);
441 if (data->list && MSG_IS_DELETED(msginfo->flags)) {
442 GSList* list = vfolder_filter_msgs_list(data->list, vitem);
443 if (list && list->data) {
444 MsgInfo* msg = (MsgInfo *) list->data;
445 MSG_SET_PERM_FLAGS(msg->flags, MSG_DELETED);
447 g_slist_free(data->list);
450 vfolder_item_update(data);
451 add_msg_data_free(&data);
452 g_slist_free(add_msg_data);
461 for (cur_msg = add_msg_data; cur_msg; cur_msg = g_slist_next(cur_msg)) {
462 data = (AddMsgData *) cur_msg->data;
463 GSList* list = vfolder_filter_msgs_list(data->list, data->item);
464 g_slist_free(data->list);
466 vfolder_item_update(data);
467 add_msg_data_free(&data);
469 g_slist_free(add_msg_data);
474 static gboolean
vfolder_folder_update_hook(gpointer source
, gpointer data
) {
475 FolderUpdateData
* hookdata
;
477 g_return_val_if_fail(source
!= NULL
, FALSE
);
478 hookdata
= (FolderUpdateData
*) source
;
480 if (! hookdata
->folder
|| IS_VFOLDER_FOLDER(hookdata
->folder
))
483 if (hookdata
->update_flags
& FOLDER_REMOVE_FOLDERITEM
) {
484 /* TODO: check if the removed folder item is foundation for vfolder */
485 debug_print("FOLDER_REMOVE_FOLDERITEM\n");
488 if (hookdata
->update_flags
& FOLDER_REMOVE_FOLDER
) {
489 /* TODO: check if the removed folder is foundation for vfolder */
490 debug_print("FOLDER_REMOVE_FOLDER\n");
493 if (hookdata
->update_flags
& FOLDER_TREE_CHANGED
) {
494 /* TODO: check if the removed folder is foundation for vfolder */
495 debug_print("FOLDER_TREE_CHANGED\n");
498 if (hookdata
->update_flags
& FOLDER_RENAME_FOLDERITEM
) {
499 /* TODO: check if the removed folder is foundation for vfolder */
500 debug_print("FOLDER_RENAME_FOLDERITEM\n");
506 static gboolean
vfolder_folder_item_update_hook(gpointer source
, gpointer data
) {
507 FolderItemUpdateData
* hookdata
;
508 // gint save_state = -1;
511 // MainWindow* mainwindow;
513 g_return_val_if_fail(source
!= NULL
, FALSE
);
514 hookdata
= (FolderItemUpdateData
*) source
;
516 if (! hookdata
->item
|| IS_VFOLDER_FOLDER_ITEM(hookdata
->item
))
519 if (hookdata
->update_flags
& F_ITEM_UPDATE_REMOVEMSG
) {
520 debug_print("F_ITEM_UPDATE_REMOVEMSG\n");
521 items
= vfolder_get_vfolder_from_source(hookdata
->item
);
523 for (cur
= items
; cur
; cur
= g_list_next(cur
)) {
524 vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur
->data
), F_ITEM_UPDATE_REMOVEMSG
);
530 else if (hookdata
->update_flags
& F_ITEM_UPDATE_CONTENT
) {
531 debug_print("F_ITEM_UPDATE_CONTENT\n");
532 items
= vfolder_get_vfolder_from_source(hookdata
->item
);
534 for (cur
= items
; cur
; cur
= g_list_next(cur
)) {
535 vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur
->data
), F_ITEM_UPDATE_CONTENT
);
539 //mainwindow = mainwindow_get_mainwindow();
540 //summary_execute(mainwindow->summaryview);
543 else if (hookdata
->update_flags
& F_ITEM_UPDATE_ADDMSG
) {
544 debug_print("F_ITEM_UPDATE_ADDMSG\n");
545 items
= vfolder_get_vfolder_from_source(hookdata
->item
);
547 for (cur
= items
; cur
; cur
= g_list_next(cur
)) {
548 vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur
->data
), F_ITEM_UPDATE_ADDMSG
);
554 else if (hookdata
->update_flags
& F_ITEM_UPDATE_MSGCNT
) {
555 debug_print("F_ITEM_UPDATE_MSGCNT\n");
556 /* if (IS_VFOLDER_FOLDER_ITEM(item)) {
558 if (! (VFOLDER_ITEM(item))->deep_copy) {
559 if (! (VFOLDER_ITEM(item))->active) {
560 r = vfolder_hide_widgets(VFOLDER_ITEM(item));
562 VFOLDER_ITEM(item)->active = TRUE;
565 r = vfolder_show_widgets(VFOLDER_ITEM(item));
567 VFOLDER_ITEM(item)->active = FALSE;
576 vfolder_show_widgets(VFOLDER_ITEM(item));
579 if (!vfolder_widgets_is_visible())
580 vfolder_show_widgets(VFOLDER_ITEM(item));
583 items = vfolder_get_vfolder_from_source(hookdata->item);
585 for (cur = items; cur; cur = g_list_next(cur)) {
586 vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_MSGCNT);
593 else if (hookdata
->update_flags
& F_ITEM_UPDATE_NAME
) {
594 /* TODO: need update? */
595 debug_print("F_ITEM_UPDATE_NAME\n");
596 items
= vfolder_get_vfolder_from_source(hookdata
->item
);
598 for (cur
= items
; cur
; cur
= g_list_next(cur
)) {
599 vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur
->data
), F_ITEM_UPDATE_NAME
);
606 /* Unhandled callback */
607 debug_print("Unhandled FolderItem callback\n");
611 MainWindow* mainwindow = mainwindow_get_mainwindow();
612 alertpanel_error(_("%s: Could not hide dangerous actions"), hookdata->item->name);
613 summary_lock(mainwindow->summaryview);
619 static gboolean vfolder_msg_info_update_hook(gpointer source, gpointer data) {
620 MsgInfoUpdate* hookdata;
621 MainWindow* mainwindow;
624 g_return_val_if_fail(source != NULL, FALSE);
625 hookdata = (MsgInfoUpdate *) source;
626 msginfo = hookdata->msginfo;
628 g_return_val_if_fail(msginfo != NULL, TRUE);
630 if (IS_VFOLDER_MSGINFO(msginfo))
633 debug_print("\n\nPermflag: %u Tmpflag: %u (scanned: %u)\n\n\n",
634 (guint32) msginfo->flags.perm_flags, (guint32) msginfo->flags.tmp_flags, 1U << 31);
635 if (MSG_IS_NEW(msginfo->flags)) {
636 debug_print("MSG_IS_NEW\n");
637 vfolder_update_affected_folder_items(msginfo);
638 mainwindow = mainwindow_get_mainwindow();
639 summary_execute(mainwindow->summaryview);
642 if (MSG_IS_DELETED(msginfo->flags)) {
643 debug_print("MSG_IS_DELETED\n");
644 vfolder_update_affected_folder_items(msginfo);
645 mainwindow = mainwindow_get_mainwindow();
646 summary_execute(mainwindow->summaryview);
649 if (MSG_IS_MOVE(msginfo->flags)) {
650 debug_print("MSG_IS_MOVE\n");
651 vfolder_update_affected_folder_items(msginfo);
652 mainwindow = mainwindow_get_mainwindow();
653 summary_execute(mainwindow->summaryview);
656 if (MSG_IS_COPY(msginfo->flags)) {
657 debug_print("MSG_IS_COPY\n");
658 vfolder_update_affected_folder_items(msginfo);
659 mainwindow = mainwindow_get_mainwindow();
660 summary_execute(mainwindow->summaryview);
663 // if (MSG_IS_POSTFILTERED(msginfo->flags)) {
664 // debug_print("MSG_IS_POSTFILTERED\n");
665 // vfolder_update_affected_folder_items(msginfo);
666 // mainwindow = mainwindow_get_mainwindow();
667 // summary_execute(mainwindow->summaryview);
674 static gchar
* vfolder_get_rc_file(VFolderItem
* item
) {
675 gchar
* (*item_get_path
) (Folder
* folder
, FolderItem
* item
);
679 item_get_path
= FOLDER_ITEM(item
)->folder
->klass
->item_get_path
;
681 path
= item_get_path(FOLDER_ITEM(item
)->folder
, FOLDER_ITEM(item
));
682 rc_file
= g_strconcat(path
, G_DIR_SEPARATOR_S
, "folderitemrc", NULL
);
688 FolderPropsResponse
vfolder_folder_item_props_write(VFolderItem
* item
) {
695 FolderPropsResponse resp
= FOLDER_ITEM_PROPS_NO_ITEM
;
700 g_return_val_if_fail(item
!= NULL
, resp
);
702 rc_file
= vfolder_get_rc_file(item
);
703 config
= g_key_file_new();
706 g_key_file_set_string(config
, CONFIG_GROUP
, "filter", item
->filter
);
708 g_key_file_set_integer(config
, CONFIG_GROUP
, "searchtype", item
->search
);
709 g_key_file_set_boolean(config
, CONFIG_GROUP
, "frozen", item
->frozen
);
710 g_key_file_set_boolean(config
, CONFIG_GROUP
, "deep_copy", item
->deep_copy
);
713 id
= folder_item_get_identifier(item
->source
);
715 g_key_file_set_string(config
, CONFIG_GROUP
, "source", id
);
720 if (item
->claws_to_me
&& item
->me_to_claws
) {
722 g_hash_table_iter_init(&iter
, item
->claws_to_me
);
723 while (g_hash_table_iter_next(&iter
, &key
, &value
)) {
725 MsgBridge
* bridge
= value
;
727 gchar
* tmp
= g_strdup(numstr
);
729 numstr
= g_strdup_printf("%s, %u:%u",
730 tmp
, bridge
->my_num
, bridge
->claws_num
);
734 numstr
= g_strdup_printf("%u:%u", bridge
->my_num
, bridge
->claws_num
);
737 g_key_file_set_string(config
, CONFIG_GROUP
, "file_id_list", numstr
);
741 if (g_file_test(rc_file
, G_FILE_TEST_EXISTS
)) {
742 gchar
* bakpath
= g_strconcat(rc_file
, ".bak", NULL
);
743 if (g_rename(rc_file
, bakpath
) < 0) {
744 g_warning("%s: Could not create", bakpath
);
745 resp
= FOLDER_ITEM_PROPS_BACKUP_FAIL
;
750 // g_key_file_set_integer(config, CONFIG_GROUP, "filter-function", item->filter_func);
752 data
= g_key_file_to_data(config
, &len
, NULL
);
754 g_warning("Could not get config data");
755 resp
= FOLDER_ITEM_PROPS_READ_DATA_FAIL
;
758 fp
= g_fopen(rc_file
, "w");
760 gchar
* dir_path_end
= g_strrstr(rc_file
, G_DIR_SEPARATOR_S
);
761 gchar
* rc_dir
= g_strndup(rc_file
, dir_path_end
- rc_file
);
762 debug_print("rc_dir: %s\n", rc_dir
);
763 int r
= g_mkdir_with_parents(rc_dir
, 0700);
765 resp
= FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL
;
767 if (resp
== FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL
)
769 fp
= g_fopen(rc_file
, "w");
771 resp
= FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL
;
775 fwrite(data
, len
, 1, fp
);
777 resp
= FOLDER_ITEM_PROPS_OK
;
783 g_key_file_free(config
);
789 FolderPropsResponse
vfolder_folder_item_props_read(VFolderItem
* item
) {
792 GError
* error
= NULL
;
794 gchar
**list
, **head
;
795 FolderPropsResponse resp
= FOLDER_ITEM_PROPS_NO_ITEM
;
798 g_return_val_if_fail(item
!= NULL
, resp
);
800 rc_file
= vfolder_get_rc_file(item
);
801 config
= g_key_file_new();
803 if (g_file_test(rc_file
, G_FILE_TEST_EXISTS
)) {
804 g_key_file_load_from_file(config
, rc_file
, G_KEY_FILE_KEEP_COMMENTS
, &error
);
806 g_warning("%s. Using defaults", error
->message
);
808 resp
= FOLDER_ITEM_PROPS_READ_USING_DEFAULT
;
811 item
->filter
= g_key_file_get_string(config
, CONFIG_GROUP
, "filter", NULL
);
812 item
->search
= g_key_file_get_integer(config
, CONFIG_GROUP
, "searchtype", NULL
);
813 item
->frozen
= g_key_file_get_boolean(config
, CONFIG_GROUP
, "frozen", NULL
);
814 item
->deep_copy
= g_key_file_get_boolean(config
, CONFIG_GROUP
, "deep_copy", NULL
);
815 // item->filter_func = g_key_file_get_integer(config, CONFIG_GROUP, "filter_function", NULL);
817 id
= g_key_file_get_string(config
, CONFIG_GROUP
, "source", NULL
);
819 item
->source
= folder_find_item_from_identifier(id
);
822 msgnums
= g_key_file_get_string(config
, CONFIG_GROUP
, "file_id_list", NULL
);
824 list
= g_strsplit(msgnums
, ",", 0);
828 gchar
* anum
= g_strdup(*list
++);
830 MsgBridge
* bridge
= vfolder_split_file_id(anum
);
832 if (lastnum
< (gint
) bridge
->my_num
)
833 lastnum
= bridge
->my_num
;
834 if (bridge
->my_num
> 0) {
835 vfolder_add_message_to_bridge(item
, bridge
);
839 FOLDER_ITEM(item
)->last_num
= lastnum
;
843 resp
= FOLDER_ITEM_PROPS_OK
;
847 g_key_file_free(config
);
853 gboolean
vfolder_gtk_init(gchar
** error
) {
854 vfolder_fill_popup_menu_labels();
855 folderview_register_popup(&vfolder_popup
);
857 folder_hook_id
= hooks_register_hook(FOLDER_UPDATE_HOOKLIST
,
858 vfolder_folder_update_hook
, NULL
);
859 if (folder_hook_id
== -1) {
860 *error
= g_strdup(_("Failed to register folder update hook"));
864 item_hook_id
= hooks_register_hook(FOLDER_ITEM_UPDATE_HOOKLIST
,
865 vfolder_folder_item_update_hook
, NULL
);
866 if (item_hook_id
== -1) {
867 *error
= g_strdup(_("Failed to register folder item update hook"));
868 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST
, folder_hook_id
);
872 /* msginfo_hook_id = hooks_register_hook(MSGINFO_UPDATE_HOOKLIST,
873 vfolder_msg_info_update_hook, NULL);
874 if (msginfo_hook_id == -1) {
875 *error = g_strdup(_("Failed to register message info update hook"));
876 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id);
877 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id);
881 if (! get_menu_widgets()) {
882 *error
= g_strdup(_("Failed to get menu widgets"));
883 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST
, folder_hook_id
);
884 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST
, item_hook_id
);
885 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST
, msginfo_hook_id
);
892 void vfolder_gtk_done(void) {
893 MainWindow
*mainwin
= mainwindow_get_mainwindow();
894 FolderView
*folderview
= NULL
;
895 FolderItem
*fitem
= NULL
;
897 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST
, folder_hook_id
);
898 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST
, item_hook_id
);
899 //hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, msginfo_hook_id);
901 if (mainwin
== NULL
|| claws_is_exiting())
904 folderview
= mainwin
->folderview
;
905 fitem
= folderview
->summaryview
->folder_item
;
907 if (fitem
&& IS_VFOLDER_FOLDER_ITEM(fitem
)) {
908 vfolder_show_widgets(VFOLDER_ITEM(fitem
));
909 gslist_menu_item_free(&widgets
);
911 folderview_unselect(folderview
);
912 summary_clear_all(folderview
->summaryview
);
915 folderview_unregister_popup(&vfolder_popup
);
918 void vfolder_properties_cb(GtkAction
* action
, gpointer data
) {
919 FolderView
*folderview
= (FolderView
*)data
;
922 g_return_if_fail(folderview
!= NULL
);
924 item
= folderview_get_selected_item(folderview
);
926 g_return_if_fail(item
!= NULL
);
927 g_return_if_fail(item
->path
!= NULL
);
928 g_return_if_fail(item
->folder
!= NULL
);
930 if (vfolder_edit_item_dialog(VFOLDER_ITEM(item
))) {
932 if (debug_get_mode()) {
936 g_hash_table_iter_init(&iter
, VFOLDER_ITEM(item
)->me_to_claws
);
937 while (g_hash_table_iter_next(&iter
, &key
, &value
)) {
938 gchar
* buf
= g_new0(gchar
, BUFSIZ
);
939 MsgInfo
* msginfo
= vfolder_find_msg_from_vfolder_num(
940 VFOLDER_ITEM(item
), GPOINTER_TO_UINT(key
));
941 FILE* msg
= procmsg_open_message(msginfo
);
942 while (fread(buf
, 1, BUFSIZ
- 1, msg
) > 0) {
943 fprintf(stderr
, "%s", buf
);
945 buf
= g_new0(gchar
, BUFSIZ
);
947 fprintf(stderr
, "\n");
953 vfolder_folder_item_props_write(VFOLDER_ITEM(item
));
957 void vfolder_new_folder_cb(GtkAction
* action
, gpointer data
) {
958 FolderView
*folderview
= (FolderView
*)data
;
959 GtkCMCTree
*ctree
= GTK_CMCTREE(folderview
->ctree
);
961 FolderItem
*new_item
;
966 if (!folderview
->selected
) return;
968 item
= gtk_cmctree_node_get_row_data(ctree
, folderview
->selected
);
970 item
= FOLDER_ITEM(vfolder_get_vfolder_item(NULL
));
973 g_return_if_fail(item
!= NULL
);
974 g_return_if_fail(item
->folder
!= NULL
);
977 alertpanel_error(N_("Virtual folders cannot contain subfolders"));
981 new_folder
= input_dialog(_("New folder"),
982 _("Input the name of new folder:"),
984 if (!new_folder
) return;
985 AUTORELEASE_STR(new_folder
, {g_free(new_folder
); return;});
987 p
= strchr(new_folder
, G_DIR_SEPARATOR
);
989 alertpanel_error(_("'%c' can't be included in folder name."),
994 name
= trim_string(new_folder
, 32);
995 AUTORELEASE_STR(name
, {g_free(name
); return;});
997 /* find whether the directory already exists */
998 if (folder_find_child_item_by_name(item
, new_folder
)) {
999 alertpanel_error(_("The folder '%s' already exists."), name
);
1003 new_item
= folder_create_folder(item
, new_folder
);
1005 alertpanel_error(_("Can't create the folder '%s'."), name
);
1009 if (! vfolder_create_item_dialog(new_item
)) {
1010 //VFolderItem* vitem = VFOLDER_ITEM(new_item);
1011 new_item
->folder
->klass
->remove_folder(new_item
->folder
, new_item
);
1016 folder_write_list();
1019 void vfolder_remove_folder_cb(GtkAction
* action
, gpointer data
) {
1020 FolderView
*folderview
= (FolderView
*)data
;
1021 GtkCMCTree
*ctree
= GTK_CMCTREE(folderview
->ctree
);
1023 gchar
*message
, *name
;
1025 gchar
*old_path
= NULL
;
1028 /* Silence lame warnings */
1029 old_id
= (old_path
) ? NULL
: old_path
;
1031 item
= folderview_get_selected_item(folderview
);
1032 g_return_if_fail(item
!= NULL
);
1033 g_return_if_fail(item
->path
!= NULL
);
1034 g_return_if_fail(item
->folder
!= NULL
);
1036 name
= trim_string(item
->name
, 32);
1037 AUTORELEASE_STR(name
, {g_free(name
); return;});
1038 message
= g_strdup_printf
1039 (_("All folders and messages under '%s' will be permanently deleted. "
1040 "Recovery will not be possible.\n\n"
1041 "Do you really want to delete?"), name
);
1042 avalue
= alertpanel_full(_("Delete folder"), message
,
1043 GTK_STOCK_CANCEL
, GTK_STOCK_DELETE
, NULL
, FALSE
,
1044 NULL
, ALERT_WARNING
, G_ALERTDEFAULT
);
1046 if (avalue
!= G_ALERTALTERNATE
) return;
1048 Xstrdup_a(old_path
, item
->path
, return);
1049 old_id
= folder_item_get_identifier(item
);
1051 if (folderview
->opened
== folderview
->selected
||
1052 gtk_cmctree_is_ancestor(ctree
,
1053 folderview
->selected
,
1054 folderview
->opened
)) {
1055 summary_clear_all(folderview
->summaryview
);
1056 folderview
->opened
= NULL
;
1059 if (item
->folder
->klass
->remove_folder(item
->folder
, item
) < 0) {
1060 folder_item_scan(item
);
1061 alertpanel_error(_("Can't remove the folder '%s'."), name
);
1066 folder_write_list();