2 * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2003-2012 the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "claws-features.h"
28 #include <glib/gi18n.h>
30 #include <gdk/gdkkeysyms.h>
36 #if !GTK_CHECK_VERSION(3, 0, 0)
37 #include "gtkcmoptionmenu.h"
40 #include "prefs_gtk.h"
41 #include "prefs_filtering_action.h"
42 #include "prefs_common.h"
43 #include "mainwindow.h"
44 #include "foldersel.h"
45 #include "manage_window.h"
50 #include "alertpanel.h"
52 #include "description_window.h"
53 #include "addr_compl.h"
55 #include "matcher_parser.h"
56 #include "colorlabel.h"
59 #ifndef USE_ALT_ADDRBOOK
60 #include "addressbook.h"
70 static void prefs_filtering_action_create(void);
71 static void prefs_filtering_action_delete_cb(void);
72 static void prefs_filtering_action_substitute_cb(void);
73 static void prefs_filtering_action_register_cb(void);
74 static void prefs_filtering_action_reset_dialog(void);
75 static gboolean
prefs_filtering_action_key_pressed(GtkWidget
*widget
,
76 GdkEventKey
*event
, gpointer data
);
77 static void prefs_filtering_action_cancel(void);
78 static void prefs_filtering_action_ok(void);
79 static gint
prefs_filtering_action_deleted(GtkWidget
*widget
,
80 GdkEventAny
*event
, gpointer data
);
81 static void prefs_filtering_action_type_selection_changed(GtkWidget
*widget
,
83 static void prefs_filtering_action_select_dest(void);
84 #ifndef USE_ALT_ADDRBOOK
85 static void prefs_filtering_action_select_addressbook(void);
87 static void prefs_filtering_action_up(void);
88 static void prefs_filtering_action_down(void);
89 static void prefs_filtering_action_set_dialog(GSList
*action_list
);
90 static GSList
*prefs_filtering_action_get_list(void);
92 static GtkListStore
* prefs_filtering_action_create_data_store (void);
93 static void prefs_filtering_action_list_view_insert_action (GtkWidget
*list_view
,
97 static GtkWidget
*prefs_filtering_action_list_view_create (void);
98 static void prefs_filtering_action_create_list_view_columns (GtkTreeView
*list_view
);
99 static gboolean
prefs_filtering_actions_selected (GtkTreeSelection
*selector
,
102 gboolean currently_selected
,
105 static void prefs_filtering_action_exec_info (GtkWidget
*widget
,
109 *\brief UI data for matcher dialog
111 static struct FilteringAction_
{
116 GtkWidget
*action_list_view
;
120 GtkWidget
*action_combo
;
121 GtkWidget
*account_combo
;
122 GtkWidget
*dest_entry
;
125 #if !GTK_CHECK_VERSION(3, 0, 0)
126 GtkWidget
*color_optmenu
;
128 GtkWidget
*header_combo
;
129 GtkWidget
*header_entry
;
130 #ifndef USE_ALT_ADDRBOOK
131 GtkWidget
*addressbook_btn
;
133 GtkWidget
*score_entry
;
134 GtkWidget
*tags_combo
;
140 typedef enum Action_
{
149 ACTION_MARK_AS_UNREAD
,
153 ACTION_FORWARD_AS_ATTACHMENT
,
165 ACTION_ADD_TO_ADDRESSBOOK
,
167 /* add other action constants */
175 { NULL
, N_("Move"), ACTION_MOVE
},
176 { NULL
, N_("Copy"), ACTION_COPY
},
177 { NULL
, N_("Delete"), ACTION_DELETE
},
178 { NULL
, N_("Hide"), ACTION_HIDE
},
179 { N_("Message flags"), N_("Mark"), ACTION_MARK
},
180 { N_("Message flags"), N_("Unmark"), ACTION_UNMARK
},
181 { N_("Message flags"), N_("Lock"), ACTION_LOCK
},
182 { N_("Message flags"), N_("Unlock"), ACTION_UNLOCK
},
183 { N_("Message flags"), N_("Mark as read"), ACTION_MARK_AS_READ
},
184 { N_("Message flags"), N_("Mark as unread"), ACTION_MARK_AS_UNREAD
},
185 { N_("Message flags"), N_("Mark as spam"), ACTION_MARK_AS_SPAM
},
186 { N_("Message flags"), N_("Mark as ham"), ACTION_MARK_AS_HAM
},
187 { NULL
, N_("Execute"), ACTION_EXECUTE
},
188 #if !GTK_CHECK_VERSION(3, 0, 0)
189 { NULL
, N_("Color label"), ACTION_COLOR
},
191 { N_("Resend"), N_("Forward"), ACTION_FORWARD
},
192 { N_("Resend"), N_("Forward as attachment"), ACTION_FORWARD_AS_ATTACHMENT
},
193 { N_("Resend"), N_("Redirect"), ACTION_REDIRECT
},
194 { N_("Score"), N_("Change score"), ACTION_CHANGE_SCORE
},
195 { N_("Score"), N_("Set score"), ACTION_SET_SCORE
},
196 { N_("Tags"), N_("Apply tag"), ACTION_SET_TAG
},
197 { N_("Tags"), N_("Unset tag"), ACTION_UNSET_TAG
},
198 { N_("Tags"), N_("Clear tags"), ACTION_CLEAR_TAGS
},
199 { N_("Threads"), N_("Ignore thread"), ACTION_IGNORE
},
200 { N_("Threads"), N_("Watch thread"), ACTION_WATCH
},
201 { NULL
, N_("Add to address book"), ACTION_ADD_TO_ADDRESSBOOK
},
202 { NULL
, N_("Stop filter"), ACTION_STOP
},
216 static PrefsFilteringActionSignal
*filtering_action_callback
;
218 static GtkTreeModel
*prefs_filtering_action_create_model(void)
220 GtkTreeIter iter
, iter2
;
222 gchar
*curr_menu
= NULL
;
225 store
= gtk_tree_store_new(N_ACTION_COMBO
, G_TYPE_STRING
, G_TYPE_INT
,
228 for (i
= 0; action_menu
[i
].menu
|| action_menu
[i
].text
; i
++)
230 if (action_menu
[i
].menu
) {
231 if (!curr_menu
|| strcmp(action_menu
[i
].menu
, curr_menu
)) {
232 gtk_tree_store_append(store
, &iter
, NULL
);
233 gtk_tree_store_set(store
, &iter
,
235 gettext(action_menu
[i
].menu
),
236 ACTION_COMBO_SENS
, TRUE
,
238 curr_menu
= action_menu
[i
].menu
;
241 gtk_tree_store_append(store
, &iter2
, &iter
);
242 gtk_tree_store_set(store
, &iter2
,
243 ACTION_COMBO_TEXT
, gettext(action_menu
[i
].text
),
244 ACTION_COMBO_DATA
, action_menu
[i
].action
,
245 ACTION_COMBO_SENS
, TRUE
,
250 gtk_tree_store_append(store
, &iter
, NULL
);
251 gtk_tree_store_set(store
, &iter
,
252 ACTION_COMBO_TEXT
, gettext(action_menu
[i
].text
),
253 ACTION_COMBO_DATA
, action_menu
[i
].action
,
254 ACTION_COMBO_SENS
, TRUE
,
259 return GTK_TREE_MODEL(store
);
262 static void cell_is_sensitive(GtkCellLayout
*cell_layout
,
263 GtkCellRenderer
*cell
,
264 GtkTreeModel
*tree_model
,
268 if(gtk_tree_model_iter_has_child (tree_model
, iter
)) {
269 g_object_set (cell
, "sensitive", FALSE
, NULL
);
274 *\brief Opens the filtering action dialog with a list of actions
276 *\param matchers List of conditions
280 void prefs_filtering_action_open(GSList
*action_list
,
281 PrefsFilteringActionSignal
*cb
)
285 if (!filtering_action
.window
) {
286 prefs_filtering_action_create();
288 #if !GTK_CHECK_VERSION(3, 0, 0)
289 /* update color label menu */
290 gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(filtering_action
.color_optmenu
),
291 colorlabel_create_color_menu());
295 manage_window_set_transient(GTK_WINDOW(filtering_action
.window
));
296 gtk_widget_grab_focus(filtering_action
.ok_btn
);
298 filtering_action_callback
= cb
;
300 prefs_filtering_action_set_dialog(action_list
);
302 gtk_widget_show(filtering_action
.window
);
303 gtk_window_set_modal(GTK_WINDOW(filtering_action
.window
), TRUE
);
307 *\brief Save Gtk object size to prefs dataset
309 static void prefs_filtering_action_size_allocate_cb(GtkWidget
*widget
,
310 GtkAllocation
*allocation
)
312 cm_return_if_fail(allocation
!= NULL
);
314 prefs_common
.filteringactionwin_width
= allocation
->width
;
315 prefs_common
.filteringactionwin_height
= allocation
->height
;
318 #define LABELS_WIDTH 80
319 #define SECOND_ROW_WIDTH 250
321 static void prefs_filtering_action_check_widget_width(GtkWidget
*widget
)
325 gtk_widget_size_request(widget
, &req
);
326 if(req
.width
> SECOND_ROW_WIDTH
)
327 gtk_widget_set_size_request(widget
, SECOND_ROW_WIDTH
, -1);
331 *\brief Create the matcher dialog
333 static void prefs_filtering_action_create(void)
338 GtkWidget
*cancel_btn
;
339 GtkWidget
*confirm_area
;
349 GtkWidget
*action_combo
;
350 GtkWidget
*account_combo
;
351 GtkWidget
*header_combo
;
352 GtkWidget
*header_entry
;
353 #ifndef USE_ALT_ADDRBOOK
354 GtkWidget
*addressbook_btn
;
356 GtkWidget
*dest_entry
;
358 GtkWidget
*score_entry
;
359 GtkWidget
*tags_combo
;
365 GtkWidget
*subst_btn
;
368 GtkWidget
*action_hbox
;
369 GtkWidget
*action_scrolledwin
;
370 GtkWidget
*action_list_view
;
378 #if !GTK_CHECK_VERSION(3, 0, 0)
379 GtkWidget
*color_optmenu
;
382 static GdkGeometry geometry
;
387 GtkSizeGroup
*size_group
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
388 GtkSizeGroup
*size_action
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
390 GtkCellRenderer
*renderer
;
392 debug_print("Creating matcher configuration window...\n");
394 window
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "prefs_filtering_action");
395 gtk_container_set_border_width(GTK_CONTAINER(window
), VBOX_BORDER
);
396 gtk_window_set_position(GTK_WINDOW(window
), GTK_WIN_POS_CENTER
);
397 gtk_window_set_resizable(GTK_WINDOW(window
), TRUE
);
399 vbox
= gtk_vbox_new(FALSE
, 6);
400 gtk_container_add(GTK_CONTAINER(window
), vbox
);
402 gtkut_stock_button_set_create(&confirm_area
,
403 &cancel_btn
, GTK_STOCK_CANCEL
,
404 &ok_btn
, GTK_STOCK_OK
,
406 gtk_box_pack_end(GTK_BOX(vbox
), confirm_area
, FALSE
, FALSE
, 0);
407 gtk_widget_grab_default(ok_btn
);
409 gtk_window_set_title(GTK_WINDOW(window
),
410 _("Action configuration"));
411 g_signal_connect(G_OBJECT(window
), "delete_event",
412 G_CALLBACK(prefs_filtering_action_deleted
), NULL
);
413 g_signal_connect(G_OBJECT(window
), "size_allocate",
414 G_CALLBACK(prefs_filtering_action_size_allocate_cb
), NULL
);
415 g_signal_connect(G_OBJECT(window
), "key_press_event",
416 G_CALLBACK(prefs_filtering_action_key_pressed
), NULL
);
417 MANAGE_WINDOW_SIGNALS_CONNECT(window
);
418 g_signal_connect(G_OBJECT(ok_btn
), "clicked",
419 G_CALLBACK(prefs_filtering_action_ok
), NULL
);
420 g_signal_connect(G_OBJECT(cancel_btn
), "clicked",
421 G_CALLBACK(prefs_filtering_action_cancel
), NULL
);
423 vbox1
= gtk_vbox_new(FALSE
, VSPACING
);
424 gtk_box_pack_start(GTK_BOX(vbox
), vbox1
, TRUE
, TRUE
, 0);
425 gtk_container_set_border_width(GTK_CONTAINER (vbox1
), 2);
427 frame
= gtk_frame_new(_("Rule"));
428 gtk_frame_set_label_align(GTK_FRAME(frame
), 0.01, 0.5);
429 gtk_box_pack_start (GTK_BOX (vbox1
), frame
, FALSE
, FALSE
, 0);
430 gtk_widget_set_size_request(frame
, -1, 110);
432 table
= gtk_table_new(3, 3, FALSE
);
433 gtk_container_set_border_width(GTK_CONTAINER(table
), 2);
434 gtk_table_set_row_spacings (GTK_TABLE (table
), VSPACING_NARROW_2
);
435 gtk_table_set_col_spacings (GTK_TABLE (table
), HSPACING_NARROW
);
436 gtk_container_add(GTK_CONTAINER(frame
), table
);
438 /* first row labels */
440 label1
= gtk_label_new (_("Action"));
441 gtk_widget_set_size_request(label1
, LABELS_WIDTH
, -1);
442 gtk_size_group_add_widget(size_group
, label1
);
443 gtk_misc_set_alignment (GTK_MISC (label1
), 1, 0.5);
444 gtk_table_attach(GTK_TABLE(table
), label1
, 0, 1, 0, 1,
445 GTK_FILL
, GTK_SHRINK
, 0, 0);
447 label2
= gtk_label_new ("");
448 gtk_size_group_add_widget(size_group
, label2
);
449 gtk_misc_set_alignment (GTK_MISC (label2
), 1, 0.5);
450 gtk_table_attach(GTK_TABLE(table
), label2
, 0, 1, 1, 2,
451 GTK_FILL
, GTK_SHRINK
, 0, 0);
453 label3
= gtk_label_new ("");
454 gtk_size_group_add_widget(size_group
, label3
);
455 gtk_misc_set_alignment (GTK_MISC (label3
), 1, 0.5);
456 gtk_table_attach(GTK_TABLE(table
), label3
, 0, 1, 2, 3,
457 GTK_FILL
, GTK_SHRINK
, 0, 0);
461 hbox1
= gtk_hbox_new(FALSE
, 0);
462 gtk_table_attach(GTK_TABLE(table
), hbox1
, 1, 2, 0, 1,
463 GTK_FILL
, GTK_SHRINK
, 0, 0);
465 model
= prefs_filtering_action_create_model();
466 action_combo
= gtk_combo_box_new_with_model(model
);
467 gtk_size_group_add_widget(size_action
, action_combo
);
469 renderer
= gtk_cell_renderer_text_new();
470 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(action_combo
), renderer
, TRUE
);
471 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(action_combo
), renderer
,
472 "text", ACTION_COMBO_TEXT
,
473 "sensitive", ACTION_COMBO_SENS
,
475 gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(action_combo
), renderer
,
476 cell_is_sensitive
, NULL
, NULL
);
478 combobox_select_by_data(GTK_COMBO_BOX(action_combo
), ACTION_MOVE
);
479 g_signal_connect(G_OBJECT(action_combo
), "changed",
480 G_CALLBACK(prefs_filtering_action_type_selection_changed
),
482 gtk_box_pack_start(GTK_BOX(hbox1
), action_combo
, FALSE
, FALSE
, 0);
483 gtk_box_pack_start(GTK_BOX(hbox1
), gtk_label_new(""), TRUE
, TRUE
, 0);
487 hbox1
= gtk_hbox_new (FALSE
, 0);
488 gtk_table_attach(GTK_TABLE(table
), hbox1
, 1, 2, 1, 2,
489 GTK_FILL
| GTK_EXPAND
, GTK_SHRINK
, 0, 0);
491 #if !GTK_CHECK_VERSION(2, 24, 0)
492 account_combo
= gtk_combo_box_new_text ();
494 account_combo
= gtk_combo_box_text_new ();
496 gtk_size_group_add_widget(size_action
, account_combo
);
498 for (accounts
= account_get_list() ; accounts
!= NULL
;
499 accounts
= accounts
->next
) {
500 PrefsAccount
*ac
= (PrefsAccount
*)accounts
->data
;
501 gchar
*name
= g_strdup(ac
->account_name
);
502 #if !GTK_CHECK_VERSION(2, 24, 0)
503 gtk_combo_box_append_text(GTK_COMBO_BOX(account_combo
), (gpointer
) name
);
505 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(account_combo
), (gpointer
) name
);
510 prefs_filtering_action_check_widget_width(account_combo
);
511 gtk_combo_box_set_active(GTK_COMBO_BOX(account_combo
), 0);
512 gtk_box_pack_start (GTK_BOX (hbox1
), account_combo
,
517 header_combo
= combobox_text_new(TRUE
, "From", "To", "Cc", "Reply-To", "Sender", NULL
);
518 gtk_size_group_add_widget(size_action
, header_combo
);
519 gtk_box_pack_start (GTK_BOX (hbox1
), header_combo
,
521 header_entry
= gtk_bin_get_child(GTK_BIN((header_combo
)));
525 hbox1
= gtk_hbox_new (FALSE
, 0);
526 gtk_table_attach(GTK_TABLE(table
), hbox1
, 1, 2, 2, 3,
527 GTK_FILL
| GTK_EXPAND
, GTK_SHRINK
, 0, 0);
529 dest_entry
= gtk_entry_new ();
530 gtk_box_pack_start (GTK_BOX (hbox1
), dest_entry
, TRUE
, TRUE
, 0);
532 score_entry
= gtk_spin_button_new_with_range(-1000, 1000, 1);
533 gtk_box_pack_start(GTK_BOX(hbox1
), score_entry
, FALSE
, FALSE
, 0);
535 #if !GTK_CHECK_VERSION(3, 0, 0)
536 color_optmenu
= gtk_cmoption_menu_new();
537 gtk_size_group_add_widget(size_action
, color_optmenu
);
538 gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(color_optmenu
),
539 colorlabel_create_color_menu());
540 prefs_filtering_action_check_widget_width(color_optmenu
);
541 gtk_box_pack_start(GTK_BOX(hbox1
), color_optmenu
, FALSE
, FALSE
, 0);
544 #if !GTK_CHECK_VERSION(2, 24, 0)
545 tags_combo
= gtk_combo_box_new_text ();
547 tags_combo
= gtk_combo_box_text_new ();
549 gtk_size_group_add_widget(size_action
, tags_combo
);
551 for (tmp
= tags
= tags_get_list() ; tmp
!= NULL
;
553 gchar
*name
= g_strdup(tags_get_tag(GPOINTER_TO_INT(tmp
->data
)));
555 #if !GTK_CHECK_VERSION(2, 24, 0)
556 gtk_combo_box_append_text(GTK_COMBO_BOX(tags_combo
), (gpointer
) name
);
558 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tags_combo
), (gpointer
) name
);
564 prefs_filtering_action_check_widget_width(tags_combo
);
565 gtk_combo_box_set_active(GTK_COMBO_BOX(tags_combo
), 0);
566 gtk_box_pack_start (GTK_BOX (hbox1
), tags_combo
,
569 hbox1
= gtk_hbox_new (FALSE
, 0);
570 gtk_table_attach(GTK_TABLE(table
), hbox1
, 2, 3, 2, 3,
571 GTK_FILL
, GTK_SHRINK
, 0, 0);
573 dest_btn
= gtk_button_new_with_label (_("Select..."));
574 gtk_box_pack_start (GTK_BOX (hbox1
), dest_btn
, FALSE
, FALSE
, 0);
575 g_signal_connect (G_OBJECT (dest_btn
), "clicked",
576 G_CALLBACK(prefs_filtering_action_select_dest
),
579 #ifndef USE_ALT_ADDRBOOK
580 addressbook_btn
= gtk_button_new_with_label (_("Select..."));
581 gtk_box_pack_start (GTK_BOX (hbox1
), addressbook_btn
, FALSE
, FALSE
, 0);
582 g_signal_connect (G_OBJECT (addressbook_btn
), "clicked",
583 G_CALLBACK(prefs_filtering_action_select_addressbook
),
587 exec_btn
= gtk_button_new_from_stock(GTK_STOCK_INFO
);
588 gtk_box_pack_start (GTK_BOX (hbox1
), exec_btn
, FALSE
, FALSE
, 0);
589 g_signal_connect (G_OBJECT (exec_btn
), "clicked",
590 G_CALLBACK(prefs_filtering_action_exec_info
),
593 /* register / substitute / delete */
595 reg_hbox
= gtk_hbox_new(FALSE
, 4);
596 gtk_box_pack_start(GTK_BOX(vbox1
), reg_hbox
, FALSE
, FALSE
, 0);
598 arrow
= gtk_arrow_new(GTK_ARROW_DOWN
, GTK_SHADOW_OUT
);
599 gtk_box_pack_start(GTK_BOX(reg_hbox
), arrow
, FALSE
, FALSE
, 0);
600 gtk_widget_set_size_request(arrow
, -1, 16);
602 btn_hbox
= gtk_hbox_new(TRUE
, 4);
603 gtk_box_pack_start(GTK_BOX(reg_hbox
), btn_hbox
, FALSE
, FALSE
, 0);
605 reg_btn
= gtk_button_new_from_stock(GTK_STOCK_ADD
);
606 gtk_box_pack_start(GTK_BOX(btn_hbox
), reg_btn
, FALSE
, TRUE
, 0);
607 g_signal_connect(G_OBJECT(reg_btn
), "clicked",
608 G_CALLBACK(prefs_filtering_action_register_cb
), NULL
);
610 subst_btn
= gtkut_get_replace_btn(_("_Replace"));
611 gtk_box_pack_start(GTK_BOX(btn_hbox
), subst_btn
, FALSE
, TRUE
, 0);
612 g_signal_connect(G_OBJECT(subst_btn
), "clicked",
613 G_CALLBACK(prefs_filtering_action_substitute_cb
),
616 del_btn
= gtk_button_new_with_mnemonic (_("D_elete"));
617 gtk_button_set_image(GTK_BUTTON(del_btn
),
618 gtk_image_new_from_stock(GTK_STOCK_REMOVE
,GTK_ICON_SIZE_BUTTON
));
619 gtk_box_pack_start(GTK_BOX(btn_hbox
), del_btn
, FALSE
, TRUE
, 0);
620 g_signal_connect(G_OBJECT(del_btn
), "clicked",
621 G_CALLBACK(prefs_filtering_action_delete_cb
), NULL
);
623 action_hbox
= gtk_hbox_new(FALSE
, 8);
624 gtk_box_pack_start(GTK_BOX(vbox1
), action_hbox
, TRUE
, TRUE
, 0);
626 action_scrolledwin
= gtk_scrolled_window_new(NULL
, NULL
);
627 gtk_widget_set_size_request(action_scrolledwin
, -1, 150);
628 gtk_box_pack_start(GTK_BOX(action_hbox
), action_scrolledwin
,
630 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(action_scrolledwin
),
631 GTK_SHADOW_ETCHED_IN
);
632 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(action_scrolledwin
),
633 GTK_POLICY_AUTOMATIC
,
634 GTK_POLICY_AUTOMATIC
);
636 action_list_view
= prefs_filtering_action_list_view_create();
637 gtk_container_add(GTK_CONTAINER(action_scrolledwin
), action_list_view
);
639 btn_vbox
= gtk_vbox_new(FALSE
, 8);
640 gtk_box_pack_start(GTK_BOX(action_hbox
), btn_vbox
, FALSE
, FALSE
, 0);
642 up_btn
= gtk_button_new_from_stock(GTK_STOCK_GO_UP
);
643 gtk_box_pack_start(GTK_BOX(btn_vbox
), up_btn
, FALSE
, FALSE
, 0);
644 g_signal_connect(G_OBJECT(up_btn
), "clicked",
645 G_CALLBACK(prefs_filtering_action_up
), NULL
);
647 down_btn
= gtk_button_new_from_stock(GTK_STOCK_GO_DOWN
);
648 gtk_box_pack_start(GTK_BOX(btn_vbox
), down_btn
, FALSE
, FALSE
, 0);
649 g_signal_connect(G_OBJECT(down_btn
), "clicked",
650 G_CALLBACK(prefs_filtering_action_down
), NULL
);
652 if (!geometry
.min_height
) {
653 geometry
.min_width
= 490;
654 geometry
.min_height
= 348;
657 gtk_window_set_geometry_hints(GTK_WINDOW(window
), NULL
, &geometry
,
659 gtk_widget_set_size_request(window
, prefs_common
.filteringactionwin_width
,
660 prefs_common
.filteringactionwin_height
);
662 gtk_widget_show_all(window
);
664 filtering_action
.window
= window
;
665 filtering_action
.label1
= label1
;
666 filtering_action
.label2
= label2
;
667 filtering_action
.label3
= label3
;
668 filtering_action
.action_combo
= action_combo
;
669 filtering_action
.account_combo
= account_combo
;
670 filtering_action
.tags_combo
= tags_combo
;
671 filtering_action
.dest_entry
= dest_entry
;
672 filtering_action
.dest_btn
= dest_btn
;
673 filtering_action
.exec_btn
= exec_btn
;
674 #if !GTK_CHECK_VERSION(3, 0, 0)
675 filtering_action
.color_optmenu
= color_optmenu
;
677 filtering_action
.score_entry
= score_entry
;
678 filtering_action
.header_combo
= header_combo
;
679 filtering_action
.header_entry
= header_entry
;
680 #ifndef USE_ALT_ADDRBOOK
681 filtering_action
.addressbook_btn
= addressbook_btn
;
683 filtering_action
.ok_btn
= ok_btn
;
684 filtering_action
.action_list_view
= action_list_view
;
686 prefs_filtering_action_type_selection_changed(NULL
, NULL
);
690 *\brief Set the contents of a row
692 *\param row Index of row to set
693 *\param prop Condition to set
696 static void prefs_filtering_action_list_view_set_row(GtkTreeIter
*row
,
697 FilteringAction
*action
)
701 if (row
== NULL
&& action
== NULL
) {
702 prefs_filtering_action_list_view_insert_action
703 (filtering_action
.action_list_view
,
704 NULL
, _("(New)"), FALSE
);
708 buf
= filteringaction_to_string(action
);
710 prefs_filtering_action_list_view_insert_action
711 (filtering_action
.action_list_view
,
717 *\brief Initializes dialog with a set of conditions
719 *\param matchers List of conditions
721 static void prefs_filtering_action_set_dialog(GSList
*action_list
)
725 gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model
726 (GTK_TREE_VIEW(filtering_action
.action_list_view
))));
728 prefs_filtering_action_list_view_set_row(NULL
, NULL
);
729 if (action_list
!= NULL
) {
730 for (cur
= action_list
; cur
!= NULL
;
731 cur
= g_slist_next(cur
)) {
732 FilteringAction
*action
;
733 action
= (FilteringAction
*) cur
->data
;
734 prefs_filtering_action_list_view_set_row(NULL
, action
);
738 prefs_filtering_action_reset_dialog();
740 combobox_set_sensitive(GTK_COMBO_BOX(filtering_action
.action_combo
), 9,
741 (tags_get_size() > 0) ? TRUE
: FALSE
);
745 *\brief Converts current actions in list box in
746 * an action list used by the filtering system.
748 *\return GSList * List of actions.
750 static GSList
*prefs_filtering_action_get_list(void)
756 GtkTreeView
*list_view
= GTK_TREE_VIEW(filtering_action
.action_list_view
);
757 GtkTreeModel
*model
= gtk_tree_view_get_model(list_view
);
762 while (gtk_tree_model_iter_nth_child(model
, &iter
, NULL
, row
)) {
764 gtk_tree_model_get(model
, &iter
,
765 PFA_ACTION
, &action_str
,
766 PFA_VALID_ACTION
, &is_valid
,
770 GSList
* tmp_action_list
;
771 tmp_action_list
= matcher_parser_get_action_list(action_str
);
773 if (tmp_action_list
== NULL
) {
778 action_list
= g_slist_concat(action_list
,
792 *\brief Returns account ID from the given list index
794 *\return gint account ID
796 static gint
get_account_id_from_list_id(gint list_id
)
800 for (accounts
= account_get_list() ; accounts
!= NULL
;
801 accounts
= accounts
->next
) {
802 PrefsAccount
*ac
= (PrefsAccount
*)accounts
->data
;
805 return ac
->account_id
;
812 *\brief Returns list index from the given account ID
814 *\return gint list index
816 static gint
get_list_id_from_account_id(gint account_id
)
821 for (accounts
= account_get_list() ; accounts
!= NULL
;
822 accounts
= accounts
->next
) {
823 PrefsAccount
*ac
= (PrefsAccount
*)accounts
->data
;
825 if (account_id
== ac
->account_id
)
834 *\brief Returns parser action ID from internal action ID
836 *\return gint parser action ID
838 static gint
prefs_filtering_action_get_matching_from_action(Action action_id
)
842 return MATCHACTION_MOVE
;
844 return MATCHACTION_SET_TAG
;
845 case ACTION_UNSET_TAG
:
846 return MATCHACTION_UNSET_TAG
;
847 case ACTION_CLEAR_TAGS
:
848 return MATCHACTION_CLEAR_TAGS
;
850 return MATCHACTION_COPY
;
852 return MATCHACTION_DELETE
;
854 return MATCHACTION_MARK
;
856 return MATCHACTION_UNMARK
;
858 return MATCHACTION_LOCK
;
860 return MATCHACTION_UNLOCK
;
861 case ACTION_MARK_AS_READ
:
862 return MATCHACTION_MARK_AS_READ
;
863 case ACTION_MARK_AS_UNREAD
:
864 return MATCHACTION_MARK_AS_UNREAD
;
865 case ACTION_MARK_AS_SPAM
:
866 return MATCHACTION_MARK_AS_SPAM
;
867 case ACTION_MARK_AS_HAM
:
868 return MATCHACTION_MARK_AS_HAM
;
870 return MATCHACTION_FORWARD
;
871 case ACTION_FORWARD_AS_ATTACHMENT
:
872 return MATCHACTION_FORWARD_AS_ATTACHMENT
;
873 case ACTION_REDIRECT
:
874 return MATCHACTION_REDIRECT
;
876 return MATCHACTION_EXECUTE
;
877 #if !GTK_CHECK_VERSION(3, 0, 0)
879 return MATCHACTION_COLOR
;
882 return MATCHACTION_HIDE
;
884 return MATCHACTION_IGNORE
;
886 return MATCHACTION_WATCH
;
888 return MATCHACTION_STOP
;
889 case ACTION_CHANGE_SCORE
:
890 return MATCHACTION_CHANGE_SCORE
;
891 case ACTION_SET_SCORE
:
892 return MATCHACTION_SET_SCORE
;
893 case ACTION_ADD_TO_ADDRESSBOOK
:
894 return MATCHACTION_ADD_TO_ADDRESSBOOK
;
901 *\brief Returns action from the content of the dialog
903 *\param alert specifies whether alert dialog boxes should be shown
906 *\return FilteringAction * action entered in the dialog box.
908 static FilteringAction
* prefs_filtering_action_dialog_to_action(gboolean alert
)
914 gchar
* destination
= NULL
;
916 FilteringAction
* action
;
918 gchar
* header
= NULL
;
920 action_id
= combobox_get_active_data(GTK_COMBO_BOX(filtering_action
.action_combo
));
921 action_type
= prefs_filtering_action_get_matching_from_action(action_id
);
922 list_id
= gtk_combo_box_get_active(GTK_COMBO_BOX(filtering_action
.account_combo
));
923 account_id
= get_account_id_from_list_id(list_id
);
931 destination
= gtk_editable_get_chars(GTK_EDITABLE(filtering_action
.dest_entry
), 0, -1);
932 if (*destination
== '\0') {
934 alertpanel_error(action_id
== ACTION_EXECUTE
935 ? _("Command-line not set")
936 : _("Destination is not set."));
942 case ACTION_FORWARD_AS_ATTACHMENT
:
943 case ACTION_REDIRECT
:
944 destination
= gtk_editable_get_chars(GTK_EDITABLE(filtering_action
.dest_entry
), 0, -1);
945 if (*destination
== '\0') {
947 alertpanel_error(_("Recipient is not set."));
952 #if !GTK_CHECK_VERSION(3, 0, 0)
954 labelcolor
= colorlabel_get_color_menu_active_item(
955 gtk_cmoption_menu_get_menu(GTK_CMOPTION_MENU(filtering_action
.color_optmenu
)));
959 case ACTION_CHANGE_SCORE
:
960 case ACTION_SET_SCORE
:
961 score
= gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(
962 filtering_action
.score_entry
));
963 if (!score
&& action_id
== ACTION_CHANGE_SCORE
) {
965 alertpanel_error(_("Score is not set"));
969 case ACTION_ADD_TO_ADDRESSBOOK
:
970 header
= gtk_editable_get_chars(GTK_EDITABLE(filtering_action
.header_entry
), 0, -1);
971 if (*header
== '\0') {
973 alertpanel_error(_("Header is not set."));
977 destination
= gtk_editable_get_chars(GTK_EDITABLE(filtering_action
.dest_entry
), 0, -1);
978 if (*destination
== '\0') {
980 alertpanel_error(_("Target addressbook/folder is not set."));
986 case ACTION_UNSET_TAG
:
987 #if !GTK_CHECK_VERSION(2, 24, 0)
988 destination
= gtk_combo_box_get_active_text(GTK_COMBO_BOX(filtering_action
.tags_combo
));
990 destination
= gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(filtering_action
.tags_combo
));
992 if (!destination
|| *destination
== '\0') {
994 alertpanel_error(_("Tag name is empty."));
1008 case ACTION_MARK_AS_READ
:
1009 case ACTION_MARK_AS_UNREAD
:
1010 case ACTION_MARK_AS_SPAM
:
1011 case ACTION_MARK_AS_HAM
:
1012 case ACTION_CLEAR_TAGS
:
1016 action
= filteringaction_new(action_type
, account_id
,
1017 destination
, labelcolor
, score
, header
);
1019 g_free(destination
);
1024 *\brief Signal handler for register button
1026 static void prefs_filtering_action_register_cb(void)
1028 FilteringAction
*action
;
1030 action
= prefs_filtering_action_dialog_to_action(TRUE
);
1034 prefs_filtering_action_list_view_set_row(NULL
, action
);
1036 filteringaction_free(action
);
1038 * (presumably gtk_list_select_item(), called by
1039 * prefs_filtering_action_reset_dialog() activates
1040 * what seems to be a bug. this causes any other
1041 * list items to be unselectable)
1042 * prefs_filtering_action_reset_dialog(); */
1043 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
), 0);
1044 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.tags_combo
), 0);
1045 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), "");
1049 *\brief Signal handler for substitute button
1051 static void prefs_filtering_action_substitute_cb(void)
1053 GtkTreeView
*list_view
= GTK_TREE_VIEW
1054 (filtering_action
.action_list_view
);
1055 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(list_view
);
1056 GtkTreeModel
*model
;
1059 FilteringAction
*action
;
1061 if (!gtk_tree_selection_get_selected(selection
, &model
, &row
))
1064 gtk_tree_model_get(model
, &row
, PFA_VALID_ACTION
, &is_valid
, -1);
1068 action
= prefs_filtering_action_dialog_to_action(TRUE
);
1072 prefs_filtering_action_list_view_set_row(&row
, action
);
1074 filteringaction_free(action
);
1076 prefs_filtering_action_reset_dialog();
1080 *\brief Signal handler for delete button
1082 static void prefs_filtering_action_delete_cb(void)
1084 GtkTreeView
*list_view
= GTK_TREE_VIEW
1085 (filtering_action
.action_list_view
);
1086 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(list_view
);
1087 GtkTreeModel
*model
;
1091 if (!gtk_tree_selection_get_selected(selection
, &model
, &row
))
1094 gtk_tree_model_get(model
, &row
, PFA_VALID_ACTION
, &is_valid
, -1);
1098 gtk_list_store_remove(GTK_LIST_STORE(model
), &row
);
1100 prefs_filtering_action_reset_dialog();
1104 *\brief Signal handler for 'move up' button
1106 static void prefs_filtering_action_up(void)
1108 GtkTreePath
*prev
, *sel
, *try;
1110 GtkListStore
*store
= NULL
;
1111 GtkTreeModel
*model
= NULL
;
1114 if (!gtk_tree_selection_get_selected
1115 (gtk_tree_view_get_selection
1116 (GTK_TREE_VIEW(filtering_action
.action_list_view
)),
1120 store
= (GtkListStore
*)model
;
1121 sel
= gtk_tree_model_get_path(GTK_TREE_MODEL(store
), &isel
);
1125 /* no move if we're at row 0 or 1, looks phony, but other
1126 * solutions are more convoluted... */
1127 try = gtk_tree_path_copy(sel
);
1128 if (!gtk_tree_path_prev(try) || !gtk_tree_path_prev(try)) {
1129 gtk_tree_path_free(try);
1130 gtk_tree_path_free(sel
);
1133 gtk_tree_path_free(try);
1135 prev
= gtk_tree_path_copy(sel
);
1136 if (gtk_tree_path_prev(prev
)) {
1137 gtk_tree_model_get_iter(GTK_TREE_MODEL(store
),
1139 gtk_list_store_swap(store
, &iprev
, &isel
);
1140 /* XXX: GTK2 select row?? */
1143 gtk_tree_path_free(sel
);
1144 gtk_tree_path_free(prev
);
1148 *\brief Signal handler for 'move down' button
1150 static void prefs_filtering_action_down(void)
1152 GtkListStore
*store
= NULL
;
1153 GtkTreeModel
*model
= NULL
;
1154 GtkTreeIter next
, sel
;
1157 if (!gtk_tree_selection_get_selected
1158 (gtk_tree_view_get_selection
1159 (GTK_TREE_VIEW(filtering_action
.action_list_view
)),
1163 store
= (GtkListStore
*)model
;
1164 try = gtk_tree_model_get_path(GTK_TREE_MODEL(store
), &sel
);
1168 /* move when not at row 0 ... */
1169 if (gtk_tree_path_prev(try)) {
1171 if (gtk_tree_model_iter_next(GTK_TREE_MODEL(store
), &next
))
1172 gtk_list_store_swap(store
, &next
, &sel
);
1175 gtk_tree_path_free(try);
1179 *\brief Handle key press
1181 *\param widget Widget receiving key press
1182 *\param event Key event
1183 *\param data User data
1185 static gboolean
prefs_filtering_action_key_pressed(GtkWidget
*widget
,
1186 GdkEventKey
*event
, gpointer data
)
1188 if (event
&& event
->keyval
== GDK_KEY_Escape
) {
1189 prefs_filtering_action_cancel();
1196 *\brief Cancel matcher dialog
1198 static void prefs_filtering_action_cancel(void)
1200 gtk_widget_destroy(filtering_action
.window
);
1201 filtering_action
.window
= NULL
;
1206 *\brief Accept current matchers
1208 static void prefs_filtering_action_ok(void)
1210 GSList
* action_list
;
1213 action_list
= prefs_filtering_action_get_list();
1215 if (action_list
== NULL
) {
1216 alertpanel_error(_("No action was defined."));
1220 if (filtering_action_callback
!= NULL
)
1221 filtering_action_callback(action_list
);
1222 for(cur
= action_list
; cur
!= NULL
; cur
= cur
->next
) {
1223 filteringaction_free(cur
->data
);
1225 g_slist_free(action_list
);
1227 gtk_widget_destroy(filtering_action
.window
);
1228 filtering_action
.window
= NULL
;
1233 *\brief Called when closing dialog box
1235 *\param widget Dialog widget
1236 *\param event Event info
1237 *\param data User data
1241 static gint
prefs_filtering_action_deleted(GtkWidget
*widget
,
1242 GdkEventAny
*event
, gpointer data
)
1244 prefs_filtering_action_cancel();
1249 * Strings describing exec format strings
1251 * When adding new lines, remember to put 2 strings for each line
1253 static gchar
*exec_desc_strings
[] = {
1254 "%%", N_("literal %"),
1255 "%s", N_("Subject"),
1260 "%i", N_("Message-ID"),
1261 "%n", N_("Newsgroups"),
1262 "%r", N_("References"),
1263 "%F", N_("filename (should not be modified)"),
1264 "\\n", N_("new line"),
1265 "\\", N_("escape character for quotes"),
1266 "\\\"", N_("quote character"),
1270 static DescriptionWindow exec_desc_win
= {
1275 N_("Filtering Action: 'Execute'"),
1276 N_("'Execute' allows you to send a message or message element "
1277 "to an external program or script.\n"
1278 "The following symbols can be used:"),
1283 *\brief Show Execute action's info
1285 static void prefs_filtering_action_exec_info(GtkWidget
*widget
, GtkWidget
*parent
)
1287 exec_desc_win
.parent
= parent
;
1288 description_window_create(&exec_desc_win
);
1291 static void prefs_filtering_action_select_dest(void)
1296 dest
= foldersel_folder_sel(NULL
, FOLDER_SEL_COPY
, NULL
, FALSE
);
1299 path
= folder_item_get_identifier(dest
);
1301 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), path
);
1305 #ifndef USE_ALT_ADDRBOOK
1306 static void prefs_filtering_action_select_addressbook(void)
1308 const gchar
*folderpath
= NULL
;
1309 gchar
*new_path
= NULL
;
1311 folderpath
= gtk_entry_get_text(GTK_ENTRY(filtering_action
.dest_entry
));
1312 new_path
= addressbook_folder_selection(folderpath
);
1314 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), new_path
);
1320 static void prefs_filtering_action_enable_widget(GtkWidget
* widget
, const gboolean enable
)
1322 cm_return_if_fail(widget
!= NULL
);
1326 #if !GTK_CHECK_VERSION(2,24,0)
1327 if(GTK_IS_COMBO_BOX(widget
) || GTK_IS_COMBO_BOX_ENTRY(widget
))
1329 if(GTK_IS_COMBO_BOX(widget
))
1331 gtk_combo_box_set_active(GTK_COMBO_BOX(widget
), 0);
1332 else if(GTK_IS_SPIN_BUTTON(widget
))
1333 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget
), 0);
1334 else if(GTK_IS_ENTRY(widget
))
1335 gtk_entry_set_text(GTK_ENTRY(widget
), "");
1336 #if !GTK_CHECK_VERSION(3, 0, 0)
1337 else if(GTK_IS_CMOPTION_MENU(widget
))
1338 gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(widget
), 0);
1341 gtk_widget_set_sensitive(widget
, TRUE
);
1342 gtk_widget_show(widget
);
1344 gtk_widget_set_sensitive(widget
, FALSE
);
1345 gtk_widget_hide(widget
);
1349 #define ACTION_SEND(x) (x == ACTION_FORWARD || x == ACTION_REDIRECT || \
1350 x == ACTION_FORWARD_AS_ATTACHMENT)
1351 #define ACTION_SCORE(x) (x == ACTION_CHANGE_SCORE || x == ACTION_SET_SCORE)
1352 #define ACTION_TAG(x) (x == ACTION_SET_TAG || x == ACTION_UNSET_TAG)
1353 #define ACTION_FILEOP(x) (x == ACTION_MOVE || x == ACTION_COPY)
1355 static void prefs_filtering_action_type_selection_changed(GtkWidget
*combo
,
1360 value
= combobox_get_active_data(GTK_COMBO_BOX(filtering_action
.action_combo
));
1362 if (filtering_action
.current_action
!= value
) {
1363 if (ACTION_SEND(filtering_action
.current_action
)) {
1364 debug_print("unregistering address completion entry\n");
1365 address_completion_unregister_entry(GTK_ENTRY(filtering_action
.dest_entry
));
1366 address_completion_end(filtering_action
.window
);
1368 if (ACTION_SEND(value
)) {
1369 debug_print("registering address completion entry\n");
1370 address_completion_start(filtering_action
.window
);
1371 address_completion_register_entry(
1372 GTK_ENTRY(filtering_action
.dest_entry
),
1375 filtering_action
.current_action
= value
;
1378 prefs_filtering_action_enable_widget(filtering_action
.label2
,
1379 (ACTION_SEND(value
) || value
== ACTION_ADD_TO_ADDRESSBOOK
));
1381 prefs_filtering_action_enable_widget(filtering_action
.label3
,
1382 (ACTION_SEND(value
) || ACTION_TAG(value
) ||
1383 ACTION_SCORE(value
) || ACTION_FILEOP(value
) ||
1384 value
== ACTION_COLOR
|| value
== ACTION_EXECUTE
||
1385 value
== ACTION_ADD_TO_ADDRESSBOOK
));
1387 prefs_filtering_action_enable_widget(filtering_action
.account_combo
,
1388 ACTION_SEND(value
));
1390 prefs_filtering_action_enable_widget(filtering_action
.tags_combo
,
1393 prefs_filtering_action_enable_widget(filtering_action
.dest_entry
,
1394 (ACTION_FILEOP(value
) || value
== ACTION_EXECUTE
||
1395 ACTION_SEND(value
) || value
== ACTION_ADD_TO_ADDRESSBOOK
));
1397 prefs_filtering_action_enable_widget(filtering_action
.dest_btn
,
1398 ACTION_FILEOP(value
));
1400 prefs_filtering_action_enable_widget(filtering_action
.exec_btn
,
1401 (value
== ACTION_EXECUTE
));
1403 #if !GTK_CHECK_VERSION(3, 0, 0)
1404 prefs_filtering_action_enable_widget(filtering_action
.color_optmenu
,
1405 (value
== ACTION_COLOR
));
1408 prefs_filtering_action_enable_widget(filtering_action
.header_combo
,
1409 (value
== ACTION_ADD_TO_ADDRESSBOOK
));
1410 #ifndef USE_ALT_ADDRBOOK
1411 prefs_filtering_action_enable_widget(filtering_action
.addressbook_btn
,
1412 (value
== ACTION_ADD_TO_ADDRESSBOOK
));
1414 prefs_filtering_action_enable_widget(filtering_action
.score_entry
,
1415 ACTION_SCORE(value
));
1418 case ACTION_FORWARD
:
1419 case ACTION_FORWARD_AS_ATTACHMENT
:
1420 case ACTION_REDIRECT
:
1421 gtk_label_set_text(GTK_LABEL(filtering_action
.label2
), _("Account"));
1422 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Recipient"));
1424 case ACTION_ADD_TO_ADDRESSBOOK
:
1425 gtk_label_set_text(GTK_LABEL(filtering_action
.label2
), _("Header Name"));
1426 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Book/Folder"));
1430 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Destination"));
1432 #if !GTK_CHECK_VERSION(3, 0, 0)
1434 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Color"));
1437 case ACTION_EXECUTE
:
1438 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Execute"));
1440 case ACTION_SET_SCORE
:
1441 case ACTION_CHANGE_SCORE
:
1442 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Score"));
1444 case ACTION_SET_TAG
:
1445 case ACTION_UNSET_TAG
:
1446 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Tag"));
1451 static void prefs_filtering_action_reset_dialog(void)
1453 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
), ACTION_MOVE
);
1454 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
), 0);
1455 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), "");
1456 gtk_spin_button_set_value(GTK_SPIN_BUTTON(filtering_action
.score_entry
), 0);
1459 static GtkListStore
* prefs_filtering_action_create_data_store(void)
1461 return gtk_list_store_new(N_PFA_COLUMNS
,
1467 static void prefs_filtering_action_list_view_insert_action(GtkWidget
*list_view
,
1469 const gchar
*action
,
1472 GtkListStore
*store
= GTK_LIST_STORE(gtk_tree_view_get_model
1473 (GTK_TREE_VIEW(list_view
)));
1477 /* see if row exists, if not append */
1479 gtk_list_store_append(store
, &iter
);
1483 gtk_list_store_set(store
, &iter
,
1485 PFA_VALID_ACTION
, is_valid
,
1489 static GtkWidget
*prefs_filtering_action_list_view_create(void)
1491 GtkTreeView
*list_view
;
1492 GtkTreeModel
*model
;
1493 GtkTreeSelection
*selector
;
1495 model
= GTK_TREE_MODEL(prefs_filtering_action_create_data_store());
1496 list_view
= GTK_TREE_VIEW(gtk_tree_view_new_with_model(model
));
1497 g_object_unref(model
);
1499 gtk_tree_view_set_rules_hint(list_view
, prefs_common
.use_stripes_everywhere
);
1500 gtk_tree_view_set_reorderable(list_view
, TRUE
);
1502 selector
= gtk_tree_view_get_selection(list_view
);
1503 gtk_tree_selection_set_mode(selector
, GTK_SELECTION_BROWSE
);
1504 gtk_tree_selection_set_select_function
1505 (selector
, prefs_filtering_actions_selected
, NULL
, NULL
);
1507 /* create the columns */
1508 prefs_filtering_action_create_list_view_columns(list_view
);
1510 return GTK_WIDGET(list_view
);
1513 static void prefs_filtering_action_create_list_view_columns(GtkTreeView
*list_view
)
1515 GtkTreeViewColumn
*column
;
1516 GtkCellRenderer
*renderer
;
1518 renderer
= gtk_cell_renderer_text_new();
1519 column
= gtk_tree_view_column_new_with_attributes
1520 (_("Current action list"),
1524 gtk_tree_view_append_column(list_view
, column
);
1527 static gboolean prefs_filtering_actions_selected
1528 (GtkTreeSelection
*selector
,
1529 GtkTreeModel
*model
,
1531 gboolean currently_selected
,
1535 FilteringAction
*action
;
1536 GSList
* action_list
;
1542 if (currently_selected
)
1545 if (!gtk_tree_model_get_iter(model
, &iter
, path
))
1548 gtk_tree_model_get(model
, &iter
,
1549 PFA_VALID_ACTION
, &is_valid
,
1553 prefs_filtering_action_reset_dialog();
1557 gtk_tree_model_get(model
, &iter
,
1558 PFA_ACTION
, &action_str
,
1561 action_list
= matcher_parser_get_action_list(action_str
);
1564 if (action_list
== NULL
)
1567 action
= action_list
->data
;
1568 g_slist_free(action_list
);
1570 switch(action
->type
) {
1571 case MATCHACTION_MOVE
:
1572 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1575 case MATCHACTION_COPY
:
1576 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1579 case MATCHACTION_DELETE
:
1580 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1583 case MATCHACTION_MARK
:
1584 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1587 case MATCHACTION_UNMARK
:
1588 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1591 case MATCHACTION_LOCK
:
1592 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1595 case MATCHACTION_UNLOCK
:
1596 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1599 case MATCHACTION_MARK_AS_READ
:
1600 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1601 ACTION_MARK_AS_READ
);
1603 case MATCHACTION_MARK_AS_UNREAD
:
1604 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1605 ACTION_MARK_AS_UNREAD
);
1607 case MATCHACTION_MARK_AS_SPAM
:
1608 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1609 ACTION_MARK_AS_SPAM
);
1611 case MATCHACTION_MARK_AS_HAM
:
1612 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1613 ACTION_MARK_AS_HAM
);
1615 case MATCHACTION_FORWARD
:
1616 list_id
= get_list_id_from_account_id(action
->account_id
);
1617 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1619 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
),
1622 case MATCHACTION_FORWARD_AS_ATTACHMENT
:
1623 list_id
= get_list_id_from_account_id(action
->account_id
);
1624 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1625 ACTION_FORWARD_AS_ATTACHMENT
);
1626 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
),
1629 case MATCHACTION_REDIRECT
:
1630 list_id
= get_list_id_from_account_id(action
->account_id
);
1631 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1633 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
),
1636 case MATCHACTION_EXECUTE
:
1637 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1640 #if !GTK_CHECK_VERSION(3, 0, 0)
1641 case MATCHACTION_COLOR
:
1642 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1644 gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(filtering_action
.color_optmenu
),
1645 action
->labelcolor
+ 1);
1646 menu
= gtk_cmoption_menu_get_menu(GTK_CMOPTION_MENU(
1647 filtering_action
.color_optmenu
));
1648 g_signal_emit_by_name(G_OBJECT(menu
), "selection-done", menu
);
1651 case MATCHACTION_CHANGE_SCORE
:
1652 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1653 ACTION_CHANGE_SCORE
);
1654 gtk_spin_button_set_value(GTK_SPIN_BUTTON(filtering_action
.score_entry
),
1657 case MATCHACTION_SET_SCORE
:
1658 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1660 gtk_spin_button_set_value(GTK_SPIN_BUTTON(filtering_action
.score_entry
),
1663 case MATCHACTION_STOP
:
1664 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1667 case MATCHACTION_HIDE
:
1668 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1671 case MATCHACTION_IGNORE
:
1672 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1675 case MATCHACTION_WATCH
:
1676 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1679 case MATCHACTION_ADD_TO_ADDRESSBOOK
:
1681 gtk_entry_set_text(GTK_ENTRY(filtering_action
.header_entry
), action
->header
);
1683 gtk_entry_set_text(GTK_ENTRY(filtering_action
.header_entry
), "");
1684 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1685 ACTION_ADD_TO_ADDRESSBOOK
);
1687 case MATCHACTION_SET_TAG
:
1688 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1690 combobox_select_by_text(GTK_COMBO_BOX(filtering_action
.tags_combo
),
1691 action
->destination
);
1693 case MATCHACTION_UNSET_TAG
:
1694 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1696 combobox_select_by_text(GTK_COMBO_BOX(filtering_action
.tags_combo
),
1697 action
->destination
);
1699 case MATCHACTION_CLEAR_TAGS
:
1700 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1704 g_warning("unhandled action type");
1706 if (action
->destination
)
1707 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), action
->destination
);
1709 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), "");
1711 filteringaction_free(action
); /* XXX: memleak */