/* * $Id: $ */ /* vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: */ /* * Virtual folder plugin for claws-mail * * Claws Mail is Copyright (C) 1999-2012 by the Claws Mail Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifdef HAVE_CONFIG_H # include #endif #include "gtk/menu.h" #include "gtk/gtk.h" #include "mainwindow.h" #include "inputdialog.h" #include "folder.h" #include "folderview.h" #include "alertpanel.h" #include "hooks.h" #include "utils.h" #include "summaryview.h" #include "gettext.h" #include "main.h" #include "gtkutils.h" #include "vfolder_gtk.h" #include "vfolder.h" #include "vfolder_prop.h" #define CONFIG_GROUP "VFolder" static guint folder_hook_id; static guint item_hook_id; static guint msginfo_hook_id; static GSList* widgets = NULL; typedef struct { MsgInfoList* list; VFolderItem* item; gchar* file; } AddMsgData; typedef struct { GtkWidget* widget; GtkAction* action; } MenuItem; static char* vfolder_popup_menu_labels[] = { N_("_Refresh folder"), N_("Refresh _all folders"), N_("Folder pr_operties..."), N_("Rena_me..."), N_("_Create new folder..."), N_("_Delete folder..."), NULL }; static GtkActionEntry vfolder_popup_entries[] = { {"FolderViewPopup/RefreshFolder", NULL, NULL, NULL, NULL, NULL /*G_CALLBACK(vfolder_refresh_cb)*/ }, {"FolderViewPopup/RefreshAllFolders", NULL, NULL, NULL, NULL, NULL /*G_CALLBACK(vfolder_refresh_cb)*/ }, {"FolderViewPopup/FolderProperties", NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_properties_cb) }, {"FolderViewPopup/RenameFolder", NULL, NULL, NULL, NULL, NULL /*G_CALLBACK(vfolder_refresh_cb)*/ }, {"FolderViewPopup/NewFolder", NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_new_folder_cb) }, {"FolderViewPopup/RemoveFolder", NULL, NULL, NULL, NULL, G_CALLBACK(vfolder_remove_folder_cb) }, }; static void vfolder_add_menuitems(GtkUIManager *ui_manager, FolderItem *item) { MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RefreshFolder", "FolderViewPopup/RefreshFolder", GTK_UI_MANAGER_MENUITEM) MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RefreshAllFolders", "FolderViewPopup/RefreshAllFolders", GTK_UI_MANAGER_MENUITEM) MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVF1", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR) MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "FolderProperties", "FolderViewPopup/FolderProperties", GTK_UI_MANAGER_MENUITEM) MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVF2", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR) MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RenameFolder", "FolderViewPopup/RenameFolder", GTK_UI_MANAGER_MENUITEM) MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVF3", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR) MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "NewFolder", "FolderViewPopup/NewFolder", GTK_UI_MANAGER_MENUITEM) MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RemoveFolder", "FolderViewPopup/RemoveFolder", GTK_UI_MANAGER_MENUITEM) MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVF4", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR) } static void vfolder_set_sensitivity(GtkUIManager *ui_manager, FolderItem *item) { #define SET_SENS(name, sens) \ cm_menu_set_sensitive_full(ui_manager, "Popup/"name, sens) VFolderItem *ritem = (VFolderItem *)item; SET_SENS("FolderViewPopup/RefreshFolder", folder_item_parent(item) != NULL && ! ritem->frozen); SET_SENS("FolderViewPopup/RefreshAllFolders", folder_item_parent(item) == NULL && ! ritem->frozen); SET_SENS("FolderViewPopup/FolderProperties", folder_item_parent(item) != NULL); SET_SENS("FolderViewPopup/RenameFolder", folder_item_parent(item) != NULL); SET_SENS("FolderViewPopup/NewFolder", TRUE); SET_SENS("FolderViewPopup/RemoveFolder", folder_item_parent(item) != NULL); #undef SET_SENS } static FolderViewPopup vfolder_popup = { "vfolder", "", vfolder_popup_entries, G_N_ELEMENTS(vfolder_popup_entries), NULL, 0, NULL, 0, 0, NULL, vfolder_add_menuitems, vfolder_set_sensitivity }; static void vfolder_fill_popup_menu_labels(void) { gint i; for (i = 0; vfolder_popup_menu_labels[i] != NULL; i++) { (vfolder_popup_entries[i]).label = _(vfolder_popup_menu_labels[i]); } } static void gslist_menu_item_free(GSList** menu_list) { GSList* list; if (! menu_list || ! *menu_list) return; for (list = *menu_list; list; list = g_slist_next(list)) { MenuItem* menu = (MenuItem *) list->data; g_free(menu); } g_slist_free(*menu_list); *menu_list = NULL; } static MsgBridge* vfolder_split_file_id(gchar* id) { MsgBridge* resp = NULL; if (! id) return NULL; gchar** tokens = g_strsplit(id, ":", 0); if (g_strv_length(tokens) != 2) goto bail; resp = g_new0(MsgBridge, 1); resp->my_num = to_number(tokens[0]); resp->claws_num = to_number(tokens[1]); bail: g_strfreev(tokens); return resp; } static gboolean get_menu_widgets() { MainWindow* mainwindow; MenuItem* menuitem = NULL; GtkWidget* widget; mainwindow = mainwindow_get_mainwindow(); if (mainwindow && mainwindow->ui_manager) { widget = gtk_ui_manager_get_widget( mainwindow->ui_manager, "/Menus/SummaryViewPopup/Move/"); if (widget) { menuitem = g_new0(MenuItem, 1); menuitem->widget = widget; menuitem->action = gtk_ui_manager_get_action( mainwindow->ui_manager, "/Menus/SummaryViewPopup/Move/"); widgets = g_slist_prepend(widgets, menuitem); } else return FALSE; widget = gtk_ui_manager_get_widget( mainwindow->ui_manager, "/Menus/SummaryViewPopup/Trash/"); if (widget) { menuitem = g_new0(MenuItem, 1); menuitem->widget = widget; menuitem->action = gtk_ui_manager_get_action( mainwindow->ui_manager, "/Menus/SummaryViewPopup/Trash/"); widgets = g_slist_prepend(widgets, menuitem); } else { gslist_menu_item_free(&widgets); return FALSE; } widget = gtk_ui_manager_get_widget( mainwindow->ui_manager, "/Menus/SummaryViewPopup/Delete/"); if (widget) { menuitem = g_new0(MenuItem, 1); menuitem->widget = widget; menuitem->action = gtk_ui_manager_get_action( mainwindow->ui_manager, "/Menus/SummaryViewPopup/Delete/"); widgets = g_slist_prepend(widgets, menuitem); } else { gslist_menu_item_free(&widgets); return FALSE; } widget = gtk_ui_manager_get_widget( mainwindow->ui_manager, "/Menu/Message/Move/"); if (widget) { menuitem = g_new0(MenuItem, 1); menuitem->widget = widget; menuitem->action = gtk_ui_manager_get_action( mainwindow->ui_manager, "/Menu/Message/Move/"); widgets = g_slist_prepend(widgets, menuitem); } else { gslist_menu_item_free(&widgets); return FALSE; } widget = gtk_ui_manager_get_widget( mainwindow->ui_manager, "/Menu/Message/Trash/"); if (widget) { menuitem = g_new0(MenuItem, 1); menuitem->widget = widget; menuitem->action = gtk_ui_manager_get_action( mainwindow->ui_manager, "/Menu/Message/Trash/"); widgets = g_slist_prepend(widgets, menuitem); } else { gslist_menu_item_free(&widgets); return FALSE; } widget = gtk_ui_manager_get_widget( mainwindow->ui_manager, "/Menu/Message/Delete/"); if (widget) { menuitem = g_new0(MenuItem, 1); menuitem->widget = widget; menuitem->action = gtk_ui_manager_get_action( mainwindow->ui_manager, "/Menu/Message/Delete/"); widgets = g_slist_prepend(widgets, menuitem); } else { gslist_menu_item_free(&widgets); return FALSE; } } else return FALSE; return TRUE; } /* static gboolean vfolder_widgets_is_visible() { gboolean visible = TRUE; if (widgets && widgets->data) { MenuItem* menu = (MenuItem *) widgets->data; visible = gtk_widget_get_visible(menu->widget); } return visible; } static gboolean vfolder_hide_widgets(VFolderItem* item) { GSList* list; MainWindow* mainwindow; // if (! item->deep_copy) { for (list = widgets; list; list = g_slist_next(list)) { MenuItem* menu = (MenuItem *) list->data; gtk_widget_hide(menu->widget); gtk_action_block_activate(menu->action); } mainwindow = mainwindow_get_mainwindow(); if (mainwindow && mainwindow->toolbar) { if (mainwindow->toolbar->trash_btn) gtk_widget_hide(mainwindow->toolbar->trash_btn); if (mainwindow->toolbar->delete_btn) gtk_widget_hide(mainwindow->toolbar->delete_btn); } // } return TRUE; } */ static gboolean vfolder_show_widgets(VFolderItem* item) { GSList* list; MainWindow* mainwindow; // if (! item->deep_copy) { for (list = widgets; list; list = g_slist_next(list)) { MenuItem* menu = (MenuItem *) list->data; gtk_widget_show(menu->widget); gtk_action_unblock_activate(menu->action); } mainwindow = mainwindow_get_mainwindow(); if (mainwindow && mainwindow->toolbar) { if (mainwindow->toolbar->trash_btn) gtk_widget_show(mainwindow->toolbar->trash_btn); if (mainwindow->toolbar->delete_btn) gtk_widget_show(mainwindow->toolbar->delete_btn); } // } return TRUE; } /* static gchar* vfolder_get_message_file_path(VFolderItem* item, MsgInfo* msg) { gchar* path; GSList* list = NULL, *cur; Folder* folder; gboolean old_uid; guint last = 0; if (item->deep_copy) { path = procmsg_get_message_file_path(msg); } else { gchar* root = folder_item_get_path(msg->to_folder); folder = msg->to_folder->folder; guint num = folder->klass->get_num_list(folder, msg->to_folder, &list, &old_uid); if (num >= 0) { for (cur = list, last = 0; cur; cur = g_slist_next(cur)) { guint tmp = GPOINTER_TO_UINT(cur->data); if (tmp > last) last = tmp; } } g_slist_free(list); path = g_strdup_printf("%s%s%u", root, G_DIR_SEPARATOR_S, last + 1); g_free(root); } return path; } */ /* static void vfolder_item_update(AddMsgData* msgdata) { MsgInfoList* cur; GSList update; MsgFileInfo fileinfo; if (!msgdata->item || !msgdata->list->data) return; for (cur = msgdata->list; cur; cur = g_slist_next(cur)) { MsgInfo* msg = (MsgInfo *) cur->data; if (MSG_IS_DELETED(msg->flags)) { folder_item_remove_msg(FOLDER_ITEM(msgdata->item), msg->msgnum); } else { fileinfo.msginfo = msg; fileinfo.flags = &msg->flags; fileinfo.file = msgdata->file; update.data = &fileinfo; update.next = NULL; folder_item_scan(msg->folder); gint n = folder_item_add_msgs(FOLDER_ITEM(msgdata->item), &update, FALSE); gchar* p = strrchr(fileinfo.file, G_DIR_SEPARATOR); p += 1; guint num = to_number((const gchar *) p); vfolder_replace_key_in_bridge(msgdata->item, msg->msgnum, num); FOLDER_ITEM(msgdata->item)->last_num = n; } } //procmsg_message_file_list_free(list); //item->msginfos = folder_item_get_msg_list(FOLDER_ITEM(item)); } */ /* static void add_msg_data_free(AddMsgData** rec) { if (rec && *rec) { AddMsgData* data = *rec; g_slist_free(data->list); g_free(data->file); g_free(data); *rec = NULL; } } */ /* static void vfolder_update_affected_folder_items(MsgInfo* msginfo) { GList *vfolders, *cur; GSList* cur_msg; gchar* src; AddMsgData* data; MsgInfo* msg; if (! msginfo) return; if (MSG_IS_NEW(msginfo->flags) || MSG_IS_MOVE(msginfo->flags) || MSG_IS_COPY(msginfo->flags) || MSG_IS_DELETED(msginfo->flags)) { vfolders = vfolder_get_vfolder_items(); for (cur = vfolders; cur; cur = g_list_next(cur)) { data = g_new0(AddMsgData, 1); VFolderItem* vitem = VFOLDER_ITEM(cur->data); if (MSG_IS_MOVE(msginfo->flags) || MSG_IS_COPY(msginfo->flags)) src = folder_item_get_identifier(msginfo->to_folder); else src = folder_item_get_identifier(msginfo->folder); gchar* shadow = folder_item_get_identifier(vitem->source); debug_print("cmp %s : %s\n", src, shadow); if (src && shadow && strcmp(src, shadow) == 0) { if (MSG_IS_DELETED(msginfo->flags)) { msg = vfolder_find_msg_from_claws_num(vitem, msginfo->msgnum); if (msg) data->list = g_slist_append(data->list, msg); else { add_msg_data_free(&data); g_slist_free(add_msg_data); add_msg_data = NULL; g_free(src); g_free(shadow); return; } } else { data->list = g_slist_append(data->list, msginfo); data->item = vitem; data->file = vfolder_get_message_file_path(vitem, msginfo); add_msg_data = g_slist_prepend(add_msg_data, data); } if (data->list && MSG_IS_DELETED(msginfo->flags)) { GSList* list = vfolder_filter_msgs_list(data->list, vitem); if (list && list->data) { MsgInfo* msg = (MsgInfo *) list->data; MSG_SET_PERM_FLAGS(msg->flags, MSG_DELETED); } g_slist_free(data->list); data->list = list; data->item = vitem; vfolder_item_update(data); add_msg_data_free(&data); g_slist_free(add_msg_data); add_msg_data = NULL; } } g_free(src); g_free(shadow); } } if (add_msg_data) { for (cur_msg = add_msg_data; cur_msg; cur_msg = g_slist_next(cur_msg)) { data = (AddMsgData *) cur_msg->data; GSList* list = vfolder_filter_msgs_list(data->list, data->item); g_slist_free(data->list); data->list = list; vfolder_item_update(data); add_msg_data_free(&data); } g_slist_free(add_msg_data); add_msg_data = NULL; } } */ static gboolean vfolder_folder_update_hook(gpointer source, gpointer data) { FolderUpdateData* hookdata; g_return_val_if_fail(source != NULL, FALSE); hookdata = (FolderUpdateData *) source; if (! hookdata->folder || IS_VFOLDER_FOLDER(hookdata->folder)) return FALSE; if (hookdata->update_flags & FOLDER_REMOVE_FOLDERITEM) { /* TODO: check if the removed folder item is foundation for vfolder */ debug_print("FOLDER_REMOVE_FOLDERITEM\n"); } if (hookdata->update_flags & FOLDER_REMOVE_FOLDER) { /* TODO: check if the removed folder is foundation for vfolder */ debug_print("FOLDER_REMOVE_FOLDER\n"); } if (hookdata->update_flags & FOLDER_TREE_CHANGED) { /* TODO: check if the removed folder is foundation for vfolder */ debug_print("FOLDER_TREE_CHANGED\n"); } if (hookdata->update_flags & FOLDER_RENAME_FOLDERITEM) { /* TODO: check if the removed folder is foundation for vfolder */ debug_print("FOLDER_RENAME_FOLDERITEM\n"); } return FALSE; } static gboolean vfolder_folder_item_update_hook(gpointer source, gpointer data) { FolderItemUpdateData* hookdata; // gint save_state = -1; GList *items, *cur; // gboolean r; // MainWindow* mainwindow; g_return_val_if_fail(source != NULL, FALSE); hookdata = (FolderItemUpdateData *) source; if (! hookdata->item || IS_VFOLDER_FOLDER_ITEM(hookdata->item)) return FALSE; if (hookdata->update_flags & F_ITEM_UPDATE_REMOVEMSG ) { debug_print("F_ITEM_UPDATE_REMOVEMSG\n"); items = vfolder_get_vfolder_from_source(hookdata->item); if (items) { for (cur = items; cur; cur = g_list_next(cur)) { vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_REMOVEMSG); } g_list_free(items); } } else if (hookdata->update_flags & F_ITEM_UPDATE_CONTENT) { debug_print("F_ITEM_UPDATE_CONTENT\n"); items = vfolder_get_vfolder_from_source(hookdata->item); if (items) { for (cur = items; cur; cur = g_list_next(cur)) { vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_CONTENT); } g_list_free(items); } //mainwindow = mainwindow_get_mainwindow(); //summary_execute(mainwindow->summaryview); } else if (hookdata->update_flags & F_ITEM_UPDATE_ADDMSG) { debug_print("F_ITEM_UPDATE_ADDMSG\n"); items = vfolder_get_vfolder_from_source(hookdata->item); if (items) { for (cur = items; cur; cur = g_list_next(cur)) { vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_ADDMSG); } g_list_free(items); } } else if (hookdata->update_flags & F_ITEM_UPDATE_MSGCNT) { debug_print("F_ITEM_UPDATE_MSGCNT\n"); /* if (IS_VFOLDER_FOLDER_ITEM(item)) { if (! (VFOLDER_ITEM(item))->deep_copy) { if (! (VFOLDER_ITEM(item))->active) { r = vfolder_hide_widgets(VFOLDER_ITEM(item)); if (r) VFOLDER_ITEM(item)->active = TRUE; } else { r = vfolder_show_widgets(VFOLDER_ITEM(item)); if (r) VFOLDER_ITEM(item)->active = FALSE; } if (r) save_state = 1; else save_state = 0; } else vfolder_show_widgets(VFOLDER_ITEM(item)); } else { if (!vfolder_widgets_is_visible()) vfolder_show_widgets(VFOLDER_ITEM(item)); }*/ /* items = vfolder_get_vfolder_from_source(hookdata->item); if (items) { for (cur = items; cur; cur = g_list_next(cur)) { vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_MSGCNT); } g_list_free(items); } */ } else if (hookdata->update_flags & F_ITEM_UPDATE_NAME) { /* TODO: need update? */ debug_print("F_ITEM_UPDATE_NAME\n"); items = vfolder_get_vfolder_from_source(hookdata->item); if (items) { for (cur = items; cur; cur = g_list_next(cur)) { vfolder_folder_item_update_msgs(VFOLDER_ITEM(cur->data), F_ITEM_UPDATE_NAME); } g_list_free(items); } } else { /* Unhandled callback */ debug_print("Unhandled FolderItem callback\n"); } /* if (!save_state) { MainWindow* mainwindow = mainwindow_get_mainwindow(); alertpanel_error(_("%s: Could not hide dangerous actions"), hookdata->item->name); summary_lock(mainwindow->summaryview); } */ return FALSE; } /* static gboolean vfolder_msg_info_update_hook(gpointer source, gpointer data) { MsgInfoUpdate* hookdata; MainWindow* mainwindow; MsgInfo* msginfo; g_return_val_if_fail(source != NULL, FALSE); hookdata = (MsgInfoUpdate *) source; msginfo = hookdata->msginfo; g_return_val_if_fail(msginfo != NULL, TRUE); if (IS_VFOLDER_MSGINFO(msginfo)) return FALSE; debug_print("\n\nPermflag: %u Tmpflag: %u (scanned: %u)\n\n\n", (guint32) msginfo->flags.perm_flags, (guint32) msginfo->flags.tmp_flags, 1U << 31); if (MSG_IS_NEW(msginfo->flags)) { debug_print("MSG_IS_NEW\n"); vfolder_update_affected_folder_items(msginfo); mainwindow = mainwindow_get_mainwindow(); summary_execute(mainwindow->summaryview); } if (MSG_IS_DELETED(msginfo->flags)) { debug_print("MSG_IS_DELETED\n"); vfolder_update_affected_folder_items(msginfo); mainwindow = mainwindow_get_mainwindow(); summary_execute(mainwindow->summaryview); } if (MSG_IS_MOVE(msginfo->flags)) { debug_print("MSG_IS_MOVE\n"); vfolder_update_affected_folder_items(msginfo); mainwindow = mainwindow_get_mainwindow(); summary_execute(mainwindow->summaryview); } if (MSG_IS_COPY(msginfo->flags)) { debug_print("MSG_IS_COPY\n"); vfolder_update_affected_folder_items(msginfo); mainwindow = mainwindow_get_mainwindow(); summary_execute(mainwindow->summaryview); } // if (MSG_IS_POSTFILTERED(msginfo->flags)) { // debug_print("MSG_IS_POSTFILTERED\n"); // vfolder_update_affected_folder_items(msginfo); // mainwindow = mainwindow_get_mainwindow(); // summary_execute(mainwindow->summaryview); // } return FALSE; } */ static gchar* vfolder_get_rc_file(VFolderItem* item) { gchar* (*item_get_path) (Folder* folder, FolderItem* item); gchar* path; gchar* rc_file; item_get_path = FOLDER_ITEM(item)->folder->klass->item_get_path; path = item_get_path(FOLDER_ITEM(item)->folder, FOLDER_ITEM(item)); rc_file = g_strconcat(path, G_DIR_SEPARATOR_S, "folderitemrc", NULL); g_free(path); return rc_file; } FolderPropsResponse vfolder_folder_item_props_write(VFolderItem* item) { gchar* rc_file; GKeyFile* config; gchar* id; gchar* data = NULL; FILE* fp; gsize len = 0; FolderPropsResponse resp = FOLDER_ITEM_PROPS_NO_ITEM; gchar* numstr; GHashTableIter iter; gpointer key, value; g_return_val_if_fail(item != NULL, resp); rc_file = vfolder_get_rc_file(item); config = g_key_file_new(); if (item->filter) g_key_file_set_string(config, CONFIG_GROUP, "filter", item->filter); g_key_file_set_integer(config, CONFIG_GROUP, "searchtype", item->search); g_key_file_set_boolean(config, CONFIG_GROUP, "frozen", item->frozen); g_key_file_set_boolean(config, CONFIG_GROUP, "deep_copy", item->deep_copy); if (item->source) { id = folder_item_get_identifier(item->source); if (id) { g_key_file_set_string(config, CONFIG_GROUP, "source", id); g_free(id); } } if (item->claws_to_me && item->me_to_claws) { numstr = NULL; g_hash_table_iter_init(&iter, item->claws_to_me); while (g_hash_table_iter_next(&iter, &key, &value)) { len++; MsgBridge* bridge = value; if (numstr) { gchar* tmp = g_strdup(numstr); g_free(numstr); numstr = g_strdup_printf("%s, %u:%u", tmp, bridge->my_num, bridge->claws_num); g_free(tmp); } else numstr = g_strdup_printf("%u:%u", bridge->my_num, bridge->claws_num); } g_key_file_set_string(config, CONFIG_GROUP, "file_id_list", numstr); g_free(numstr); } if (g_file_test(rc_file, G_FILE_TEST_EXISTS)) { gchar* bakpath = g_strconcat(rc_file, ".bak", NULL); if (g_rename(rc_file, bakpath) < 0) { g_warning("%s: Could not create", bakpath); resp = FOLDER_ITEM_PROPS_BACKUP_FAIL; } g_free(bakpath); } // g_key_file_set_integer(config, CONFIG_GROUP, "filter-function", item->filter_func); data = g_key_file_to_data(config, &len, NULL); if (len < 1) { g_warning("Could not get config data"); resp = FOLDER_ITEM_PROPS_READ_DATA_FAIL; } else { fp = g_fopen(rc_file, "w"); if (fp == NULL) { gchar* dir_path_end = g_strrstr(rc_file, G_DIR_SEPARATOR_S); gchar* rc_dir = g_strndup(rc_file, dir_path_end - rc_file); debug_print("rc_dir: %s\n", rc_dir); int r = g_mkdir_with_parents(rc_dir, 0700); if (r != 0) resp = FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL; g_free(rc_dir); if (resp == FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL) goto error; fp = g_fopen(rc_file, "w"); if (fp == NULL) { resp = FOLDER_ITEM_PROPS_MAKE_RC_DIR_FAIL; goto error; } } fwrite(data, len, 1, fp); fclose(fp); resp = FOLDER_ITEM_PROPS_OK; } error: g_free(data); g_key_file_free(config); g_free(rc_file); return resp; } FolderPropsResponse vfolder_folder_item_props_read(VFolderItem* item) { gchar* rc_file; GKeyFile* config; GError* error = NULL; gchar *id, *msgnums; gchar **list, **head; FolderPropsResponse resp = FOLDER_ITEM_PROPS_NO_ITEM; gint lastnum; g_return_val_if_fail(item != NULL, resp); rc_file = vfolder_get_rc_file(item); config = g_key_file_new(); if (g_file_test(rc_file, G_FILE_TEST_EXISTS)) { g_key_file_load_from_file(config, rc_file, G_KEY_FILE_KEEP_COMMENTS, &error); if (error) { g_warning("%s. Using defaults", error->message); g_error_free(error); resp = FOLDER_ITEM_PROPS_READ_USING_DEFAULT; } else { item->filter = g_key_file_get_string(config, CONFIG_GROUP, "filter", NULL); item->search = g_key_file_get_integer(config, CONFIG_GROUP, "searchtype", NULL); item->frozen = g_key_file_get_boolean(config, CONFIG_GROUP, "frozen", NULL); item->deep_copy = g_key_file_get_boolean(config, CONFIG_GROUP, "deep_copy", NULL); // item->filter_func = g_key_file_get_integer(config, CONFIG_GROUP, "filter_function", NULL); id = g_key_file_get_string(config, CONFIG_GROUP, "source", NULL); if (id) { item->source = folder_find_item_from_identifier(id); g_free(id); } msgnums = g_key_file_get_string(config, CONFIG_GROUP, "file_id_list", NULL); if (msgnums) { list = g_strsplit(msgnums, ",", 0); head = list; lastnum = -1; while (*list) { gchar* anum = g_strdup(*list++); g_strstrip(anum); MsgBridge* bridge = vfolder_split_file_id(anum); g_free(anum); if (lastnum < (gint) bridge->my_num) lastnum = bridge->my_num; if (bridge->my_num > 0) { vfolder_add_message_to_bridge(item, bridge); } g_free(bridge); } FOLDER_ITEM(item)->last_num = lastnum; g_strfreev(head); g_free(msgnums); } resp = FOLDER_ITEM_PROPS_OK; } } g_key_file_free(config); g_free(rc_file); return resp; } gboolean vfolder_gtk_init(gchar** error) { vfolder_fill_popup_menu_labels(); folderview_register_popup(&vfolder_popup); folder_hook_id = hooks_register_hook(FOLDER_UPDATE_HOOKLIST, vfolder_folder_update_hook, NULL); if (folder_hook_id == -1) { *error = g_strdup(_("Failed to register folder update hook")); return FALSE; } item_hook_id = hooks_register_hook(FOLDER_ITEM_UPDATE_HOOKLIST, vfolder_folder_item_update_hook, NULL); if (item_hook_id == -1) { *error = g_strdup(_("Failed to register folder item update hook")); hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id); return FALSE; } /* msginfo_hook_id = hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, vfolder_msg_info_update_hook, NULL); if (msginfo_hook_id == -1) { *error = g_strdup(_("Failed to register message info update hook")); hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id); hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id); return FALSE; }*/ if (! get_menu_widgets()) { *error = g_strdup(_("Failed to get menu widgets")); hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id); hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id); hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, msginfo_hook_id); return FALSE; } return TRUE; } void vfolder_gtk_done(void) { MainWindow *mainwin = mainwindow_get_mainwindow(); FolderView *folderview = NULL; FolderItem *fitem = NULL; hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, folder_hook_id); hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, item_hook_id); //hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, msginfo_hook_id); if (mainwin == NULL || claws_is_exiting()) return; folderview = mainwin->folderview; fitem = folderview->summaryview->folder_item; if (fitem && IS_VFOLDER_FOLDER_ITEM(fitem)) { vfolder_show_widgets(VFOLDER_ITEM(fitem)); gslist_menu_item_free(&widgets); folderview_unselect(folderview); summary_clear_all(folderview->summaryview); } folderview_unregister_popup(&vfolder_popup); } void vfolder_properties_cb(GtkAction* action, gpointer data) { FolderView *folderview = (FolderView *)data; FolderItem *item; g_return_if_fail(folderview != NULL); item = folderview_get_selected_item(folderview); g_return_if_fail(item != NULL); g_return_if_fail(item->path != NULL); g_return_if_fail(item->folder != NULL); if (vfolder_edit_item_dialog(VFOLDER_ITEM(item))) { /* TODO: update */ if (debug_get_mode()) { GHashTableIter iter; gpointer key, value; g_hash_table_iter_init(&iter, VFOLDER_ITEM(item)->me_to_claws); while (g_hash_table_iter_next(&iter, &key, &value)) { gchar* buf = g_new0(gchar, BUFSIZ); MsgInfo* msginfo = vfolder_find_msg_from_vfolder_num( VFOLDER_ITEM(item), GPOINTER_TO_UINT(key)); FILE* msg = procmsg_open_message(msginfo); while (fread(buf, 1, BUFSIZ - 1, msg) > 0) { fprintf(stderr, "%s", buf); g_free(buf); buf = g_new0(gchar, BUFSIZ); } fprintf(stderr, "\n"); if (buf) g_free(buf); fclose(msg); } } vfolder_folder_item_props_write(VFOLDER_ITEM(item)); } } void vfolder_new_folder_cb(GtkAction* action, gpointer data) { FolderView *folderview = (FolderView *)data; GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree); FolderItem *item; FolderItem *new_item; gchar *new_folder; gchar *name; gchar *p; if (!folderview->selected) return; item = gtk_cmctree_node_get_row_data(ctree, folderview->selected); if (! item) { item = FOLDER_ITEM(vfolder_get_vfolder_item(NULL)); } g_return_if_fail(item != NULL); g_return_if_fail(item->folder != NULL); if (item->no_sub) { alertpanel_error(N_("Virtual folders cannot contain subfolders")); return; } new_folder = input_dialog(_("New folder"), _("Input the name of new folder:"), _("NewFolder")); if (!new_folder) return; AUTORELEASE_STR(new_folder, {g_free(new_folder); return;}); p = strchr(new_folder, G_DIR_SEPARATOR); if (p) { alertpanel_error(_("'%c' can't be included in folder name."), G_DIR_SEPARATOR); return; } name = trim_string(new_folder, 32); AUTORELEASE_STR(name, {g_free(name); return;}); /* find whether the directory already exists */ if (folder_find_child_item_by_name(item, new_folder)) { alertpanel_error(_("The folder '%s' already exists."), name); return; } new_item = folder_create_folder(item, new_folder); if (!new_item) { alertpanel_error(_("Can't create the folder '%s'."), name); return; } if (! vfolder_create_item_dialog(new_item)) { //VFolderItem* vitem = VFOLDER_ITEM(new_item); new_item->folder->klass->remove_folder(new_item->folder, new_item); new_item = NULL; return; } folder_write_list(); } void vfolder_remove_folder_cb(GtkAction* action, gpointer data) { FolderView *folderview = (FolderView *)data; GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree); FolderItem *item; gchar *message, *name; AlertValue avalue; gchar *old_path = NULL; gchar *old_id; /* Silence lame warnings */ old_id = (old_path) ? NULL : old_path; item = folderview_get_selected_item(folderview); g_return_if_fail(item != NULL); g_return_if_fail(item->path != NULL); g_return_if_fail(item->folder != NULL); name = trim_string(item->name, 32); AUTORELEASE_STR(name, {g_free(name); return;}); message = g_strdup_printf (_("All folders and messages under '%s' will be permanently deleted. " "Recovery will not be possible.\n\n" "Do you really want to delete?"), name); avalue = alertpanel_full(_("Delete folder"), message, GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, FALSE, NULL, ALERT_WARNING, G_ALERTDEFAULT); g_free(message); if (avalue != G_ALERTALTERNATE) return; Xstrdup_a(old_path, item->path, return); old_id = folder_item_get_identifier(item); if (folderview->opened == folderview->selected || gtk_cmctree_is_ancestor(ctree, folderview->selected, folderview->opened)) { summary_clear_all(folderview->summaryview); folderview->opened = NULL; } if (item->folder->klass->remove_folder(item->folder, item) < 0) { folder_item_scan(item); alertpanel_error(_("Can't remove the folder '%s'."), name); g_free(old_id); return; } folder_write_list(); g_free(old_id); }