diff options
author | hiro <hiro@ee746299-78ed-0310-b773-934348b2243d> | 2005-12-19 06:41:50 +0000 |
---|---|---|
committer | hiro <hiro@ee746299-78ed-0310-b773-934348b2243d> | 2005-12-19 06:41:50 +0000 |
commit | d55459c79d6ddfa0b006c5696d408a7e388cf8c8 (patch) | |
tree | 98e8ea35bfce5bc235adbc544de8aba1f754b8ac /src | |
parent | 1ca5b9aa126b860d9198f85e44104f857513bef5 (diff) |
implemented query search and virtual folder (merged from newsearch branch).
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@836 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'src')
-rw-r--r-- | src/folderview.c | 29 | ||||
-rw-r--r-- | src/mainwindow.c | 9 | ||||
-rw-r--r-- | src/prefs_filter_edit.c | 7 | ||||
-rw-r--r-- | src/prefs_filter_edit.h | 19 | ||||
-rw-r--r-- | src/prefs_folder_item.c | 3 | ||||
-rw-r--r-- | src/summary_search.c | 1156 | ||||
-rw-r--r-- | src/summary_search.h | 4 | ||||
-rw-r--r-- | src/summaryview.c | 2 |
8 files changed, 873 insertions, 356 deletions
diff --git a/src/folderview.c b/src/folderview.c index 43ff7732..42965160 100644 --- a/src/folderview.c +++ b/src/folderview.c @@ -105,6 +105,7 @@ static GdkPixbuf *folderopen_pixbuf; static GdkPixbuf *foldernoselect_pixbuf; static GdkPixbuf *draft_pixbuf; static GdkPixbuf *trash_pixbuf; +static GdkPixbuf *virtual_pixbuf; static void folderview_set_columns (FolderView *folderview); @@ -516,6 +517,7 @@ void folderview_init(FolderView *folderview) &foldernoselect_pixbuf); stock_pixbuf_gdk(treeview, STOCK_PIXMAP_DRAFT, &draft_pixbuf); stock_pixbuf_gdk(treeview, STOCK_PIXMAP_TRASH, &trash_pixbuf); + stock_pixbuf_gdk(treeview, STOCK_PIXMAP_GROUP, &virtual_pixbuf); } void folderview_reflect_prefs(FolderView *folderview) @@ -1170,6 +1172,19 @@ static void folderview_update_row(FolderView *folderview, GtkTreeIter *iter) !strcmp2(item->name, DRAFT_DIR) ? _("Drafts") : item->name); break; +#if 0 + case F_JUNK: + pixbuf = folder_pixbuf; + open_pixbuf = folderopen_pixbuf; + name = g_strdup(FOLDER_IS_LOCAL(item->folder) && + !strcmp2(item->name, JUNK_DIR) ? _("Junk") : + item->name); + break; +#endif + case F_VIRTUAL: + pixbuf = open_pixbuf = virtual_pixbuf; + name = g_strdup(item->name); + break; default: if (item->no_select) { pixbuf = open_pixbuf = foldernoselect_pixbuf; @@ -1540,14 +1555,13 @@ static gboolean folderview_menu_popup(FolderView *folderview, if (folderview->mainwin->lock_count == 0) { new_folder = TRUE; folder_property = TRUE; + search_folder = TRUE; if (item->parent == NULL) { update_tree = remove_tree = TRUE; } else { if (gtkut_tree_row_reference_equal - (folderview->selected, folderview->opened)) { + (folderview->selected, folderview->opened)) update_summary = TRUE; - search_folder = TRUE; - } } if (FOLDER_IS_LOCAL(folder) || FOLDER_TYPE(folder) == F_IMAP) { if (item->parent == NULL) @@ -1562,6 +1576,9 @@ static gboolean folderview_menu_popup(FolderView *folderview, if (item->parent != NULL) delete_folder = TRUE; } + if (item->stype == F_VIRTUAL) { + rename_folder = delete_folder = TRUE; + } if (FOLDER_TYPE(folder) == F_IMAP || FOLDER_TYPE(folder) == F_NEWS) { if (item->parent != NULL && item->no_select == FALSE) @@ -2608,7 +2625,11 @@ static void folderview_rm_news_server_cb(FolderView *folderview, guint action, static void folderview_search_cb(FolderView *folderview, guint action, GtkWidget *widget) { - summary_search(folderview->summaryview); + FolderItem *item; + + item = folderview_get_selected_item(folderview); + if (item) + summary_search(folderview->summaryview, item); } static void folderview_property_cb(FolderView *folderview, guint action, diff --git a/src/mainwindow.c b/src/mainwindow.c index 19afdda3..d7f90d19 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -2758,9 +2758,12 @@ static void app_exit_cb(MainWindow *mainwin, guint action, GtkWidget *widget) static void search_cb(MainWindow *mainwin, guint action, GtkWidget *widget) { - if (action == 1) - summary_search(mainwin->summaryview); - else + if (action == 1) { + FolderItem *item; + + item = folderview_get_selected_item(mainwin->folderview); + summary_search(mainwin->summaryview, item); + } else message_search(mainwin->messageview); } diff --git a/src/prefs_filter_edit.c b/src/prefs_filter_edit.c index 52821448..af804aed 100644 --- a/src/prefs_filter_edit.c +++ b/src/prefs_filter_edit.c @@ -335,6 +335,7 @@ FilterCondEdit *prefs_filter_edit_cond_edit_create(void) cond_edit->cond_hbox_list = NULL; cond_edit->hdr_list = NULL; cond_edit->rule_hdr_list = NULL; + cond_edit->add_hbox = NULL; return cond_edit; } @@ -1243,6 +1244,8 @@ static void prefs_filter_edit_add_rule_cond(FilterCondEdit *cond_edit, hbox = prefs_filter_edit_cond_hbox_create(cond_edit); prefs_filter_edit_set_cond_hbox_widgets(hbox, PF_COND_HEADER); prefs_filter_edit_insert_cond_hbox(cond_edit, hbox, -1); + if (cond_edit->add_hbox) + cond_edit->add_hbox(hbox); return; } @@ -1252,6 +1255,8 @@ static void prefs_filter_edit_add_rule_cond(FilterCondEdit *cond_edit, hbox = prefs_filter_edit_cond_hbox_create(cond_edit); prefs_filter_edit_cond_hbox_set(hbox, cond); prefs_filter_edit_insert_cond_hbox(cond_edit, hbox, -1); + if (cond_edit->add_hbox) + cond_edit->add_hbox(hbox); } } @@ -1964,6 +1969,8 @@ static void prefs_filter_cond_add_cb(GtkWidget *widget, gpointer data) new_hbox = prefs_filter_edit_cond_hbox_create(cond_edit); prefs_filter_edit_set_cond_hbox_widgets(new_hbox, PF_COND_HEADER); prefs_filter_edit_insert_cond_hbox(cond_edit, new_hbox, index + 1); + if (cond_edit->add_hbox) + cond_edit->add_hbox(new_hbox); } static void prefs_filter_action_del_cb(GtkWidget *widget, gpointer data) diff --git a/src/prefs_filter_edit.h b/src/prefs_filter_edit.h index fd720fa2..dbc967f3 100644 --- a/src/prefs_filter_edit.h +++ b/src/prefs_filter_edit.h @@ -24,6 +24,10 @@ #include "filter.h" +typedef struct _FilterCondEdit FilterCondEdit; +typedef struct _CondHBox CondHBox; +typedef struct _ActionHBox ActionHBox; + typedef enum { PF_COND_HEADER, @@ -81,15 +85,18 @@ typedef enum PF_ACTION_NONE } ActionMenuType; -typedef struct _FilterCondEdit { +struct _FilterCondEdit { GtkWidget *cond_vbox; GSList *cond_hbox_list; GSList *hdr_list; GSList *rule_hdr_list; -} FilterCondEdit; -typedef struct _CondHBox { + /* callback */ + void (*add_hbox) (CondHBox *hbox); +}; + +struct _CondHBox { GtkWidget *hbox; GtkWidget *cond_type_optmenu; @@ -107,9 +114,9 @@ typedef struct _CondHBox { gchar *cur_header_name; FilterCondEdit *cond_edit; -} CondHBox; +}; -typedef struct _ActionHBox { +struct _ActionHBox { GtkWidget *hbox; GtkWidget *action_type_optmenu; @@ -125,7 +132,7 @@ typedef struct _ActionHBox { GtkWidget *del_btn; GtkWidget *add_btn; -} ActionHBox; +}; FilterRule *prefs_filter_edit_open (FilterRule *rule, diff --git a/src/prefs_folder_item.c b/src/prefs_folder_item.c index fefe44bc..9d777eba 100644 --- a/src/prefs_folder_item.c +++ b/src/prefs_folder_item.c @@ -561,6 +561,9 @@ static void prefs_folder_item_apply_cb(GtkWidget *widget, prev_item = folder->trash; folder->trash = item; break; + default: + type = item->stype; + break; } item->stype = type; diff --git a/src/summary_search.c b/src/summary_search.c index c388944a..d6a76017 100644 --- a/src/summary_search.c +++ b/src/summary_search.c @@ -40,69 +40,139 @@ #include <gtk/gtkmenuitem.h> #include <gtk/gtkstock.h> #include <gtk/gtktreemodel.h> +#include <gtk/gtkliststore.h> +#include <gtk/gtktreeview.h> #include <gtk/gtktreeselection.h> +#include <gtk/gtkcellrenderertext.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "main.h" #include "summary_search.h" +#include "prefs_filter_edit.h" #include "summaryview.h" #include "messageview.h" #include "mainwindow.h" +#include "folderview.h" #include "menu.h" #include "utils.h" #include "gtkutils.h" #include "manage_window.h" #include "alertpanel.h" +#include "foldersel.h" +#include "procmsg.h" +#include "procheader.h" +#include "folder.h" +#include "filter.h" +#include "prefs_filter.h" +#include "prefs_filter_edit.h" + +enum +{ + COL_FOLDER, + COL_SUBJECT, + COL_FROM, + COL_DATE, + COL_MSGINFO, + N_COLS +}; static struct SummarySearchWindow { GtkWidget *window; GtkWidget *bool_optmenu; - GtkWidget *from_entry; - GtkWidget *to_entry; - GtkWidget *subject_entry; - GtkWidget *body_entry; + FilterCondEdit *cond_edit; + + GtkWidget *folder_entry; + GtkWidget *folder_btn; + GtkWidget *subfolder_checkbtn; GtkWidget *case_checkbtn; + GtkWidget *treeview; + GtkListStore *store; + + GtkWidget *status_label; + GtkWidget *clear_btn; + GtkWidget *search_btn; + GtkWidget *save_btn; GtkWidget *close_btn; - GtkWidget *all_btn; - GtkWidget *prev_btn; - GtkWidget *next_btn; SummaryView *summaryview; + + FilterRule *rule; + gboolean requires_full_headers; + + gboolean on_search; + gboolean cancelled; } search_window; +typedef struct { + GtkWidget *window; + + GtkWidget *folder_entry; + GtkWidget *name_entry; + + gboolean cancelled; + gboolean finished; +} SummarySearchSaveDialog; + static void summary_search_create (void); -static void summary_search_execute (gboolean backward, - gboolean search_all); +static FilterRule *summary_search_dialog_to_rule + (const gchar *name, + FolderItem **item); + +static void summary_search_query (void); +static void summary_search_folder (FolderItem *item); + +static gboolean summary_search_recursive_func (GNode *node, + gpointer data); + +static void summary_search_append_msg (MsgInfo *msginfo); +static void summary_search_clear_list (void); + +static void summary_search_hbox_added (CondHBox *hbox); + +static void row_activated (GtkTreeView *treeview, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer data); + +static gboolean row_selected (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean cur_selected, + gpointer data); static void summary_search_clear (GtkButton *button, gpointer data); -static void summary_search_prev_clicked (GtkButton *button, +static void summary_select_folder (GtkButton *button, + gpointer data); +static void summary_search_clicked (GtkButton *button, gpointer data); -static void summary_search_next_clicked (GtkButton *button, +static void summary_search_save (GtkButton *button, gpointer data); -static void summary_search_all_clicked (GtkButton *button, +static void summary_search_close (GtkButton *button, gpointer data); -static void from_activated (void); -static void to_activated (void); -static void subject_activated (void); -static void body_activated (void); +static void summary_search_entry_activated (GtkWidget *widget, + gpointer data); +static gint summary_search_deleted (GtkWidget *widget, + GdkEventAny *event, + gpointer data); static gboolean key_pressed (GtkWidget *widget, GdkEventKey *event, gpointer data); -void summary_search(SummaryView *summaryview) +void summary_search(SummaryView *summaryview, FolderItem *item) { + gchar *id; + if (!search_window.window) summary_search_create(); else @@ -110,8 +180,14 @@ void summary_search(SummaryView *summaryview) search_window.summaryview = summaryview; - gtk_widget_grab_focus(search_window.next_btn); - gtk_widget_grab_focus(search_window.subject_entry); + if (item) { + id = folder_item_get_identifier(item); + gtk_entry_set_text(GTK_ENTRY(search_window.folder_entry), id); + g_free(id); + } else + gtk_entry_set_text(GTK_ENTRY(search_window.folder_entry), ""); + + gtk_widget_grab_focus(search_window.search_btn); gtk_widget_show(search_window.window); } @@ -124,42 +200,51 @@ static void summary_search_create(void) GtkWidget *bool_menu; GtkWidget *menuitem; GtkWidget *clear_btn; + GtkWidget *search_btn; - GtkWidget *table1; - GtkWidget *from_label; - GtkWidget *from_entry; - GtkWidget *to_label; - GtkWidget *to_entry; - GtkWidget *subject_label; - GtkWidget *subject_entry; - GtkWidget *body_label; - GtkWidget *body_entry; + GtkWidget *scrolledwin; + FilterCondEdit *cond_edit; + CondHBox *cond_hbox; + + GtkWidget *folder_hbox; + GtkWidget *folder_label; + GtkWidget *folder_entry; + GtkWidget *folder_btn; GtkWidget *checkbtn_hbox; + GtkWidget *subfolder_checkbtn; GtkWidget *case_checkbtn; + GtkWidget *treeview; + GtkListStore *store; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkTreeSelection *selection; + GtkWidget *confirm_area; + + GtkWidget *status_label; + + GtkWidget *hbbox; + GtkWidget *save_btn; GtkWidget *close_btn; - GtkWidget *all_btn; - GtkWidget *prev_btn; - GtkWidget *next_btn; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW (window), _("Search messages")); - gtk_widget_set_size_request(window, 450, -1); + gtk_widget_set_size_request(window, 600, -1); gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, TRUE); gtk_container_set_border_width(GTK_CONTAINER (window), 8); g_signal_connect(G_OBJECT(window), "delete_event", - G_CALLBACK(gtk_widget_hide_on_delete), NULL); + G_CALLBACK(summary_search_deleted), NULL); g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(key_pressed), NULL); MANAGE_WINDOW_SIGNALS_CONNECT(window); - vbox1 = gtk_vbox_new (FALSE, 0); + vbox1 = gtk_vbox_new (FALSE, 6); gtk_widget_show (vbox1); gtk_container_add (GTK_CONTAINER (window), vbox1); - bool_hbox = gtk_hbox_new(FALSE, 4); + bool_hbox = gtk_hbox_new(FALSE, 12); gtk_widget_show(bool_hbox); gtk_box_pack_start(GTK_BOX(vbox1), bool_hbox, FALSE, FALSE, 0); @@ -168,389 +253,778 @@ static void summary_search_create(void) gtk_box_pack_start(GTK_BOX(bool_hbox), bool_optmenu, FALSE, FALSE, 0); bool_menu = gtk_menu_new(); - MENUITEM_ADD(bool_menu, menuitem, _("Match any of the following"), 0); - MENUITEM_ADD(bool_menu, menuitem, _("Match all of the following"), 1); + MENUITEM_ADD(bool_menu, menuitem, _("Match any of the following"), + FLT_OR); + MENUITEM_ADD(bool_menu, menuitem, _("Match all of the following"), + FLT_AND); gtk_option_menu_set_menu(GTK_OPTION_MENU(bool_optmenu), bool_menu); + hbbox = gtk_hbutton_box_new(); + gtk_widget_show(hbbox); + gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox), GTK_BUTTONBOX_END); + gtk_box_set_spacing(GTK_BOX(hbbox), 6); + gtk_box_pack_end(GTK_BOX(bool_hbox), hbbox, FALSE, FALSE, 0); + clear_btn = gtk_button_new_from_stock(GTK_STOCK_CLEAR); gtk_widget_show(clear_btn); - gtk_box_pack_end(GTK_BOX(bool_hbox), clear_btn, FALSE, FALSE, 0); - - table1 = gtk_table_new (4, 3, FALSE); - gtk_widget_show (table1); - gtk_box_pack_start (GTK_BOX (vbox1), table1, TRUE, TRUE, 0); - gtk_container_set_border_width (GTK_CONTAINER (table1), 4); - gtk_table_set_row_spacings (GTK_TABLE (table1), 8); - gtk_table_set_col_spacings (GTK_TABLE (table1), 8); - - from_entry = gtk_entry_new (); - gtk_widget_show (from_entry); - gtk_table_attach (GTK_TABLE (table1), from_entry, 1, 3, 0, 1, - GTK_EXPAND|GTK_FILL, 0, 0, 0); - g_signal_connect(G_OBJECT(from_entry), "activate", - G_CALLBACK(from_activated), NULL); - - to_entry = gtk_entry_new (); - gtk_widget_show (to_entry); - gtk_table_attach (GTK_TABLE (table1), to_entry, 1, 3, 1, 2, - GTK_EXPAND|GTK_FILL, 0, 0, 0); - g_signal_connect(G_OBJECT(to_entry), "activate", - G_CALLBACK(to_activated), NULL); - - subject_entry = gtk_entry_new (); - gtk_widget_show (subject_entry); - gtk_table_attach (GTK_TABLE (table1), subject_entry, 1, 3, 2, 3, - GTK_EXPAND|GTK_FILL, 0, 0, 0); - g_signal_connect(G_OBJECT(subject_entry), "activate", - G_CALLBACK(subject_activated), NULL); - - body_entry = gtk_entry_new (); - gtk_widget_show (body_entry); - gtk_table_attach (GTK_TABLE (table1), body_entry, 1, 3, 3, 4, - GTK_EXPAND|GTK_FILL, 0, 0, 0); - g_signal_connect(G_OBJECT(body_entry), "activate", - G_CALLBACK(body_activated), NULL); - - from_label = gtk_label_new (_("From:")); - gtk_widget_show (from_label); - gtk_table_attach (GTK_TABLE (table1), from_label, 0, 1, 0, 1, - GTK_FILL, 0, 0, 0); - gtk_label_set_justify (GTK_LABEL (from_label), GTK_JUSTIFY_RIGHT); - gtk_misc_set_alignment (GTK_MISC (from_label), 1, 0.5); - - to_label = gtk_label_new (_("To:")); - gtk_widget_show (to_label); - gtk_table_attach (GTK_TABLE (table1), to_label, 0, 1, 1, 2, - GTK_FILL, 0, 0, 0); - gtk_label_set_justify (GTK_LABEL (to_label), GTK_JUSTIFY_RIGHT); - gtk_misc_set_alignment (GTK_MISC (to_label), 1, 0.5); - - subject_label = gtk_label_new (_("Subject:")); - gtk_widget_show (subject_label); - gtk_table_attach (GTK_TABLE (table1), subject_label, 0, 1, 2, 3, - GTK_FILL, 0, 0, 0); - gtk_label_set_justify (GTK_LABEL (subject_label), GTK_JUSTIFY_RIGHT); - gtk_misc_set_alignment (GTK_MISC (subject_label), 1, 0.5); - - body_label = gtk_label_new (_("Body:")); - gtk_widget_show (body_label); - gtk_table_attach (GTK_TABLE (table1), body_label, 0, 1, 3, 4, - GTK_FILL, 0, 0, 0); - gtk_label_set_justify (GTK_LABEL (body_label), GTK_JUSTIFY_RIGHT); - gtk_misc_set_alignment (GTK_MISC (body_label), 1, 0.5); - - checkbtn_hbox = gtk_hbox_new (FALSE, 8); + gtk_box_pack_start(GTK_BOX(hbbox), clear_btn, FALSE, FALSE, 0); + + search_btn = gtk_button_new_from_stock(GTK_STOCK_FIND); + GTK_WIDGET_SET_FLAGS(search_btn, GTK_CAN_DEFAULT); + gtk_widget_show(search_btn); + gtk_box_pack_start(GTK_BOX(hbbox), search_btn, FALSE, FALSE, 0); + gtk_widget_grab_default(search_btn); + + scrolledwin = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_show(scrolledwin); + gtk_box_pack_start(GTK_BOX(vbox1), scrolledwin, FALSE, FALSE, 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_widget_set_size_request(scrolledwin, -1, 120); + + cond_edit = prefs_filter_edit_cond_edit_create(); + cond_edit->add_hbox = summary_search_hbox_added; + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwin), + cond_edit->cond_vbox); + prefs_filter_set_header_list(NULL); + prefs_filter_edit_set_header_list(cond_edit, NULL); + cond_hbox = prefs_filter_edit_cond_hbox_create(cond_edit); + prefs_filter_edit_set_cond_hbox_widgets(cond_hbox, PF_COND_HEADER); + prefs_filter_edit_insert_cond_hbox(cond_edit, cond_hbox, -1); + if (cond_edit->add_hbox) + cond_edit->add_hbox(cond_hbox); + + folder_hbox = gtk_hbox_new (FALSE, 8); + gtk_widget_show (folder_hbox); + gtk_box_pack_start (GTK_BOX (vbox1), folder_hbox, FALSE, FALSE, 0); + + folder_label = gtk_label_new (_("Folder:")); + gtk_widget_show (folder_label); + gtk_box_pack_start (GTK_BOX (folder_hbox), folder_label, + FALSE, FALSE, 0); + + folder_entry = gtk_entry_new (); + gtk_widget_show (folder_entry); + gtk_box_pack_start (GTK_BOX (folder_hbox), folder_entry, TRUE, TRUE, 0); + + folder_btn = gtk_button_new_with_label("..."); + gtk_widget_show (folder_btn); + gtk_box_pack_start (GTK_BOX (folder_hbox), folder_btn, FALSE, FALSE, 0); + + checkbtn_hbox = gtk_hbox_new (FALSE, 12); gtk_widget_show (checkbtn_hbox); - gtk_box_pack_start (GTK_BOX (vbox1), checkbtn_hbox, TRUE, TRUE, 0); - gtk_container_set_border_width (GTK_CONTAINER (checkbtn_hbox), 8); + gtk_box_pack_start (GTK_BOX (vbox1), checkbtn_hbox, FALSE, FALSE, 0); + + subfolder_checkbtn = + gtk_check_button_new_with_label (_("Search subfolders")); + gtk_widget_show (subfolder_checkbtn); + gtk_box_pack_start (GTK_BOX (checkbtn_hbox), subfolder_checkbtn, + FALSE, FALSE, 0); case_checkbtn = gtk_check_button_new_with_label (_("Case sensitive")); gtk_widget_show (case_checkbtn); gtk_box_pack_start (GTK_BOX (checkbtn_hbox), case_checkbtn, FALSE, FALSE, 0); - confirm_area = gtk_hbutton_box_new(); - gtk_widget_show (confirm_area); - gtk_button_box_set_layout(GTK_BUTTON_BOX(confirm_area), - GTK_BUTTONBOX_END); - gtk_box_set_spacing(GTK_BOX(confirm_area), 6); + scrolledwin = gtk_scrolled_window_new(NULL, NULL); + gtk_box_pack_start(GTK_BOX(vbox1), scrolledwin, TRUE, TRUE, 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin), + GTK_SHADOW_IN); + gtk_widget_set_size_request(scrolledwin, -1, 150); + + store = gtk_list_store_new(N_COLS, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_POINTER); + treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + g_object_unref(store); + gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); + g_signal_connect(G_OBJECT(treeview), "row-activated", + G_CALLBACK(row_activated), NULL); + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); + gtk_tree_selection_set_select_function(selection, row_selected, + NULL, NULL); + + gtk_container_add(GTK_CONTAINER(scrolledwin), treeview); + +#define APPEND_COLUMN(label, col, width) \ +{ \ + renderer = gtk_cell_renderer_text_new(); \ + column = gtk_tree_view_column_new_with_attributes \ + (label, renderer, "text", col, NULL); \ + gtk_tree_view_column_set_resizable(column, TRUE); \ + if (width) { \ + gtk_tree_view_column_set_sizing \ + (column, GTK_TREE_VIEW_COLUMN_FIXED); \ + gtk_tree_view_column_set_fixed_width(column, width); \ + } \ + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); \ +} - close_btn = gtk_button_new_from_stock(GTK_STOCK_CLOSE); - GTK_WIDGET_SET_FLAGS(close_btn, GTK_CAN_DEFAULT); - gtk_box_pack_start(GTK_BOX(confirm_area), close_btn, TRUE, TRUE, 0); - gtk_widget_show(close_btn); + APPEND_COLUMN(_("Folder"), COL_FOLDER, 0); + APPEND_COLUMN(_("Subject"), COL_SUBJECT, 200); + APPEND_COLUMN(_("From"), COL_FROM, 180); + APPEND_COLUMN(_("Date"), COL_DATE, 0); + + gtk_widget_show_all(scrolledwin); - all_btn = gtk_button_new_from_stock(_("Find all")); - GTK_WIDGET_SET_FLAGS(all_btn, GTK_CAN_DEFAULT); - gtk_box_pack_start(GTK_BOX(confirm_area), all_btn, TRUE, TRUE, 0); - gtk_widget_show(all_btn); + confirm_area = gtk_hbox_new(FALSE, 12); + gtk_widget_show(confirm_area); + gtk_box_pack_start(GTK_BOX(vbox1), confirm_area, FALSE, FALSE, 0); - prev_btn = gtk_button_new_from_stock(GTK_STOCK_GO_BACK); - GTK_WIDGET_SET_FLAGS(prev_btn, GTK_CAN_DEFAULT); - gtk_box_pack_start(GTK_BOX(confirm_area), prev_btn, TRUE, TRUE, 0); - gtk_widget_show(prev_btn); + status_label = gtk_label_new(""); + gtk_widget_show(status_label); + gtk_box_pack_start(GTK_BOX(confirm_area), status_label, + FALSE, FALSE, 0); - next_btn = gtk_button_new_from_stock(GTK_STOCK_GO_FORWARD); - GTK_WIDGET_SET_FLAGS(next_btn, GTK_CAN_DEFAULT); - gtk_box_pack_start(GTK_BOX(confirm_area), next_btn, TRUE, TRUE, 0); - gtk_widget_show(next_btn); + hbbox = gtk_hbutton_box_new(); + gtk_widget_show(hbbox); + gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox), GTK_BUTTONBOX_END); + gtk_box_set_spacing(GTK_BOX(hbbox), 6); + gtk_box_pack_end(GTK_BOX(confirm_area), hbbox, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox1), confirm_area, FALSE, FALSE, 0); - gtk_widget_grab_default(next_btn); + save_btn = gtk_button_new_with_mnemonic(_("_Save as search folder")); + gtk_box_pack_start(GTK_BOX(hbbox), save_btn, FALSE, FALSE, 0); + gtk_widget_show(save_btn); + + close_btn = gtk_button_new_from_stock(GTK_STOCK_CLOSE); + GTK_WIDGET_SET_FLAGS(close_btn, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(hbbox), close_btn, FALSE, FALSE, 0); + gtk_widget_show(close_btn); g_signal_connect(G_OBJECT(clear_btn), "clicked", G_CALLBACK(summary_search_clear), NULL); - g_signal_connect(G_OBJECT(all_btn), "clicked", - G_CALLBACK(summary_search_all_clicked), NULL); - g_signal_connect(G_OBJECT(prev_btn), "clicked", - G_CALLBACK(summary_search_prev_clicked), NULL); - g_signal_connect(G_OBJECT(next_btn), "clicked", - G_CALLBACK(summary_search_next_clicked), NULL); - g_signal_connect_closure - (G_OBJECT(close_btn), "clicked", - g_cclosure_new_swap(G_CALLBACK(gtk_widget_hide), - window, NULL), - FALSE); + g_signal_connect(G_OBJECT(folder_btn), "clicked", + G_CALLBACK(summary_select_folder), NULL); + g_signal_connect(G_OBJECT(search_btn), "clicked", + G_CALLBACK(summary_search_clicked), NULL); + g_signal_connect(G_OBJECT(save_btn), "clicked", + G_CALLBACK(summary_search_save), NULL); + g_signal_connect(G_OBJECT(close_btn), "clicked", + G_CALLBACK(summary_search_close), NULL); search_window.window = window; search_window.bool_optmenu = bool_optmenu; - search_window.from_entry = from_entry; - search_window.to_entry = to_entry; - search_window.subject_entry = subject_entry; - search_window.body_entry = body_entry; + + search_window.cond_edit = cond_edit; + + search_window.folder_entry = folder_entry; + search_window.folder_btn = folder_btn; + search_window.subfolder_checkbtn = subfolder_checkbtn; search_window.case_checkbtn = case_checkbtn; + + search_window.treeview = treeview; + search_window.store = store; + + search_window.status_label = status_label; + search_window.clear_btn = clear_btn; + search_window.search_btn = search_btn; + search_window.save_btn = save_btn; search_window.close_btn = close_btn; - search_window.all_btn = all_btn; - search_window.prev_btn = prev_btn; - search_window.next_btn = next_btn; } -static void summary_search_execute(gboolean backward, gboolean search_all) +static FilterRule *summary_search_dialog_to_rule(const gchar *name, + FolderItem **item) { - SummaryView *summaryview = search_window.summaryview; - GtkTreeModel *model; - GtkTreeIter iter; - MsgInfo *msginfo; - gboolean bool_and; + const gchar *id; + FolderItem *item_; + FilterBoolOp bool_op = FLT_OR; + gboolean recursive; gboolean case_sens; - gboolean all_searched = FALSE; - gboolean matched; - gboolean body_matched; - const gchar *from_str, *to_str, *subject_str, *body_str; - StrFindFunc str_find_func; - gboolean valid; - - if (summary_is_locked(summaryview)) return; - summary_lock(summaryview); - - model = GTK_TREE_MODEL(summaryview->store); - - bool_and = menu_get_option_menu_active_index + GSList *cond_list = NULL; + FilterCond *cond; + FilterRule *rule; + GSList *cur; + + id = gtk_entry_get_text(GTK_ENTRY(search_window.folder_entry)); + item_ = folder_find_item_from_identifier(id); + if (!item_) + return NULL; + if (item) + *item = item_; + + bool_op = menu_get_option_menu_active_index (GTK_OPTION_MENU(search_window.bool_optmenu)); + recursive = gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON(search_window.subfolder_checkbtn)); case_sens = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(search_window.case_checkbtn)); - if (case_sens) - str_find_func = str_find; - else - str_find_func = str_case_find; - - from_str = gtk_entry_get_text(GTK_ENTRY(search_window.from_entry)); - to_str = gtk_entry_get_text(GTK_ENTRY(search_window.to_entry)); - subject_str = gtk_entry_get_text(GTK_ENTRY(search_window.subject_entry)); - body_str = gtk_entry_get_text(GTK_ENTRY(search_window.body_entry)); - - if (search_all) { - summary_unselect_all(summaryview); - valid = gtk_tree_model_get_iter_first(model, &iter); - backward = FALSE; - } else if (!summaryview->selected) { - if (backward) - valid = gtkut_tree_model_get_iter_last(model, &iter); - else - valid = gtk_tree_model_get_iter_first(model, &iter); - if (!valid) { - summary_unlock(summaryview); - return; - } - } else { - valid = gtkut_tree_row_reference_get_iter - (model, summaryview->selected, &iter); - if (!valid) { - summary_unlock(summaryview); - return; + for (cur = search_window.cond_edit->cond_hbox_list; cur != NULL; + cur = cur->next) { + CondHBox *hbox = (CondHBox *)cur->data; + gchar *error_msg; + + cond = prefs_filter_edit_cond_hbox_to_cond(hbox, case_sens, + &error_msg); + if (cond) { + cond_list = g_slist_append(cond_list, cond); + } else { + if (!error_msg) + error_msg = _("Invalid condition exists."); + alertpanel_error("%s", error_msg); + filter_cond_list_free(cond_list); + return NULL; } + } - if (backward) - valid = gtkut_tree_model_prev(model, &iter); - else - valid = gtkut_tree_model_next(model, &iter); + if (!cond_list) + return NULL; + + rule = filter_rule_new(name, bool_op, cond_list, NULL); + rule->target_folder = g_strdup(id); + rule->recursive = recursive; + + return rule; +} + +static void summary_search_query(void) +{ + FolderItem *item; + + if (search_window.on_search) + return; + + search_window.on_search = TRUE; + + search_window.rule = summary_search_dialog_to_rule("Query rule", &item); + if (!search_window.rule) { + search_window.on_search = FALSE; + return; } + search_window.requires_full_headers = + filter_rule_requires_full_headers(search_window.rule); - if (*body_str) - main_window_cursor_wait(summaryview->mainwin); + search_window.cancelled = FALSE; - for (;;) { - if (!valid) { - gchar *str; - AlertValue val; + gtk_button_set_label(GTK_BUTTON(search_window.search_btn), + GTK_STOCK_STOP); + summary_search_clear_list(); - if (search_all) { - break; - } + if (search_window.rule->recursive) + g_node_traverse(item->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, + summary_search_recursive_func, NULL); + else + summary_search_folder(item); - if (all_searched) { - alertpanel_message - (_("Search failed"), - _("Search string not found."), - ALERT_WARNING); - break; - } + filter_rule_free(search_window.rule); + search_window.rule = NULL; + search_window.requires_full_headers = FALSE; - if (backward) - str = _("Beginning of list reached; continue from end?"); - else - str = _("End of list reached; continue from beginning?"); - - val = alertpanel(_("Search finished"), str, - GTK_STOCK_YES, GTK_STOCK_NO, NULL); - if (G_ALERTDEFAULT == val) { - if (backward) - valid = gtkut_tree_model_get_iter_last - (model, &iter); - else - valid = gtk_tree_model_get_iter_first - (model, &iter); - all_searched = TRUE; - manage_window_focus_in(search_window.window, - NULL, NULL); - } else - break; - } + gtk_button_set_label(GTK_BUTTON(search_window.search_btn), + GTK_STOCK_FIND); + gtk_label_set_text(GTK_LABEL(search_window.status_label), _("Done.")); - gtk_tree_model_get(model, &iter, S_COL_MSG_INFO, &msginfo, -1); - body_matched = FALSE; + if (search_window.cancelled) + debug_print("* query search cancelled.\n"); + debug_print("query search finished.\n"); - if (bool_and) { - matched = TRUE; - if (*from_str) { - if (!msginfo->from || - !str_find_func(msginfo->from, from_str)) - matched = FALSE; - } - if (matched && *to_str) { - if (!msginfo->to || - !str_find_func(msginfo->to, to_str)) - matched = FALSE; - } - if (matched && *subject_str) { - if (!msginfo->subject || - !str_find_func(msginfo->subject, subject_str)) - matched = FALSE; - } - if (matched && *body_str) { - if (procmime_find_string(msginfo, body_str, - str_find_func)) - body_matched = TRUE; - else - matched = FALSE; - } - if (matched && !*from_str && !*to_str && - !*subject_str && !*body_str) - matched = FALSE; - } else { - matched = FALSE; - if (*from_str && msginfo->from) { - if (str_find_func(msginfo->from, from_str)) - matched = TRUE; - } - if (!matched && *to_str && msginfo->to) { - if (str_find_func(msginfo->to, to_str)) - matched = TRUE; - } - if (!matched && *subject_str && msginfo->subject) { - if (str_find_func(msginfo->subject, subject_str)) - matched = TRUE; - } - if (!matched && *body_str) { - if (procmime_find_string(msginfo, body_str, - str_find_func)) { - matched = TRUE; - body_matched = TRUE; - } - } - } + search_window.on_search = FALSE; + search_window.cancelled = FALSE; +} - if (matched) { - if (search_all) { - gtk_tree_selection_select_iter - (summaryview->selection, &iter); - } else { - if (messageview_is_visible - (summaryview->messageview)) { - summary_unlock(summaryview); - summary_select_row - (summaryview, &iter, - TRUE, TRUE); - summary_lock(summaryview); - if (body_matched) { - messageview_search_string - (summaryview->messageview, - body_str, case_sens); - } - } else { - summary_select_row - (summaryview, &iter, - FALSE, TRUE); - } - break; - } +static void summary_search_folder(FolderItem *item) +{ + gchar *folder_name, *str; + GSList *mlist; + FilterInfo fltinfo; + GSList *cur; + gint count = 1, total; + GTimeVal tv_prev, tv_cur; + + if (!item->path) + return; + + folder_name = g_path_get_basename(item->path); + str = g_strdup_printf(_("Searching %s ..."), folder_name); + gtk_label_set_text(GTK_LABEL(search_window.status_label), str); + g_free(str); + g_get_current_time(&tv_prev); + ui_update(); + + if (search_window.cancelled) { + g_free(folder_name); + return; + } + + mlist = folder_item_get_msg_list(item, TRUE); + total = g_slist_length(mlist); + + memset(&fltinfo, 0, sizeof(FilterInfo)); + + debug_print("requires_full_headers: %d\n", + search_window.requires_full_headers); + debug_print("start query search: %s\n", item->path ? item->path : ""); + + for (cur = mlist; cur != NULL; cur = cur->next) { + MsgInfo *msginfo = (MsgInfo *)cur->data; + GSList *hlist; + + g_get_current_time(&tv_cur); + if (tv_cur.tv_sec > tv_prev.tv_sec || + tv_cur.tv_usec - tv_prev.tv_usec > + PROGRESS_UPDATE_INTERVAL * 1000) { + str = g_strdup_printf(_("Searching %s (%d / %d)..."), + folder_name, count, total); + gtk_label_set_text + (GTK_LABEL(search_window.status_label), str); + g_free(str); + ui_update(); + tv_prev = tv_cur; + } + ++count; + + if (search_window.cancelled) + break; + + fltinfo.flags = msginfo->flags; + if (search_window.requires_full_headers) { + gchar *file; + + file = procmsg_get_message_file(msginfo); + hlist = procheader_get_header_list_from_file(file); + g_free(file); + } else + hlist = procheader_get_header_list_from_msginfo + (msginfo); + if (!hlist) + continue; + + if (filter_match_rule(search_window.rule, msginfo, hlist, + &fltinfo)) { + summary_search_append_msg(msginfo); + cur->data = NULL; } - if (backward) - valid = gtkut_tree_model_prev(model, &iter); - else - valid = gtkut_tree_model_next(model, &iter); + procheader_header_list_destroy(hlist); } - if (*body_str) - main_window_cursor_normal(summaryview->mainwin); + procmsg_msg_list_free(mlist); + g_free(folder_name); +} - summary_unlock(summaryview); +static gboolean summary_search_recursive_func(GNode *node, gpointer data) +{ + FolderItem *item; + + g_return_val_if_fail(node->data != NULL, FALSE); + + item = FOLDER_ITEM(node->data); + + if (!item->path) + return FALSE; + + summary_search_folder(item); + + if (search_window.cancelled) + return TRUE; + + return FALSE; +} + +static void summary_search_append_msg(MsgInfo *msginfo) +{ + GtkListStore *store = search_window.store; + GtkTreeIter iter; + gchar *folder; + gchar date_buf[80]; + const gchar *subject, *from, *date; + gchar *id; + + id = folder_item_get_identifier(msginfo->folder); + folder = g_path_get_basename(id); + g_free(id); + subject = msginfo->subject ? msginfo->subject : _("(No Subject)"); + from = msginfo->from ? msginfo->from : _("(No From)"); + if (msginfo->date_t) { + procheader_date_get_localtime(date_buf, sizeof(date_buf), + msginfo->date_t); + date = date_buf; + } else if (msginfo->date) + date = msginfo->date; + else + date = _("(No Date)"); + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + COL_FOLDER, folder, + COL_SUBJECT, subject, + COL_FROM, from, + COL_DATE, date, + COL_MSGINFO, msginfo, + -1); + + g_free(folder); +} + +static void summary_search_clear_list(void) +{ + GtkTreeIter iter; + GtkTreeModel *model = GTK_TREE_MODEL(search_window.store); + MsgInfo *msginfo; + + if (!gtk_tree_model_get_iter_first(model, &iter)) + return; + + do { + gtk_tree_model_get(model, &iter, COL_MSGINFO, &msginfo, -1); + procmsg_msginfo_free(msginfo); + } while (gtk_tree_model_iter_next(model, &iter)); + + gtk_list_store_clear(search_window.store); +} + +static void summary_search_hbox_added(CondHBox *hbox) +{ + g_signal_connect(hbox->key_entry, "activate", + G_CALLBACK(summary_search_entry_activated), NULL); +} + +static void row_activated(GtkTreeView *treeview, GtkTreePath *path, + GtkTreeViewColumn *column, gpointer data) +{ + GtkTreeIter iter; + GtkTreeModel *model = GTK_TREE_MODEL(search_window.store); + MsgInfo *msginfo; + MessageView *msgview; + + if (!gtk_tree_model_get_iter(model, &iter, path)) + return; + + gtk_tree_model_get(model, &iter, COL_MSGINFO, &msginfo, -1); + msgview = messageview_create_with_new_window(); + messageview_show(msgview, msginfo, FALSE); +} + +static gboolean row_selected(GtkTreeSelection *selection, + GtkTreeModel *model, GtkTreePath *path, + gboolean cur_selected, gpointer data) +{ + return TRUE; } static void summary_search_clear(GtkButton *button, gpointer data) { - gtk_editable_delete_text(GTK_EDITABLE(search_window.from_entry), - 0, -1); - gtk_editable_delete_text(GTK_EDITABLE(search_window.to_entry), - 0, -1); - gtk_editable_delete_text(GTK_EDITABLE(search_window.subject_entry), - 0, -1); - gtk_editable_delete_text(GTK_EDITABLE(search_window.body_entry), - 0, -1); + CondHBox *cond_hbox; + + prefs_filter_edit_clear_cond_edit(search_window.cond_edit); + prefs_filter_set_header_list(NULL); + prefs_filter_edit_set_header_list(search_window.cond_edit, NULL); + cond_hbox = prefs_filter_edit_cond_hbox_create(search_window.cond_edit); + prefs_filter_edit_set_cond_hbox_widgets(cond_hbox, PF_COND_HEADER); + prefs_filter_edit_insert_cond_hbox + (search_window.cond_edit, cond_hbox, -1); + if (search_window.cond_edit->add_hbox) + search_window.cond_edit->add_hbox(cond_hbox); + + gtk_label_set_text(GTK_LABEL(search_window.status_label), ""); + + summary_search_clear_list(); } -static void summary_search_prev_clicked(GtkButton *button, gpointer data) +static void summary_select_folder(GtkButton *button, gpointer data) { - summary_search_execute(TRUE, FALSE); + FolderItem *item; + gchar *id; + + item = foldersel_folder_sel(NULL, FOLDER_SEL_ALL, NULL); + if (!item) + return; + + id = folder_item_get_identifier(item); + if (id) { + gtk_entry_set_text(GTK_ENTRY(search_window.folder_entry), id); + g_free(id); + } } -static void summary_search_next_clicked(GtkButton *button, gpointer data) +static void summary_search_clicked(GtkButton *button, gpointer data) { - summary_search_execute(FALSE, FALSE); + if (search_window.on_search) + search_window.cancelled = TRUE; + else + summary_search_query(); } -static void summary_search_all_clicked(GtkButton *button, gpointer data) +static gint summary_search_save_dialog_deleted(GtkWidget *widget, + GdkEventAny *event, + gpointer data) { - summary_search_execute(FALSE, TRUE); + SummarySearchSaveDialog *dialog = (SummarySearchSaveDialog *)data; + + dialog->cancelled = TRUE; + dialog->finished = TRUE; + return TRUE; } -static void from_activated(void) +static gint summary_search_save_dialog_key_pressed(GtkWidget *widget, + GdkEventKey *event, + gpointer data) { - gtk_widget_grab_focus(search_window.to_entry); + SummarySearchSaveDialog *dialog = (SummarySearchSaveDialog *)data; + + if (event && event->keyval == GDK_Escape) { + dialog->cancelled = TRUE; + dialog->finished = TRUE; + } + return FALSE; } -static void to_activated(void) +static void summary_search_save_dialog_select_folder(GtkButton *button, + gpointer data) { - gtk_widget_grab_focus(search_window.subject_entry); + SummarySearchSaveDialog *dialog = (SummarySearchSaveDialog *)data; + FolderItem *item; + gchar *id; + + item = foldersel_folder_sel(NULL, FOLDER_SEL_ALL, NULL); + if (!item) + return; + + id = folder_item_get_identifier(item); + if (id) { + gtk_entry_set_text(GTK_ENTRY(dialog->folder_entry), id); + g_free(id); + } } -static void subject_activated(void) +static void summary_search_save_ok(GtkButton *button, gpointer data) { - gtk_button_clicked(GTK_BUTTON(search_window.next_btn)); + SummarySearchSaveDialog *dialog = (SummarySearchSaveDialog *)data; + + dialog->finished = TRUE; } -static void body_activated(void) +static void summary_search_save_cancel(GtkButton *button, gpointer data) { - gtk_button_clicked(GTK_BUTTON(search_window.next_btn)); + SummarySearchSaveDialog *dialog = (SummarySearchSaveDialog *)data; + + dialog->cancelled = TRUE; + dialog->finished = TRUE; +} + +static SummarySearchSaveDialog *summary_search_save_dialog_create(void) +{ + SummarySearchSaveDialog *dialog; + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *label; + GtkWidget *folder_entry; + GtkWidget *folder_btn; + GtkWidget *name_entry; + + GtkWidget *confirm_area; + GtkWidget *hbbox; + GtkWidget *cancel_btn; + GtkWidget *ok_btn; + + dialog = g_new0(SummarySearchSaveDialog, 1); + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), _("Save as search folder")); + gtk_widget_set_size_request(window, 400, -1); + gtk_container_set_border_width(GTK_CONTAINER(window), 8); + gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + gtk_window_set_modal(GTK_WINDOW(window), TRUE); + gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE); + g_signal_connect(G_OBJECT(window), "delete_event", + G_CALLBACK(summary_search_save_dialog_deleted), + dialog); + g_signal_connect(G_OBJECT(window), "key_press_event", + G_CALLBACK(summary_search_save_dialog_key_pressed), + dialog); + MANAGE_WINDOW_SIGNALS_CONNECT(window); + manage_window_set_transient(GTK_WINDOW(window)); + + vbox = gtk_vbox_new(FALSE, 8); + gtk_container_add(GTK_CONTAINER(window), vbox); + + hbox = gtk_hbox_new(FALSE, 8); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + + label = gtk_label_new(_("Location:")); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + folder_entry = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox), folder_entry, TRUE, TRUE, 0); + + folder_btn = gtk_button_new_with_label("..."); + gtk_box_pack_start(GTK_BOX(hbox), folder_btn, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(folder_btn), "clicked", + G_CALLBACK(summary_search_save_dialog_select_folder), + dialog); + + hbox = gtk_hbox_new(FALSE, 8); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + + label = gtk_label_new(_("Folder name:")); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + name_entry = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox), name_entry, TRUE, TRUE, 0); + + confirm_area = gtk_hbox_new(FALSE, 12); + gtk_box_pack_end(GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0); + + gtkut_stock_button_set_create(&hbbox, + &ok_btn, GTK_STOCK_OK, + &cancel_btn, GTK_STOCK_CANCEL, + NULL, NULL); + gtk_box_pack_end(GTK_BOX(confirm_area), hbbox, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(ok_btn), "clicked", + G_CALLBACK(summary_search_save_ok), dialog); + g_signal_connect(G_OBJECT(cancel_btn), "clicked", + G_CALLBACK(summary_search_save_cancel), dialog); + + gtk_widget_show_all(window); + + dialog->window = window; + dialog->folder_entry = folder_entry; + dialog->name_entry = name_entry; + dialog->cancelled = FALSE; + dialog->finished = FALSE; + + return dialog; +} + +static void summary_search_save_dialog_destroy(SummarySearchSaveDialog *dialog) +{ + gtk_widget_destroy(dialog->window); + g_free(dialog); +} + +static FolderItem *summary_search_create_vfolder(FolderItem *parent, + const gchar *name) +{ + gchar *path; + gchar *fs_name; + gchar *fullpath; + FolderItem *item; + + g_return_val_if_fail(parent != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + + path = folder_item_get_path(parent); + fs_name = g_filename_from_utf8(name, -1, NULL, NULL, NULL); + fullpath = g_strconcat(path, G_DIR_SEPARATOR_S, + fs_name ? fs_name : name, NULL); + g_free(fs_name); + g_free(path); + + if (make_dir_hier(fullpath) < 0) { + g_free(fullpath); + return NULL; + } + + if (parent->path) + path = g_strconcat(parent->path, G_DIR_SEPARATOR_S, name, NULL); + else + path = g_strdup(name); + + item = folder_item_new(name, path); + item->stype = F_VIRTUAL; + folder_item_append(parent, item); + + g_free(path); + + return item; +} + +static void summary_search_vfolder_update_rule(FolderItem *item) +{ + GSList list; + FilterRule *rule; + gchar *file; + gchar *path; + + rule = summary_search_dialog_to_rule(item->name, NULL); + list.data = rule; + list.next = NULL; + + path = folder_item_get_path(item); + file = g_strconcat(path, G_DIR_SEPARATOR_S, FILTER_LIST, NULL); + filter_write_file(&list, file); + g_free(file); + g_free(path); + + filter_rule_free(rule); +} + +static void summary_search_save(GtkButton *button, gpointer data) +{ + SummarySearchSaveDialog *dialog; + + dialog = summary_search_save_dialog_create(); + + while (!dialog->finished) + gtk_main_iteration(); + + if (!dialog->cancelled) { + const gchar *id, *name; + FolderItem *parent, *item; + + id = gtk_entry_get_text(GTK_ENTRY(dialog->folder_entry)); + parent = folder_find_item_from_identifier(id); + name = gtk_entry_get_text(GTK_ENTRY(dialog->name_entry)); + if (parent && name && *name) { + if (folder_find_child_item_by_name(parent, name)) { + alertpanel_error + (_("The folder `%s' already exists."), + name); + } else { + item = summary_search_create_vfolder + (parent, name); + if (item) { + summary_search_vfolder_update_rule + (item); + folderview_append_item(folderview_get(), + NULL, item, + TRUE); + folder_write_list(); + } + } + } + } + + summary_search_save_dialog_destroy(dialog); +} + +static void summary_search_close(GtkButton *button, gpointer data) +{ + if (search_window.on_search) + search_window.cancelled = TRUE; + gtk_widget_hide(search_window.window); +} + +static void summary_search_entry_activated(GtkWidget *widget, gpointer data) +{ + gtk_button_clicked(GTK_BUTTON(search_window.search_btn)); +} + +static gint summary_search_deleted(GtkWidget *widget, GdkEventAny *event, + gpointer data) +{ + gtk_button_clicked(GTK_BUTTON(search_window.close_btn)); + return TRUE; } static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data) { - if (event && event->keyval == GDK_Escape) - gtk_widget_hide(search_window.window); + if (event && event->keyval == GDK_Escape) { + if (search_window.on_search) + gtk_button_clicked + (GTK_BUTTON(search_window.search_btn)); + else + gtk_button_clicked(GTK_BUTTON(search_window.close_btn)); + return TRUE; + } return FALSE; } diff --git a/src/summary_search.h b/src/summary_search.h index 8e3fcc0c..2b0d3cc6 100644 --- a/src/summary_search.h +++ b/src/summary_search.h @@ -23,7 +23,9 @@ #include <glib.h> #include "summaryview.h" +#include "folder.h" -void summary_search (SummaryView *summaryview); +void summary_search (SummaryView *summaryview, + FolderItem *item); #endif /* __SUMMARY_SEARCH_H__ */ diff --git a/src/summaryview.c b/src/summaryview.c index 498d965e..214c735d 100644 --- a/src/summaryview.c +++ b/src/summaryview.c @@ -649,7 +649,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item, buf = NULL; if (!item || !item->path || !item->parent || item->no_select || - (FOLDER_TYPE(item->folder) == F_MH && + (FOLDER_TYPE(item->folder) == F_MH && item->stype != F_VIRTUAL && ((buf = folder_item_get_path(item)) == NULL || change_dir(buf) < 0))) { g_free(buf); |