2007-12-06 [colin] 3.1.0cvs62
[claws.git] / src / prefs_filtering_action.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2007 Hiroyuki Yamamoto
4  *
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.
9  *
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.
14  *
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/>.
17  * 
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "defs.h"
25
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <gtk/gtk.h>
29 #include <gdk/gdkkeysyms.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34
35 #include "main.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"
42 #include "inc.h"
43 #include "matcher.h"
44 #include "utils.h"
45 #include "gtkutils.h"
46 #include "alertpanel.h"
47 #include "folder.h"
48 #include "description_window.h"
49 #include "addr_compl.h"
50 #include "tags.h"
51 #include "matcher_parser.h"
52 #include "colorlabel.h"
53 #include "combobox.h"
54
55 enum {
56         PFA_ACTION,
57         PFA_VALID_ACTION,
58         N_PFA_COLUMNS
59 };
60
61
62 static void prefs_filtering_action_create(void);
63 static void prefs_filtering_action_delete_cb(void);
64 static void prefs_filtering_action_substitute_cb(void);
65 static void prefs_filtering_action_register_cb(void);
66 static void prefs_filtering_action_reset_dialog(void);
67 static gboolean prefs_filtering_action_key_pressed(GtkWidget *widget,
68     GdkEventKey *event, gpointer data);
69 static void prefs_filtering_action_cancel(void);
70 static void prefs_filtering_action_ok(void);
71 static gint prefs_filtering_action_deleted(GtkWidget *widget,
72     GdkEventAny *event, gpointer data);
73 static void prefs_filtering_action_type_selection_changed(GtkWidget *widget,
74     gpointer user_data);
75 static void prefs_filtering_action_select_dest(void);
76 static void prefs_filtering_action_select_addressbook(void);
77 static void prefs_filtering_action_up(void);
78 static void prefs_filtering_action_down(void);
79 static void prefs_filtering_action_set_dialog(GSList *action_list);
80 static GSList *prefs_filtering_action_get_list(void);
81
82 static GtkListStore* prefs_filtering_action_create_data_store   (void);
83 static void prefs_filtering_action_list_view_insert_action      (GtkWidget   *list_view,
84                                                                  GtkTreeIter *row,
85                                                                  const gchar *action,
86                                                                  gboolean     is_valid);
87 static GtkWidget *prefs_filtering_action_list_view_create       (void);
88 static void prefs_filtering_action_create_list_view_columns     (GtkTreeView *list_view);
89 static gboolean prefs_filtering_actions_selected                (GtkTreeSelection *selector,
90                                                                  GtkTreeModel *model, 
91                                                                  GtkTreePath *path,
92                                                                  gboolean currently_selected,
93                                                                  gpointer data);
94
95 static void prefs_filtering_action_exec_info(void);
96
97 /*!
98  *\brief        UI data for matcher dialog
99  */
100 static struct FilteringAction_ {
101         GtkWidget *window;
102
103         GtkWidget *ok_btn;
104
105         GtkWidget *action_list_view;
106         GtkWidget *action_combo;
107         GtkWidget *account_label;
108         GtkWidget *account_combo;
109         GtkWidget *dest_entry;
110         GtkWidget *dest_btn;
111         GtkWidget *dest_label;
112         GtkWidget *recip_label;
113         GtkWidget *exec_label;
114         GtkWidget *exec_btn;
115         GtkWidget *color_label;
116         GtkWidget *color_optmenu;
117         GtkWidget *score_label;
118         GtkWidget *header_label;
119         GtkWidget *header_combo;
120         GtkWidget *header_entry;
121         GtkWidget *addressbook_label;
122         GtkWidget *addressbook_btn;
123         GtkWidget *tags_label;
124         GtkWidget *tags_combo;
125
126         gint current_action;
127 } filtering_action;
128
129
130 typedef enum Action_ {
131         ACTION_MOVE,
132         ACTION_COPY,
133         ACTION_DELETE,
134         ACTION_MARK,
135         ACTION_UNMARK,
136         ACTION_LOCK,
137         ACTION_UNLOCK,
138         ACTION_MARK_AS_READ,
139         ACTION_MARK_AS_UNREAD,
140         ACTION_MARK_AS_SPAM,
141         ACTION_MARK_AS_HAM,
142         ACTION_FORWARD,
143         ACTION_FORWARD_AS_ATTACHMENT,
144         ACTION_REDIRECT,
145         ACTION_EXECUTE,
146         ACTION_COLOR,
147         ACTION_CHANGE_SCORE,
148         ACTION_SET_SCORE,
149         ACTION_SET_TAG,
150         ACTION_UNSET_TAG,
151         ACTION_CLEAR_TAGS,
152         ACTION_HIDE,
153         ACTION_IGNORE,
154         ACTION_WATCH,
155         ACTION_ADD_TO_ADDRESSBOOK,
156         ACTION_STOP,
157         /* add other action constants */
158 } Action;
159
160 static struct {
161         gchar *text;
162         Action action;
163 } action_text [] = {
164         { N_("Move"),                   ACTION_MOVE     },      
165         { N_("Copy"),                   ACTION_COPY     },
166         { N_("Delete"),                 ACTION_DELETE   },
167         { N_("Mark"),                   ACTION_MARK     },
168         { N_("Unmark"),                 ACTION_UNMARK   },
169         { N_("Lock"),                   ACTION_LOCK     },
170         { N_("Unlock"),                 ACTION_UNLOCK   },
171         { N_("Mark as read"),           ACTION_MARK_AS_READ },
172         { N_("Mark as unread"),         ACTION_MARK_AS_UNREAD },
173         { N_("Mark as spam"),           ACTION_MARK_AS_SPAM },
174         { N_("Mark as ham"),            ACTION_MARK_AS_HAM },
175         { N_("Forward"),                ACTION_FORWARD  },
176         { N_("Forward as attachment"),  ACTION_FORWARD_AS_ATTACHMENT },
177         { N_("Redirect"),               ACTION_REDIRECT },
178         { N_("Execute"),                ACTION_EXECUTE  },
179         { N_("Color"),                  ACTION_COLOR    },
180         { N_("Change score"),           ACTION_CHANGE_SCORE},
181         { N_("Set score"),              ACTION_SET_SCORE},
182         { N_("Apply tag"),              ACTION_SET_TAG},
183         { N_("Unset tag"),              ACTION_UNSET_TAG},
184         { N_("Clear tags"),             ACTION_CLEAR_TAGS},
185         { N_("Hide"),                   ACTION_HIDE     },
186         { N_("Ignore thread"),          ACTION_IGNORE   },
187         { N_("Watch thread"),           ACTION_WATCH    },
188         { N_("Add to address book"),    ACTION_ADD_TO_ADDRESSBOOK       },
189         { N_("Stop filter"),            ACTION_STOP     },
190 };
191
192
193 /*!
194  *\brief        Hooks
195  */
196 static PrefsFilteringActionSignal *filtering_action_callback;
197
198 /*!
199  *\brief        Opens the filtering action dialog with a list of actions
200  *
201  *\param        matchers List of conditions
202  *\param        cb Callback
203  *
204  */
205 void prefs_filtering_action_open(GSList *action_list,
206     PrefsFilteringActionSignal *cb)
207 {
208         inc_lock();
209
210         if (!filtering_action.window) {
211                 prefs_filtering_action_create();
212         } else {
213                 /* update color label menu */
214                 gtk_option_menu_set_menu(GTK_OPTION_MENU(filtering_action.color_optmenu),
215                                 colorlabel_create_color_menu());
216         }
217
218         manage_window_set_transient(GTK_WINDOW(filtering_action.window));
219         gtk_widget_grab_focus(filtering_action.ok_btn);
220
221         filtering_action_callback = cb;
222
223         prefs_filtering_action_set_dialog(action_list);
224
225         gtk_widget_show(filtering_action.window);
226 }
227
228 /*!
229  *\brief        Save Gtk object size to prefs dataset
230  */
231 static void prefs_filtering_action_size_allocate_cb(GtkWidget *widget,
232                                          GtkAllocation *allocation)
233 {
234         g_return_if_fail(allocation != NULL);
235
236         prefs_common.filteringactionwin_width = allocation->width;
237         prefs_common.filteringactionwin_height = allocation->height;
238 }
239
240 /*!
241  *\brief        Create the matcher dialog
242  */
243 static void prefs_filtering_action_create(void)
244 {
245         GtkWidget *window;
246         GtkWidget *vbox;
247         GtkWidget *ok_btn;
248         GtkWidget *cancel_btn;
249         GtkWidget *confirm_area;
250
251         GtkWidget *vbox1;
252
253         GtkWidget *hbox1;
254
255         GtkWidget *action_label;
256         GtkWidget *recip_label;
257         GtkWidget *action_combo;
258         GtkWidget *dest_label;
259         GtkWidget *exec_label;
260         GtkWidget *score_label;
261         GtkWidget *color_label;
262         GtkWidget *account_label;
263         GtkWidget *account_combo;
264         GtkWidget *header_label;
265         GtkWidget *header_combo;
266         GtkWidget *header_entry;
267         GtkWidget *addressbook_label;
268         GtkWidget *addressbook_btn;
269         GtkWidget *dest_entry;
270         GtkWidget *dest_btn;
271         GtkWidget *tags_label;
272         GtkWidget *tags_combo;
273
274         GtkWidget *reg_hbox;
275         GtkWidget *btn_hbox;
276         GtkWidget *arrow;
277         GtkWidget *reg_btn;
278         GtkWidget *subst_btn;
279         GtkWidget *del_btn;
280
281         GtkWidget *action_hbox;
282         GtkWidget *action_scrolledwin;
283         GtkWidget *action_list_view;
284
285         GtkWidget *btn_vbox;
286         GtkWidget *up_btn;
287         GtkWidget *down_btn;
288
289         GtkWidget *exec_btn;
290
291         GtkWidget *color_optmenu;
292
293         gint i;
294         static GdkGeometry geometry;
295
296         GList * accounts;
297         GSList *tmp, *tags;
298
299         debug_print("Creating matcher configuration window...\n");
300
301         window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "prefs_filtering_action");
302         gtk_container_set_border_width(GTK_CONTAINER(window), 8);
303         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
304         gtk_window_set_modal(GTK_WINDOW(window), TRUE);
305         gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
306
307         vbox = gtk_vbox_new(FALSE, 6);
308         gtk_widget_show(vbox);
309         gtk_container_add(GTK_CONTAINER(window), vbox);
310
311         gtkut_stock_button_set_create(&confirm_area,
312                                       &cancel_btn, GTK_STOCK_CANCEL,
313                                       &ok_btn, GTK_STOCK_OK,
314                                       NULL, NULL);
315         gtk_widget_show(confirm_area);
316         gtk_box_pack_end(GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
317         gtk_widget_grab_default(ok_btn);
318
319         gtk_window_set_title(GTK_WINDOW(window),
320                              _("Filtering action configuration"));
321         g_signal_connect(G_OBJECT(window), "delete_event",
322                          G_CALLBACK(prefs_filtering_action_deleted), NULL);
323         g_signal_connect(G_OBJECT(window), "size_allocate",
324                          G_CALLBACK(prefs_filtering_action_size_allocate_cb), NULL);
325         g_signal_connect(G_OBJECT(window), "key_press_event",
326                          G_CALLBACK(prefs_filtering_action_key_pressed), NULL);
327         MANAGE_WINDOW_SIGNALS_CONNECT(window);
328         g_signal_connect(G_OBJECT(ok_btn), "clicked",
329                          G_CALLBACK(prefs_filtering_action_ok), NULL);
330         g_signal_connect(G_OBJECT(cancel_btn), "clicked",
331                          G_CALLBACK(prefs_filtering_action_cancel), NULL);
332
333         vbox1 = gtk_vbox_new(FALSE, VSPACING);
334         gtk_widget_show(vbox1);
335         gtk_box_pack_start(GTK_BOX(vbox), vbox1, TRUE, TRUE, 0);
336         gtk_container_set_border_width(GTK_CONTAINER (vbox1), 2);
337
338         /* action to be defined */
339
340         hbox1 = gtk_hbox_new (FALSE, VSPACING);
341         gtk_widget_show (hbox1);
342         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
343         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
344
345         action_label = gtk_label_new (_("Action"));
346         gtk_widget_show (action_label);
347         gtk_misc_set_alignment (GTK_MISC (action_label), 0, 0.5);
348         gtk_box_pack_start (GTK_BOX (hbox1), action_label, FALSE, FALSE, 0);
349
350         action_combo = gtk_combo_box_new_text ();
351         gtk_widget_show (action_combo);
352
353         for (i = 0; i < sizeof action_text / sizeof action_text[0]; i++)
354                 gtk_combo_box_append_text(GTK_COMBO_BOX(action_combo),
355                                         (gpointer) _(action_text[i].text));
356         gtk_combo_box_set_active(GTK_COMBO_BOX(action_combo), 0);
357         gtk_box_pack_start (GTK_BOX (hbox1), action_combo,
358                             TRUE, TRUE, 0);
359         g_signal_connect(G_OBJECT(action_combo), "changed",
360                          G_CALLBACK(prefs_filtering_action_type_selection_changed),
361                          NULL);
362
363         /* accounts */
364
365         hbox1 = gtk_hbox_new (FALSE, VSPACING);
366         gtk_widget_show (vbox1);
367         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
368         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
369
370         account_label = gtk_label_new (_("Account"));
371         gtk_widget_show (account_label);
372         gtk_misc_set_alignment (GTK_MISC (account_label), 0, 0.5);
373         gtk_box_pack_start (GTK_BOX (hbox1), account_label, FALSE, FALSE, 0);
374
375         account_combo = gtk_combo_box_new_text ();
376         gtk_widget_set_size_request (account_combo, 150, -1);
377         gtk_widget_show (account_combo);
378
379         for (accounts = account_get_list() ; accounts != NULL;
380              accounts = accounts->next) {
381                 PrefsAccount *ac = (PrefsAccount *)accounts->data;
382                 gchar *name;
383
384                 name = g_strdup_printf("%s <%s> (%s)",
385                                        ac->name, ac->address,
386                                        ac->account_name);
387                 gtk_combo_box_append_text(GTK_COMBO_BOX(account_combo), (gpointer) name);
388                 g_free(name);
389         }
390
391         gtk_combo_box_set_active(GTK_COMBO_BOX(account_combo), 0);
392         gtk_box_pack_start (GTK_BOX (hbox1), account_combo,
393                             TRUE, TRUE, 0);
394
395         /* header */
396
397         header_label = gtk_label_new(_("Header name"));
398         gtk_widget_show(header_label);
399         gtk_misc_set_alignment(GTK_MISC(header_label), 0, 0.5);
400         gtk_box_pack_start (GTK_BOX (hbox1), header_label, FALSE, FALSE, 0);
401
402         header_combo = combobox_text_new(TRUE, "From", "To", "Cc", "Reply-To", "Sender", NULL);
403         gtk_widget_set_size_request(header_combo, 120, -1);
404         gtk_box_pack_start (GTK_BOX (hbox1), header_combo,
405                             TRUE, TRUE, 0);
406         header_entry = GTK_BIN(header_combo)->child;
407
408         /* destination */
409
410         hbox1 = gtk_hbox_new (FALSE, VSPACING);
411         gtk_widget_show (vbox1);
412         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
413         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
414
415         dest_label = gtk_label_new (_("Destination"));
416         gtk_widget_show (dest_label);
417         gtk_misc_set_alignment (GTK_MISC (dest_label), 0, 0.5);
418         gtk_box_pack_start (GTK_BOX (hbox1), dest_label, FALSE, FALSE, 0);
419
420         recip_label = gtk_label_new (_("Recipient"));
421         gtk_widget_show (recip_label);
422         gtk_misc_set_alignment (GTK_MISC (recip_label), 0, 0.5);
423         gtk_box_pack_start (GTK_BOX (hbox1), recip_label, FALSE, FALSE, 0);
424
425         exec_label = gtk_label_new (_("Execute"));
426         gtk_widget_show (exec_label);
427         gtk_misc_set_alignment (GTK_MISC (exec_label), 0, 0.5);
428         gtk_box_pack_start (GTK_BOX (hbox1), exec_label, FALSE, FALSE, 0);
429         
430         color_label = gtk_label_new (_("Color"));
431         gtk_widget_show(color_label);
432         gtk_misc_set_alignment(GTK_MISC(color_label), 0, 0.5);
433         gtk_box_pack_start(GTK_BOX(hbox1), color_label, FALSE, FALSE, 0);
434
435         score_label = gtk_label_new (_("Score"));
436         gtk_widget_show (score_label);
437         gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
438         gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
439
440         addressbook_label = gtk_label_new (_("Book/folder"));
441         gtk_widget_show(addressbook_label);
442         gtk_misc_set_alignment(GTK_MISC(addressbook_label), 0, 0.5);
443         gtk_box_pack_start(GTK_BOX(hbox1), addressbook_label, FALSE, FALSE, 0);
444
445         tags_label = gtk_label_new (_("Tag"));
446         gtk_widget_show (tags_label);
447         gtk_misc_set_alignment (GTK_MISC (tags_label), 0, 0.5);
448         gtk_box_pack_start (GTK_BOX (hbox1), tags_label, FALSE, FALSE, 0);
449
450         dest_entry = gtk_entry_new ();
451         gtk_widget_set_size_request (dest_entry, 150, -1);
452         gtk_widget_show (dest_entry);
453         gtk_box_pack_start (GTK_BOX (hbox1), dest_entry, TRUE, TRUE, 0);
454         
455         color_optmenu = gtk_option_menu_new();
456         gtk_option_menu_set_menu(GTK_OPTION_MENU(color_optmenu),
457                                  colorlabel_create_color_menu());
458         gtk_box_pack_start(GTK_BOX(hbox1), color_optmenu, TRUE, TRUE, 0);
459
460         tags_combo = gtk_combo_box_new_text ();
461         gtk_widget_set_size_request (tags_combo, 150, -1);
462         gtk_widget_show (tags_combo);
463
464         for (tmp = tags = tags_get_list() ; tmp != NULL;
465              tmp = tmp->next) {
466                 gchar *name = g_strdup(tags_get_tag(GPOINTER_TO_INT(tmp->data)));
467
468                 gtk_combo_box_append_text(GTK_COMBO_BOX(tags_combo), (gpointer) name);
469                 g_free(name);
470         }
471
472         gtk_combo_box_set_active(GTK_COMBO_BOX(tags_combo), 0);
473         gtk_box_pack_start (GTK_BOX (hbox1), tags_combo,
474                             TRUE, TRUE, 0);
475
476         dest_btn = gtk_button_new_with_label (_("Select ..."));
477         gtk_widget_show (dest_btn);
478         gtk_box_pack_start (GTK_BOX (hbox1), dest_btn, FALSE, FALSE, 0);
479         g_signal_connect (G_OBJECT (dest_btn), "clicked",
480                           G_CALLBACK(prefs_filtering_action_select_dest),
481                           NULL);
482
483         addressbook_btn = gtk_button_new_with_label (_("Select ..."));
484         gtk_widget_show (addressbook_btn);
485         gtk_box_pack_start (GTK_BOX (hbox1), addressbook_btn, FALSE, FALSE, 0);
486         g_signal_connect (G_OBJECT (addressbook_btn), "clicked",
487                           G_CALLBACK(prefs_filtering_action_select_addressbook),
488                           NULL);
489
490 #if GTK_CHECK_VERSION(2, 8, 0)
491         exec_btn = gtk_button_new_from_stock(GTK_STOCK_INFO);
492 #else
493         exec_btn = gtk_button_new_with_label (_("Info..."));
494 #endif
495         gtk_widget_show (exec_btn);
496         gtk_box_pack_start (GTK_BOX (hbox1), exec_btn, FALSE, FALSE, 0);
497         g_signal_connect (G_OBJECT (exec_btn), "clicked",
498                           G_CALLBACK(prefs_filtering_action_exec_info),
499                           NULL);
500
501         /* register / substitute / delete */
502
503         reg_hbox = gtk_hbox_new(FALSE, 4);
504         gtk_widget_show(reg_hbox);
505         gtk_box_pack_start(GTK_BOX(vbox1), reg_hbox, FALSE, FALSE, 0);
506
507         arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
508         gtk_widget_show(arrow);
509         gtk_box_pack_start(GTK_BOX(reg_hbox), arrow, FALSE, FALSE, 0);
510         gtk_widget_set_size_request(arrow, -1, 16);
511
512         btn_hbox = gtk_hbox_new(TRUE, 4);
513         gtk_widget_show(btn_hbox);
514         gtk_box_pack_start(GTK_BOX(reg_hbox), btn_hbox, FALSE, FALSE, 0);
515
516         reg_btn = gtk_button_new_from_stock(GTK_STOCK_ADD);
517         gtk_widget_show(reg_btn);
518         gtk_box_pack_start(GTK_BOX(btn_hbox), reg_btn, FALSE, TRUE, 0);
519         g_signal_connect(G_OBJECT(reg_btn), "clicked",
520                          G_CALLBACK(prefs_filtering_action_register_cb), NULL);
521
522         subst_btn = gtkut_get_replace_btn(_("Replace"));
523         gtk_widget_show(subst_btn);
524         gtk_box_pack_start(GTK_BOX(btn_hbox), subst_btn, FALSE, TRUE, 0);
525         g_signal_connect(G_OBJECT(subst_btn), "clicked",
526                          G_CALLBACK(prefs_filtering_action_substitute_cb),
527                          NULL);
528
529         del_btn = gtk_button_new_from_stock(GTK_STOCK_DELETE);
530         gtk_widget_show(del_btn);
531         gtk_box_pack_start(GTK_BOX(btn_hbox), del_btn, FALSE, TRUE, 0);
532         g_signal_connect(G_OBJECT(del_btn), "clicked",
533                          G_CALLBACK(prefs_filtering_action_delete_cb), NULL);
534
535         action_hbox = gtk_hbox_new(FALSE, 8);
536         gtk_widget_show(action_hbox);
537         gtk_box_pack_start(GTK_BOX(vbox1), action_hbox, TRUE, TRUE, 0);
538
539         action_scrolledwin = gtk_scrolled_window_new(NULL, NULL);
540         gtk_widget_show(action_scrolledwin);
541         gtk_widget_set_size_request(action_scrolledwin, -1, 150);
542         gtk_box_pack_start(GTK_BOX(action_hbox), action_scrolledwin,
543                            TRUE, TRUE, 0);
544         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(action_scrolledwin),
545                                        GTK_POLICY_AUTOMATIC,
546                                        GTK_POLICY_AUTOMATIC);
547
548         action_list_view = prefs_filtering_action_list_view_create();
549         gtk_widget_show(action_list_view);
550         gtk_container_add(GTK_CONTAINER(action_scrolledwin), action_list_view);
551
552         btn_vbox = gtk_vbox_new(FALSE, 8);
553         gtk_widget_show(btn_vbox);
554         gtk_box_pack_start(GTK_BOX(action_hbox), btn_vbox, FALSE, FALSE, 0);
555
556         up_btn = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
557         gtk_widget_show(up_btn);
558         gtk_box_pack_start(GTK_BOX(btn_vbox), up_btn, FALSE, FALSE, 0);
559         g_signal_connect(G_OBJECT(up_btn), "clicked",
560                          G_CALLBACK(prefs_filtering_action_up), NULL);
561
562         down_btn = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
563         gtk_widget_show(down_btn);
564         gtk_box_pack_start(GTK_BOX(btn_vbox), down_btn, FALSE, FALSE, 0);
565         g_signal_connect(G_OBJECT(down_btn), "clicked",
566                          G_CALLBACK(prefs_filtering_action_down), NULL);
567
568         if (!geometry.min_height) {
569                 geometry.min_width = 490;
570                 geometry.min_height = 328;
571         }
572
573         gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
574                                       GDK_HINT_MIN_SIZE);
575         gtk_widget_set_size_request(window, prefs_common.filteringactionwin_width,
576                                     prefs_common.filteringactionwin_height);
577
578         gtk_widget_show_all(window);
579
580         filtering_action.window    = window;
581         filtering_action.action_combo = action_combo;
582         filtering_action.account_label = account_label;
583         filtering_action.account_combo = account_combo;
584         filtering_action.tags_label = tags_label;
585         filtering_action.tags_combo = tags_combo;
586         filtering_action.dest_entry = dest_entry;
587         filtering_action.dest_btn = dest_btn;
588         filtering_action.dest_label = dest_label;
589         filtering_action.recip_label = recip_label;
590         filtering_action.exec_label = exec_label;
591         filtering_action.exec_btn = exec_btn;
592         filtering_action.color_label   = color_label;
593         filtering_action.color_optmenu = color_optmenu;
594         filtering_action.score_label = score_label;
595         filtering_action.header_label = header_label;
596         filtering_action.header_combo = header_combo;
597         filtering_action.header_entry = header_entry;
598         filtering_action.addressbook_label = addressbook_label;
599         filtering_action.addressbook_btn = addressbook_btn;
600         filtering_action.ok_btn = ok_btn;
601         filtering_action.action_list_view = action_list_view;
602         
603         prefs_filtering_action_type_selection_changed(NULL, NULL);
604 }
605
606 /*!
607  *\brief        Set the contents of a row
608  *
609  *\param        row Index of row to set
610  *\param        prop Condition to set
611  *
612  */
613 static void prefs_filtering_action_list_view_set_row(GtkTreeIter *row, 
614                                                      FilteringAction *action)
615 {
616         gchar buf[256];
617
618         if (row == NULL && action == NULL) {
619                 prefs_filtering_action_list_view_insert_action
620                         (filtering_action.action_list_view,
621                          NULL, _("(New)"), FALSE);
622                 return;
623         }                        
624
625         filteringaction_to_string(buf, sizeof buf, action);
626
627         prefs_filtering_action_list_view_insert_action
628                         (filtering_action.action_list_view,
629                          row, buf, TRUE);
630 }
631
632 /*!
633  *\brief        Initializes dialog with a set of conditions
634  *
635  *\param        matchers List of conditions
636  */
637 static void prefs_filtering_action_set_dialog(GSList *action_list)
638 {
639         GSList *cur;
640
641         gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model
642                         (GTK_TREE_VIEW(filtering_action.action_list_view))));
643
644         prefs_filtering_action_list_view_set_row(NULL, NULL);
645         if (action_list != NULL) {
646                 for (cur = action_list; cur != NULL;
647                      cur = g_slist_next(cur)) {
648                         FilteringAction *action;
649                         action = (FilteringAction *) cur->data;
650                         prefs_filtering_action_list_view_set_row(NULL, action);
651                 }
652         }
653         
654         prefs_filtering_action_reset_dialog();
655 }
656
657 /*!
658  *\brief        Converts current actions in list box in
659  *              an action list used by the filtering system.
660  *
661  *\return       GSList * List of actions.
662  */
663 static GSList *prefs_filtering_action_get_list(void)
664 {
665         gchar *action_str;
666         gboolean is_valid;
667         gint row = 1;
668         GSList *action_list;
669         GtkTreeView *list_view = GTK_TREE_VIEW(filtering_action.action_list_view);
670         GtkTreeModel *model = gtk_tree_view_get_model(list_view);
671         GtkTreeIter iter;
672
673         action_list = NULL;
674
675         while (gtk_tree_model_iter_nth_child(model, &iter, NULL, row)) {
676
677                 gtk_tree_model_get(model, &iter, 
678                                    PFA_ACTION, &action_str,
679                                    PFA_VALID_ACTION, &is_valid,
680                                    -1);
681
682                 if (is_valid) {                            
683                         GSList * tmp_action_list;
684                         tmp_action_list = matcher_parser_get_action_list(action_str);
685                         
686                         if (tmp_action_list == NULL) {
687                                 g_free(action_str);
688                                 break;
689                         }                               
690
691                         action_list = g_slist_concat(action_list,
692                             tmp_action_list);
693                 }
694
695                 g_free(action_str);
696                 action_str = NULL;
697                 row ++;
698                 
699         }
700
701         return action_list;
702 }
703
704 /*!
705  *\brief        Returns account ID from the given list index
706  *
707  *\return       gint account ID
708  */
709 static gint get_account_id_from_list_id(gint list_id)
710 {
711         GList * accounts;
712
713         for (accounts = account_get_list() ; accounts != NULL;
714              accounts = accounts->next) {
715                 PrefsAccount *ac = (PrefsAccount *)accounts->data;
716
717                 if (list_id == 0)
718                         return ac->account_id;
719                 list_id--;
720         }
721         return 0;
722 }
723
724 /*!
725  *\brief        Returns list index from the given account ID
726  *
727  *\return       gint list index
728  */
729 static gint get_list_id_from_account_id(gint account_id)
730 {
731         GList * accounts;
732         gint list_id = 0;
733
734         for (accounts = account_get_list() ; accounts != NULL;
735              accounts = accounts->next) {
736                 PrefsAccount *ac = (PrefsAccount *)accounts->data;
737
738                 if (account_id == ac->account_id)
739                         return list_id;
740                 list_id++;
741         }
742         return 0;
743 }
744
745
746 /*!
747  *\brief        Returns parser action ID from internal action ID
748  *
749  *\return       gint parser action ID
750  */
751 static gint prefs_filtering_action_get_matching_from_action(Action action_id)
752 {
753         switch (action_id) {
754         case ACTION_MOVE:
755                 return MATCHACTION_MOVE;
756         case ACTION_SET_TAG:
757                 return MATCHACTION_SET_TAG;
758         case ACTION_UNSET_TAG:
759                 return MATCHACTION_UNSET_TAG;
760         case ACTION_CLEAR_TAGS:
761                 return MATCHACTION_CLEAR_TAGS;
762         case ACTION_COPY:
763                 return MATCHACTION_COPY;
764         case ACTION_DELETE:
765                 return MATCHACTION_DELETE;
766         case ACTION_MARK:
767                 return MATCHACTION_MARK;
768         case ACTION_UNMARK:
769                 return MATCHACTION_UNMARK;
770         case ACTION_LOCK:
771                 return MATCHACTION_LOCK;
772         case ACTION_UNLOCK:
773                 return MATCHACTION_UNLOCK;
774         case ACTION_MARK_AS_READ:
775                 return MATCHACTION_MARK_AS_READ;
776         case ACTION_MARK_AS_UNREAD:
777                 return MATCHACTION_MARK_AS_UNREAD;
778         case ACTION_MARK_AS_SPAM:
779                 return MATCHACTION_MARK_AS_SPAM;
780         case ACTION_MARK_AS_HAM:
781                 return MATCHACTION_MARK_AS_HAM;
782         case ACTION_FORWARD:
783                 return MATCHACTION_FORWARD;
784         case ACTION_FORWARD_AS_ATTACHMENT:
785                 return MATCHACTION_FORWARD_AS_ATTACHMENT;
786         case ACTION_REDIRECT:
787                 return MATCHACTION_REDIRECT;
788         case ACTION_EXECUTE:
789                 return MATCHACTION_EXECUTE;
790         case ACTION_COLOR:
791                 return MATCHACTION_COLOR;
792         case ACTION_HIDE:
793                 return MATCHACTION_HIDE;
794         case ACTION_IGNORE:
795                 return MATCHACTION_IGNORE;
796         case ACTION_WATCH:
797                 return MATCHACTION_WATCH;
798         case ACTION_STOP:
799                 return MATCHACTION_STOP;
800         case ACTION_CHANGE_SCORE:
801                 return MATCHACTION_CHANGE_SCORE;
802         case ACTION_SET_SCORE:
803                 return MATCHACTION_SET_SCORE;
804         case ACTION_ADD_TO_ADDRESSBOOK:
805                 return MATCHACTION_ADD_TO_ADDRESSBOOK;
806         default:
807                 return -1;
808         }
809 }
810
811 /*!
812  *\brief        Returns action from the content of the dialog
813  *
814  *\param        alert specifies whether alert dialog boxes should be shown
815  *                or not.
816  *
817  *\return       FilteringAction * action entered in the dialog box.
818  */
819 static FilteringAction * prefs_filtering_action_dialog_to_action(gboolean alert)
820 {
821         Action action_id;
822         gint action_type;
823         gint list_id;
824         gint account_id;
825         gchar * destination = NULL;
826         gint labelcolor = 0;
827         FilteringAction * action;
828         gchar * score_str = NULL;
829         gint score;
830         gchar * header = NULL;
831         
832         action_id = gtk_combo_box_get_active(GTK_COMBO_BOX(filtering_action.action_combo));
833         action_type = prefs_filtering_action_get_matching_from_action(action_id);
834         list_id = gtk_combo_box_get_active(GTK_COMBO_BOX(filtering_action.account_combo));
835         account_id = get_account_id_from_list_id(list_id);
836         score = 0;
837         destination = NULL;
838         
839         switch (action_id) {
840         case ACTION_MOVE:
841         case ACTION_COPY:
842         case ACTION_EXECUTE:
843                 destination = gtk_editable_get_chars(GTK_EDITABLE(filtering_action.dest_entry), 0, -1);
844                 if (*destination == '\0') {
845                         if (alert)
846                                 alertpanel_error(action_id == ACTION_EXECUTE 
847                                                  ? _("Command line not set")
848                                                  : _("Destination is not set."));
849                         g_free(destination);
850                         return NULL;
851                 }
852                 break;
853         case ACTION_FORWARD:
854         case ACTION_FORWARD_AS_ATTACHMENT:
855         case ACTION_REDIRECT:
856                 destination = gtk_editable_get_chars(GTK_EDITABLE(filtering_action.dest_entry), 0, -1);
857                 if (*destination == '\0') {
858                         if (alert)
859                                 alertpanel_error(_("Recipient is not set."));
860                         g_free(destination);
861                         return NULL;
862                 }
863                 break;
864         case ACTION_COLOR:
865                 labelcolor = colorlabel_get_color_menu_active_item(
866                         gtk_option_menu_get_menu(GTK_OPTION_MENU(filtering_action.color_optmenu)));
867                 destination = NULL;     
868                 break;
869         case ACTION_CHANGE_SCORE:
870         case ACTION_SET_SCORE:
871                 score_str = gtk_editable_get_chars(GTK_EDITABLE(filtering_action.dest_entry), 0, -1);
872                 if (*score_str == '\0') {
873                         if (alert)
874                                 alertpanel_error(_("Score is not set"));
875                         g_free(score_str);
876                         return NULL;
877                 }
878                 score = strtol(score_str, NULL, 10);
879                 break;
880         case ACTION_ADD_TO_ADDRESSBOOK:
881                 header = gtk_editable_get_chars(GTK_EDITABLE(filtering_action.header_entry), 0, -1);
882                 if (*header == '\0') {
883                         if (alert)
884                                 alertpanel_error(_("Header is not set."));
885                         g_free(header);
886                         return NULL;
887                 }
888                 destination = gtk_editable_get_chars(GTK_EDITABLE(filtering_action.dest_entry), 0, -1);
889                 if (*destination == '\0') {
890                         if (alert)
891                                 alertpanel_error(_("Target addressbook/folder is not set."));
892                         g_free(destination);
893                         return NULL;
894                 }
895                 break;
896         case ACTION_SET_TAG:
897         case ACTION_UNSET_TAG:
898                 destination = gtk_combo_box_get_active_text(GTK_COMBO_BOX(filtering_action.tags_combo));
899                 if (!destination || *destination == '\0') {
900                         if (alert)
901                                 alertpanel_error(_("Tag name is empty."));
902                         g_free(destination);
903                         return NULL;
904                 }
905                 break;
906         case ACTION_STOP:
907         case ACTION_HIDE:
908         case ACTION_IGNORE:
909         case ACTION_WATCH:
910         case ACTION_DELETE:
911         case ACTION_MARK:
912         case ACTION_UNMARK:
913         case ACTION_LOCK:
914         case ACTION_UNLOCK:
915         case ACTION_MARK_AS_READ:
916         case ACTION_MARK_AS_UNREAD:
917         case ACTION_MARK_AS_SPAM:
918         case ACTION_MARK_AS_HAM:
919         case ACTION_CLEAR_TAGS:
920         default:
921                 break;
922         }
923         action = filteringaction_new(action_type, account_id,
924             destination, labelcolor, score, header);
925         
926         g_free(destination);
927         g_free(score_str);
928         return action;
929 }
930
931 /*!
932  *\brief        Signal handler for register button
933  */
934 static void prefs_filtering_action_register_cb(void)
935 {
936         FilteringAction *action;
937         
938         action = prefs_filtering_action_dialog_to_action(TRUE);
939         if (action == NULL)
940                 return;
941
942         prefs_filtering_action_list_view_set_row(NULL, action);
943
944         filteringaction_free(action);
945         /* GTK 1 NOTE:
946          * (presumably gtk_list_select_item(), called by 
947          * prefs_filtering_action_reset_dialog() activates 
948          * what seems to be a bug. this causes any other 
949          * list items to be unselectable)
950          * prefs_filtering_action_reset_dialog(); */
951         gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.account_combo), 0);
952         gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.tags_combo), 0);
953         gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), "");
954 }
955
956 /*!
957  *\brief        Signal handler for substitute button
958  */
959 static void prefs_filtering_action_substitute_cb(void)
960 {
961         GtkTreeView *list_view = GTK_TREE_VIEW
962                         (filtering_action.action_list_view);
963         GtkTreeSelection *selection = gtk_tree_view_get_selection(list_view);
964         GtkTreeModel *model;
965         gboolean is_valid;
966         GtkTreeIter row;
967         FilteringAction *action;
968
969         if (!gtk_tree_selection_get_selected(selection, &model, &row))
970                 return;
971
972         gtk_tree_model_get(model, &row, PFA_VALID_ACTION, &is_valid, -1);
973         if (!is_valid)
974                 return;
975
976         action = prefs_filtering_action_dialog_to_action(TRUE);
977         if (action == NULL)
978                 return;
979
980         prefs_filtering_action_list_view_set_row(&row, action);
981
982         filteringaction_free(action);
983
984         prefs_filtering_action_reset_dialog();
985 }
986
987 /*!
988  *\brief        Signal handler for delete button
989  */
990 static void prefs_filtering_action_delete_cb(void)
991 {
992         GtkTreeView *list_view = GTK_TREE_VIEW
993                         (filtering_action.action_list_view);
994         GtkTreeSelection *selection = gtk_tree_view_get_selection(list_view);
995         GtkTreeModel *model;
996         gboolean is_valid;
997         GtkTreeIter row;
998
999         if (!gtk_tree_selection_get_selected(selection, &model, &row))
1000                 return;
1001
1002         gtk_tree_model_get(model, &row, PFA_VALID_ACTION, &is_valid, -1);
1003         if (!is_valid)
1004                 return;
1005
1006         gtk_list_store_remove(GTK_LIST_STORE(model), &row);             
1007
1008         prefs_filtering_action_reset_dialog();
1009 }
1010
1011 /*!
1012  *\brief        Signal handler for 'move up' button
1013  */
1014 static void prefs_filtering_action_up(void)
1015 {
1016         GtkTreePath *prev, *sel, *try;
1017         GtkTreeIter isel;
1018         GtkListStore *store = NULL;
1019         GtkTreeModel *model = NULL;
1020         GtkTreeIter iprev;
1021         
1022         if (!gtk_tree_selection_get_selected
1023                 (gtk_tree_view_get_selection
1024                         (GTK_TREE_VIEW(filtering_action.action_list_view)),
1025                  &model,        
1026                  &isel))
1027                 return;
1028         store = (GtkListStore *)model;
1029         sel = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &isel);
1030         if (!sel)
1031                 return;
1032         
1033         /* no move if we're at row 0 or 1, looks phony, but other
1034          * solutions are more convoluted... */
1035         try = gtk_tree_path_copy(sel);
1036         if (!gtk_tree_path_prev(try) || !gtk_tree_path_prev(try)) {
1037                 gtk_tree_path_free(try);
1038                 gtk_tree_path_free(sel);
1039                 return;
1040         }
1041         gtk_tree_path_free(try);
1042
1043         prev = gtk_tree_path_copy(sel);         
1044         if (gtk_tree_path_prev(prev)) {
1045                 gtk_tree_model_get_iter(GTK_TREE_MODEL(store),
1046                                         &iprev, prev);
1047                 gtk_list_store_swap(store, &iprev, &isel);
1048                 /* XXX: GTK2 select row?? */
1049         }
1050
1051         gtk_tree_path_free(sel);
1052         gtk_tree_path_free(prev);
1053 }
1054
1055 /*!
1056  *\brief        Signal handler for 'move down' button
1057  */
1058 static void prefs_filtering_action_down(void)
1059 {
1060         GtkListStore *store = NULL;
1061         GtkTreeModel *model = NULL;
1062         GtkTreeIter next, sel;
1063         GtkTreePath *try;
1064         
1065         if (!gtk_tree_selection_get_selected
1066                 (gtk_tree_view_get_selection
1067                         (GTK_TREE_VIEW(filtering_action.action_list_view)),
1068                  &model,
1069                  &sel))
1070                 return;
1071         store = (GtkListStore *)model;
1072         try = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &sel);
1073         if (!try) 
1074                 return;
1075         
1076         /* move when not at row 0 ... */
1077         if (gtk_tree_path_prev(try)) {
1078                 next = sel;
1079                 if (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &next))
1080                         gtk_list_store_swap(store, &next, &sel);
1081         }
1082                 
1083         gtk_tree_path_free(try);
1084 }
1085
1086 /*!
1087  *\brief        Handle key press
1088  *
1089  *\param        widget Widget receiving key press
1090  *\param        event Key event
1091  *\param        data User data
1092  */
1093 static gboolean prefs_filtering_action_key_pressed(GtkWidget *widget,
1094     GdkEventKey *event, gpointer data)
1095 {
1096         if (event && event->keyval == GDK_Escape) {
1097                 prefs_filtering_action_cancel();
1098                 return TRUE;            
1099         }
1100         return FALSE;
1101 }
1102
1103 /*!
1104  *\brief        Cancel matcher dialog
1105  */
1106 static void prefs_filtering_action_cancel(void)
1107 {
1108         gtk_widget_destroy(filtering_action.window);
1109         filtering_action.window = NULL;
1110         inc_unlock();
1111 }
1112
1113 /*!
1114  *\brief        Accept current matchers
1115  */
1116 static void prefs_filtering_action_ok(void)
1117 {
1118         GSList * action_list;
1119         GSList * cur;
1120
1121         action_list = prefs_filtering_action_get_list();
1122
1123         if (action_list == NULL) {
1124                 alertpanel_error(_("No action was defined."));
1125                 return;
1126         }
1127
1128         if (filtering_action_callback != NULL)
1129                 filtering_action_callback(action_list);
1130         for(cur = action_list ; cur != NULL ; cur = cur->next) {
1131                 filteringaction_free(cur->data);
1132         }
1133         g_slist_free(action_list);
1134
1135         gtk_widget_destroy(filtering_action.window);
1136         filtering_action.window = NULL;
1137         inc_unlock();
1138 }
1139
1140 /*!
1141  *\brief        Called when closing dialog box
1142  *
1143  *\param        widget Dialog widget
1144  *\param        event Event info
1145  *\param        data User data
1146  *
1147  *\return       gint TRUE
1148  */
1149 static gint prefs_filtering_action_deleted(GtkWidget *widget,
1150     GdkEventAny *event, gpointer data)
1151 {
1152         prefs_filtering_action_cancel();
1153         return TRUE;
1154 }
1155
1156 /*
1157  * Strings describing exec format strings
1158  * 
1159  * When adding new lines, remember to put 2 strings for each line
1160  */
1161 static gchar *exec_desc_strings[] = {
1162         "%%",   N_("literal %"),
1163         "%s",   N_("Subject"),
1164         "%f",   N_("From"),
1165         "%t",   N_("To"),
1166         "%c",   N_("Cc"),
1167         "%d",   N_("Date"),
1168         "%i",   N_("Message-ID"),
1169         "%n",   N_("Newsgroups"),
1170         "%r",   N_("References"),
1171         "%F",   N_("filename (should not be modified)"),
1172         "\\n",  N_("new line"),
1173         "\\",   N_("escape character for quotes"),
1174         "\\\"", N_("quote character"),
1175         NULL, NULL
1176 };
1177
1178 static DescriptionWindow exec_desc_win = { 
1179         NULL,
1180         NULL, 
1181         2,
1182         N_("Filtering Action: 'Execute'"),
1183         N_("'Execute' allows you to send a message or message element "
1184            "to an external program or script.\n"
1185            "The following symbols can be used:"),
1186        exec_desc_strings
1187 };
1188
1189 /*!
1190  *\brief        Show Execute action's info
1191  */
1192 static void prefs_filtering_action_exec_info(void)
1193 {
1194         description_window_create(&exec_desc_win);
1195 }
1196
1197 static void prefs_filtering_action_select_dest(void)
1198 {
1199         FolderItem *dest;
1200         gchar * path;
1201
1202         dest = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL);
1203         if (!dest) return;
1204
1205         path = folder_item_get_identifier(dest);
1206
1207         gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), path);
1208         g_free(path);
1209 }
1210
1211 static void prefs_filtering_action_select_addressbook(void)
1212 {
1213         const gchar *folderpath = NULL;
1214         gchar *new_path = NULL;
1215
1216         folderpath = gtk_entry_get_text(GTK_ENTRY(filtering_action.dest_entry));
1217         new_path = addressbook_folder_selection(folderpath);
1218         if (new_path) {
1219                 gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), new_path);
1220                 g_free(new_path);
1221         } 
1222 }
1223
1224 static void prefs_filtering_action_type_selection_changed(GtkWidget *combo,
1225                                                           gpointer user_data)
1226 {
1227         gint value;
1228
1229         value = gtk_combo_box_get_active(GTK_COMBO_BOX(filtering_action.action_combo));
1230
1231         if (filtering_action.current_action != value) {
1232                 if (filtering_action.current_action == ACTION_FORWARD 
1233                 ||  filtering_action.current_action == ACTION_FORWARD_AS_ATTACHMENT
1234                 ||  filtering_action.current_action == ACTION_REDIRECT) {
1235                         debug_print("unregistering address completion entry\n");
1236                         address_completion_unregister_entry(GTK_ENTRY(filtering_action.dest_entry));
1237                         address_completion_end(filtering_action.window);
1238                 }
1239                 if (value == ACTION_FORWARD || value == ACTION_FORWARD_AS_ATTACHMENT
1240                 ||  value == ACTION_REDIRECT) {
1241                         debug_print("registering address completion entry\n");
1242                         address_completion_start(filtering_action.window);
1243                         address_completion_register_entry(
1244                                         GTK_ENTRY(filtering_action.dest_entry),
1245                                         TRUE);
1246                 }
1247                 filtering_action.current_action = value;
1248         }
1249
1250         switch (value) {
1251         case ACTION_MOVE:
1252                 gtk_widget_show(filtering_action.account_label);
1253                 gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
1254                 gtk_widget_show(filtering_action.account_combo);
1255                 gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
1256                 gtk_widget_hide(filtering_action.tags_label);
1257                 gtk_widget_set_sensitive(filtering_action.tags_label, FALSE);
1258                 gtk_widget_hide(filtering_action.tags_combo);
1259                 gtk_widget_set_sensitive(filtering_action.tags_combo, FALSE);
1260                 gtk_widget_show(filtering_action.dest_entry);
1261                 gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
1262                 gtk_widget_show(filtering_action.dest_btn);
1263                 gtk_widget_set_sensitive(filtering_action.dest_btn, TRUE);
1264                 gtk_widget_show(filtering_action.dest_label);
1265                 gtk_widget_set_sensitive(filtering_action.dest_label, TRUE);
1266                 gtk_widget_hide(filtering_action.recip_label);
1267                 gtk_widget_hide(filtering_action.exec_label);
1268                 gtk_widget_hide(filtering_action.exec_btn);
1269                 gtk_widget_hide(filtering_action.color_optmenu);
1270                 gtk_widget_hide(filtering_action.color_label);
1271                 gtk_widget_hide(filtering_action.score_label);
1272                 gtk_widget_hide(filtering_action.addressbook_label);
1273                 gtk_widget_hide(filtering_action.header_label);
1274                 gtk_widget_hide(filtering_action.header_combo);
1275                 gtk_widget_hide(filtering_action.header_entry);
1276                 gtk_widget_set_sensitive(filtering_action.header_entry, FALSE);
1277                 gtk_widget_hide(filtering_action.addressbook_btn);
1278                 gtk_widget_set_sensitive(filtering_action.addressbook_btn, FALSE);
1279                 break;
1280         case ACTION_COPY:
1281                 gtk_widget_show(filtering_action.account_label);
1282                 gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
1283                 gtk_widget_show(filtering_action.account_combo);
1284                 gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
1285                 gtk_widget_hide(filtering_action.tags_label);
1286                 gtk_widget_set_sensitive(filtering_action.tags_label, FALSE);
1287                 gtk_widget_hide(filtering_action.tags_combo);
1288                 gtk_widget_set_sensitive(filtering_action.tags_combo, FALSE);
1289                 gtk_widget_show(filtering_action.dest_entry);
1290                 gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
1291                 gtk_widget_show(filtering_action.dest_btn);
1292                 gtk_widget_set_sensitive(filtering_action.dest_btn, TRUE);
1293                 gtk_widget_show(filtering_action.dest_label);
1294                 gtk_widget_set_sensitive(filtering_action.dest_label, TRUE);
1295                 gtk_widget_hide(filtering_action.recip_label);
1296                 gtk_widget_hide(filtering_action.exec_label);
1297                 gtk_widget_hide(filtering_action.exec_btn);
1298                 gtk_widget_hide(filtering_action.color_optmenu);
1299                 gtk_widget_hide(filtering_action.color_label);
1300                 gtk_widget_hide(filtering_action.score_label);
1301                 gtk_widget_hide(filtering_action.header_label);
1302                 gtk_widget_hide(filtering_action.header_combo);
1303                 gtk_widget_hide(filtering_action.header_entry);
1304                 gtk_widget_set_sensitive(filtering_action.header_entry, FALSE);
1305                 gtk_widget_hide(filtering_action.addressbook_label);
1306                 gtk_widget_hide(filtering_action.addressbook_btn);
1307                 gtk_widget_set_sensitive(filtering_action.addressbook_btn, FALSE);
1308                 break;
1309         case ACTION_DELETE:
1310                 gtk_widget_show(filtering_action.account_label);
1311                 gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
1312                 gtk_widget_show(filtering_action.account_combo);
1313                 gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
1314                 gtk_widget_hide(filtering_action.tags_label);
1315                 gtk_widget_set_sensitive(filtering_action.tags_label, FALSE);
1316                 gtk_widget_hide(filtering_action.tags_combo);
1317                 gtk_widget_set_sensitive(filtering_action.tags_combo, FALSE);
1318                 gtk_widget_show(filtering_action.dest_entry);
1319                 gtk_widget_set_sensitive(filtering_action.dest_entry, FALSE);
1320                 gtk_widget_show(filtering_action.dest_btn);
1321                 gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE);
1322                 gtk_widget_show(filtering_action.dest_label);
1323                 gtk_widget_set_sensitive(filtering_action.dest_label, FALSE);
1324                 gtk_widget_hide(filtering_action.recip_label);
1325                 gtk_widget_hide(filtering_action.exec_label);
1326                 gtk_widget_hide(filtering_action.exec_btn);
1327                 gtk_widget_hide(filtering_action.color_optmenu);
1328                 gtk_widget_hide(filtering_action.color_label);
1329                 gtk_widget_hide(filtering_action.score_label);
1330                 gtk_widget_hide(filtering_action.header_label);
1331                 gtk_widget_hide(filtering_action.header_combo);
1332                 gtk_widget_hide(filtering_action.header_entry);
1333                 gtk_widget_set_sensitive(filtering_action.header_entry, FALSE);
1334                 gtk_widget_hide(filtering_action.addressbook_label);
1335                 gtk_widget_hide(filtering_action.addressbook_btn);
1336                 gtk_widget_set_sensitive(filtering_action.addressbook_btn, FALSE);
1337                 break;
1338         case ACTION_MARK:
1339         case ACTION_UNMARK:
1340         case ACTION_LOCK:
1341         case ACTION_UNLOCK:
1342         case ACTION_MARK_AS_READ:
1343         case ACTION_MARK_AS_UNREAD:
1344         case ACTION_MARK_AS_SPAM:
1345         case ACTION_MARK_AS_HAM:
1346         case ACTION_STOP:
1347         case ACTION_HIDE:
1348         case ACTION_IGNORE:
1349         case ACTION_WATCH:
1350         case ACTION_CLEAR_TAGS:
1351                 gtk_widget_show(filtering_action.account_label);
1352                 gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
1353                 gtk_widget_show(filtering_action.account_combo);
1354                 gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
1355                 gtk_widget_hide(filtering_action.tags_label);
1356                 gtk_widget_set_sensitive(filtering_action.tags_label, FALSE);
1357                 gtk_widget_hide(filtering_action.tags_combo);
1358                 gtk_widget_set_sensitive(filtering_action.tags_combo, FALSE);
1359                 gtk_widget_show(filtering_action.dest_entry);
1360                 gtk_widget_set_sensitive(filtering_action.dest_entry, FALSE);
1361                 gtk_widget_show(filtering_action.dest_btn);
1362                 gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE);
1363                 gtk_widget_show(filtering_action.dest_label);
1364                 gtk_widget_set_sensitive(filtering_action.dest_label, FALSE);
1365                 gtk_widget_hide(filtering_action.recip_label);
1366                 gtk_widget_hide(filtering_action.exec_label);
1367                 gtk_widget_hide(filtering_action.exec_btn);
1368                 gtk_widget_hide(filtering_action.color_optmenu);
1369                 gtk_widget_hide(filtering_action.color_label);
1370                 gtk_widget_hide(filtering_action.score_label);
1371                 gtk_widget_hide(filtering_action.header_label);
1372                 gtk_widget_hide(filtering_action.header_combo);
1373                 gtk_widget_hide(filtering_action.header_entry);
1374                 gtk_widget_set_sensitive(filtering_action.header_entry, FALSE);
1375                 gtk_widget_hide(filtering_action.addressbook_label);
1376                 gtk_widget_hide(filtering_action.addressbook_btn);
1377                 gtk_widget_set_sensitive(filtering_action.addressbook_btn, FALSE);
1378                 break;
1379         case ACTION_FORWARD:
1380                 gtk_widget_show(filtering_action.account_label);
1381                 gtk_widget_set_sensitive(filtering_action.account_label, TRUE);
1382                 gtk_widget_show(filtering_action.account_combo);
1383                 gtk_widget_set_sensitive(filtering_action.account_combo, TRUE);
1384                 gtk_widget_hide(filtering_action.tags_label);
1385                 gtk_widget_set_sensitive(filtering_action.tags_label, FALSE);
1386                 gtk_widget_hide(filtering_action.tags_combo);
1387                 gtk_widget_set_sensitive(filtering_action.tags_combo, FALSE);
1388                 gtk_widget_show(filtering_action.dest_entry);
1389                 gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
1390                 gtk_widget_show(filtering_action.dest_btn);
1391                 gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE);
1392                 gtk_widget_hide(filtering_action.dest_label);
1393                 gtk_widget_show(filtering_action.recip_label);
1394                 gtk_widget_set_sensitive(filtering_action.recip_label, TRUE);
1395                 gtk_widget_hide(filtering_action.exec_label);
1396                 gtk_widget_hide(filtering_action.exec_btn);
1397                 gtk_widget_hide(filtering_action.color_optmenu);
1398                 gtk_widget_hide(filtering_action.color_label);
1399                 gtk_widget_hide(filtering_action.score_label);
1400                 gtk_widget_hide(filtering_action.header_label);
1401                 gtk_widget_hide(filtering_action.header_combo);
1402                 gtk_widget_hide(filtering_action.header_entry);
1403                 gtk_widget_set_sensitive(filtering_action.header_entry, FALSE);
1404                 gtk_widget_hide(filtering_action.addressbook_label);
1405                 gtk_widget_hide(filtering_action.addressbook_btn);
1406                 gtk_widget_set_sensitive(filtering_action.addressbook_btn, FALSE);
1407                 break;
1408         case ACTION_FORWARD_AS_ATTACHMENT:
1409                 gtk_widget_show(filtering_action.account_label);
1410                 gtk_widget_set_sensitive(filtering_action.account_label, TRUE);
1411                 gtk_widget_show(filtering_action.account_combo);
1412                 gtk_widget_set_sensitive(filtering_action.account_combo, TRUE);
1413                 gtk_widget_hide(filtering_action.tags_label);
1414                 gtk_widget_set_sensitive(filtering_action.tags_label, FALSE);
1415                 gtk_widget_hide(filtering_action.tags_combo);
1416                 gtk_widget_set_sensitive(filtering_action.tags_combo, FALSE);
1417                 gtk_widget_show(filtering_action.dest_entry);
1418                 gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
1419                 gtk_widget_show(filtering_action.dest_btn);
1420                 gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE);
1421                 gtk_widget_hide(filtering_action.dest_label);
1422                 gtk_widget_show(filtering_action.recip_label);
1423                 gtk_widget_set_sensitive(filtering_action.recip_label, TRUE);
1424                 gtk_widget_hide(filtering_action.exec_label);
1425                 gtk_widget_hide(filtering_action.exec_btn);
1426                 gtk_widget_hide(filtering_action.color_optmenu);
1427                 gtk_widget_hide(filtering_action.color_label);
1428                 gtk_widget_hide(filtering_action.score_label);
1429                 gtk_widget_hide(filtering_action.header_label);
1430                 gtk_widget_hide(filtering_action.header_entry);
1431                 gtk_widget_hide(filtering_action.header_combo);
1432                 gtk_widget_set_sensitive(filtering_action.header_entry, FALSE);
1433                 gtk_widget_hide(filtering_action.addressbook_label);
1434                 gtk_widget_hide(filtering_action.addressbook_btn);
1435                 gtk_widget_set_sensitive(filtering_action.addressbook_btn, FALSE);
1436                 break;
1437         case ACTION_REDIRECT:
1438                 gtk_widget_show(filtering_action.account_label);
1439                 gtk_widget_set_sensitive(filtering_action.account_label, TRUE);
1440                 gtk_widget_show(filtering_action.account_combo);
1441                 gtk_widget_set_sensitive(filtering_action.account_combo, TRUE);
1442                 gtk_widget_hide(filtering_action.tags_label);
1443                 gtk_widget_set_sensitive(filtering_action.tags_label, FALSE);
1444                 gtk_widget_hide(filtering_action.tags_combo);
1445                 gtk_widget_set_sensitive(filtering_action.tags_combo, FALSE);
1446                 gtk_widget_show(filtering_action.dest_entry);
1447                 gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
1448                 gtk_widget_show(filtering_action.dest_btn);
1449                 gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE);
1450                 gtk_widget_hide(filtering_action.dest_label);
1451                 gtk_widget_show(filtering_action.recip_label);
1452                 gtk_widget_set_sensitive(filtering_action.recip_label, TRUE);
1453                 gtk_widget_hide(filtering_action.exec_label);
1454                 gtk_widget_hide(filtering_action.exec_btn);
1455                 gtk_widget_hide(filtering_action.color_optmenu);
1456                 gtk_widget_hide(filtering_action.color_label);
1457                 gtk_widget_hide(filtering_action.score_label);
1458                 gtk_widget_hide(filtering_action.header_label);
1459                 gtk_widget_hide(filtering_action.header_combo);
1460                 gtk_widget_hide(filtering_action.header_entry);
1461                 gtk_widget_set_sensitive(filtering_action.header_entry, FALSE);
1462                 gtk_widget_hide(filtering_action.addressbook_label);
1463                 gtk_widget_hide(filtering_action.addressbook_btn);
1464                 gtk_widget_set_sensitive(filtering_action.addressbook_btn, FALSE);
1465                 break;
1466         case ACTION_EXECUTE:
1467                 gtk_widget_show(filtering_action.account_label);
1468                 gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
1469                 gtk_widget_show(filtering_action.account_combo);
1470                 gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
1471                 gtk_widget_hide(filtering_action.tags_label);
1472                 gtk_widget_set_sensitive(filtering_action.tags_label, FALSE);
1473                 gtk_widget_hide(filtering_action.tags_combo);
1474                 gtk_widget_set_sensitive(filtering_action.tags_combo, FALSE);
1475                 gtk_widget_show(filtering_action.dest_entry);
1476                 gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
1477                 gtk_widget_hide(filtering_action.dest_btn);
1478                 gtk_widget_hide(filtering_action.dest_label);
1479                 gtk_widget_hide(filtering_action.recip_label);
1480                 gtk_widget_show(filtering_action.exec_label);
1481                 gtk_widget_set_sensitive(filtering_action.exec_btn, TRUE);
1482                 gtk_widget_show(filtering_action.exec_btn);
1483                 gtk_widget_hide(filtering_action.color_optmenu);
1484                 gtk_widget_hide(filtering_action.color_label);
1485                 gtk_widget_hide(filtering_action.score_label);
1486                 gtk_widget_hide(filtering_action.header_label);
1487                 gtk_widget_hide(filtering_action.header_combo);
1488                 gtk_widget_hide(filtering_action.header_entry);
1489                 gtk_widget_set_sensitive(filtering_action.header_entry, FALSE);
1490                 gtk_widget_hide(filtering_action.addressbook_label);
1491                 gtk_widget_hide(filtering_action.addressbook_btn);
1492                 gtk_widget_set_sensitive(filtering_action.addressbook_btn, FALSE);
1493                 break;
1494         case ACTION_COLOR:
1495                 gtk_widget_show(filtering_action.account_label);
1496                 gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
1497                 gtk_widget_show(filtering_action.account_combo);
1498                 gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
1499                 gtk_widget_hide(filtering_action.tags_label);
1500                 gtk_widget_set_sensitive(filtering_action.tags_label, FALSE);
1501                 gtk_widget_hide(filtering_action.tags_combo);
1502                 gtk_widget_set_sensitive(filtering_action.tags_combo, FALSE);
1503                 gtk_widget_hide(filtering_action.dest_entry);
1504                 gtk_widget_hide(filtering_action.dest_btn);
1505                 gtk_widget_hide(filtering_action.dest_label);
1506                 gtk_widget_hide(filtering_action.recip_label);
1507                 gtk_widget_hide(filtering_action.exec_label);
1508                 gtk_widget_show(filtering_action.exec_btn);
1509                 gtk_widget_set_sensitive(filtering_action.exec_btn, FALSE);
1510                 gtk_widget_show(filtering_action.color_optmenu);
1511                 gtk_widget_show(filtering_action.color_label);
1512                 gtk_widget_hide(filtering_action.score_label);
1513                 gtk_widget_hide(filtering_action.header_label);
1514                 gtk_widget_hide(filtering_action.header_combo);
1515                 gtk_widget_hide(filtering_action.header_entry);
1516                 gtk_widget_set_sensitive(filtering_action.header_entry, FALSE);
1517                 gtk_widget_hide(filtering_action.addressbook_label);
1518                 gtk_widget_hide(filtering_action.addressbook_btn);
1519                 gtk_widget_set_sensitive(filtering_action.addressbook_btn, FALSE);
1520                 break;
1521         case ACTION_CHANGE_SCORE:
1522         case ACTION_SET_SCORE:
1523                 gtk_widget_show(filtering_action.account_label);
1524                 gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
1525                 gtk_widget_show(filtering_action.account_combo);
1526                 gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
1527                 gtk_widget_hide(filtering_action.tags_label);
1528                 gtk_widget_set_sensitive(filtering_action.tags_label, FALSE);
1529                 gtk_widget_hide(filtering_action.tags_combo);
1530                 gtk_widget_set_sensitive(filtering_action.tags_combo, FALSE);
1531                 gtk_widget_show(filtering_action.dest_entry);
1532                 gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
1533                 gtk_widget_hide(filtering_action.dest_btn);
1534                 gtk_widget_hide(filtering_action.dest_label);
1535                 gtk_widget_hide(filtering_action.recip_label);
1536                 gtk_widget_hide(filtering_action.exec_label);
1537                 gtk_widget_show(filtering_action.exec_btn);
1538                 gtk_widget_set_sensitive(filtering_action.exec_btn, FALSE);
1539                 gtk_widget_hide(filtering_action.color_optmenu);
1540                 gtk_widget_hide(filtering_action.color_label);
1541                 gtk_widget_show(filtering_action.score_label);
1542                 gtk_widget_hide(filtering_action.header_label);
1543                 gtk_widget_hide(filtering_action.header_combo);
1544                 gtk_widget_hide(filtering_action.header_entry);
1545                 gtk_widget_set_sensitive(filtering_action.header_entry, FALSE);
1546                 gtk_widget_hide(filtering_action.addressbook_label);
1547                 gtk_widget_hide(filtering_action.addressbook_btn);
1548                 gtk_widget_set_sensitive(filtering_action.addressbook_btn, FALSE);
1549                 break;
1550         case ACTION_ADD_TO_ADDRESSBOOK:
1551                 gtk_widget_hide(filtering_action.account_label);
1552                 gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
1553                 gtk_widget_hide(filtering_action.account_combo);
1554                 gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
1555                 gtk_widget_hide(filtering_action.tags_label);
1556                 gtk_widget_set_sensitive(filtering_action.tags_label, FALSE);
1557                 gtk_widget_hide(filtering_action.tags_combo);
1558                 gtk_widget_set_sensitive(filtering_action.tags_combo, FALSE);
1559                 gtk_widget_show(filtering_action.dest_entry);
1560                 gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
1561                 gtk_widget_hide(filtering_action.dest_btn);
1562                 gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE);
1563                 gtk_widget_hide(filtering_action.dest_label);
1564                 gtk_widget_set_sensitive(filtering_action.dest_label, FALSE);
1565                 gtk_widget_hide(filtering_action.recip_label);
1566                 gtk_widget_hide(filtering_action.exec_label);
1567                 gtk_widget_hide(filtering_action.exec_btn);
1568                 gtk_widget_hide(filtering_action.color_optmenu);
1569                 gtk_widget_hide(filtering_action.color_label);
1570                 gtk_widget_hide(filtering_action.score_label);
1571                 gtk_widget_show(filtering_action.header_label);
1572                 gtk_widget_show(filtering_action.header_combo);
1573                 gtk_widget_show(filtering_action.header_entry);
1574                 gtk_widget_set_sensitive(filtering_action.header_entry, TRUE);
1575                 gtk_widget_show(filtering_action.addressbook_label);
1576                 gtk_widget_show(filtering_action.addressbook_btn);
1577                 gtk_widget_set_sensitive(filtering_action.addressbook_btn, TRUE);
1578                 break;
1579         case ACTION_SET_TAG:
1580         case ACTION_UNSET_TAG:
1581                 gtk_widget_show(filtering_action.account_label);
1582                 gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
1583                 gtk_widget_show(filtering_action.account_combo);
1584                 gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
1585                 gtk_widget_show(filtering_action.tags_label);
1586                 gtk_widget_set_sensitive(filtering_action.tags_label, TRUE);
1587                 gtk_widget_show(filtering_action.tags_combo);
1588                 gtk_widget_set_sensitive(filtering_action.tags_combo, TRUE);
1589                 gtk_widget_hide(filtering_action.dest_entry);
1590                 gtk_widget_set_sensitive(filtering_action.dest_entry, FALSE);
1591                 gtk_widget_hide(filtering_action.dest_btn);
1592                 gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE);
1593                 gtk_widget_hide(filtering_action.dest_label);
1594                 gtk_widget_hide(filtering_action.recip_label);
1595                 gtk_widget_set_sensitive(filtering_action.recip_label, TRUE);
1596                 gtk_widget_hide(filtering_action.exec_label);
1597                 gtk_widget_hide(filtering_action.exec_btn);
1598                 gtk_widget_hide(filtering_action.color_optmenu);
1599                 gtk_widget_hide(filtering_action.color_label);
1600                 gtk_widget_hide(filtering_action.score_label);
1601                 gtk_widget_hide(filtering_action.header_label);
1602                 gtk_widget_hide(filtering_action.header_combo);
1603                 gtk_widget_hide(filtering_action.header_entry);
1604                 gtk_widget_set_sensitive(filtering_action.header_entry, FALSE);
1605                 gtk_widget_hide(filtering_action.addressbook_label);
1606                 gtk_widget_hide(filtering_action.addressbook_btn);
1607                 gtk_widget_set_sensitive(filtering_action.addressbook_btn, FALSE);
1608                 break;
1609         }
1610 }
1611
1612 static void prefs_filtering_action_reset_dialog(void)
1613 {
1614         gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo), 0);
1615         gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.account_combo), 0);
1616         gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), "");
1617 }
1618
1619 static GtkListStore* prefs_filtering_action_create_data_store(void)
1620 {
1621         return gtk_list_store_new(N_PFA_COLUMNS,
1622                                   G_TYPE_STRING,
1623                                   G_TYPE_BOOLEAN,
1624                                   -1);
1625 }
1626
1627 static void prefs_filtering_action_list_view_insert_action(GtkWidget   *list_view,
1628                                                            GtkTreeIter *row,
1629                                                            const gchar *action,
1630                                                            gboolean     is_valid)
1631 {
1632         GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model
1633                                         (GTK_TREE_VIEW(list_view)));
1634         GtkTreeIter iter;
1635         
1636         
1637         /* see if row exists, if not append */
1638         if (row == NULL)
1639                 gtk_list_store_append(store, &iter);
1640         else
1641                 iter = *row;
1642
1643         gtk_list_store_set(store, &iter,
1644                            PFA_ACTION, action,
1645                            PFA_VALID_ACTION, is_valid,
1646                            -1);
1647 }
1648
1649 static GtkWidget *prefs_filtering_action_list_view_create(void)
1650 {
1651         GtkTreeView *list_view;
1652         GtkTreeModel *model;
1653         GtkTreeSelection *selector;
1654
1655         model = GTK_TREE_MODEL(prefs_filtering_action_create_data_store());
1656         list_view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
1657         g_object_unref(model);  
1658         
1659         gtk_tree_view_set_rules_hint(list_view, prefs_common.use_stripes_everywhere);
1660
1661         selector = gtk_tree_view_get_selection(list_view);
1662         gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE);
1663         gtk_tree_selection_set_select_function
1664                 (selector, prefs_filtering_actions_selected, NULL, NULL);
1665         
1666         /* create the columns */
1667         prefs_filtering_action_create_list_view_columns(list_view);
1668
1669         return GTK_WIDGET(list_view);
1670 }
1671
1672 static void prefs_filtering_action_create_list_view_columns(GtkTreeView *list_view)
1673 {
1674         GtkTreeViewColumn *column;
1675         GtkCellRenderer *renderer;
1676
1677         renderer = gtk_cell_renderer_text_new();
1678         column = gtk_tree_view_column_new_with_attributes
1679                 (_("Current action list"),
1680                  renderer,
1681                  "text", PFA_ACTION,
1682                  NULL);
1683         gtk_tree_view_append_column(list_view, column);         
1684 }
1685
1686 static gboolean prefs_filtering_actions_selected
1687                         (GtkTreeSelection *selector,
1688                          GtkTreeModel *model, 
1689                          GtkTreePath *path,
1690                          gboolean currently_selected,
1691                          gpointer data)
1692 {
1693         gchar *action_str;
1694         FilteringAction *action;
1695         GSList * action_list;
1696         gint list_id;
1697         GtkTreeIter iter;
1698         gboolean is_valid;
1699
1700         if (currently_selected)
1701                 return TRUE;
1702
1703         if (!gtk_tree_model_get_iter(model, &iter, path))
1704                 return TRUE;
1705
1706         gtk_tree_model_get(model, &iter, 
1707                            PFA_VALID_ACTION,  &is_valid,
1708                            -1);
1709
1710         if (!is_valid) {
1711                 prefs_filtering_action_reset_dialog();
1712                 return TRUE;
1713         }
1714
1715         gtk_tree_model_get(model, &iter, 
1716                            PFA_ACTION, &action_str,
1717                            -1);
1718
1719         action_list = matcher_parser_get_action_list(action_str);
1720         g_free(action_str);
1721
1722         if (action_list == NULL)
1723                 return TRUE;
1724
1725         action = action_list->data;
1726         g_slist_free(action_list);
1727
1728         if (action->destination)
1729                 gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), action->destination);
1730         else
1731                 gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), "");
1732
1733         switch(action->type) {
1734         case MATCHACTION_MOVE:
1735                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1736                                      ACTION_MOVE);
1737                 break;
1738         case MATCHACTION_COPY:
1739                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1740                                      ACTION_COPY);
1741                 break;
1742         case MATCHACTION_DELETE:
1743                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1744                                      ACTION_DELETE);
1745                 break;
1746         case MATCHACTION_MARK:
1747                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1748                                      ACTION_MARK);
1749                 break;
1750         case MATCHACTION_UNMARK:
1751                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1752                                      ACTION_UNMARK);
1753                 break;
1754         case MATCHACTION_LOCK:
1755                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1756                                      ACTION_LOCK);
1757                 break;
1758         case MATCHACTION_UNLOCK:
1759                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1760                                      ACTION_UNLOCK);
1761                 break;
1762         case MATCHACTION_MARK_AS_READ:
1763                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1764                                      ACTION_MARK_AS_READ);
1765                 break;
1766         case MATCHACTION_MARK_AS_UNREAD:
1767                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1768                                      ACTION_MARK_AS_UNREAD);
1769                 break;
1770         case MATCHACTION_MARK_AS_SPAM:
1771                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1772                                      ACTION_MARK_AS_SPAM);
1773                 break;
1774         case MATCHACTION_MARK_AS_HAM:
1775                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1776                                      ACTION_MARK_AS_HAM);
1777                 break;
1778         case MATCHACTION_FORWARD:
1779                 list_id = get_list_id_from_account_id(action->account_id);
1780                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1781                                      ACTION_FORWARD);
1782                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.account_combo),
1783                                      list_id);
1784                 break;
1785         case MATCHACTION_FORWARD_AS_ATTACHMENT:
1786                 list_id = get_list_id_from_account_id(action->account_id);
1787                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1788                                      ACTION_FORWARD_AS_ATTACHMENT);
1789                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.account_combo),
1790                                      list_id);
1791                 break;
1792         case MATCHACTION_REDIRECT:
1793                 list_id = get_list_id_from_account_id(action->account_id);
1794                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1795                                      ACTION_REDIRECT);
1796                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.account_combo),
1797                                      list_id);
1798                 break;
1799         case MATCHACTION_EXECUTE:
1800                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1801                                      ACTION_EXECUTE);
1802                 break;
1803         case MATCHACTION_COLOR:
1804                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1805                                      ACTION_COLOR);
1806                 gtk_option_menu_set_history(GTK_OPTION_MENU(filtering_action.color_optmenu), action->labelcolor);     
1807                 break;
1808         case MATCHACTION_CHANGE_SCORE:
1809                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1810                                      ACTION_CHANGE_SCORE);
1811                 break;
1812         case MATCHACTION_SET_SCORE:
1813                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1814                                      ACTION_SET_SCORE);
1815                 break;
1816         case MATCHACTION_STOP:
1817                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1818                                      ACTION_STOP);
1819                 break;
1820         case MATCHACTION_HIDE:
1821                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1822                                      ACTION_HIDE);
1823                 break;
1824         case MATCHACTION_IGNORE:
1825                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1826                                      ACTION_IGNORE);
1827                 break;
1828         case MATCHACTION_WATCH:
1829                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1830                                      ACTION_WATCH);
1831                 break;
1832         case MATCHACTION_ADD_TO_ADDRESSBOOK:
1833                 if (action->header)
1834                         gtk_entry_set_text(GTK_ENTRY(filtering_action.header_entry), action->header);
1835                 else
1836                         gtk_entry_set_text(GTK_ENTRY(filtering_action.header_entry), "");
1837                 gtk_combo_box_set_active(GTK_COMBO_BOX(filtering_action.action_combo),
1838                                      ACTION_ADD_TO_ADDRESSBOOK);
1839         }
1840
1841         filteringaction_free(action); /* XXX: memleak */
1842         return TRUE;
1843 }