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 #include "gtkcmoptionmenu.h"
38 #include "prefs_gtk.h"
39 #include "prefs_filtering_action.h"
40 #include "prefs_common.h"
41 #include "mainwindow.h"
42 #include "foldersel.h"
43 #include "manage_window.h"
48 #include "alertpanel.h"
50 #include "description_window.h"
51 #include "addr_compl.h"
53 #include "matcher_parser.h"
54 #include "colorlabel.h"
57 #ifndef USE_ALT_ADDRBOOK
58 #include "addressbook.h"
68 static void prefs_filtering_action_create(void);
69 static void prefs_filtering_action_delete_cb(void);
70 static void prefs_filtering_action_substitute_cb(void);
71 static void prefs_filtering_action_register_cb(void);
72 static void prefs_filtering_action_reset_dialog(void);
73 static gboolean
prefs_filtering_action_key_pressed(GtkWidget
*widget
,
74 GdkEventKey
*event
, gpointer data
);
75 static void prefs_filtering_action_cancel(void);
76 static void prefs_filtering_action_ok(void);
77 static gint
prefs_filtering_action_deleted(GtkWidget
*widget
,
78 GdkEventAny
*event
, gpointer data
);
79 static void prefs_filtering_action_type_selection_changed(GtkWidget
*widget
,
81 static void prefs_filtering_action_select_dest(void);
82 #ifndef USE_ALT_ADDRBOOK
83 static void prefs_filtering_action_select_addressbook(void);
85 static void prefs_filtering_action_up(void);
86 static void prefs_filtering_action_down(void);
87 static void prefs_filtering_action_set_dialog(GSList
*action_list
);
88 static GSList
*prefs_filtering_action_get_list(void);
90 static GtkListStore
* prefs_filtering_action_create_data_store (void);
91 static void prefs_filtering_action_list_view_insert_action (GtkWidget
*list_view
,
95 static GtkWidget
*prefs_filtering_action_list_view_create (void);
96 static void prefs_filtering_action_create_list_view_columns (GtkTreeView
*list_view
);
97 static gboolean
prefs_filtering_actions_selected (GtkTreeSelection
*selector
,
100 gboolean currently_selected
,
103 static void prefs_filtering_action_exec_info (GtkWidget
*widget
,
107 *\brief UI data for matcher dialog
109 static struct FilteringAction_
{
114 GtkWidget
*action_list_view
;
118 GtkWidget
*action_combo
;
119 GtkWidget
*account_combo
;
120 GtkWidget
*dest_entry
;
123 GtkWidget
*color_optmenu
;
124 GtkWidget
*header_combo
;
125 GtkWidget
*header_entry
;
126 #ifndef USE_ALT_ADDRBOOK
127 GtkWidget
*addressbook_btn
;
129 GtkWidget
*score_entry
;
130 GtkWidget
*tags_combo
;
136 typedef enum Action_
{
145 ACTION_MARK_AS_UNREAD
,
149 ACTION_FORWARD_AS_ATTACHMENT
,
161 ACTION_ADD_TO_ADDRESSBOOK
,
163 /* add other action constants */
171 { NULL
, N_("Move"), ACTION_MOVE
},
172 { NULL
, N_("Copy"), ACTION_COPY
},
173 { NULL
, N_("Delete"), ACTION_DELETE
},
174 { NULL
, N_("Hide"), ACTION_HIDE
},
175 { N_("Message flags"), N_("Mark"), ACTION_MARK
},
176 { N_("Message flags"), N_("Unmark"), ACTION_UNMARK
},
177 { N_("Message flags"), N_("Lock"), ACTION_LOCK
},
178 { N_("Message flags"), N_("Unlock"), ACTION_UNLOCK
},
179 { N_("Message flags"), N_("Mark as read"), ACTION_MARK_AS_READ
},
180 { N_("Message flags"), N_("Mark as unread"), ACTION_MARK_AS_UNREAD
},
181 { N_("Message flags"), N_("Mark as spam"), ACTION_MARK_AS_SPAM
},
182 { N_("Message flags"), N_("Mark as ham"), ACTION_MARK_AS_HAM
},
183 { NULL
, N_("Execute"), ACTION_EXECUTE
},
184 { NULL
, N_("Color label"), ACTION_COLOR
},
185 { N_("Resend"), N_("Forward"), ACTION_FORWARD
},
186 { N_("Resend"), N_("Forward as attachment"), ACTION_FORWARD_AS_ATTACHMENT
},
187 { N_("Resend"), N_("Redirect"), ACTION_REDIRECT
},
188 { N_("Score"), N_("Change score"), ACTION_CHANGE_SCORE
},
189 { N_("Score"), N_("Set score"), ACTION_SET_SCORE
},
190 { N_("Tags"), N_("Apply tag"), ACTION_SET_TAG
},
191 { N_("Tags"), N_("Unset tag"), ACTION_UNSET_TAG
},
192 { N_("Tags"), N_("Clear tags"), ACTION_CLEAR_TAGS
},
193 { N_("Threads"), N_("Ignore thread"), ACTION_IGNORE
},
194 { N_("Threads"), N_("Watch thread"), ACTION_WATCH
},
195 { NULL
, N_("Add to address book"), ACTION_ADD_TO_ADDRESSBOOK
},
196 { NULL
, N_("Stop filter"), ACTION_STOP
},
210 static PrefsFilteringActionSignal
*filtering_action_callback
;
212 static GtkTreeModel
*prefs_filtering_action_create_model(void)
214 GtkTreeIter iter
, iter2
;
216 gchar
*curr_menu
= NULL
;
219 store
= gtk_tree_store_new(N_ACTION_COMBO
, G_TYPE_STRING
, G_TYPE_INT
,
222 for (i
= 0; action_menu
[i
].menu
|| action_menu
[i
].text
; i
++)
224 if (action_menu
[i
].menu
) {
225 if (!curr_menu
|| strcmp(action_menu
[i
].menu
, curr_menu
)) {
226 gtk_tree_store_append(store
, &iter
, NULL
);
227 gtk_tree_store_set(store
, &iter
,
229 gettext(action_menu
[i
].menu
),
230 ACTION_COMBO_SENS
, TRUE
,
232 curr_menu
= action_menu
[i
].menu
;
235 gtk_tree_store_append(store
, &iter2
, &iter
);
236 gtk_tree_store_set(store
, &iter2
,
237 ACTION_COMBO_TEXT
, gettext(action_menu
[i
].text
),
238 ACTION_COMBO_DATA
, action_menu
[i
].action
,
239 ACTION_COMBO_SENS
, TRUE
,
244 gtk_tree_store_append(store
, &iter
, NULL
);
245 gtk_tree_store_set(store
, &iter
,
246 ACTION_COMBO_TEXT
, gettext(action_menu
[i
].text
),
247 ACTION_COMBO_DATA
, action_menu
[i
].action
,
248 ACTION_COMBO_SENS
, TRUE
,
253 return GTK_TREE_MODEL(store
);
256 static void cell_is_sensitive(GtkCellLayout
*cell_layout
,
257 GtkCellRenderer
*cell
,
258 GtkTreeModel
*tree_model
,
262 if(gtk_tree_model_iter_has_child (tree_model
, iter
)) {
263 g_object_set (cell
, "sensitive", FALSE
, NULL
);
268 *\brief Opens the filtering action dialog with a list of actions
270 *\param matchers List of conditions
274 void prefs_filtering_action_open(GSList
*action_list
,
275 PrefsFilteringActionSignal
*cb
)
279 if (!filtering_action
.window
) {
280 prefs_filtering_action_create();
282 /* update color label menu */
283 gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(filtering_action
.color_optmenu
),
284 colorlabel_create_color_menu());
287 manage_window_set_transient(GTK_WINDOW(filtering_action
.window
));
288 gtk_widget_grab_focus(filtering_action
.ok_btn
);
290 filtering_action_callback
= cb
;
292 prefs_filtering_action_set_dialog(action_list
);
294 gtk_widget_show(filtering_action
.window
);
295 gtk_window_set_modal(GTK_WINDOW(filtering_action
.window
), TRUE
);
299 *\brief Save Gtk object size to prefs dataset
301 static void prefs_filtering_action_size_allocate_cb(GtkWidget
*widget
,
302 GtkAllocation
*allocation
)
304 cm_return_if_fail(allocation
!= NULL
);
306 prefs_common
.filteringactionwin_width
= allocation
->width
;
307 prefs_common
.filteringactionwin_height
= allocation
->height
;
310 #define LABELS_WIDTH 80
311 #define SECOND_ROW_WIDTH 250
313 static void prefs_filtering_action_check_widget_width(GtkWidget
*widget
)
317 gtk_widget_size_request(widget
, &req
);
318 if(req
.width
> SECOND_ROW_WIDTH
)
319 gtk_widget_set_size_request(widget
, SECOND_ROW_WIDTH
, -1);
323 *\brief Create the matcher dialog
325 static void prefs_filtering_action_create(void)
330 GtkWidget
*cancel_btn
;
331 GtkWidget
*confirm_area
;
341 GtkWidget
*action_combo
;
342 GtkWidget
*account_combo
;
343 GtkWidget
*header_combo
;
344 GtkWidget
*header_entry
;
345 #ifndef USE_ALT_ADDRBOOK
346 GtkWidget
*addressbook_btn
;
348 GtkWidget
*dest_entry
;
350 GtkWidget
*score_entry
;
351 GtkWidget
*tags_combo
;
357 GtkWidget
*subst_btn
;
360 GtkWidget
*action_hbox
;
361 GtkWidget
*action_scrolledwin
;
362 GtkWidget
*action_list_view
;
370 GtkWidget
*color_optmenu
;
372 static GdkGeometry geometry
;
377 GtkSizeGroup
*size_group
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
378 GtkSizeGroup
*size_action
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
380 GtkCellRenderer
*renderer
;
382 debug_print("Creating matcher configuration window...\n");
384 window
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "prefs_filtering_action");
385 gtk_container_set_border_width(GTK_CONTAINER(window
), VBOX_BORDER
);
386 gtk_window_set_position(GTK_WINDOW(window
), GTK_WIN_POS_CENTER
);
387 gtk_window_set_resizable(GTK_WINDOW(window
), TRUE
);
388 gtk_window_set_type_hint(GTK_WINDOW(window
), GDK_WINDOW_TYPE_HINT_DIALOG
);
390 vbox
= gtk_vbox_new(FALSE
, 6);
391 gtk_container_add(GTK_CONTAINER(window
), vbox
);
393 gtkut_stock_button_set_create(&confirm_area
,
394 &cancel_btn
, GTK_STOCK_CANCEL
,
395 &ok_btn
, GTK_STOCK_OK
,
397 gtk_box_pack_end(GTK_BOX(vbox
), confirm_area
, FALSE
, FALSE
, 0);
398 gtk_widget_grab_default(ok_btn
);
400 gtk_window_set_title(GTK_WINDOW(window
),
401 _("Action configuration"));
402 g_signal_connect(G_OBJECT(window
), "delete_event",
403 G_CALLBACK(prefs_filtering_action_deleted
), NULL
);
404 g_signal_connect(G_OBJECT(window
), "size_allocate",
405 G_CALLBACK(prefs_filtering_action_size_allocate_cb
), NULL
);
406 g_signal_connect(G_OBJECT(window
), "key_press_event",
407 G_CALLBACK(prefs_filtering_action_key_pressed
), NULL
);
408 MANAGE_WINDOW_SIGNALS_CONNECT(window
);
409 g_signal_connect(G_OBJECT(ok_btn
), "clicked",
410 G_CALLBACK(prefs_filtering_action_ok
), NULL
);
411 g_signal_connect(G_OBJECT(cancel_btn
), "clicked",
412 G_CALLBACK(prefs_filtering_action_cancel
), NULL
);
414 vbox1
= gtk_vbox_new(FALSE
, VSPACING
);
415 gtk_box_pack_start(GTK_BOX(vbox
), vbox1
, TRUE
, TRUE
, 0);
416 gtk_container_set_border_width(GTK_CONTAINER (vbox1
), 2);
418 frame
= gtk_frame_new(_("Rule"));
419 gtk_frame_set_label_align(GTK_FRAME(frame
), 0.01, 0.5);
420 gtk_box_pack_start (GTK_BOX (vbox1
), frame
, FALSE
, FALSE
, 0);
421 gtk_widget_set_size_request(frame
, -1, 110);
423 table
= gtk_table_new(3, 3, FALSE
);
424 gtk_container_set_border_width(GTK_CONTAINER(table
), 2);
425 gtk_table_set_row_spacings (GTK_TABLE (table
), VSPACING_NARROW_2
);
426 gtk_table_set_col_spacings (GTK_TABLE (table
), HSPACING_NARROW
);
427 gtk_container_add(GTK_CONTAINER(frame
), table
);
429 /* first row labels */
431 label1
= gtk_label_new (_("Action"));
432 gtk_widget_set_size_request(label1
, LABELS_WIDTH
, -1);
433 gtk_size_group_add_widget(size_group
, label1
);
434 gtk_misc_set_alignment (GTK_MISC (label1
), 1, 0.5);
435 gtk_table_attach(GTK_TABLE(table
), label1
, 0, 1, 0, 1,
436 GTK_FILL
, GTK_SHRINK
, 0, 0);
438 label2
= gtk_label_new ("");
439 gtk_size_group_add_widget(size_group
, label2
);
440 gtk_misc_set_alignment (GTK_MISC (label2
), 1, 0.5);
441 gtk_table_attach(GTK_TABLE(table
), label2
, 0, 1, 1, 2,
442 GTK_FILL
, GTK_SHRINK
, 0, 0);
444 label3
= gtk_label_new ("");
445 gtk_size_group_add_widget(size_group
, label3
);
446 gtk_misc_set_alignment (GTK_MISC (label3
), 1, 0.5);
447 gtk_table_attach(GTK_TABLE(table
), label3
, 0, 1, 2, 3,
448 GTK_FILL
, GTK_SHRINK
, 0, 0);
452 hbox1
= gtk_hbox_new(FALSE
, 0);
453 gtk_table_attach(GTK_TABLE(table
), hbox1
, 1, 2, 0, 1,
454 GTK_FILL
, GTK_SHRINK
, 0, 0);
456 model
= prefs_filtering_action_create_model();
457 action_combo
= gtk_combo_box_new_with_model(model
);
458 gtk_size_group_add_widget(size_action
, action_combo
);
460 renderer
= gtk_cell_renderer_text_new();
461 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(action_combo
), renderer
, TRUE
);
462 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(action_combo
), renderer
,
463 "text", ACTION_COMBO_TEXT
,
464 "sensitive", ACTION_COMBO_SENS
,
466 gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(action_combo
), renderer
,
467 cell_is_sensitive
, NULL
, NULL
);
469 combobox_select_by_data(GTK_COMBO_BOX(action_combo
), ACTION_MOVE
);
470 g_signal_connect(G_OBJECT(action_combo
), "changed",
471 G_CALLBACK(prefs_filtering_action_type_selection_changed
),
473 gtk_box_pack_start(GTK_BOX(hbox1
), action_combo
, FALSE
, FALSE
, 0);
474 gtk_box_pack_start(GTK_BOX(hbox1
), gtk_label_new(""), TRUE
, TRUE
, 0);
478 hbox1
= gtk_hbox_new (FALSE
, 0);
479 gtk_table_attach(GTK_TABLE(table
), hbox1
, 1, 2, 1, 2,
480 GTK_FILL
| GTK_EXPAND
, GTK_SHRINK
, 0, 0);
482 account_combo
= gtk_combo_box_text_new ();
483 gtk_size_group_add_widget(size_action
, account_combo
);
485 for (accounts
= account_get_list() ; accounts
!= NULL
;
486 accounts
= accounts
->next
) {
487 PrefsAccount
*ac
= (PrefsAccount
*)accounts
->data
;
488 gchar
*name
= g_strdup(ac
->account_name
);
489 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(account_combo
), (gpointer
) name
);
493 prefs_filtering_action_check_widget_width(account_combo
);
494 gtk_combo_box_set_active(GTK_COMBO_BOX(account_combo
), 0);
495 gtk_box_pack_start (GTK_BOX (hbox1
), account_combo
,
500 header_combo
= combobox_text_new(TRUE
, "From", "To", "Cc", "Reply-To", "Sender", NULL
);
501 gtk_size_group_add_widget(size_action
, header_combo
);
502 gtk_box_pack_start (GTK_BOX (hbox1
), header_combo
,
504 header_entry
= gtk_bin_get_child(GTK_BIN((header_combo
)));
508 hbox1
= gtk_hbox_new (FALSE
, 0);
509 gtk_table_attach(GTK_TABLE(table
), hbox1
, 1, 2, 2, 3,
510 GTK_FILL
| GTK_EXPAND
, GTK_SHRINK
, 0, 0);
512 dest_entry
= gtk_entry_new ();
513 gtk_box_pack_start (GTK_BOX (hbox1
), dest_entry
, TRUE
, TRUE
, 0);
515 score_entry
= gtk_spin_button_new_with_range(-1000, 1000, 1);
516 gtk_box_pack_start(GTK_BOX(hbox1
), score_entry
, FALSE
, FALSE
, 0);
518 color_optmenu
= gtk_cmoption_menu_new();
519 gtk_size_group_add_widget(size_action
, color_optmenu
);
520 gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(color_optmenu
),
521 colorlabel_create_color_menu());
522 prefs_filtering_action_check_widget_width(color_optmenu
);
523 gtk_box_pack_start(GTK_BOX(hbox1
), color_optmenu
, FALSE
, FALSE
, 0);
525 tags_combo
= gtk_combo_box_text_new ();
526 gtk_size_group_add_widget(size_action
, tags_combo
);
528 for (tmp
= tags
= tags_get_list() ; tmp
!= NULL
;
530 gchar
*name
= g_strdup(tags_get_tag(GPOINTER_TO_INT(tmp
->data
)));
532 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tags_combo
), (gpointer
) name
);
537 prefs_filtering_action_check_widget_width(tags_combo
);
538 gtk_combo_box_set_active(GTK_COMBO_BOX(tags_combo
), 0);
539 gtk_box_pack_start (GTK_BOX (hbox1
), tags_combo
,
542 hbox1
= gtk_hbox_new (FALSE
, 0);
543 gtk_table_attach(GTK_TABLE(table
), hbox1
, 2, 3, 2, 3,
544 GTK_FILL
, GTK_SHRINK
, 0, 0);
546 dest_btn
= gtk_button_new_with_label (_("Select..."));
547 gtk_box_pack_start (GTK_BOX (hbox1
), dest_btn
, FALSE
, FALSE
, 0);
548 g_signal_connect (G_OBJECT (dest_btn
), "clicked",
549 G_CALLBACK(prefs_filtering_action_select_dest
),
552 #ifndef USE_ALT_ADDRBOOK
553 addressbook_btn
= gtk_button_new_with_label (_("Select..."));
554 gtk_box_pack_start (GTK_BOX (hbox1
), addressbook_btn
, FALSE
, FALSE
, 0);
555 g_signal_connect (G_OBJECT (addressbook_btn
), "clicked",
556 G_CALLBACK(prefs_filtering_action_select_addressbook
),
560 exec_btn
= gtk_button_new_from_stock(GTK_STOCK_INFO
);
561 gtk_box_pack_start (GTK_BOX (hbox1
), exec_btn
, FALSE
, FALSE
, 0);
562 g_signal_connect (G_OBJECT (exec_btn
), "clicked",
563 G_CALLBACK(prefs_filtering_action_exec_info
),
566 /* register / substitute / delete */
568 reg_hbox
= gtk_hbox_new(FALSE
, 4);
569 gtk_box_pack_start(GTK_BOX(vbox1
), reg_hbox
, FALSE
, FALSE
, 0);
571 arrow
= gtk_arrow_new(GTK_ARROW_DOWN
, GTK_SHADOW_OUT
);
572 gtk_box_pack_start(GTK_BOX(reg_hbox
), arrow
, FALSE
, FALSE
, 0);
573 gtk_widget_set_size_request(arrow
, -1, 16);
575 btn_hbox
= gtk_hbox_new(TRUE
, 4);
576 gtk_box_pack_start(GTK_BOX(reg_hbox
), btn_hbox
, FALSE
, FALSE
, 0);
578 reg_btn
= gtk_button_new_from_stock(GTK_STOCK_ADD
);
579 gtk_box_pack_start(GTK_BOX(btn_hbox
), reg_btn
, FALSE
, TRUE
, 0);
580 g_signal_connect(G_OBJECT(reg_btn
), "clicked",
581 G_CALLBACK(prefs_filtering_action_register_cb
), NULL
);
583 subst_btn
= gtkut_get_replace_btn(_("_Replace"));
584 gtk_box_pack_start(GTK_BOX(btn_hbox
), subst_btn
, FALSE
, TRUE
, 0);
585 g_signal_connect(G_OBJECT(subst_btn
), "clicked",
586 G_CALLBACK(prefs_filtering_action_substitute_cb
),
589 del_btn
= gtk_button_new_with_mnemonic (_("D_elete"));
590 gtk_button_set_image(GTK_BUTTON(del_btn
),
591 gtk_image_new_from_stock(GTK_STOCK_REMOVE
,GTK_ICON_SIZE_BUTTON
));
592 gtk_box_pack_start(GTK_BOX(btn_hbox
), del_btn
, FALSE
, TRUE
, 0);
593 g_signal_connect(G_OBJECT(del_btn
), "clicked",
594 G_CALLBACK(prefs_filtering_action_delete_cb
), NULL
);
596 action_hbox
= gtk_hbox_new(FALSE
, 8);
597 gtk_box_pack_start(GTK_BOX(vbox1
), action_hbox
, TRUE
, TRUE
, 0);
599 action_scrolledwin
= gtk_scrolled_window_new(NULL
, NULL
);
600 gtk_widget_set_size_request(action_scrolledwin
, -1, 150);
601 gtk_box_pack_start(GTK_BOX(action_hbox
), action_scrolledwin
,
603 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(action_scrolledwin
),
604 GTK_SHADOW_ETCHED_IN
);
605 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(action_scrolledwin
),
606 GTK_POLICY_AUTOMATIC
,
607 GTK_POLICY_AUTOMATIC
);
609 action_list_view
= prefs_filtering_action_list_view_create();
610 gtk_container_add(GTK_CONTAINER(action_scrolledwin
), action_list_view
);
612 btn_vbox
= gtk_vbox_new(FALSE
, 8);
613 gtk_box_pack_start(GTK_BOX(action_hbox
), btn_vbox
, FALSE
, FALSE
, 0);
615 up_btn
= gtk_button_new_from_stock(GTK_STOCK_GO_UP
);
616 gtk_box_pack_start(GTK_BOX(btn_vbox
), up_btn
, FALSE
, FALSE
, 0);
617 g_signal_connect(G_OBJECT(up_btn
), "clicked",
618 G_CALLBACK(prefs_filtering_action_up
), NULL
);
620 down_btn
= gtk_button_new_from_stock(GTK_STOCK_GO_DOWN
);
621 gtk_box_pack_start(GTK_BOX(btn_vbox
), down_btn
, FALSE
, FALSE
, 0);
622 g_signal_connect(G_OBJECT(down_btn
), "clicked",
623 G_CALLBACK(prefs_filtering_action_down
), NULL
);
625 if (!geometry
.min_height
) {
626 geometry
.min_width
= 490;
627 geometry
.min_height
= 348;
630 gtk_window_set_geometry_hints(GTK_WINDOW(window
), NULL
, &geometry
,
632 gtk_widget_set_size_request(window
, prefs_common
.filteringactionwin_width
,
633 prefs_common
.filteringactionwin_height
);
635 g_object_unref(G_OBJECT(size_group
));
636 g_object_unref(G_OBJECT(size_action
));
638 gtk_widget_show_all(window
);
640 filtering_action
.window
= window
;
641 filtering_action
.label1
= label1
;
642 filtering_action
.label2
= label2
;
643 filtering_action
.label3
= label3
;
644 filtering_action
.action_combo
= action_combo
;
645 filtering_action
.account_combo
= account_combo
;
646 filtering_action
.tags_combo
= tags_combo
;
647 filtering_action
.dest_entry
= dest_entry
;
648 filtering_action
.dest_btn
= dest_btn
;
649 filtering_action
.exec_btn
= exec_btn
;
650 filtering_action
.color_optmenu
= color_optmenu
;
651 filtering_action
.score_entry
= score_entry
;
652 filtering_action
.header_combo
= header_combo
;
653 filtering_action
.header_entry
= header_entry
;
654 #ifndef USE_ALT_ADDRBOOK
655 filtering_action
.addressbook_btn
= addressbook_btn
;
657 filtering_action
.ok_btn
= ok_btn
;
658 filtering_action
.action_list_view
= action_list_view
;
660 prefs_filtering_action_type_selection_changed(NULL
, NULL
);
664 *\brief Set the contents of a row
666 *\param row Index of row to set
667 *\param prop Condition to set
670 static void prefs_filtering_action_list_view_set_row(GtkTreeIter
*row
,
671 FilteringAction
*action
)
675 if (row
== NULL
&& action
== NULL
) {
676 prefs_filtering_action_list_view_insert_action
677 (filtering_action
.action_list_view
,
678 NULL
, _("(New)"), FALSE
);
682 buf
= filteringaction_to_string(action
);
684 prefs_filtering_action_list_view_insert_action
685 (filtering_action
.action_list_view
,
691 *\brief Initializes dialog with a set of conditions
693 *\param matchers List of conditions
695 static void prefs_filtering_action_set_dialog(GSList
*action_list
)
699 gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model
700 (GTK_TREE_VIEW(filtering_action
.action_list_view
))));
702 prefs_filtering_action_list_view_set_row(NULL
, NULL
);
703 if (action_list
!= NULL
) {
704 for (cur
= action_list
; cur
!= NULL
;
705 cur
= g_slist_next(cur
)) {
706 FilteringAction
*action
;
707 action
= (FilteringAction
*) cur
->data
;
708 prefs_filtering_action_list_view_set_row(NULL
, action
);
712 prefs_filtering_action_reset_dialog();
714 combobox_set_sensitive(GTK_COMBO_BOX(filtering_action
.action_combo
), 9,
715 (tags_get_size() > 0) ? TRUE
: FALSE
);
719 *\brief Converts current actions in list box in
720 * an action list used by the filtering system.
722 *\return GSList * List of actions.
724 static GSList
*prefs_filtering_action_get_list(void)
730 GtkTreeView
*list_view
= GTK_TREE_VIEW(filtering_action
.action_list_view
);
731 GtkTreeModel
*model
= gtk_tree_view_get_model(list_view
);
736 while (gtk_tree_model_iter_nth_child(model
, &iter
, NULL
, row
)) {
738 gtk_tree_model_get(model
, &iter
,
739 PFA_ACTION
, &action_str
,
740 PFA_VALID_ACTION
, &is_valid
,
744 GSList
* tmp_action_list
;
745 tmp_action_list
= matcher_parser_get_action_list(action_str
);
747 if (tmp_action_list
== NULL
) {
752 action_list
= g_slist_concat(action_list
,
766 *\brief Returns account ID from the given list index
768 *\return gint account ID
770 static gint
get_account_id_from_list_id(gint list_id
)
774 for (accounts
= account_get_list() ; accounts
!= NULL
;
775 accounts
= accounts
->next
) {
776 PrefsAccount
*ac
= (PrefsAccount
*)accounts
->data
;
779 return ac
->account_id
;
786 *\brief Returns list index from the given account ID
788 *\return gint list index
790 static gint
get_list_id_from_account_id(gint account_id
)
795 for (accounts
= account_get_list() ; accounts
!= NULL
;
796 accounts
= accounts
->next
) {
797 PrefsAccount
*ac
= (PrefsAccount
*)accounts
->data
;
799 if (account_id
== ac
->account_id
)
808 *\brief Returns parser action ID from internal action ID
810 *\return gint parser action ID
812 static gint
prefs_filtering_action_get_matching_from_action(Action action_id
)
816 return MATCHACTION_MOVE
;
818 return MATCHACTION_SET_TAG
;
819 case ACTION_UNSET_TAG
:
820 return MATCHACTION_UNSET_TAG
;
821 case ACTION_CLEAR_TAGS
:
822 return MATCHACTION_CLEAR_TAGS
;
824 return MATCHACTION_COPY
;
826 return MATCHACTION_DELETE
;
828 return MATCHACTION_MARK
;
830 return MATCHACTION_UNMARK
;
832 return MATCHACTION_LOCK
;
834 return MATCHACTION_UNLOCK
;
835 case ACTION_MARK_AS_READ
:
836 return MATCHACTION_MARK_AS_READ
;
837 case ACTION_MARK_AS_UNREAD
:
838 return MATCHACTION_MARK_AS_UNREAD
;
839 case ACTION_MARK_AS_SPAM
:
840 return MATCHACTION_MARK_AS_SPAM
;
841 case ACTION_MARK_AS_HAM
:
842 return MATCHACTION_MARK_AS_HAM
;
844 return MATCHACTION_FORWARD
;
845 case ACTION_FORWARD_AS_ATTACHMENT
:
846 return MATCHACTION_FORWARD_AS_ATTACHMENT
;
847 case ACTION_REDIRECT
:
848 return MATCHACTION_REDIRECT
;
850 return MATCHACTION_EXECUTE
;
852 return MATCHACTION_COLOR
;
854 return MATCHACTION_HIDE
;
856 return MATCHACTION_IGNORE
;
858 return MATCHACTION_WATCH
;
860 return MATCHACTION_STOP
;
861 case ACTION_CHANGE_SCORE
:
862 return MATCHACTION_CHANGE_SCORE
;
863 case ACTION_SET_SCORE
:
864 return MATCHACTION_SET_SCORE
;
865 case ACTION_ADD_TO_ADDRESSBOOK
:
866 return MATCHACTION_ADD_TO_ADDRESSBOOK
;
873 *\brief Returns action from the content of the dialog
875 *\param alert specifies whether alert dialog boxes should be shown
878 *\return FilteringAction * action entered in the dialog box.
880 static FilteringAction
* prefs_filtering_action_dialog_to_action(gboolean alert
)
886 gchar
* destination
= NULL
;
888 FilteringAction
* action
;
890 gchar
* header
= NULL
;
892 action_id
= combobox_get_active_data(GTK_COMBO_BOX(filtering_action
.action_combo
));
893 action_type
= prefs_filtering_action_get_matching_from_action(action_id
);
894 list_id
= gtk_combo_box_get_active(GTK_COMBO_BOX(filtering_action
.account_combo
));
895 account_id
= get_account_id_from_list_id(list_id
);
903 destination
= gtk_editable_get_chars(GTK_EDITABLE(filtering_action
.dest_entry
), 0, -1);
904 if (*destination
== '\0') {
906 alertpanel_error(action_id
== ACTION_EXECUTE
907 ? _("Command-line not set")
908 : _("Destination is not set."));
914 case ACTION_FORWARD_AS_ATTACHMENT
:
915 case ACTION_REDIRECT
:
916 destination
= gtk_editable_get_chars(GTK_EDITABLE(filtering_action
.dest_entry
), 0, -1);
917 if (*destination
== '\0') {
919 alertpanel_error(_("Recipient is not set."));
925 labelcolor
= colorlabel_get_color_menu_active_item(
926 gtk_cmoption_menu_get_menu(GTK_CMOPTION_MENU(filtering_action
.color_optmenu
)));
929 case ACTION_CHANGE_SCORE
:
930 case ACTION_SET_SCORE
:
931 score
= gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(
932 filtering_action
.score_entry
));
933 if (!score
&& action_id
== ACTION_CHANGE_SCORE
) {
935 alertpanel_error(_("Score is not set"));
939 case ACTION_ADD_TO_ADDRESSBOOK
:
940 header
= gtk_editable_get_chars(GTK_EDITABLE(filtering_action
.header_entry
), 0, -1);
941 if (*header
== '\0') {
943 alertpanel_error(_("Header is not set."));
947 destination
= gtk_editable_get_chars(GTK_EDITABLE(filtering_action
.dest_entry
), 0, -1);
948 if (*destination
== '\0') {
950 alertpanel_error(_("Target addressbook/folder is not set."));
956 case ACTION_UNSET_TAG
:
957 destination
= gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(filtering_action
.tags_combo
));
958 if (!destination
|| *destination
== '\0') {
960 alertpanel_error(_("Tag name is empty."));
974 case ACTION_MARK_AS_READ
:
975 case ACTION_MARK_AS_UNREAD
:
976 case ACTION_MARK_AS_SPAM
:
977 case ACTION_MARK_AS_HAM
:
978 case ACTION_CLEAR_TAGS
:
982 action
= filteringaction_new(action_type
, account_id
,
983 destination
, labelcolor
, score
, header
);
990 *\brief Signal handler for register button
992 static void prefs_filtering_action_register_cb(void)
994 FilteringAction
*action
;
996 action
= prefs_filtering_action_dialog_to_action(TRUE
);
1000 prefs_filtering_action_list_view_set_row(NULL
, action
);
1002 filteringaction_free(action
);
1004 * (presumably gtk_list_select_item(), called by
1005 * prefs_filtering_action_reset_dialog() activates
1006 * what seems to be a bug. this causes any other
1007 * list items to be unselectable)
1008 * prefs_filtering_action_reset_dialog(); */
1009 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
), 0);
1010 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.tags_combo
), 0);
1011 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), "");
1015 *\brief Signal handler for substitute button
1017 static void prefs_filtering_action_substitute_cb(void)
1019 GtkTreeView
*list_view
= GTK_TREE_VIEW
1020 (filtering_action
.action_list_view
);
1021 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(list_view
);
1022 GtkTreeModel
*model
;
1025 FilteringAction
*action
;
1027 if (!gtk_tree_selection_get_selected(selection
, &model
, &row
))
1030 gtk_tree_model_get(model
, &row
, PFA_VALID_ACTION
, &is_valid
, -1);
1034 action
= prefs_filtering_action_dialog_to_action(TRUE
);
1038 prefs_filtering_action_list_view_set_row(&row
, action
);
1040 filteringaction_free(action
);
1042 prefs_filtering_action_reset_dialog();
1046 *\brief Signal handler for delete button
1048 static void prefs_filtering_action_delete_cb(void)
1050 GtkTreeView
*list_view
= GTK_TREE_VIEW
1051 (filtering_action
.action_list_view
);
1052 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(list_view
);
1053 GtkTreeModel
*model
;
1057 if (!gtk_tree_selection_get_selected(selection
, &model
, &row
))
1060 gtk_tree_model_get(model
, &row
, PFA_VALID_ACTION
, &is_valid
, -1);
1064 gtk_list_store_remove(GTK_LIST_STORE(model
), &row
);
1066 prefs_filtering_action_reset_dialog();
1070 *\brief Signal handler for 'move up' button
1072 static void prefs_filtering_action_up(void)
1074 GtkTreePath
*prev
, *sel
, *try;
1076 GtkListStore
*store
= NULL
;
1077 GtkTreeModel
*model
= NULL
;
1080 if (!gtk_tree_selection_get_selected
1081 (gtk_tree_view_get_selection
1082 (GTK_TREE_VIEW(filtering_action
.action_list_view
)),
1086 store
= (GtkListStore
*)model
;
1087 sel
= gtk_tree_model_get_path(GTK_TREE_MODEL(store
), &isel
);
1091 /* no move if we're at row 0 or 1, looks phony, but other
1092 * solutions are more convoluted... */
1093 try = gtk_tree_path_copy(sel
);
1094 if (!gtk_tree_path_prev(try) || !gtk_tree_path_prev(try)) {
1095 gtk_tree_path_free(try);
1096 gtk_tree_path_free(sel
);
1099 gtk_tree_path_free(try);
1101 prev
= gtk_tree_path_copy(sel
);
1102 if (gtk_tree_path_prev(prev
)) {
1103 gtk_tree_model_get_iter(GTK_TREE_MODEL(store
),
1105 gtk_list_store_swap(store
, &iprev
, &isel
);
1106 /* XXX: GTK2 select row?? */
1109 gtk_tree_path_free(sel
);
1110 gtk_tree_path_free(prev
);
1114 *\brief Signal handler for 'move down' button
1116 static void prefs_filtering_action_down(void)
1118 GtkListStore
*store
= NULL
;
1119 GtkTreeModel
*model
= NULL
;
1120 GtkTreeIter next
, sel
;
1123 if (!gtk_tree_selection_get_selected
1124 (gtk_tree_view_get_selection
1125 (GTK_TREE_VIEW(filtering_action
.action_list_view
)),
1129 store
= (GtkListStore
*)model
;
1130 try = gtk_tree_model_get_path(GTK_TREE_MODEL(store
), &sel
);
1134 /* move when not at row 0 ... */
1135 if (gtk_tree_path_prev(try)) {
1137 if (gtk_tree_model_iter_next(GTK_TREE_MODEL(store
), &next
))
1138 gtk_list_store_swap(store
, &next
, &sel
);
1141 gtk_tree_path_free(try);
1145 *\brief Handle key press
1147 *\param widget Widget receiving key press
1148 *\param event Key event
1149 *\param data User data
1151 static gboolean
prefs_filtering_action_key_pressed(GtkWidget
*widget
,
1152 GdkEventKey
*event
, gpointer data
)
1154 if (event
&& event
->keyval
== GDK_KEY_Escape
) {
1155 prefs_filtering_action_cancel();
1162 *\brief Cancel matcher dialog
1164 static void prefs_filtering_action_cancel(void)
1166 gtk_widget_destroy(filtering_action
.window
);
1167 filtering_action
.window
= NULL
;
1172 *\brief Accept current matchers
1174 static void prefs_filtering_action_ok(void)
1176 GSList
* action_list
;
1179 action_list
= prefs_filtering_action_get_list();
1181 if (action_list
== NULL
) {
1182 alertpanel_error(_("No action was defined."));
1186 if (filtering_action_callback
!= NULL
)
1187 filtering_action_callback(action_list
);
1188 for(cur
= action_list
; cur
!= NULL
; cur
= cur
->next
) {
1189 filteringaction_free(cur
->data
);
1191 g_slist_free(action_list
);
1193 gtk_widget_destroy(filtering_action
.window
);
1194 filtering_action
.window
= NULL
;
1199 *\brief Called when closing dialog box
1201 *\param widget Dialog widget
1202 *\param event Event info
1203 *\param data User data
1207 static gint
prefs_filtering_action_deleted(GtkWidget
*widget
,
1208 GdkEventAny
*event
, gpointer data
)
1210 prefs_filtering_action_cancel();
1215 * Strings describing exec format strings
1217 * When adding new lines, remember to put 2 strings for each line
1219 static gchar
*exec_desc_strings
[] = {
1220 "%%", N_("literal %"),
1221 "%s", N_("Subject"),
1226 "%i", N_("Message-ID"),
1227 "%n", N_("Newsgroups"),
1228 "%r", N_("References"),
1229 "%F", N_("filename (should not be modified)"),
1230 "\\n", N_("new line"),
1231 "\\", N_("escape character for quotes"),
1232 "\\\"", N_("quote character"),
1236 static DescriptionWindow exec_desc_win
= {
1241 N_("Filtering Action: 'Execute'"),
1242 N_("'Execute' allows you to send a message or message element "
1243 "to an external program or script.\n"
1244 "The following symbols can be used:"),
1249 *\brief Show Execute action's info
1251 static void prefs_filtering_action_exec_info(GtkWidget
*widget
, GtkWidget
*parent
)
1253 exec_desc_win
.parent
= parent
;
1254 description_window_create(&exec_desc_win
);
1257 static void prefs_filtering_action_select_dest(void)
1262 dest
= foldersel_folder_sel(NULL
, FOLDER_SEL_COPY
, NULL
, FALSE
,
1263 _("Select destination folder"));
1266 path
= folder_item_get_identifier(dest
);
1268 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), path
);
1272 #ifndef USE_ALT_ADDRBOOK
1273 static void prefs_filtering_action_select_addressbook(void)
1275 const gchar
*folderpath
= NULL
;
1276 gchar
*new_path
= NULL
;
1278 folderpath
= gtk_entry_get_text(GTK_ENTRY(filtering_action
.dest_entry
));
1279 new_path
= addressbook_folder_selection(folderpath
);
1281 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), new_path
);
1287 static void prefs_filtering_action_enable_widget(GtkWidget
* widget
, const gboolean enable
)
1289 cm_return_if_fail(widget
!= NULL
);
1293 if(GTK_IS_COMBO_BOX(widget
))
1294 gtk_combo_box_set_active(GTK_COMBO_BOX(widget
), 0);
1295 else if(GTK_IS_SPIN_BUTTON(widget
))
1296 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget
), 0);
1297 else if(GTK_IS_ENTRY(widget
))
1298 gtk_entry_set_text(GTK_ENTRY(widget
), "");
1299 else if(GTK_IS_CMOPTION_MENU(widget
))
1300 gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(widget
), 0);
1302 gtk_widget_set_sensitive(widget
, TRUE
);
1303 gtk_widget_show(widget
);
1305 gtk_widget_set_sensitive(widget
, FALSE
);
1306 gtk_widget_hide(widget
);
1310 #define ACTION_SEND(x) (x == ACTION_FORWARD || x == ACTION_REDIRECT || \
1311 x == ACTION_FORWARD_AS_ATTACHMENT)
1312 #define ACTION_SCORE(x) (x == ACTION_CHANGE_SCORE || x == ACTION_SET_SCORE)
1313 #define ACTION_TAG(x) (x == ACTION_SET_TAG || x == ACTION_UNSET_TAG)
1314 #define ACTION_FILEOP(x) (x == ACTION_MOVE || x == ACTION_COPY)
1316 static void prefs_filtering_action_type_selection_changed(GtkWidget
*combo
,
1321 value
= combobox_get_active_data(GTK_COMBO_BOX(filtering_action
.action_combo
));
1323 if (filtering_action
.current_action
!= value
) {
1324 if (ACTION_SEND(filtering_action
.current_action
)) {
1325 debug_print("unregistering address completion entry\n");
1326 address_completion_unregister_entry(GTK_ENTRY(filtering_action
.dest_entry
));
1327 address_completion_end(filtering_action
.window
);
1329 if (ACTION_SEND(value
)) {
1330 debug_print("registering address completion entry\n");
1331 address_completion_start(filtering_action
.window
);
1332 address_completion_register_entry(
1333 GTK_ENTRY(filtering_action
.dest_entry
),
1336 filtering_action
.current_action
= value
;
1339 prefs_filtering_action_enable_widget(filtering_action
.label2
,
1340 (ACTION_SEND(value
) || value
== ACTION_ADD_TO_ADDRESSBOOK
));
1342 prefs_filtering_action_enable_widget(filtering_action
.label3
,
1343 (ACTION_SEND(value
) || ACTION_TAG(value
) ||
1344 ACTION_SCORE(value
) || ACTION_FILEOP(value
) ||
1345 value
== ACTION_COLOR
|| value
== ACTION_EXECUTE
||
1346 value
== ACTION_ADD_TO_ADDRESSBOOK
));
1348 prefs_filtering_action_enable_widget(filtering_action
.account_combo
,
1349 ACTION_SEND(value
));
1351 prefs_filtering_action_enable_widget(filtering_action
.tags_combo
,
1354 prefs_filtering_action_enable_widget(filtering_action
.dest_entry
,
1355 (ACTION_FILEOP(value
) || value
== ACTION_EXECUTE
||
1356 ACTION_SEND(value
) || value
== ACTION_ADD_TO_ADDRESSBOOK
));
1358 prefs_filtering_action_enable_widget(filtering_action
.dest_btn
,
1359 ACTION_FILEOP(value
));
1361 prefs_filtering_action_enable_widget(filtering_action
.exec_btn
,
1362 (value
== ACTION_EXECUTE
));
1364 prefs_filtering_action_enable_widget(filtering_action
.color_optmenu
,
1365 (value
== ACTION_COLOR
));
1367 prefs_filtering_action_enable_widget(filtering_action
.header_combo
,
1368 (value
== ACTION_ADD_TO_ADDRESSBOOK
));
1369 #ifndef USE_ALT_ADDRBOOK
1370 prefs_filtering_action_enable_widget(filtering_action
.addressbook_btn
,
1371 (value
== ACTION_ADD_TO_ADDRESSBOOK
));
1373 prefs_filtering_action_enable_widget(filtering_action
.score_entry
,
1374 ACTION_SCORE(value
));
1377 case ACTION_FORWARD
:
1378 case ACTION_FORWARD_AS_ATTACHMENT
:
1379 case ACTION_REDIRECT
:
1380 gtk_label_set_text(GTK_LABEL(filtering_action
.label2
), _("Account"));
1381 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Recipient"));
1383 case ACTION_ADD_TO_ADDRESSBOOK
:
1384 gtk_label_set_text(GTK_LABEL(filtering_action
.label2
), _("Header Name"));
1385 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Book/Folder"));
1389 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Destination"));
1392 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Color"));
1394 case ACTION_EXECUTE
:
1395 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Execute"));
1397 case ACTION_SET_SCORE
:
1398 case ACTION_CHANGE_SCORE
:
1399 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Score"));
1401 case ACTION_SET_TAG
:
1402 case ACTION_UNSET_TAG
:
1403 gtk_label_set_text(GTK_LABEL(filtering_action
.label3
), _("Tag"));
1408 static void prefs_filtering_action_reset_dialog(void)
1410 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
), ACTION_MOVE
);
1411 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
), 0);
1412 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), "");
1413 gtk_spin_button_set_value(GTK_SPIN_BUTTON(filtering_action
.score_entry
), 0);
1416 static GtkListStore
* prefs_filtering_action_create_data_store(void)
1418 return gtk_list_store_new(N_PFA_COLUMNS
,
1424 static void prefs_filtering_action_list_view_insert_action(GtkWidget
*list_view
,
1426 const gchar
*action
,
1429 GtkListStore
*store
= GTK_LIST_STORE(gtk_tree_view_get_model
1430 (GTK_TREE_VIEW(list_view
)));
1434 /* see if row exists, if not append */
1436 gtk_list_store_append(store
, &iter
);
1440 gtk_list_store_set(store
, &iter
,
1442 PFA_VALID_ACTION
, is_valid
,
1446 static GtkWidget
*prefs_filtering_action_list_view_create(void)
1448 GtkTreeView
*list_view
;
1449 GtkTreeModel
*model
;
1450 GtkTreeSelection
*selector
;
1452 model
= GTK_TREE_MODEL(prefs_filtering_action_create_data_store());
1453 list_view
= GTK_TREE_VIEW(gtk_tree_view_new_with_model(model
));
1454 g_object_unref(model
);
1456 gtk_tree_view_set_rules_hint(list_view
, prefs_common
.use_stripes_everywhere
);
1457 gtk_tree_view_set_reorderable(list_view
, TRUE
);
1459 selector
= gtk_tree_view_get_selection(list_view
);
1460 gtk_tree_selection_set_mode(selector
, GTK_SELECTION_BROWSE
);
1461 gtk_tree_selection_set_select_function
1462 (selector
, prefs_filtering_actions_selected
, NULL
, NULL
);
1464 /* create the columns */
1465 prefs_filtering_action_create_list_view_columns(list_view
);
1467 return GTK_WIDGET(list_view
);
1470 static void prefs_filtering_action_create_list_view_columns(GtkTreeView
*list_view
)
1472 GtkTreeViewColumn
*column
;
1473 GtkCellRenderer
*renderer
;
1475 renderer
= gtk_cell_renderer_text_new();
1476 column
= gtk_tree_view_column_new_with_attributes
1477 (_("Current action list"),
1481 gtk_tree_view_append_column(list_view
, column
);
1484 static gboolean prefs_filtering_actions_selected
1485 (GtkTreeSelection
*selector
,
1486 GtkTreeModel
*model
,
1488 gboolean currently_selected
,
1492 FilteringAction
*action
;
1493 GSList
* action_list
;
1499 if (currently_selected
)
1502 if (!gtk_tree_model_get_iter(model
, &iter
, path
))
1505 gtk_tree_model_get(model
, &iter
,
1506 PFA_VALID_ACTION
, &is_valid
,
1510 prefs_filtering_action_reset_dialog();
1514 gtk_tree_model_get(model
, &iter
,
1515 PFA_ACTION
, &action_str
,
1518 action_list
= matcher_parser_get_action_list(action_str
);
1521 if (action_list
== NULL
)
1524 action
= action_list
->data
;
1525 g_slist_free(action_list
);
1527 switch(action
->type
) {
1528 case MATCHACTION_MOVE
:
1529 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1532 case MATCHACTION_COPY
:
1533 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1536 case MATCHACTION_DELETE
:
1537 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1540 case MATCHACTION_MARK
:
1541 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1544 case MATCHACTION_UNMARK
:
1545 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1548 case MATCHACTION_LOCK
:
1549 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1552 case MATCHACTION_UNLOCK
:
1553 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1556 case MATCHACTION_MARK_AS_READ
:
1557 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1558 ACTION_MARK_AS_READ
);
1560 case MATCHACTION_MARK_AS_UNREAD
:
1561 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1562 ACTION_MARK_AS_UNREAD
);
1564 case MATCHACTION_MARK_AS_SPAM
:
1565 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1566 ACTION_MARK_AS_SPAM
);
1568 case MATCHACTION_MARK_AS_HAM
:
1569 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1570 ACTION_MARK_AS_HAM
);
1572 case MATCHACTION_FORWARD
:
1573 list_id
= get_list_id_from_account_id(action
->account_id
);
1574 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1576 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
),
1579 case MATCHACTION_FORWARD_AS_ATTACHMENT
:
1580 list_id
= get_list_id_from_account_id(action
->account_id
);
1581 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1582 ACTION_FORWARD_AS_ATTACHMENT
);
1583 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
),
1586 case MATCHACTION_REDIRECT
:
1587 list_id
= get_list_id_from_account_id(action
->account_id
);
1588 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1590 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
),
1593 case MATCHACTION_EXECUTE
:
1594 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1597 case MATCHACTION_COLOR
:
1598 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1600 gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(filtering_action
.color_optmenu
),
1601 action
->labelcolor
+ 1);
1602 menu
= gtk_cmoption_menu_get_menu(GTK_CMOPTION_MENU(
1603 filtering_action
.color_optmenu
));
1604 g_signal_emit_by_name(G_OBJECT(menu
), "selection-done", menu
);
1606 case MATCHACTION_CHANGE_SCORE
:
1607 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1608 ACTION_CHANGE_SCORE
);
1609 gtk_spin_button_set_value(GTK_SPIN_BUTTON(filtering_action
.score_entry
),
1612 case MATCHACTION_SET_SCORE
:
1613 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1615 gtk_spin_button_set_value(GTK_SPIN_BUTTON(filtering_action
.score_entry
),
1618 case MATCHACTION_STOP
:
1619 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1622 case MATCHACTION_HIDE
:
1623 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1626 case MATCHACTION_IGNORE
:
1627 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1630 case MATCHACTION_WATCH
:
1631 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1634 case MATCHACTION_ADD_TO_ADDRESSBOOK
:
1636 gtk_entry_set_text(GTK_ENTRY(filtering_action
.header_entry
), action
->header
);
1638 gtk_entry_set_text(GTK_ENTRY(filtering_action
.header_entry
), "");
1639 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1640 ACTION_ADD_TO_ADDRESSBOOK
);
1642 case MATCHACTION_SET_TAG
:
1643 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1645 combobox_select_by_text(GTK_COMBO_BOX(filtering_action
.tags_combo
),
1646 action
->destination
);
1648 case MATCHACTION_UNSET_TAG
:
1649 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1651 combobox_select_by_text(GTK_COMBO_BOX(filtering_action
.tags_combo
),
1652 action
->destination
);
1654 case MATCHACTION_CLEAR_TAGS
:
1655 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1659 g_warning("unhandled action type");
1661 if (action
->destination
)
1662 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), action
->destination
);
1664 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), "");
1666 filteringaction_free(action
); /* XXX: memleak */