From 7bfd77448f67347b2e194f129c9334b591762281 Mon Sep 17 00:00:00 2001 From: hiro Date: Tue, 21 Nov 2017 08:38:53 +0000 Subject: added context menu for search result of query search dialog. git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@3579 ee746299-78ed-0310-b773-934348b2243d --- ChangeLog | 4 + src/query_search.c | 440 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 428 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11a41b06..5eb05d0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2017-11-21 + + * src/query_search.c: added context menu for search result. + 2017-11-17 * libsylph/procmime.c: diff --git a/src/query_search.c b/src/query_search.c index b5cf6326..27a38ba7 100644 --- a/src/query_search.c +++ b/src/query_search.c @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2014 Hiroyuki Yamamoto + * Copyright (C) 1999-2017 Hiroyuki Yamamoto * * 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 @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -64,8 +65,12 @@ #include "procheader.h" #include "folder.h" #include "filter.h" +#include "prefs_common.h" #include "prefs_filter.h" #include "prefs_filter_edit.h" +#include "compose.h" +#include "sourcewindow.h" +#include "printing.h" enum { @@ -100,6 +105,9 @@ static struct QuerySearchWindow { GtkWidget *save_btn; GtkWidget *close_btn; + GtkActionGroup *group; + GtkUIManager *ui; + FilterRule *rule; gboolean requires_full_headers; @@ -124,6 +132,38 @@ typedef struct { gboolean finished; } QuerySearchSaveDialog; +static const gchar *ui_def = + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; + static void query_search_create (void); static FilterRule *query_search_dialog_to_rule (const gchar *name, @@ -151,6 +191,10 @@ static gboolean row_selected (GtkTreeSelection *selection, gboolean cur_selected, gpointer data); +static gboolean treeview_button_pressed (GtkWidget *widget, + GdkEventButton *event, + gpointer data); + static void query_search_clear (GtkButton *button, gpointer data); static void query_select_folder (GtkButton *button, @@ -172,6 +216,27 @@ static gboolean key_pressed (GtkWidget *widget, GdkEventKey *event, gpointer data); +static void query_search_open_msg (gboolean new_window); + +/* Popup menu callbacks */ +static void reply_cb(void); +static void reply_all_cb(void); +static void reply_sender_cb(void); +static void reply_list_cb(void); +static void forward_cb(void); +static void forward_attach_cb(void); +static void redirect_cb(void); +static void move_cb(void); +static void copy_cb(void); +static void add_address_cb(void); +static void create_filter_auto_cb(void); +static void create_filter_from_cb(void); +static void create_filter_to_cb(void); +static void create_filter_subject_cb(void); +static void open_cb (void); +static void open_source_cb (void); +static void print_cb (void); + static gint query_search_cmp_by_folder (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, @@ -189,6 +254,33 @@ static gint query_search_cmp_by_date (GtkTreeModel *model, GtkTreeIter *b, gpointer data); +static GtkActionEntry action_entries[] = { + {"ReplyAction", NULL, N_("_Reply"), NULL, NULL, reply_cb}, + {"ReplyToAction", NULL, N_("Repl_y to"), NULL, NULL, NULL}, + {"ReplyAllAction", NULL, N_("Reply to _all"), NULL, NULL, reply_all_cb}, + {"ReplySenderAction", NULL, N_("Reply to _sender"), NULL, NULL, reply_sender_cb}, + {"ReplyListAction", NULL, N_("Reply to _list"), NULL, NULL, reply_list_cb}, + + {"ForwardAction", NULL, N_("_Forward"), NULL, NULL, forward_cb}, + {"ForwardAsAttachAction", NULL, N_("For_ward as attachment"), NULL, NULL, forward_attach_cb}, + {"RedirectAction", NULL, N_("Redirec_t"), NULL, NULL, redirect_cb}, + + {"MoveMsgAction", NULL, N_("M_ove messages to..."), NULL, NULL, move_cb}, + {"CopyMsgAction", NULL, N_("_Copy messages to..."), NULL, NULL, copy_cb}, + + {"AddAddressAction", NULL, N_("Add sender to address boo_k..."), NULL, NULL, add_address_cb}, + {"CreateFilterAction", NULL, N_("Create f_ilter rule"), NULL, NULL, NULL}, + {"FilterAutoAction", NULL, N_("_Automatically"), NULL, NULL, create_filter_auto_cb}, + {"FilterFromAction", NULL, N_("by _From"), NULL, NULL, create_filter_from_cb}, + {"FilterToAction", NULL, N_("by _To"), NULL, NULL, create_filter_to_cb}, + {"FilterSubjectAction", NULL, N_("by _Subject"), NULL, NULL, create_filter_subject_cb}, + + {"OpenAction", GTK_STOCK_OPEN, N_("_Open in new window"), NULL, NULL, open_cb}, + {"OpenSourceAction", NULL, N_("View mess_age source"), NULL, NULL, open_source_cb}, + + {"PrintAction", GTK_STOCK_PRINT, N_("_Print..."), NULL, NULL, print_cb}, +}; + void query_search(FolderItem *item) { @@ -249,6 +341,9 @@ static void query_search_create(void) GtkWidget *save_btn; GtkWidget *close_btn; + GtkActionGroup *group; + GtkUIManager *ui; + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW (window), _("Search messages")); gtk_widget_set_size_request(window, 600 * gtkut_get_dpi_multiplier(), -1); @@ -365,6 +460,8 @@ static void query_search_create(void) gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); g_signal_connect(G_OBJECT(treeview), "row-activated", G_CALLBACK(row_activated), NULL); + g_signal_connect(G_OBJECT(treeview), "button-press-event", + G_CALLBACK(treeview_button_pressed), NULL); gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), COL_FOLDER, query_search_cmp_by_folder, NULL, NULL); @@ -441,6 +538,16 @@ static void query_search_create(void) g_signal_connect(G_OBJECT(close_btn), "clicked", G_CALLBACK(query_search_close), NULL); + group = gtk_action_group_new("main"); + gtk_action_group_set_translation_domain(group, GETTEXT_PACKAGE); + gtk_action_group_add_actions(group, action_entries, + sizeof(action_entries) / + sizeof(action_entries[0]), NULL); + + ui = gtk_ui_manager_new(); + gtk_ui_manager_insert_action_group(ui, group, 0); + gtk_ui_manager_add_ui_from_string(ui, ui_def, -1, NULL); + search_window.window = window; search_window.bool_optmenu = bool_optmenu; @@ -460,6 +567,9 @@ static void query_search_create(void) search_window.search_btn = search_btn; search_window.save_btn = save_btn; search_window.close_btn = close_btn; + + search_window.group = group; + search_window.ui = ui; } static FilterRule *query_search_dialog_to_rule(const gchar *name, @@ -843,21 +953,7 @@ static void query_search_hbox_added(CondHBox *hbox) 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); - if (!summary_select_by_msginfo(main_window_get()->summaryview, - msginfo)) { - msgview = messageview_create_with_new_window(); - messageview_show(msgview, msginfo, FALSE); - statusbar_pop_all(); - } + query_search_open_msg(FALSE); } static gboolean row_selected(GtkTreeSelection *selection, @@ -867,6 +963,56 @@ static gboolean row_selected(GtkTreeSelection *selection, return TRUE; } +static gboolean treeview_button_pressed(GtkWidget *widget, + GdkEventButton *event, gpointer data) +{ + GtkTreeIter iter; + GtkTreeModel *model = GTK_TREE_MODEL(search_window.store); + GtkWidget *menu; + GtkTreeSelection *selection; + GtkTreePath *path; + GtkTreeViewColumn *column = NULL; + gboolean is_selected; + gint px, py; + + debug_print("treeview_button_pressed\n"); + + if (!event) + return FALSE; + + if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), + event->x, event->y, &path, &column, + NULL, NULL)) + return FALSE; + + // ?? + gtk_widget_get_pointer(widget, &px, &py); + if (py == (gint)event->y) { + gtk_tree_path_free(path); + return FALSE; + } + + if (!gtk_tree_model_get_iter(model, &iter, path)) { + gtk_tree_path_free(path); + return FALSE; + } + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + is_selected = gtk_tree_selection_path_is_selected(selection, path); + gtk_tree_path_free(path); + + if (event->button == 3) { + menu = gtk_ui_manager_get_widget(search_window.ui, + "/PopUpMenu"); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, + event->button, event->time); + if (is_selected) + return TRUE; + } + + return FALSE; +} + static void query_search_clear(GtkButton *button, gpointer data) { CondHBox *cond_hbox; @@ -1206,6 +1352,268 @@ static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event, return FALSE; } +static GSList *query_search_get_selected_msg_list(void) +{ + GtkTreeModel *model = GTK_TREE_MODEL(search_window.store); + GtkTreeSelection *selection; + GList *list, *cur; + GtkTreePath *path; + GtkTreeIter iter; + GSList *mlist = NULL; + MsgInfo *msginfo; + + selection = gtk_tree_view_get_selection + (GTK_TREE_VIEW(search_window.treeview)); + list = gtk_tree_selection_get_selected_rows(selection, NULL); + if (!list) + return NULL; + + for (cur = list; cur != NULL; cur = cur->next) { + path = cur->data; + if (!gtk_tree_model_get_iter(model, &iter, path)) + break; + msginfo = NULL; + gtk_tree_model_get(model, &iter, COL_MSGINFO, &msginfo, -1); + if (msginfo) + mlist = g_slist_prepend(mlist, msginfo); + } + mlist = g_slist_reverse(mlist); + + g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL); + g_list_free(list); + + return mlist; +} + +static void query_search_open_msg(gboolean new_window) +{ + GSList *mlist; + MsgInfo *msginfo; + MessageView *msgview; + + mlist = query_search_get_selected_msg_list(); + if (!mlist) + return; + msginfo = (MsgInfo *)mlist->data; + g_slist_free(mlist); + + if (new_window || !summary_select_by_msginfo(main_window_get()->summaryview, msginfo)) { + msgview = messageview_create_with_new_window(); + messageview_show(msgview, msginfo, FALSE); + statusbar_pop_all(); + } +} + +static void query_search_reply_forward(ComposeMode mode) +{ + GSList *mlist; + MsgInfo *msginfo; + + mlist = query_search_get_selected_msg_list(); + if (!mlist) + return; + msginfo = (MsgInfo *)mlist->data; + + if (prefs_common.reply_with_quote) + mode |= COMPOSE_WITH_QUOTE; + + switch (COMPOSE_MODE(mode)) { + case COMPOSE_REPLY: + case COMPOSE_REPLY_TO_SENDER: + case COMPOSE_REPLY_TO_ALL: + case COMPOSE_REPLY_TO_LIST: + compose_reply(msginfo, msginfo->folder, mode, NULL); + break; + case COMPOSE_FORWARD: + compose_forward(mlist, NULL, FALSE, NULL); + break; + case COMPOSE_FORWARD_AS_ATTACH: + compose_forward(mlist, NULL, TRUE, NULL); + break; + case COMPOSE_REDIRECT: + compose_redirect(msginfo, msginfo->folder); + break; + default: + g_warning("query_search_reply_forward: invalid mode: %d", mode); + } + + g_slist_free(mlist); +} + +static void query_search_move_copy(gboolean is_copy) +{ + GSList *mlist, *cur; + FolderItem *dest; + MsgInfo *msginfo; + + debug_print("query_search_move_copy: is_copy: %d\n", is_copy); + + mlist = query_search_get_selected_msg_list(); + if (!mlist) + return; + + dest = foldersel_folder_sel_full(NULL, FOLDER_SEL_MOVE, NULL, + _("Select folder to move")); + if (!dest || dest->stype == F_VIRTUAL || !FOLDER_ITEM_CAN_ADD(dest)) { + g_slist_free(mlist); + return; + } + if (summary_is_locked(main_window_get()->summaryview)) { + g_slist_free(mlist); + return; + } + + for (cur = mlist; cur != NULL; cur = cur->next) { + msginfo = (MsgInfo *)cur->data; + if (!msginfo) + continue; + + if (is_copy) { + folder_item_copy_msg(dest, msginfo); + } else { + folder_item_move_msg(dest, msginfo); + } + } + + folderview_update_all_updated(TRUE); + g_slist_free(mlist); +} + +static void query_search_create_filter(FilterCreateType type) +{ + GSList *mlist; + MsgInfo *msginfo; + gchar *header = NULL; + gchar *key = NULL; + + mlist = query_search_get_selected_msg_list(); + if (!mlist) + return; + msginfo = (MsgInfo *)mlist->data; + g_slist_free(mlist); + + filter_get_keyword_from_msg(msginfo, &header, &key, type); + prefs_filter_open(msginfo, header, key); + + g_free(header); + g_free(key); +} + +static void reply_cb(void) +{ + query_search_reply_forward(COMPOSE_REPLY); +} + +static void reply_all_cb(void) +{ + query_search_reply_forward(COMPOSE_REPLY_TO_ALL); +} + +static void reply_sender_cb(void) +{ + query_search_reply_forward(COMPOSE_REPLY_TO_SENDER); +} + +static void reply_list_cb(void) +{ + query_search_reply_forward(COMPOSE_REPLY_TO_LIST); +} + +static void forward_cb(void) +{ + query_search_reply_forward(COMPOSE_FORWARD); +} + +static void forward_attach_cb(void) +{ + query_search_reply_forward(COMPOSE_FORWARD_AS_ATTACH); +} + +static void redirect_cb(void) +{ + query_search_reply_forward(COMPOSE_REDIRECT); +} + +static void move_cb(void) +{ + query_search_move_copy(FALSE); +} + +static void copy_cb(void) +{ + query_search_move_copy(TRUE); +} + +static void add_address_cb(void) +{ + GSList *mlist; + MsgInfo *msginfo; + gchar from[BUFFSIZE]; + + mlist = query_search_get_selected_msg_list(); + if (!mlist) + return; + msginfo = (MsgInfo *)mlist->data; + g_slist_free(mlist); + + strncpy2(from, msginfo->from, sizeof(from)); + extract_address(from); + addressbook_add_contact(msginfo->fromname, from, NULL); +} + +static void create_filter_auto_cb(void) +{ + query_search_create_filter(FLT_BY_AUTO); +} + +static void create_filter_from_cb(void) +{ + query_search_create_filter(FLT_BY_FROM); +} + +static void create_filter_to_cb(void) +{ + query_search_create_filter(FLT_BY_TO); +} + +static void create_filter_subject_cb(void) +{ + query_search_create_filter(FLT_BY_SUBJECT); +} + +static void open_cb(void) +{ + query_search_open_msg(TRUE); +} + +static void open_source_cb(void) +{ + GSList *mlist; + MsgInfo *msginfo; + SourceWindow *srcwin; + + mlist = query_search_get_selected_msg_list(); + if (!mlist) + return; + msginfo = (MsgInfo *)mlist->data; + g_slist_free(mlist); + + srcwin = source_window_create(); + source_window_show_msg(srcwin, msginfo); + source_window_show(srcwin); +} + +static void print_cb(void) +{ + GSList *mlist; + + mlist = query_search_get_selected_msg_list(); + if (!mlist) + return; + printing_print_messages(mlist, FALSE); + g_slist_free(mlist); +} + static gint query_search_cmp_by_folder(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data) -- cgit v1.2.3