2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 2003-2022 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/>.
21 #include "claws-features.h"
27 #include <glib/gi18n.h>
29 #include <gdk/gdkkeysyms.h>
36 #include "prefs_gtk.h"
37 #include "prefs_filtering_action.h"
38 #include "prefs_common.h"
39 #include "mainwindow.h"
40 #include "foldersel.h"
41 #include "manage_window.h"
46 #include "alertpanel.h"
48 #include "description_window.h"
49 #include "addr_compl.h"
51 #include "matcher_parser.h"
52 #include "colorlabel.h"
55 #ifndef USE_ALT_ADDRBOOK
56 #include "addressbook.h"
66 static void prefs_filtering_action_create(void);
67 static void prefs_filtering_action_delete_cb(void);
68 static void prefs_filtering_action_substitute_cb(void);
69 static void prefs_filtering_action_register_cb(void);
70 static void prefs_filtering_action_reset_dialog(void);
71 static gboolean
prefs_filtering_action_key_pressed(GtkWidget
*widget
,
72 GdkEventKey
*event
, gpointer data
);
73 static void prefs_filtering_action_cancel(void);
74 static void prefs_filtering_action_ok(void);
75 static gint
prefs_filtering_action_deleted(GtkWidget
*widget
,
76 GdkEventAny
*event
, gpointer data
);
77 static void prefs_filtering_action_type_selection_changed(GtkWidget
*widget
,
79 static void prefs_filtering_action_select_dest(void);
80 #ifndef USE_ALT_ADDRBOOK
81 static void prefs_filtering_action_select_addressbook(void);
83 static void prefs_filtering_action_up(void);
84 static void prefs_filtering_action_down(void);
85 static void prefs_filtering_action_set_dialog(GSList
*action_list
);
86 static GSList
*prefs_filtering_action_get_list(void);
88 static GtkListStore
* prefs_filtering_action_create_data_store (void);
89 static void prefs_filtering_action_list_view_insert_action (GtkWidget
*list_view
,
93 static GtkWidget
*prefs_filtering_action_list_view_create (void);
94 static void prefs_filtering_action_create_list_view_columns (GtkTreeView
*list_view
);
95 static gboolean
prefs_filtering_actions_selected (GtkTreeSelection
*selector
,
98 gboolean currently_selected
,
101 static void prefs_filtering_action_exec_info (GtkWidget
*widget
,
105 *\brief UI data for matcher dialog
107 static struct FilteringAction_
{
112 GtkWidget
*action_list_view
;
116 GtkWidget
*action_combo
;
117 GtkWidget
*account_combo
;
118 GtkWidget
*dest_entry
;
121 GtkWidget
*color_optmenu
;
122 GtkWidget
*header_combo
;
123 GtkWidget
*header_entry
;
124 #ifndef USE_ALT_ADDRBOOK
125 GtkWidget
*addressbook_btn
;
127 GtkWidget
*score_entry
;
128 GtkWidget
*tags_combo
;
134 typedef enum Action_
{
143 ACTION_MARK_AS_UNREAD
,
147 ACTION_FORWARD_AS_ATTACHMENT
,
159 ACTION_ADD_TO_ADDRESSBOOK
,
161 /* add other action constants */
169 { NULL
, N_("Move"), ACTION_MOVE
},
170 { NULL
, N_("Copy"), ACTION_COPY
},
171 { NULL
, N_("Delete"), ACTION_DELETE
},
172 { NULL
, N_("Hide"), ACTION_HIDE
},
173 { N_("Message flags"), N_("Mark"), ACTION_MARK
},
174 { N_("Message flags"), N_("Unmark"), ACTION_UNMARK
},
175 { N_("Message flags"), N_("Lock"), ACTION_LOCK
},
176 { N_("Message flags"), N_("Unlock"), ACTION_UNLOCK
},
177 { N_("Message flags"), N_("Mark as read"), ACTION_MARK_AS_READ
},
178 { N_("Message flags"), N_("Mark as unread"), ACTION_MARK_AS_UNREAD
},
179 { N_("Message flags"), N_("Mark as spam"), ACTION_MARK_AS_SPAM
},
180 { N_("Message flags"), N_("Mark as ham"), ACTION_MARK_AS_HAM
},
181 { NULL
, N_("Execute"), ACTION_EXECUTE
},
182 { NULL
, N_("Color label"), ACTION_COLOR
},
183 { N_("Resend"), N_("Forward"), ACTION_FORWARD
},
184 { N_("Resend"), N_("Forward as attachment"), ACTION_FORWARD_AS_ATTACHMENT
},
185 { N_("Resend"), N_("Redirect"), ACTION_REDIRECT
},
186 { N_("Score"), N_("Change score"), ACTION_CHANGE_SCORE
},
187 { N_("Score"), N_("Set score"), ACTION_SET_SCORE
},
188 { N_("Tags"), N_("Apply tag"), ACTION_SET_TAG
},
189 { N_("Tags"), N_("Unset tag"), ACTION_UNSET_TAG
},
190 { N_("Tags"), N_("Clear tags"), ACTION_CLEAR_TAGS
},
191 { N_("Threads"), N_("Ignore thread"), ACTION_IGNORE
},
192 { N_("Threads"), N_("Watch thread"), ACTION_WATCH
},
193 { NULL
, N_("Add to address book"), ACTION_ADD_TO_ADDRESSBOOK
},
194 { NULL
, N_("Stop filter"), ACTION_STOP
},
208 static PrefsFilteringActionSignal
*filtering_action_callback
;
210 static GtkTreeModel
*prefs_filtering_action_create_model(void)
212 GtkTreeIter iter
, iter2
;
214 gchar
*curr_menu
= NULL
;
217 store
= gtk_tree_store_new(N_ACTION_COMBO
, G_TYPE_STRING
, G_TYPE_INT
,
220 for (i
= 0; action_menu
[i
].menu
|| action_menu
[i
].text
; i
++)
222 if (action_menu
[i
].menu
) {
223 if (!curr_menu
|| strcmp(action_menu
[i
].menu
, curr_menu
)) {
224 gtk_tree_store_append(store
, &iter
, NULL
);
225 gtk_tree_store_set(store
, &iter
,
227 gettext(action_menu
[i
].menu
),
228 ACTION_COMBO_SENS
, TRUE
,
230 curr_menu
= action_menu
[i
].menu
;
233 gtk_tree_store_append(store
, &iter2
, &iter
);
234 gtk_tree_store_set(store
, &iter2
,
235 ACTION_COMBO_TEXT
, gettext(action_menu
[i
].text
),
236 ACTION_COMBO_DATA
, action_menu
[i
].action
,
237 ACTION_COMBO_SENS
, TRUE
,
242 gtk_tree_store_append(store
, &iter
, NULL
);
243 gtk_tree_store_set(store
, &iter
,
244 ACTION_COMBO_TEXT
, gettext(action_menu
[i
].text
),
245 ACTION_COMBO_DATA
, action_menu
[i
].action
,
246 ACTION_COMBO_SENS
, TRUE
,
251 return GTK_TREE_MODEL(store
);
254 static void cell_is_sensitive(GtkCellLayout
*cell_layout
,
255 GtkCellRenderer
*cell
,
256 GtkTreeModel
*tree_model
,
260 if(gtk_tree_model_iter_has_child (tree_model
, iter
)) {
261 g_object_set (cell
, "sensitive", FALSE
, NULL
);
266 *\brief Opens the filtering action dialog with a list of actions
268 *\param matchers List of conditions
272 void prefs_filtering_action_open(GSList
*action_list
,
273 PrefsFilteringActionSignal
*cb
)
277 if (!filtering_action
.window
) {
278 prefs_filtering_action_create();
280 /* update color label menu */
281 colorlabel_refill_combobox_colormenu(
282 GTK_COMBO_BOX(filtering_action
.color_optmenu
));
285 manage_window_set_transient(GTK_WINDOW(filtering_action
.window
));
286 gtk_widget_grab_focus(filtering_action
.ok_btn
);
288 filtering_action_callback
= cb
;
290 prefs_filtering_action_set_dialog(action_list
);
292 gtk_widget_show(filtering_action
.window
);
293 gtk_window_set_modal(GTK_WINDOW(filtering_action
.window
), TRUE
);
297 *\brief Save Gtk object size to prefs dataset
299 static void prefs_filtering_action_size_allocate_cb(GtkWidget
*widget
,
300 GtkAllocation
*allocation
)
302 cm_return_if_fail(allocation
!= NULL
);
304 gtk_window_get_size(GTK_WINDOW(widget
),
305 &prefs_common
.filteringactionwin_width
, &prefs_common
.filteringactionwin_height
);
308 #define LABELS_WIDTH 80
309 #define SECOND_ROW_WIDTH 250
311 static void prefs_filtering_action_check_widget_width(GtkWidget
*widget
)
315 gtk_widget_get_preferred_size(widget
, &req
, NULL
);
316 if(req
.width
> SECOND_ROW_WIDTH
)
317 gtk_widget_set_size_request(widget
, SECOND_ROW_WIDTH
, -1);
321 *\brief Create the matcher dialog
323 static void prefs_filtering_action_create(void)
328 GtkWidget
*cancel_btn
;
329 GtkWidget
*confirm_area
;
339 GtkWidget
*action_combo
;
340 GtkWidget
*account_combo
;
341 GtkWidget
*header_combo
;
342 GtkWidget
*header_entry
;
343 #ifndef USE_ALT_ADDRBOOK
344 GtkWidget
*addressbook_btn
;
346 GtkWidget
*dest_entry
;
348 GtkWidget
*score_entry
;
349 GtkWidget
*tags_combo
;
355 GtkWidget
*subst_btn
;
358 GtkWidget
*action_hbox
;
359 GtkWidget
*action_scrolledwin
;
360 GtkWidget
*action_list_view
;
368 GtkWidget
*color_optmenu
;
370 static GdkGeometry geometry
;
375 GtkSizeGroup
*size_group
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
376 GtkSizeGroup
*size_action
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
378 GtkCellRenderer
*renderer
;
380 debug_print("Creating matcher configuration window...\n");
382 window
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "prefs_filtering_action");
383 gtk_container_set_border_width(GTK_CONTAINER(window
), VBOX_BORDER
);
384 gtk_window_set_position(GTK_WINDOW(window
), GTK_WIN_POS_CENTER
);
385 gtk_window_set_resizable(GTK_WINDOW(window
), TRUE
);
386 gtk_window_set_type_hint(GTK_WINDOW(window
), GDK_WINDOW_TYPE_HINT_DIALOG
);
388 vbox
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 6);
389 gtk_container_add(GTK_CONTAINER(window
), vbox
);
391 gtkut_stock_button_set_create(&confirm_area
,
392 &cancel_btn
, NULL
, _("_Cancel"),
393 &ok_btn
, NULL
, _("_OK"),
395 gtk_box_pack_end(GTK_BOX(vbox
), confirm_area
, FALSE
, FALSE
, 0);
396 gtk_widget_grab_default(ok_btn
);
398 gtk_window_set_title(GTK_WINDOW(window
),
399 _("Action configuration"));
400 g_signal_connect(G_OBJECT(window
), "delete_event",
401 G_CALLBACK(prefs_filtering_action_deleted
), NULL
);
402 g_signal_connect(G_OBJECT(window
), "size_allocate",
403 G_CALLBACK(prefs_filtering_action_size_allocate_cb
), NULL
);
404 g_signal_connect(G_OBJECT(window
), "key_press_event",
405 G_CALLBACK(prefs_filtering_action_key_pressed
), NULL
);
406 MANAGE_WINDOW_SIGNALS_CONNECT(window
);
407 g_signal_connect(G_OBJECT(ok_btn
), "clicked",
408 G_CALLBACK(prefs_filtering_action_ok
), NULL
);
409 g_signal_connect(G_OBJECT(cancel_btn
), "clicked",
410 G_CALLBACK(prefs_filtering_action_cancel
), NULL
);
412 vbox1
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, VSPACING
);
413 gtk_box_pack_start(GTK_BOX(vbox
), vbox1
, TRUE
, TRUE
, 0);
414 gtk_container_set_border_width(GTK_CONTAINER (vbox1
), 2);
416 frame
= gtk_frame_new(_("Rule"));
417 gtk_frame_set_label_align(GTK_FRAME(frame
), 0.01, 0.5);
418 gtk_box_pack_start (GTK_BOX (vbox1
), frame
, FALSE
, FALSE
, 0);
419 gtk_widget_set_size_request(frame
, -1, 110);
421 table
= gtk_grid_new();
422 gtk_container_set_border_width(GTK_CONTAINER(table
), 2);
423 gtk_grid_set_row_spacing(GTK_GRID(table
), VSPACING_NARROW_2
);
424 gtk_grid_set_column_spacing(GTK_GRID(table
), VSPACING_NARROW
);
426 gtk_container_add(GTK_CONTAINER(frame
), table
);
428 /* first row labels */
430 label1
= gtk_label_new (_("Action"));
431 gtk_widget_set_size_request(label1
, LABELS_WIDTH
, -1);
432 gtk_size_group_add_widget(size_group
, label1
);
433 gtk_label_set_xalign(GTK_LABEL(label1
), 1.0);
434 gtk_grid_attach(GTK_GRID(table
), label1
, 0, 0, 1, 1);
436 label2
= gtk_label_new ("");
437 gtk_size_group_add_widget(size_group
, label2
);
438 gtk_label_set_xalign(GTK_LABEL(label2
), 1.0);
439 gtk_grid_attach(GTK_GRID(table
), label2
, 0, 1, 1, 1);
440 gtk_widget_set_hexpand(label2
, TRUE
);
441 gtk_widget_set_halign(label2
, GTK_ALIGN_FILL
);
443 label3
= gtk_label_new ("");
444 gtk_size_group_add_widget(size_group
, label3
);
445 gtk_label_set_xalign(GTK_LABEL(label3
), 1.0);
446 gtk_grid_attach(GTK_GRID(table
), label3
, 0, 2, 1, 1);
447 gtk_widget_set_hexpand(label3
, TRUE
);
448 gtk_widget_set_halign(label3
, GTK_ALIGN_FILL
);
452 hbox1
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0);
453 gtk_grid_attach(GTK_GRID(table
), hbox1
, 1, 0, 1, 1);
454 gtk_widget_set_hexpand(hbox1
, TRUE
);
455 gtk_widget_set_halign(hbox1
, GTK_ALIGN_FILL
);
457 model
= prefs_filtering_action_create_model();
458 action_combo
= gtk_combo_box_new_with_model(model
);
459 gtk_size_group_add_widget(size_action
, action_combo
);
461 renderer
= gtk_cell_renderer_text_new();
462 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(action_combo
), renderer
, TRUE
);
463 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(action_combo
), renderer
,
464 "text", ACTION_COMBO_TEXT
,
465 "sensitive", ACTION_COMBO_SENS
,
467 gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(action_combo
), renderer
,
468 cell_is_sensitive
, NULL
, NULL
);
470 combobox_select_by_data(GTK_COMBO_BOX(action_combo
), ACTION_MOVE
);
471 g_signal_connect(G_OBJECT(action_combo
), "changed",
472 G_CALLBACK(prefs_filtering_action_type_selection_changed
),
474 gtk_box_pack_start(GTK_BOX(hbox1
), action_combo
, FALSE
, FALSE
, 0);
475 gtk_box_pack_start(GTK_BOX(hbox1
), gtk_label_new(""), TRUE
, TRUE
, 0);
479 hbox1
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0);
480 gtk_grid_attach(GTK_GRID(table
), hbox1
, 1, 1, 1, 1);
481 gtk_widget_set_hexpand(hbox1
, TRUE
);
482 gtk_widget_set_halign(hbox1
, GTK_ALIGN_FILL
);
484 account_combo
= gtk_combo_box_text_new ();
485 gtk_size_group_add_widget(size_action
, account_combo
);
487 for (accounts
= account_get_list() ; accounts
!= NULL
;
488 accounts
= accounts
->next
) {
489 PrefsAccount
*ac
= (PrefsAccount
*)accounts
->data
;
490 gchar
*name
= g_strdup(ac
->account_name
);
491 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(account_combo
), (gpointer
) name
);
495 prefs_filtering_action_check_widget_width(account_combo
);
496 gtk_combo_box_set_active(GTK_COMBO_BOX(account_combo
), 0);
497 gtk_box_pack_start (GTK_BOX (hbox1
), account_combo
,
502 header_combo
= combobox_text_new(TRUE
, "From", "To", "Cc", "Reply-To", "Sender", NULL
);
503 gtk_size_group_add_widget(size_action
, header_combo
);
504 gtk_box_pack_start (GTK_BOX (hbox1
), header_combo
,
506 header_entry
= gtk_bin_get_child(GTK_BIN((header_combo
)));
510 hbox1
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0);
511 gtk_grid_attach(GTK_GRID(table
), hbox1
, 1, 2, 1, 1);
512 gtk_widget_set_hexpand(hbox1
, TRUE
);
513 gtk_widget_set_halign(hbox1
, GTK_ALIGN_FILL
);
515 dest_entry
= gtk_entry_new ();
516 gtk_box_pack_start (GTK_BOX (hbox1
), dest_entry
, TRUE
, TRUE
, 0);
518 score_entry
= gtk_spin_button_new_with_range(-1000, 1000, 1);
519 gtk_box_pack_start(GTK_BOX(hbox1
), score_entry
, FALSE
, FALSE
, 0);
521 color_optmenu
= colorlabel_create_combobox_colormenu();
522 gtk_size_group_add_widget(size_action
, color_optmenu
);
523 prefs_filtering_action_check_widget_width(color_optmenu
);
524 gtk_box_pack_start(GTK_BOX(hbox1
), color_optmenu
, FALSE
, FALSE
, 0);
526 tags_combo
= gtk_combo_box_text_new ();
527 gtk_size_group_add_widget(size_action
, tags_combo
);
529 for (tmp
= tags
= tags_get_list() ; tmp
!= NULL
;
531 gchar
*name
= g_strdup(tags_get_tag(GPOINTER_TO_INT(tmp
->data
)));
533 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tags_combo
), (gpointer
) name
);
538 prefs_filtering_action_check_widget_width(tags_combo
);
539 gtk_combo_box_set_active(GTK_COMBO_BOX(tags_combo
), 0);
540 gtk_box_pack_start (GTK_BOX (hbox1
), tags_combo
,
543 hbox1
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0);
544 gtk_grid_attach(GTK_GRID(table
), hbox1
, 2, 2, 1, 1);
545 gtk_widget_set_hexpand(hbox1
, TRUE
);
546 gtk_widget_set_halign(hbox1
, GTK_ALIGN_FILL
);
548 dest_btn
= gtk_button_new_with_label (_("Select..."));
549 gtk_box_pack_start (GTK_BOX (hbox1
), dest_btn
, FALSE
, FALSE
, 0);
550 g_signal_connect (G_OBJECT (dest_btn
), "clicked",
551 G_CALLBACK(prefs_filtering_action_select_dest
),
554 #ifndef USE_ALT_ADDRBOOK
555 addressbook_btn
= gtk_button_new_with_label (_("Select..."));
556 gtk_box_pack_start (GTK_BOX (hbox1
), addressbook_btn
, FALSE
, FALSE
, 0);
557 g_signal_connect (G_OBJECT (addressbook_btn
), "clicked",
558 G_CALLBACK(prefs_filtering_action_select_addressbook
),
562 exec_btn
= gtkut_stock_button("dialog-information", _("_Information"));
563 gtk_box_pack_start (GTK_BOX (hbox1
), exec_btn
, FALSE
, FALSE
, 0);
564 g_signal_connect (G_OBJECT (exec_btn
), "clicked",
565 G_CALLBACK(prefs_filtering_action_exec_info
),
568 /* register / substitute / delete */
570 reg_hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 4);
571 gtk_box_pack_start(GTK_BOX(vbox1
), reg_hbox
, FALSE
, FALSE
, 0);
573 arrow
= gtk_image_new_from_icon_name("pan-down-symbolic", GTK_ICON_SIZE_MENU
);
574 gtk_box_pack_start(GTK_BOX(reg_hbox
), arrow
, FALSE
, FALSE
, 0);
575 gtk_widget_set_size_request(arrow
, -1, 16);
577 btn_hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 4);
578 gtk_box_pack_start(GTK_BOX(reg_hbox
), btn_hbox
, FALSE
, FALSE
, 0);
580 reg_btn
= gtkut_stock_button("list-add", _("_Add"));
581 gtk_box_pack_start(GTK_BOX(btn_hbox
), reg_btn
, FALSE
, TRUE
, 0);
582 g_signal_connect(G_OBJECT(reg_btn
), "clicked",
583 G_CALLBACK(prefs_filtering_action_register_cb
), NULL
);
585 subst_btn
= gtkut_get_replace_btn(_("_Replace"));
586 gtk_box_pack_start(GTK_BOX(btn_hbox
), subst_btn
, FALSE
, TRUE
, 0);
587 g_signal_connect(G_OBJECT(subst_btn
), "clicked",
588 G_CALLBACK(prefs_filtering_action_substitute_cb
),
591 del_btn
= gtkut_stock_button("list-remove", _("_Remove"));
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_box_new(GTK_ORIENTATION_HORIZONTAL
, 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_box_new(GTK_ORIENTATION_VERTICAL
, 8);
613 gtk_box_pack_start(GTK_BOX(action_hbox
), btn_vbox
, FALSE
, FALSE
, 0);
615 up_btn
= gtkut_stock_button("go-up", _("_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
= gtkut_stock_button("go-down", _("_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_window_set_default_size(GTK_WINDOW(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_combobox_colormenu_active(
926 GTK_COMBO_BOX(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_COMBO_BOX(widget
))
1300 gtk_combo_box_set_active(GTK_COMBO_BOX(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
;
1498 if (currently_selected
)
1501 if (!gtk_tree_model_get_iter(model
, &iter
, path
))
1504 gtk_tree_model_get(model
, &iter
,
1505 PFA_VALID_ACTION
, &is_valid
,
1509 prefs_filtering_action_reset_dialog();
1513 gtk_tree_model_get(model
, &iter
,
1514 PFA_ACTION
, &action_str
,
1517 action_list
= matcher_parser_get_action_list(action_str
);
1520 if (action_list
== NULL
)
1523 action
= action_list
->data
;
1524 g_slist_free(action_list
);
1526 switch(action
->type
) {
1527 case MATCHACTION_MOVE
:
1528 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1531 case MATCHACTION_COPY
:
1532 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1535 case MATCHACTION_DELETE
:
1536 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1539 case MATCHACTION_MARK
:
1540 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1543 case MATCHACTION_UNMARK
:
1544 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1547 case MATCHACTION_LOCK
:
1548 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1551 case MATCHACTION_UNLOCK
:
1552 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1555 case MATCHACTION_MARK_AS_READ
:
1556 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1557 ACTION_MARK_AS_READ
);
1559 case MATCHACTION_MARK_AS_UNREAD
:
1560 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1561 ACTION_MARK_AS_UNREAD
);
1563 case MATCHACTION_MARK_AS_SPAM
:
1564 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1565 ACTION_MARK_AS_SPAM
);
1567 case MATCHACTION_MARK_AS_HAM
:
1568 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1569 ACTION_MARK_AS_HAM
);
1571 case MATCHACTION_FORWARD
:
1572 list_id
= get_list_id_from_account_id(action
->account_id
);
1573 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1575 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
),
1578 case MATCHACTION_FORWARD_AS_ATTACHMENT
:
1579 list_id
= get_list_id_from_account_id(action
->account_id
);
1580 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1581 ACTION_FORWARD_AS_ATTACHMENT
);
1582 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
),
1585 case MATCHACTION_REDIRECT
:
1586 list_id
= get_list_id_from_account_id(action
->account_id
);
1587 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1589 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action
.account_combo
),
1592 case MATCHACTION_EXECUTE
:
1593 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1596 case MATCHACTION_COLOR
:
1597 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1599 colorlabel_set_combobox_colormenu_active(
1600 GTK_COMBO_BOX(filtering_action
.color_optmenu
),
1601 action
->labelcolor
);
1603 case MATCHACTION_CHANGE_SCORE
:
1604 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1605 ACTION_CHANGE_SCORE
);
1606 gtk_spin_button_set_value(GTK_SPIN_BUTTON(filtering_action
.score_entry
),
1609 case MATCHACTION_SET_SCORE
:
1610 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1612 gtk_spin_button_set_value(GTK_SPIN_BUTTON(filtering_action
.score_entry
),
1615 case MATCHACTION_STOP
:
1616 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1619 case MATCHACTION_HIDE
:
1620 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1623 case MATCHACTION_IGNORE
:
1624 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1627 case MATCHACTION_WATCH
:
1628 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1631 case MATCHACTION_ADD_TO_ADDRESSBOOK
:
1633 gtk_entry_set_text(GTK_ENTRY(filtering_action
.header_entry
), action
->header
);
1635 gtk_entry_set_text(GTK_ENTRY(filtering_action
.header_entry
), "");
1636 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1637 ACTION_ADD_TO_ADDRESSBOOK
);
1639 case MATCHACTION_SET_TAG
:
1640 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1642 combobox_select_by_text(GTK_COMBO_BOX(filtering_action
.tags_combo
),
1643 action
->destination
);
1645 case MATCHACTION_UNSET_TAG
:
1646 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1648 combobox_select_by_text(GTK_COMBO_BOX(filtering_action
.tags_combo
),
1649 action
->destination
);
1651 case MATCHACTION_CLEAR_TAGS
:
1652 combobox_select_by_data(GTK_COMBO_BOX(filtering_action
.action_combo
),
1656 g_warning("unhandled action type");
1658 if (action
->destination
)
1659 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), action
->destination
);
1661 gtk_entry_set_text(GTK_ENTRY(filtering_action
.dest_entry
), "");
1663 filteringaction_free(action
); /* XXX: memleak */