Statistics
| Revision:

root / src / prefs_filter_edit.c @ 2388

History | View | Annotate | Download (61.4 kB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2008 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 2 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, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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.h"
37
#include "prefs_filter.h"
38
#include "prefs_filter_edit.h"
39
#include "prefs_common.h"
40
#include "mainwindow.h"
41
#include "foldersel.h"
42
#include "colorlabel.h"
43
#include "manage_window.h"
44
#include "procheader.h"
45
#include "menu.h"
46
#include "filter.h"
47
#include "utils.h"
48
#include "gtkutils.h"
49
#include "stock_pixmap.h"
50
#include "alertpanel.h"
51
#include "folder.h"
52
53
static struct FilterRuleEditWindow {
54
        GtkWidget *window;
55
56
        GtkWidget *name_entry;
57
        GtkWidget *bool_op_optmenu;
58
59
        GtkWidget *cond_scrolled_win;
60
        FilterCondEdit cond_edit;
61
62
        GtkWidget *action_scrolled_win;
63
        GtkWidget *action_vbox;
64
        GSList *action_hbox_list;
65
66
        GtkWidget *ok_btn;
67
        GtkWidget *cancel_btn;
68
69
        FilterRule *new_rule;
70
        gboolean edit_finished;
71
} rule_edit_window;
72
73
static struct FilterEditHeaderListDialog {
74
        GtkWidget *window;
75
        GtkWidget *clist;
76
        GtkWidget *entry;
77
78
        gboolean finished;
79
        gboolean ok;
80
} edit_header_list_dialog;
81
82
static void prefs_filter_edit_create                (void);
83
static void prefs_filter_edit_clear                (void);
84
static void prefs_filter_edit_rule_to_dialog        (FilterRule        *rule,
85
                                                 const gchar        *default_name);
86
static void prefs_filter_edit_update_header_list(FilterCondEdit        *cond_list);
87
88
static void prefs_filter_edit_set_action_hbox_menu_sensitive
89
                                                (ActionHBox        *hbox,
90
                                                 ActionMenuType         type,
91
                                                 gboolean         sensitive);
92
static void prefs_filter_edit_set_action_hbox_menus_sensitive
93
                                                (void);
94
95
static void prefs_filter_edit_get_action_hbox_menus_selection
96
                                                (gboolean        *selection);
97
static ActionMenuType prefs_filter_edit_get_action_hbox_type
98
                                                (ActionHBox        *hbox);
99
100
static void prefs_filter_edit_insert_action_hbox(ActionHBox        *hbox,
101
                                                 gint                 pos);
102
static void prefs_filter_edit_remove_cond_hbox        (FilterCondEdit        *cond_edit,
103
                                                 CondHBox        *hbox);
104
static void prefs_filter_edit_remove_action_hbox(ActionHBox        *hbox);
105
106
static void prefs_filter_edit_add_rule_action        (FilterRule        *rule);
107
108
static void prefs_filter_edit_set_cond_header_menu
109
                                                (FilterCondEdit        *cond_edit,
110
                                                 CondHBox        *hbox);
111
112
static void prefs_filter_edit_activate_cond_header
113
                                                (FilterCondEdit        *cond_edit,
114
                                                 const gchar        *header);
115
116
static void prefs_filter_edit_edit_header_list        (FilterCondEdit        *cond_edit);
117
118
static FilterRule *prefs_filter_edit_dialog_to_rule        (void);
119
120
/* callback functions */
121
static gint prefs_filter_edit_deleted                (GtkWidget        *widget,
122
                                                 GdkEventAny        *event,
123
                                                 gpointer         data);
124
static gboolean prefs_filter_edit_key_pressed        (GtkWidget        *widget,
125
                                                 GdkEventKey        *event,
126
                                                 gpointer         data);
127
static void prefs_filter_edit_ok                (void);
128
static void prefs_filter_edit_cancel                (void);
129
130
static void prefs_filter_cond_activated_cb        (GtkWidget        *widget,
131
                                                 gpointer         data);
132
static void prefs_filter_action_activated_cb        (GtkWidget        *widget,
133
                                                 gpointer         data);
134
135
static void prefs_filter_action_select_dest_cb        (GtkWidget        *widget,
136
                                                 gpointer         data);
137
138
static void prefs_filter_cond_del_cb                (GtkWidget        *widget,
139
                                                 gpointer         data);
140
static void prefs_filter_cond_add_cb                (GtkWidget        *widget,
141
                                                 gpointer         data);
142
static void prefs_filter_action_del_cb                (GtkWidget        *widget,
143
                                                 gpointer         data);
144
static void prefs_filter_action_add_cb                (GtkWidget        *widget,
145
                                                 gpointer         data);
146
147
148
FilterRule *prefs_filter_edit_open(FilterRule *rule, const gchar *header,
149
                                   const gchar *key)
150
{
151
        static gboolean lock = FALSE;
152
        FilterRule *new_rule;
153
154
        if (lock)
155
                return NULL;
156
157
        lock = TRUE;
158
159
        if (!rule_edit_window.window)
160
                prefs_filter_edit_create();
161
162
        manage_window_set_transient(GTK_WINDOW(rule_edit_window.window));
163
164
        prefs_filter_edit_set_header_list(&rule_edit_window.cond_edit, rule);
165
        prefs_filter_edit_rule_to_dialog(rule, key);
166
        if (header)
167
                prefs_filter_edit_activate_cond_header
168
                        (&rule_edit_window.cond_edit, header);
169
        GTK_EVENTS_FLUSH();
170
        gtk_widget_show(rule_edit_window.window);
171
172
        rule_edit_window.new_rule = NULL;
173
        rule_edit_window.edit_finished = FALSE;
174
        while (rule_edit_window.edit_finished == FALSE)
175
                gtk_main_iteration();
176
177
        gtk_widget_hide(rule_edit_window.window);
178
        prefs_filter_edit_clear();
179
        prefs_filter_set_msg_header_list(NULL);
180
181
        new_rule = rule_edit_window.new_rule;
182
        rule_edit_window.new_rule = NULL;
183
184
        if (new_rule)
185
                debug_print("new rule created: %s\n", new_rule->name);
186
187
        lock = FALSE;
188
189
        return new_rule;
190
}
191
192
static void prefs_filter_edit_create(void)
193
{
194
        GtkWidget *window;
195
196
        GtkWidget *vbox;
197
198
        GtkWidget *hbox;
199
        GtkWidget *label;
200
        GtkWidget *name_entry;
201
202
        GtkWidget *bool_op_optmenu;
203
        GtkWidget *menu;
204
        GtkWidget *menuitem;
205
206
        GtkWidget *cond_scrolled_win;
207
        GtkWidget *cond_vbox;
208
209
        GtkWidget *action_scrolled_win;
210
        GtkWidget *action_vbox;
211
212
        GtkWidget *ok_btn;
213
        GtkWidget *cancel_btn;
214
        GtkWidget *confirm_area;
215
216
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
217
        gtk_container_set_border_width(GTK_CONTAINER(window), 8);
218
        gtk_widget_set_size_request(window, 632, 405);
219
        gtk_window_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
220
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);
221
        gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE);
222
        gtk_widget_realize(window);
223
224
        vbox = gtk_vbox_new(FALSE, 6);
225
        gtk_widget_show(vbox);
226
        gtk_container_add(GTK_CONTAINER(window), vbox);
227
228
        gtkut_stock_button_set_create(&confirm_area, &ok_btn, GTK_STOCK_OK,
229
                                      &cancel_btn, GTK_STOCK_CANCEL,
230
                                      NULL, NULL);
231
        gtk_widget_show(confirm_area);
232
        gtk_box_pack_end(GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
233
        gtk_widget_grab_default(ok_btn);
234
235
        gtk_window_set_title(GTK_WINDOW(window),
236
                             _("Filter rule"));
237
        g_signal_connect(G_OBJECT(window), "delete_event",
238
                         G_CALLBACK(prefs_filter_edit_deleted), NULL);
239
        g_signal_connect(G_OBJECT(window), "key_press_event",
240
                         G_CALLBACK(prefs_filter_edit_key_pressed), NULL);
241
        MANAGE_WINDOW_SIGNALS_CONNECT (window);
242
        g_signal_connect(G_OBJECT(ok_btn), "clicked",
243
                         G_CALLBACK(prefs_filter_edit_ok), NULL);
244
        g_signal_connect(G_OBJECT(cancel_btn), "clicked",
245
                         G_CALLBACK(prefs_filter_edit_cancel), NULL);
246
247
        hbox = gtk_hbox_new(FALSE, 4);
248
        gtk_widget_show(hbox);
249
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
250
251
        label = gtk_label_new(_("Name:"));
252
        gtk_widget_show(label);
253
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
254
255
        name_entry = gtk_entry_new();
256
        gtk_widget_show(name_entry);
257
        gtk_box_pack_start(GTK_BOX(hbox), name_entry, TRUE, TRUE, 0);
258
259
        hbox = gtk_hbox_new(FALSE, 4);
260
        gtk_widget_show(hbox);
261
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
262
263
        bool_op_optmenu = gtk_option_menu_new();
264
        gtk_widget_show(bool_op_optmenu);
265
        gtk_box_pack_start(GTK_BOX(hbox), bool_op_optmenu, FALSE, FALSE, 0);
266
267
        menu = gtk_menu_new();
268
        gtk_widget_show(menu);
269
        MENUITEM_ADD(menu, menuitem,
270
                     _("If any of the following condition matches"), FLT_OR);
271
        MENUITEM_ADD(menu, menuitem,
272
                     _("If all of the following conditions match"), FLT_AND);
273
        gtk_option_menu_set_menu(GTK_OPTION_MENU(bool_op_optmenu), menu);
274
275
        cond_scrolled_win = gtk_scrolled_window_new(NULL, NULL);
276
        gtk_widget_show(cond_scrolled_win);
277
        gtk_widget_set_size_request(cond_scrolled_win, -1, 125);
278
        gtk_box_pack_start(GTK_BOX(vbox), cond_scrolled_win, TRUE, TRUE, 0);
279
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(cond_scrolled_win),
280
                                       GTK_POLICY_AUTOMATIC,
281
                                       GTK_POLICY_AUTOMATIC);
282
283
        cond_vbox = gtk_vbox_new(FALSE, 2);
284
        gtk_widget_show(cond_vbox);
285
        gtk_container_set_border_width(GTK_CONTAINER(cond_vbox), 2);
286
        gtk_scrolled_window_add_with_viewport
287
                (GTK_SCROLLED_WINDOW(cond_scrolled_win), cond_vbox);
288
289
        hbox = gtk_hbox_new(FALSE, 4);
290
        gtk_widget_show(hbox);
291
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
292
293
        label = gtk_label_new(_("Perform the following actions:"));
294
        gtk_widget_show(label);
295
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
296
297
        action_scrolled_win = gtk_scrolled_window_new(NULL, NULL);
298
        gtk_widget_show(action_scrolled_win);
299
        gtk_box_pack_start(GTK_BOX(vbox), action_scrolled_win, TRUE, TRUE, 0);
300
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(action_scrolled_win),
301
                                       GTK_POLICY_AUTOMATIC,
302
                                       GTK_POLICY_AUTOMATIC);
303
304
        action_vbox = gtk_vbox_new(FALSE, 2);
305
        gtk_widget_show(action_vbox);
306
        gtk_container_set_border_width(GTK_CONTAINER(action_vbox), 2);
307
        gtk_scrolled_window_add_with_viewport
308
                (GTK_SCROLLED_WINDOW(action_scrolled_win), action_vbox);
309
310
        rule_edit_window.window = window;
311
        rule_edit_window.name_entry = name_entry;
312
313
        rule_edit_window.bool_op_optmenu = bool_op_optmenu;
314
        rule_edit_window.cond_scrolled_win = cond_scrolled_win;
315
        rule_edit_window.cond_edit.cond_vbox = cond_vbox;
316
        rule_edit_window.action_scrolled_win = action_scrolled_win;
317
        rule_edit_window.action_vbox = action_vbox;
318
319
        rule_edit_window.ok_btn = ok_btn;
320
        rule_edit_window.cancel_btn = cancel_btn;
321
}
322
323
FilterCondEdit *prefs_filter_edit_cond_edit_create(void)
324
{
325
        FilterCondEdit *cond_edit;
326
        GtkWidget *cond_vbox;
327
328
        cond_edit = g_new(FilterCondEdit, 1);
329
330
        cond_vbox = gtk_vbox_new(FALSE, 2);
331
        gtk_widget_show(cond_vbox);
332
        gtk_container_set_border_width(GTK_CONTAINER(cond_vbox), 2);
333
334
        cond_edit->cond_vbox = cond_vbox;
335
        cond_edit->cond_hbox_list = NULL;
336
        cond_edit->hdr_list = NULL;
337
        cond_edit->rule_hdr_list = NULL;
338
        cond_edit->add_hbox = NULL;
339
340
        return cond_edit;
341
}
342
343
void prefs_filter_edit_clear_cond_edit(FilterCondEdit *cond_edit)
344
{
345
        while (cond_edit->cond_hbox_list) {
346
                CondHBox *hbox = (CondHBox *)cond_edit->cond_hbox_list->data;
347
                prefs_filter_edit_remove_cond_hbox(cond_edit, hbox);
348
        }
349
350
        procheader_header_list_destroy(cond_edit->hdr_list);
351
        cond_edit->hdr_list = NULL;
352
        procheader_header_list_destroy(cond_edit->rule_hdr_list);
353
        cond_edit->rule_hdr_list = NULL;
354
}
355
356
static void prefs_filter_edit_clear(void)
357
{
358
        prefs_filter_edit_clear_cond_edit(&rule_edit_window.cond_edit);
359
360
        while (rule_edit_window.action_hbox_list) {
361
                ActionHBox *hbox =
362
                        (ActionHBox *)rule_edit_window.action_hbox_list->data;
363
                prefs_filter_edit_remove_action_hbox(hbox);
364
        }
365
}
366
367
static void prefs_filter_edit_rule_to_dialog(FilterRule *rule,
368
                                             const gchar *default_name)
369
{
370
        gint index = 0;
371
        static gint count = 1;
372
373
        if (rule && rule->name)
374
                gtk_entry_set_text(GTK_ENTRY(rule_edit_window.name_entry),
375
                                   rule->name);
376
        else if (default_name)
377
                gtk_entry_set_text(GTK_ENTRY(rule_edit_window.name_entry),
378
                                   default_name);
379
        else {
380
                gchar rule_name[32];
381
                g_snprintf(rule_name, sizeof(rule_name), "Rule %d", count++);
382
                gtk_entry_set_text(GTK_ENTRY(rule_edit_window.name_entry),
383
                                   rule_name);
384
        }
385
386
        if (rule) {
387
                index = menu_find_option_menu_index
388
                        (GTK_OPTION_MENU(rule_edit_window.bool_op_optmenu),
389
                         GINT_TO_POINTER(rule->bool_op), NULL);
390
                if (index < 0)
391
                        index = 0;
392
        }
393
        if (index >= 0) {
394
                gtk_option_menu_set_history
395
                        (GTK_OPTION_MENU(rule_edit_window.bool_op_optmenu),
396
                         index);
397
        }
398
399
        gtkut_scrolled_window_reset_position
400
                (GTK_SCROLLED_WINDOW(rule_edit_window.cond_scrolled_win));
401
        gtkut_scrolled_window_reset_position
402
                (GTK_SCROLLED_WINDOW(rule_edit_window.action_scrolled_win));
403
404
        prefs_filter_edit_add_rule_cond(&rule_edit_window.cond_edit, rule);
405
        prefs_filter_edit_add_rule_action(rule);
406
}
407
408
void prefs_filter_edit_set_header_list(FilterCondEdit *cond_edit,
409
                                       FilterRule *rule)
410
{
411
        GSList *list;
412
        GSList *rule_hdr_list = NULL;
413
        GSList *cur;
414
        FilterCond *cond;
415
416
        procheader_header_list_destroy(cond_edit->hdr_list);
417
        cond_edit->hdr_list = NULL;
418
        procheader_header_list_destroy(cond_edit->rule_hdr_list);
419
        cond_edit->rule_hdr_list = NULL;
420
421
        list = prefs_filter_get_header_list();
422
        cond_edit->hdr_list = list;
423
424
        if (!rule)
425
                return;
426
427
        for (cur = rule->cond_list; cur != NULL; cur = cur->next) {
428
                cond = (FilterCond *)cur->data;
429
430
                if (cond->type == FLT_COND_HEADER &&
431
                    procheader_find_header_list
432
                        (rule_hdr_list, cond->header_name) < 0)
433
                        rule_hdr_list = procheader_add_header_list
434
                                (rule_hdr_list, cond->header_name, NULL);
435
        }
436
437
        cond_edit->rule_hdr_list = rule_hdr_list;
438
        cond_edit->hdr_list = procheader_merge_header_list_dup(list,
439
                                                               rule_hdr_list);
440
        procheader_header_list_destroy(list);
441
}
442
443
static void prefs_filter_edit_update_header_list(FilterCondEdit *cond_edit)
444
{
445
        GSList *list;
446
447
        procheader_header_list_destroy(cond_edit->hdr_list);
448
        cond_edit->hdr_list = NULL;
449
450
        list = prefs_filter_get_header_list();
451
        cond_edit->hdr_list = procheader_merge_header_list_dup
452
                (list, cond_edit->rule_hdr_list);
453
        procheader_header_list_destroy(list);
454
}
455
456
CondHBox *prefs_filter_edit_cond_hbox_create(FilterCondEdit *cond_edit)
457
{
458
        CondHBox *cond_hbox;
459
        GtkWidget *hbox;
460
        GtkWidget *cond_type_optmenu;
461
        GtkWidget *match_type_optmenu;
462
        GtkWidget *size_match_optmenu;
463
        GtkWidget *age_match_optmenu;
464
        GtkWidget *status_match_optmenu;
465
        GtkWidget *menu;
466
        GtkWidget *menuitem;
467
        GtkWidget *key_entry;
468
        GtkObject *spin_btn_adj;
469
        GtkWidget *spin_btn;
470
        GtkWidget *label;
471
        GtkWidget *del_btn;
472
        GtkWidget *add_btn;
473
        GtkWidget *del_img;
474
        GtkWidget *add_img;
475
476
        cond_hbox = g_new0(CondHBox, 1);
477
478
        hbox = gtk_hbox_new(FALSE, 4);
479
        gtk_widget_show(hbox);
480
481
        cond_type_optmenu = gtk_option_menu_new();
482
        gtk_widget_show(cond_type_optmenu);
483
        gtk_box_pack_start(GTK_BOX(hbox), cond_type_optmenu, FALSE, FALSE, 0);
484
485
#define COND_MENUITEM_ADD(str, action)                                            \
486
{                                                                            \
487
        MENUITEM_ADD(menu, menuitem, str, action);                            \
488
        g_signal_connect(G_OBJECT(menuitem), "activate",                    \
489
                         G_CALLBACK(prefs_filter_cond_activated_cb),            \
490
                         cond_hbox);                                            \
491
}
492
493
        menu = gtk_menu_new();
494
        gtk_widget_show(menu);
495
        MENUITEM_ADD(menu, menuitem, NULL,        PF_COND_SEPARATOR);
496
        COND_MENUITEM_ADD(_("To or Cc"),          PF_COND_TO_OR_CC);
497
        COND_MENUITEM_ADD(_("Any header"),        PF_COND_ANY_HEADER);
498
        COND_MENUITEM_ADD(_("Edit header..."),    PF_COND_EDIT_HEADER);
499
500
        MENUITEM_ADD(menu, menuitem, NULL,        PF_COND_SEPARATOR);
501
        COND_MENUITEM_ADD(_("Message body"),      PF_COND_BODY);
502
        COND_MENUITEM_ADD(_("Result of command"), PF_COND_CMD_TEST);
503
        COND_MENUITEM_ADD(_("Size"),              PF_COND_SIZE);
504
        COND_MENUITEM_ADD(_("Age"),               PF_COND_AGE);
505
506
        MENUITEM_ADD(menu, menuitem, NULL,        PF_COND_SEPARATOR);
507
        COND_MENUITEM_ADD(_("Unread"),            PF_COND_UNREAD);
508
        COND_MENUITEM_ADD(_("Marked"),            PF_COND_MARK);
509
        COND_MENUITEM_ADD(_("Has color label"),   PF_COND_COLOR_LABEL);
510
        COND_MENUITEM_ADD(_("Has attachment"),    PF_COND_MIME);
511
        /* COND_MENUITEM_ADD(_("Account"),           PF_COND_ACCOUNT); */
512
513
        gtk_option_menu_set_menu(GTK_OPTION_MENU(cond_type_optmenu), menu);
514
515
#undef COND_MENUITEM_ADD
516
517
        match_type_optmenu = gtk_option_menu_new();
518
        gtk_widget_show(match_type_optmenu);
519
        gtk_box_pack_start(GTK_BOX(hbox), match_type_optmenu, FALSE, FALSE, 0);
520
521
        menu = gtk_menu_new();
522
        gtk_widget_show(menu);
523
        MENUITEM_ADD(menu, menuitem, _("contains"),
524
                     PF_MATCH_CONTAIN);
525
        MENUITEM_ADD(menu, menuitem, _("doesn't contain"),
526
                     PF_MATCH_NOT_CONTAIN);
527
        MENUITEM_ADD(menu, menuitem, _("is"),
528
                     PF_MATCH_EQUAL);
529
        MENUITEM_ADD(menu, menuitem, _("is not"),
530
                     PF_MATCH_NOT_EQUAL);
531
#if defined(USE_ONIGURUMA) || defined(HAVE_REGCOMP)
532
        MENUITEM_ADD(menu, menuitem, _("match to regex"),
533
                     PF_MATCH_REGEX);
534
        MENUITEM_ADD(menu, menuitem, _("doesn't match to regex"),
535
                     PF_MATCH_NOT_REGEX);
536
#endif
537
        gtk_option_menu_set_menu(GTK_OPTION_MENU(match_type_optmenu), menu);
538
539
        size_match_optmenu = gtk_option_menu_new();
540
        gtk_widget_show(size_match_optmenu);
541
        gtk_box_pack_start(GTK_BOX(hbox), size_match_optmenu, FALSE, FALSE, 0);
542
543
        menu = gtk_menu_new();
544
        gtk_widget_show(menu);
545
        MENUITEM_ADD(menu, menuitem, _("is larger than"), PF_SIZE_LARGER);
546
        MENUITEM_ADD(menu, menuitem, _("is smaller than"), PF_SIZE_SMALLER);
547
        gtk_option_menu_set_menu(GTK_OPTION_MENU(size_match_optmenu), menu);
548
549
        age_match_optmenu = gtk_option_menu_new();
550
        gtk_widget_show(age_match_optmenu);
551
        gtk_box_pack_start(GTK_BOX(hbox), age_match_optmenu, FALSE, FALSE, 0);
552
553
        menu = gtk_menu_new();
554
        gtk_widget_show(menu);
555
        MENUITEM_ADD(menu, menuitem, _("is longer than"), PF_AGE_LONGER);
556
        MENUITEM_ADD(menu, menuitem, _("is shorter than"), PF_AGE_SHORTER);
557
        gtk_option_menu_set_menu(GTK_OPTION_MENU(age_match_optmenu), menu);
558
559
        status_match_optmenu = gtk_option_menu_new();
560
        gtk_widget_show(status_match_optmenu);
561
        gtk_box_pack_start(GTK_BOX(hbox), status_match_optmenu,
562
                           FALSE, FALSE, 0);
563
564
        menu = gtk_menu_new();
565
        gtk_widget_show(menu);
566
        MENUITEM_ADD(menu, menuitem, _("matches to status"), PF_STATUS_MATCH);
567
        MENUITEM_ADD(menu, menuitem, _("doesn't match to status"),
568
                     PF_STATUS_NOT_MATCH);
569
        gtk_option_menu_set_menu(GTK_OPTION_MENU(status_match_optmenu), menu);
570
571
        key_entry = gtk_entry_new();
572
        gtk_widget_show(key_entry);
573
        gtk_box_pack_start(GTK_BOX(hbox), key_entry, TRUE, TRUE, 0);
574
575
        spin_btn_adj = gtk_adjustment_new(0, 0, 99999, 1, 10, 100);
576
        spin_btn = gtk_spin_button_new(GTK_ADJUSTMENT(spin_btn_adj), 1, 0);
577
        gtk_box_pack_start(GTK_BOX(hbox), spin_btn, FALSE, FALSE, 0);
578
        gtk_widget_set_size_request(spin_btn, 64, -1);
579
        gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin_btn), TRUE);
580
581
        label = gtk_label_new(_("KB"));
582
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
583
584
        del_img = gtk_image_new_from_stock
585
                (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU);
586
        gtk_widget_show(del_img);
587
588
        del_btn = gtk_button_new();
589
        gtk_container_add(GTK_CONTAINER(del_btn), del_img);
590
        gtk_widget_show(del_btn);
591
        gtk_box_pack_end(GTK_BOX(hbox), del_btn, FALSE, FALSE, 0);
592
593
        add_img = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
594
        gtk_widget_show(add_img);
595
596
        add_btn = gtk_button_new();
597
        gtk_container_add(GTK_CONTAINER(add_btn), add_img);
598
        gtk_widget_show(add_btn);
599
        gtk_box_pack_end(GTK_BOX(hbox), add_btn, FALSE, FALSE, 0);
600
601
        g_signal_connect(G_OBJECT(del_btn), "clicked",
602
                         G_CALLBACK(prefs_filter_cond_del_cb), cond_hbox);
603
        g_signal_connect(G_OBJECT(add_btn), "clicked",
604
                         G_CALLBACK(prefs_filter_cond_add_cb), cond_hbox);
605
606
        cond_hbox->hbox = hbox;
607
        cond_hbox->cond_type_optmenu = cond_type_optmenu;
608
        cond_hbox->match_type_optmenu = match_type_optmenu;
609
        cond_hbox->size_match_optmenu = size_match_optmenu;
610
        cond_hbox->age_match_optmenu = age_match_optmenu;
611
        cond_hbox->status_match_optmenu = status_match_optmenu;
612
        cond_hbox->key_entry = key_entry;
613
        cond_hbox->spin_btn = spin_btn;
614
        cond_hbox->label = label;
615
        cond_hbox->del_btn = del_btn;
616
        cond_hbox->add_btn = add_btn;
617
        cond_hbox->cur_type = PF_COND_HEADER;
618
        cond_hbox->cur_header_name = NULL;
619
        cond_hbox->cond_edit = cond_edit;
620
621
        prefs_filter_edit_set_cond_header_menu(cond_edit, cond_hbox);
622
        gtk_option_menu_set_history(GTK_OPTION_MENU(cond_type_optmenu), 0);
623
624
        return cond_hbox;
625
}
626
627
ActionHBox *prefs_filter_edit_action_hbox_create(void)
628
{
629
        ActionHBox *action_hbox;
630
        GtkWidget *hbox;
631
        GtkWidget *action_type_optmenu;
632
        GtkWidget *menu;
633
        GtkWidget *menuitem;
634
        GtkWidget *label;
635
        GtkWidget *folder_entry;
636
        GtkWidget *cmd_entry;
637
        GtkWidget *address_entry;
638
        GtkWidget *folder_img;
639
        GtkWidget *folder_sel_btn;
640
        GtkWidget *clabel_optmenu;
641
        GtkWidget *del_btn;
642
        GtkWidget *add_btn;
643
        GtkWidget *del_img;
644
        GtkWidget *add_img;
645
646
        action_hbox = g_new0(ActionHBox, 1);
647
648
        hbox = gtk_hbox_new(FALSE, 4);
649
        gtk_widget_show(hbox);
650
651
        action_type_optmenu = gtk_option_menu_new();
652
        gtk_widget_show(action_type_optmenu);
653
        gtk_box_pack_start(GTK_BOX(hbox), action_type_optmenu, FALSE, FALSE, 0);
654
655
        memset(action_hbox->action_type_menu_items, 0,
656
               sizeof(action_hbox->action_type_menu_items));
657
658
#define ACTION_MENUITEM_ADD(str, action)                                      \
659
{                                                                              \
660
        MENUITEM_ADD(menu, menuitem, str, action);                              \
661
        action_hbox->action_type_menu_items[action] = menuitem;                      \
662
        g_signal_connect(G_OBJECT(menuitem), "activate",                      \
663
                         G_CALLBACK(prefs_filter_action_activated_cb),              \
664
                         action_hbox);                                              \
665
}
666
667
        menu = gtk_menu_new();
668
        gtk_widget_show(menu);
669
        ACTION_MENUITEM_ADD(_("Move to"),               PF_ACTION_MOVE);
670
        ACTION_MENUITEM_ADD(_("Copy to"),               PF_ACTION_COPY);
671
        ACTION_MENUITEM_ADD(_("Don't receive"),         PF_ACTION_NOT_RECEIVE);
672
        ACTION_MENUITEM_ADD(_("Delete from server"),    PF_ACTION_DELETE);
673
674
        MENUITEM_ADD(menu, menuitem, NULL,              PF_ACTION_SEPARATOR);
675
        ACTION_MENUITEM_ADD(_("Set mark"),              PF_ACTION_MARK);
676
        ACTION_MENUITEM_ADD(_("Set color"),             PF_ACTION_COLOR_LABEL);
677
        ACTION_MENUITEM_ADD(_("Mark as read"),          PF_ACTION_MARK_READ);
678
679
#if 0
680
        MENUITEM_ADD(menu, menuitem, NULL,              PF_ACTION_SEPARATOR);
681
        ACTION_MENUITEM_ADD(_("Forward"),               PF_ACTION_FORWARD);
682
        ACTION_MENUITEM_ADD(_("Forward as attachment"), PF_ACTION_FORWARD_AS_ATTACHMENT);
683
        ACTION_MENUITEM_ADD(_("Redirect"),              PF_ACTION_REDIRECT);
684
#endif
685
686
        MENUITEM_ADD(menu, menuitem, NULL,              PF_ACTION_SEPARATOR);
687
        ACTION_MENUITEM_ADD(_("Execute command"),       PF_ACTION_EXEC);
688
689
        MENUITEM_ADD(menu, menuitem, NULL,              PF_ACTION_SEPARATOR);
690
        ACTION_MENUITEM_ADD(_("Stop rule evaluation"),  PF_ACTION_STOP_EVAL);
691
692
        gtk_option_menu_set_menu(GTK_OPTION_MENU(action_type_optmenu), menu);
693
694
#undef ACTION_MENUITEM_ADD
695
696
        label = gtk_label_new(_("folder:"));
697
        gtk_widget_show(label);
698
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
699
700
        folder_entry = gtk_entry_new();
701
        gtk_widget_show(folder_entry);
702
        gtk_box_pack_start(GTK_BOX(hbox), folder_entry, TRUE, TRUE, 0);
703
704
        folder_img = stock_pixbuf_widget(rule_edit_window.window,
705
                                         STOCK_PIXMAP_FOLDER_OPEN);
706
        gtk_widget_show(folder_img);
707
708
        folder_sel_btn = gtk_button_new();
709
        gtk_container_add(GTK_CONTAINER(folder_sel_btn), folder_img);
710
        gtk_widget_show(folder_sel_btn);
711
        gtk_box_pack_start(GTK_BOX(hbox), folder_sel_btn, FALSE, FALSE, 0);
712
713
        cmd_entry = gtk_entry_new();
714
        gtk_widget_show(cmd_entry);
715
        gtk_box_pack_start(GTK_BOX(hbox), cmd_entry, TRUE, TRUE, 0);
716
717
        address_entry = gtk_entry_new();
718
        gtk_widget_show(address_entry);
719
        gtk_box_pack_start(GTK_BOX(hbox), address_entry, TRUE, TRUE, 0);
720
721
        clabel_optmenu = gtk_option_menu_new();
722
        gtk_widget_show(clabel_optmenu);
723
        gtk_box_pack_start(GTK_BOX(hbox), clabel_optmenu, FALSE, FALSE, 0);
724
725
        menu = colorlabel_create_color_menu();
726
        gtk_option_menu_set_menu(GTK_OPTION_MENU(clabel_optmenu), menu);
727
728
        del_img = gtk_image_new_from_stock
729
                (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU);
730
        gtk_widget_show(del_img);
731
732
        del_btn = gtk_button_new();
733
        gtk_container_add(GTK_CONTAINER(del_btn), del_img);
734
        gtk_widget_show(del_btn);
735
        gtk_box_pack_end(GTK_BOX(hbox), del_btn, FALSE, FALSE, 0);
736
737
        add_img = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
738
        gtk_widget_show(add_img);
739
740
        add_btn = gtk_button_new();
741
        gtk_container_add(GTK_CONTAINER(add_btn), add_img);
742
        gtk_widget_show(add_btn);
743
        gtk_box_pack_end(GTK_BOX(hbox), add_btn, FALSE, FALSE, 0);
744
745
        g_signal_connect(G_OBJECT(folder_sel_btn), "clicked",
746
                         G_CALLBACK(prefs_filter_action_select_dest_cb),
747
                         action_hbox);
748
        g_signal_connect(G_OBJECT(del_btn), "clicked",
749
                         G_CALLBACK(prefs_filter_action_del_cb), action_hbox);
750
        g_signal_connect(G_OBJECT(add_btn), "clicked",
751
                         G_CALLBACK(prefs_filter_action_add_cb), action_hbox);
752
753
        action_hbox->hbox = hbox;
754
        action_hbox->action_type_optmenu = action_type_optmenu;
755
        action_hbox->label = label;
756
        action_hbox->folder_entry = folder_entry;
757
        action_hbox->cmd_entry = cmd_entry;
758
        action_hbox->address_entry = address_entry;
759
        action_hbox->folder_sel_btn = folder_sel_btn;
760
        action_hbox->clabel_optmenu = clabel_optmenu;
761
        action_hbox->del_btn = del_btn;
762
        action_hbox->add_btn = add_btn;
763
764
        return action_hbox;
765
}
766
767
void prefs_filter_edit_cond_hbox_set(CondHBox *hbox, FilterCond *cond)
768
{
769
        GtkOptionMenu *cond_type_optmenu =
770
                GTK_OPTION_MENU(hbox->cond_type_optmenu);
771
        GtkOptionMenu *match_type_optmenu =
772
                GTK_OPTION_MENU(hbox->match_type_optmenu);
773
        gint cond_index = -1;
774
        gint match_index = -1;
775
        CondMenuType cond_type = PF_COND_NONE;
776
        MatchMenuType match_type = PF_MATCH_NONE;
777
        SizeMatchType size_type = PF_SIZE_LARGER;
778
        AgeMatchType age_type = PF_AGE_LONGER;
779
        StatusMatchType status_type = PF_STATUS_MATCH;
780
781
        switch (cond->type) {
782
        case FLT_COND_HEADER:
783
                cond_type = PF_COND_HEADER; break;
784
        case FLT_COND_TO_OR_CC:
785
                cond_type = PF_COND_TO_OR_CC; break;
786
        case FLT_COND_ANY_HEADER:
787
                cond_type = PF_COND_ANY_HEADER; break;
788
        case FLT_COND_BODY:
789
                cond_type = PF_COND_BODY; break;
790
        case FLT_COND_CMD_TEST:
791
                cond_type = PF_COND_CMD_TEST; break;
792
        case FLT_COND_SIZE_GREATER:
793
                cond_type = PF_COND_SIZE;
794
                if (FLT_IS_NOT_MATCH(cond->match_flag))
795
                        size_type = PF_SIZE_SMALLER;
796
                else
797
                        size_type = PF_SIZE_LARGER;
798
                break;
799
        case FLT_COND_AGE_GREATER:
800
                cond_type = PF_COND_AGE;
801
                if (FLT_IS_NOT_MATCH(cond->match_flag))
802
                        age_type = PF_AGE_SHORTER;
803
                else
804
                        age_type = PF_AGE_LONGER;
805
                break;
806
        case FLT_COND_UNREAD:
807
                cond_type = PF_COND_UNREAD; break;
808
        case FLT_COND_MARK:
809
                cond_type = PF_COND_MARK; break;
810
        case FLT_COND_COLOR_LABEL:
811
                cond_type = PF_COND_COLOR_LABEL; break;
812
        case FLT_COND_MIME:
813
                cond_type = PF_COND_MIME; break;
814
        case FLT_COND_ACCOUNT:
815
                cond_type = PF_COND_ACCOUNT; break;
816
        default:
817
                break;
818
        }
819
820
        switch (cond->type) {
821
        case FLT_COND_HEADER:
822
        case FLT_COND_TO_OR_CC:
823
        case FLT_COND_ANY_HEADER:
824
        case FLT_COND_BODY:
825
                switch (cond->match_type) {
826
                case FLT_CONTAIN:
827
                        if (FLT_IS_NOT_MATCH(cond->match_flag))
828
                                match_type = PF_MATCH_NOT_CONTAIN;
829
                        else
830
                                match_type = PF_MATCH_CONTAIN;
831
                        break;
832
                case FLT_EQUAL:
833
                        if (FLT_IS_NOT_MATCH(cond->match_flag))
834
                                match_type = PF_MATCH_NOT_EQUAL;
835
                        else
836
                                match_type = PF_MATCH_EQUAL;
837
                        break;
838
                case FLT_REGEX:
839
                        if (FLT_IS_NOT_MATCH(cond->match_flag))
840
                                match_type = PF_MATCH_NOT_REGEX;
841
                        else
842
                                match_type = PF_MATCH_REGEX;
843
                        break;
844
                }
845
                break;
846
        case FLT_COND_UNREAD:
847
        case FLT_COND_MARK:
848
        case FLT_COND_COLOR_LABEL:
849
        case FLT_COND_MIME:
850
                if (FLT_IS_NOT_MATCH(cond->match_flag))
851
                        status_type = PF_STATUS_NOT_MATCH;
852
                else
853
                        status_type = PF_STATUS_MATCH;
854
                break;
855
        default:
856
                break;
857
        }
858
859
        if (cond_type == PF_COND_HEADER)
860
                cond_index = procheader_find_header_list
861
                        (hbox->cond_edit->hdr_list, cond->header_name);
862
        else
863
                cond_index = menu_find_option_menu_index
864
                        (cond_type_optmenu, GINT_TO_POINTER(cond_type), NULL);
865
        if (cond_index >= 0) {
866
                GtkWidget *menuitem;
867
868
                if (cond_type == PF_COND_SIZE || cond_type == PF_COND_AGE) {
869
                        gtk_spin_button_set_value
870
                                (GTK_SPIN_BUTTON(hbox->spin_btn),
871
                                 (gfloat)cond->int_value);
872
                } else {
873
                        gtk_entry_set_text(GTK_ENTRY(hbox->key_entry),
874
                                           cond->str_value ?
875
                                           cond->str_value : "");
876
                }
877
                gtk_option_menu_set_history(cond_type_optmenu, cond_index);
878
                menuitem = gtk_menu_get_active
879
                        (GTK_MENU(gtk_option_menu_get_menu(cond_type_optmenu)));
880
                gtk_menu_item_activate(GTK_MENU_ITEM(menuitem));
881
        }
882
883
        match_index = menu_find_option_menu_index
884
                (match_type_optmenu, GINT_TO_POINTER(match_type), NULL);
885
        if (match_index >= 0)
886
                gtk_option_menu_set_history(match_type_optmenu, match_index);
887
        if (cond_type == PF_COND_SIZE)
888
                gtk_option_menu_set_history
889
                        (GTK_OPTION_MENU(hbox->size_match_optmenu), size_type);
890
        else if (cond_type == PF_COND_AGE)
891
                gtk_option_menu_set_history
892
                        (GTK_OPTION_MENU(hbox->age_match_optmenu), age_type);
893
        else if (cond_type == PF_COND_UNREAD || cond_type == PF_COND_MARK ||
894
                 cond_type == PF_COND_COLOR_LABEL || cond_type == PF_COND_MIME)
895
                gtk_option_menu_set_history
896
                        (GTK_OPTION_MENU(hbox->status_match_optmenu),
897
                         status_type);
898
}
899
900
void prefs_filter_edit_action_hbox_set(ActionHBox *hbox, FilterAction *action)
901
{
902
        GtkOptionMenu *type_optmenu = GTK_OPTION_MENU(hbox->action_type_optmenu);
903
        GtkWidget *menu;
904
        ActionMenuType type = PF_ACTION_NONE;
905
906
        menu = gtk_option_menu_get_menu(type_optmenu);
907
908
        switch (action->type) {
909
        case FLT_ACTION_MOVE:
910
                type = PF_ACTION_MOVE; break;
911
        case FLT_ACTION_COPY:
912
                type = PF_ACTION_COPY; break;
913
        case FLT_ACTION_NOT_RECEIVE:
914
                type = PF_ACTION_NOT_RECEIVE; break;
915
        case FLT_ACTION_DELETE:
916
                type = PF_ACTION_DELETE; break;
917
        case FLT_ACTION_EXEC:
918
                type = PF_ACTION_EXEC; break;
919
        case FLT_ACTION_MARK:
920
                type = PF_ACTION_MARK; break;
921
        case FLT_ACTION_COLOR_LABEL:
922
                type = PF_ACTION_COLOR_LABEL; break;
923
        case FLT_ACTION_MARK_READ:
924
                type = PF_ACTION_MARK_READ; break;
925
        case FLT_ACTION_STOP_EVAL:
926
                type = PF_ACTION_STOP_EVAL; break;
927
        default:
928
                break;
929
        }
930
931
        switch (type) {
932
        case PF_ACTION_MOVE:
933
        case PF_ACTION_COPY:
934
                gtk_entry_set_text(GTK_ENTRY(hbox->folder_entry),
935
                                   action->str_value ? action->str_value : "");
936
                break;
937
        case PF_ACTION_EXEC:
938
                gtk_entry_set_text(GTK_ENTRY(hbox->cmd_entry),
939
                                   action->str_value ? action->str_value : "");
940
                break;
941
        case PF_ACTION_COLOR_LABEL:
942
                gtk_option_menu_set_history
943
                        (GTK_OPTION_MENU(hbox->clabel_optmenu),
944
                         action->int_value - 1);
945
                break;
946
        default:
947
                break;
948
        }
949
950
        prefs_filter_edit_set_action_hbox_widgets(hbox, type);
951
}
952
953
void prefs_filter_edit_cond_hbox_select(CondHBox *hbox, CondMenuType type,
954
                                        const gchar *header_name)
955
{
956
        gint index;
957
        GtkOptionMenu *cond_type_optmenu =
958
                GTK_OPTION_MENU(hbox->cond_type_optmenu);
959
        GtkWidget *menu;
960
961
        if (type == PF_COND_HEADER) {
962
                if (header_name)
963
                        index = procheader_find_header_list
964
                                (hbox->cond_edit->hdr_list, header_name);
965
                else
966
                        index = 0;
967
        } else
968
                index = menu_find_option_menu_index
969
                        (cond_type_optmenu, GINT_TO_POINTER(type), NULL);
970
971
        if (index < 0)
972
                index = 0;
973
974
        menu = gtk_option_menu_get_menu(cond_type_optmenu);
975
        gtk_option_menu_set_history(cond_type_optmenu, index);
976
}
977
978
void prefs_filter_edit_set_cond_hbox_widgets(CondHBox *hbox, CondMenuType type)
979
{
980
        switch (type) {
981
        case PF_COND_HEADER:
982
        case PF_COND_TO_OR_CC:
983
        case PF_COND_ANY_HEADER:
984
        case PF_COND_BODY:
985
                gtk_widget_show(hbox->match_type_optmenu);
986
                gtk_widget_hide(hbox->size_match_optmenu);
987
                gtk_widget_hide(hbox->age_match_optmenu);
988
                gtk_widget_hide(hbox->status_match_optmenu);
989
                gtk_widget_show(hbox->key_entry);
990
                gtk_widget_hide(hbox->spin_btn);
991
                gtk_widget_hide(hbox->label);
992
                break;
993
        case PF_COND_CMD_TEST:
994
                gtk_widget_hide(hbox->match_type_optmenu);
995
                gtk_widget_hide(hbox->size_match_optmenu);
996
                gtk_widget_hide(hbox->age_match_optmenu);
997
                gtk_widget_hide(hbox->status_match_optmenu);
998
                gtk_widget_show(hbox->key_entry);
999
                gtk_widget_hide(hbox->spin_btn);
1000
                gtk_widget_hide(hbox->label);
1001
                break;
1002
        case PF_COND_SIZE:
1003
                gtk_widget_hide(hbox->match_type_optmenu);
1004
                gtk_widget_show(hbox->size_match_optmenu);
1005
                gtk_widget_hide(hbox->age_match_optmenu);
1006
                gtk_widget_hide(hbox->status_match_optmenu);
1007
                gtk_widget_hide(hbox->key_entry);
1008
                gtk_widget_show(hbox->spin_btn);
1009
                gtk_widget_show(hbox->label);
1010
                gtk_label_set_text(GTK_LABEL(hbox->label), _("KB"));
1011
                break;
1012
        case PF_COND_AGE:
1013
                gtk_widget_hide(hbox->match_type_optmenu);
1014
                gtk_widget_hide(hbox->size_match_optmenu);
1015
                gtk_widget_show(hbox->age_match_optmenu);
1016
                gtk_widget_hide(hbox->status_match_optmenu);
1017
                gtk_widget_hide(hbox->key_entry);
1018
                gtk_widget_show(hbox->spin_btn);
1019
                gtk_widget_show(hbox->label);
1020
                gtk_label_set_text(GTK_LABEL(hbox->label), _("day(s)"));
1021
                break;
1022
        case PF_COND_UNREAD:
1023
        case PF_COND_MARK:
1024
        case PF_COND_COLOR_LABEL:
1025
        case PF_COND_MIME:
1026
                gtk_widget_hide(hbox->match_type_optmenu);
1027
                gtk_widget_hide(hbox->size_match_optmenu);
1028
                gtk_widget_hide(hbox->age_match_optmenu);
1029
                gtk_widget_show(hbox->status_match_optmenu);
1030
                gtk_widget_hide(hbox->key_entry);
1031
                gtk_widget_hide(hbox->spin_btn);
1032
                gtk_widget_hide(hbox->label);
1033
                break;
1034
        case PF_COND_ACCOUNT:
1035
                gtk_widget_hide(hbox->match_type_optmenu);
1036
                gtk_widget_hide(hbox->size_match_optmenu);
1037
                gtk_widget_hide(hbox->age_match_optmenu);
1038
                gtk_widget_hide(hbox->status_match_optmenu);
1039
                gtk_widget_hide(hbox->key_entry);
1040
                /* gtk_widget_show(hbox->account_optmenu); */
1041
                gtk_widget_hide(hbox->spin_btn);
1042
                gtk_widget_hide(hbox->label);
1043
                break;
1044
        default:
1045
                break;
1046
        }
1047
}
1048
1049
void prefs_filter_edit_set_action_hbox_widgets(ActionHBox *hbox,
1050
                                               ActionMenuType type)
1051
{
1052
        GtkOptionMenu *type_optmenu = GTK_OPTION_MENU(hbox->action_type_optmenu);
1053
        gint index;
1054
1055
        switch (type) {
1056
        case PF_ACTION_MOVE:
1057
        case PF_ACTION_COPY:
1058
                gtk_widget_show(hbox->label);
1059
                gtk_label_set_text(GTK_LABEL(hbox->label), _("folder:"));
1060
                gtk_widget_show(hbox->folder_entry);
1061
                gtk_widget_show(hbox->folder_sel_btn);
1062
                gtk_widget_hide(hbox->cmd_entry);
1063
                gtk_widget_hide(hbox->address_entry);
1064
                gtk_widget_hide(hbox->clabel_optmenu);
1065
                break;
1066
        case PF_ACTION_NOT_RECEIVE:
1067
        case PF_ACTION_DELETE:
1068
        case PF_ACTION_MARK:
1069
        case PF_ACTION_MARK_READ:
1070
        case PF_ACTION_STOP_EVAL:
1071
                gtk_widget_hide(hbox->label);
1072
                gtk_widget_hide(hbox->folder_entry);
1073
                gtk_widget_hide(hbox->folder_sel_btn);
1074
                gtk_widget_hide(hbox->cmd_entry);
1075
                gtk_widget_hide(hbox->address_entry);
1076
                gtk_widget_hide(hbox->clabel_optmenu);
1077
                break;
1078
        case PF_ACTION_EXEC:
1079
        case PF_ACTION_EXEC_ASYNC:
1080
                gtk_widget_hide(hbox->label);
1081
                gtk_widget_hide(hbox->folder_entry);
1082
                gtk_widget_hide(hbox->folder_sel_btn);
1083
                gtk_widget_show(hbox->cmd_entry);
1084
                gtk_widget_hide(hbox->address_entry);
1085
                gtk_widget_hide(hbox->clabel_optmenu);
1086
                break;
1087
        case PF_ACTION_COLOR_LABEL:
1088
                gtk_widget_hide(hbox->label);
1089
                gtk_widget_hide(hbox->folder_entry);
1090
                gtk_widget_hide(hbox->folder_sel_btn);
1091
                gtk_widget_hide(hbox->cmd_entry);
1092
                gtk_widget_hide(hbox->address_entry);
1093
                gtk_widget_show(hbox->clabel_optmenu);
1094
                break;
1095
        case PF_ACTION_FORWARD:
1096
        case PF_ACTION_FORWARD_AS_ATTACHMENT:
1097
        case PF_ACTION_REDIRECT:
1098
                gtk_widget_show(hbox->label);
1099
                gtk_label_set_text(GTK_LABEL(hbox->label), _("address:"));
1100
                gtk_widget_hide(hbox->folder_entry);
1101
                gtk_widget_hide(hbox->folder_sel_btn);
1102
                gtk_widget_hide(hbox->cmd_entry);
1103
                gtk_widget_show(hbox->address_entry);
1104
                gtk_widget_hide(hbox->clabel_optmenu);
1105
                break;
1106
        default:
1107
                break;
1108
        }
1109
1110
        index = menu_find_option_menu_index(type_optmenu, GINT_TO_POINTER(type),
1111
                                            NULL);
1112
        gtk_option_menu_set_history(type_optmenu, index);
1113
        prefs_filter_edit_set_action_hbox_menus_sensitive();
1114
}
1115
1116
static void prefs_filter_edit_set_action_hbox_menu_sensitive
1117
        (ActionHBox *hbox, ActionMenuType type, gboolean sensitive)
1118
{
1119
        GtkWidget *menuitem;
1120
1121
        menuitem = hbox->action_type_menu_items[type];
1122
        if (menuitem)
1123
                gtk_widget_set_sensitive(menuitem, sensitive);
1124
}
1125
1126
static void prefs_filter_edit_set_action_hbox_menus_sensitive(void)
1127
{
1128
        GSList *cur;
1129
        ActionHBox *cur_hbox;
1130
        ActionMenuType menu_type;
1131
        ActionMenuType cur_type;
1132
        gboolean action_menu_selection[PF_ACTION_NONE];
1133
        gboolean action_menu_sensitive[PF_ACTION_NONE];
1134
1135
        prefs_filter_edit_get_action_hbox_menus_selection
1136
                (action_menu_selection);
1137
1138
        for (cur = rule_edit_window.action_hbox_list; cur != NULL;
1139
             cur = cur->next) {
1140
                cur_hbox = (ActionHBox *)cur->data;
1141
                menu_type = prefs_filter_edit_get_action_hbox_type(cur_hbox);
1142
                for (cur_type = PF_ACTION_MOVE; cur_type < PF_ACTION_NONE;
1143
                     cur_type++)
1144
                        action_menu_sensitive[cur_type] = TRUE;
1145
1146
                for (cur_type = PF_ACTION_MOVE; cur_type < PF_ACTION_NONE;
1147
                     cur_type++) {
1148
                        switch (cur_type) {
1149
                        case PF_ACTION_MOVE:
1150
                        case PF_ACTION_NOT_RECEIVE:
1151
                        case PF_ACTION_DELETE:
1152
                                if (action_menu_selection[cur_type] == TRUE &&
1153
                                    menu_type != cur_type) {
1154
                                        action_menu_sensitive[PF_ACTION_MOVE] = FALSE;
1155
                                        action_menu_sensitive[PF_ACTION_NOT_RECEIVE] = FALSE;
1156
                                        action_menu_sensitive[PF_ACTION_DELETE] = FALSE;
1157
                                }
1158
                                break;
1159
                        case PF_ACTION_MARK:
1160
                        case PF_ACTION_COLOR_LABEL:
1161
                        case PF_ACTION_MARK_READ:
1162
                        case PF_ACTION_STOP_EVAL:
1163
                                if (action_menu_selection[cur_type] == TRUE &&
1164
                                    menu_type != cur_type)
1165
                                        action_menu_sensitive[cur_type] = FALSE;
1166
                                break;
1167
                        default:
1168
                                break;
1169
                        }
1170
                }
1171
1172
                for (cur_type = PF_ACTION_MOVE; cur_type < PF_ACTION_NONE;
1173
                     cur_type++) {
1174
                        prefs_filter_edit_set_action_hbox_menu_sensitive
1175
                                (cur_hbox, cur_type,
1176
                                 action_menu_sensitive[cur_type]);
1177
                }
1178
        }
1179
}
1180
1181
static void prefs_filter_edit_get_action_hbox_menus_selection(gboolean *selection)
1182
{
1183
        GSList *cur;
1184
        ActionHBox *cur_hbox;
1185
        ActionMenuType menu_type;
1186
        ActionMenuType cur_type;
1187
1188
        for (cur_type = PF_ACTION_MOVE; cur_type < PF_ACTION_NONE; cur_type++)
1189
                selection[cur_type] = FALSE;
1190
1191
        for (cur = rule_edit_window.action_hbox_list; cur != NULL;
1192
             cur = cur->next) {
1193
                cur_hbox = (ActionHBox *)cur->data;
1194
                menu_type = prefs_filter_edit_get_action_hbox_type(cur_hbox);
1195
                if (menu_type >= PF_ACTION_MOVE && menu_type < PF_ACTION_NONE)
1196
                        selection[menu_type] = TRUE;
1197
        }
1198
}
1199
1200
static ActionMenuType prefs_filter_edit_get_action_hbox_type(ActionHBox *hbox)
1201
{
1202
        GtkWidget *menuitem;
1203
        ActionMenuType type;
1204
1205
        g_return_val_if_fail(hbox != NULL, PF_ACTION_NONE);
1206
1207
        menuitem = gtk_menu_get_active
1208
                (GTK_MENU(gtk_option_menu_get_menu
1209
                        (GTK_OPTION_MENU(hbox->action_type_optmenu))));
1210
        type = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem),
1211
                                                 MENU_VAL_ID));
1212
1213
        return type;
1214
}
1215
1216
void prefs_filter_edit_insert_cond_hbox(FilterCondEdit *cond_edit,
1217
                                        CondHBox *hbox, gint pos)
1218
{
1219
        g_return_if_fail(cond_edit != NULL);
1220
        g_return_if_fail(hbox != NULL);
1221
1222
        if (!cond_edit->cond_hbox_list) {
1223
                gtk_widget_set_sensitive(hbox->del_btn, FALSE);
1224
        } else if (cond_edit->cond_hbox_list &&
1225
                   !cond_edit->cond_hbox_list->next) {
1226
                CondHBox *top_hbox =
1227
                        (CondHBox *)cond_edit->cond_hbox_list->data;
1228
                gtk_widget_set_sensitive(top_hbox->del_btn, TRUE);
1229
        }
1230
1231
        gtk_box_pack_start(GTK_BOX(cond_edit->cond_vbox),
1232
                           hbox->hbox, FALSE, FALSE, 0);
1233
        if (pos >= 0) {
1234
                gtk_box_reorder_child(GTK_BOX(cond_edit->cond_vbox),
1235
                                      hbox->hbox, pos);
1236
        }
1237
1238
        cond_edit->cond_hbox_list =
1239
                g_slist_insert(cond_edit->cond_hbox_list, hbox, pos);
1240
}
1241
1242
static void prefs_filter_edit_insert_action_hbox(ActionHBox *hbox, gint pos)
1243
{
1244
        g_return_if_fail(hbox != NULL);
1245
1246
        if (!rule_edit_window.action_hbox_list) {
1247
                gtk_widget_set_sensitive(hbox->del_btn, FALSE);
1248
        } else if (rule_edit_window.action_hbox_list &&
1249
                   !rule_edit_window.action_hbox_list->next) {
1250
                ActionHBox *top_hbox =
1251
                        (ActionHBox *)rule_edit_window.action_hbox_list->data;
1252
                gtk_widget_set_sensitive(top_hbox->del_btn, TRUE);
1253
        }
1254
1255
        gtk_box_pack_start(GTK_BOX(rule_edit_window.action_vbox),
1256
                           hbox->hbox, FALSE, FALSE, 0);
1257
        if (pos >= 0) {
1258
                gtk_box_reorder_child(GTK_BOX(rule_edit_window.action_vbox),
1259
                                      hbox->hbox, pos);
1260
        }
1261
1262
        rule_edit_window.action_hbox_list =
1263
                g_slist_insert(rule_edit_window.action_hbox_list, hbox, pos);
1264
}
1265
1266
static void prefs_filter_edit_remove_cond_hbox(FilterCondEdit *cond_edit,
1267
                                               CondHBox *hbox)
1268
{
1269
        g_return_if_fail(cond_edit != NULL);
1270
        g_return_if_fail(hbox != NULL);
1271
        g_return_if_fail(cond_edit->cond_hbox_list != NULL);
1272
1273
        cond_edit->cond_hbox_list =
1274
                g_slist_remove(cond_edit->cond_hbox_list, hbox);
1275
        gtk_widget_destroy(hbox->hbox);
1276
        g_free(hbox);
1277
1278
        if (cond_edit->cond_hbox_list && !cond_edit->cond_hbox_list->next) {
1279
                hbox = (CondHBox *)cond_edit->cond_hbox_list->data;
1280
                gtk_widget_set_sensitive(hbox->del_btn, FALSE);
1281
        }
1282
}
1283
1284
static void prefs_filter_edit_remove_action_hbox(ActionHBox *hbox)
1285
{
1286
        g_return_if_fail(hbox != NULL);
1287
        g_return_if_fail(rule_edit_window.action_hbox_list != NULL);
1288
1289
        rule_edit_window.action_hbox_list =
1290
                g_slist_remove(rule_edit_window.action_hbox_list, hbox);
1291
        gtk_widget_destroy(hbox->hbox);
1292
        g_free(hbox);
1293
1294
        prefs_filter_edit_set_action_hbox_menus_sensitive();
1295
1296
        if (rule_edit_window.action_hbox_list &&
1297
            !rule_edit_window.action_hbox_list->next) {
1298
                hbox = (ActionHBox *)rule_edit_window.action_hbox_list->data;
1299
                gtk_widget_set_sensitive(hbox->del_btn, FALSE);
1300
        }
1301
}
1302
1303
void prefs_filter_edit_add_rule_cond(FilterCondEdit *cond_edit,
1304
                                     FilterRule *rule)
1305
{
1306
        CondHBox *hbox;
1307
        GSList *cur;
1308
        FilterCond *cond;
1309
1310
        if (!rule || !rule->cond_list) {
1311
                hbox = prefs_filter_edit_cond_hbox_create(cond_edit);
1312
                prefs_filter_edit_set_cond_hbox_widgets(hbox, PF_COND_HEADER);
1313
                prefs_filter_edit_insert_cond_hbox(cond_edit, hbox, -1);
1314
                if (cond_edit->add_hbox)
1315
                        cond_edit->add_hbox(hbox);
1316
                return;
1317
        }
1318
1319
        for (cur = rule->cond_list; cur != NULL; cur = cur->next) {
1320
                cond = (FilterCond *)cur->data;
1321
1322
                hbox = prefs_filter_edit_cond_hbox_create(cond_edit);
1323
                prefs_filter_edit_cond_hbox_set(hbox, cond);
1324
                prefs_filter_edit_insert_cond_hbox(cond_edit, hbox, -1);
1325
                if (cond_edit->add_hbox)
1326
                        cond_edit->add_hbox(hbox);
1327
        }
1328
}
1329
1330
static void prefs_filter_edit_add_rule_action(FilterRule *rule)
1331
{
1332
        ActionHBox *hbox;
1333
        GSList *cur;
1334
1335
        if (!rule || !rule->action_list) {
1336
                hbox = prefs_filter_edit_action_hbox_create();
1337
                prefs_filter_edit_insert_action_hbox(hbox, -1);
1338
                prefs_filter_edit_set_action_hbox_widgets(hbox, PF_ACTION_MOVE);
1339
                return;
1340
        }
1341
1342
        for (cur = rule->action_list; cur != NULL; cur = cur->next) {
1343
                FilterAction *action = (FilterAction *)cur->data;
1344
1345
                hbox = prefs_filter_edit_action_hbox_create();
1346
                prefs_filter_edit_insert_action_hbox(hbox, -1);
1347
                prefs_filter_edit_action_hbox_set(hbox, action);
1348
        }
1349
}
1350
1351
static void prefs_filter_edit_set_cond_header_menu(FilterCondEdit *cond_edit,
1352
                                                   CondHBox *hbox)
1353
{
1354
        GSList *cur;
1355
        GtkWidget *menu;
1356
        GtkWidget *menuitem;
1357
        gint pos = 0;
1358
        GList *child;
1359
1360
        menu = gtk_option_menu_get_menu
1361
                (GTK_OPTION_MENU(hbox->cond_type_optmenu));
1362
1363
        /* destroy header items */
1364
        child = GTK_MENU_SHELL(menu)->children;
1365
        while (child != NULL) {
1366
                GList *next = child->next;
1367
                menuitem = GTK_WIDGET(child->data);
1368
                if (!g_object_get_data(G_OBJECT(menuitem), "header_str"))
1369
                        break;
1370
                gtk_widget_destroy(menuitem);
1371
                child = next;
1372
        }
1373
1374
        for (cur = cond_edit->hdr_list; cur != NULL; cur = cur->next, pos++) {
1375
                Header *header = (Header *)cur->data;
1376
1377
                menuitem = gtk_menu_item_new_with_label(header->name);
1378
                gtk_widget_show(menuitem);
1379
                gtk_menu_insert(GTK_MENU(menu), menuitem, pos);
1380
                g_object_set_data(G_OBJECT(menuitem), MENU_VAL_ID,
1381
                                  GINT_TO_POINTER(PF_COND_HEADER));
1382
                g_object_set_data(G_OBJECT(menuitem), "header_str",
1383
                                  header->name);
1384
                g_signal_connect(G_OBJECT(menuitem), "activate",
1385
                                 G_CALLBACK(prefs_filter_cond_activated_cb),
1386
                                 hbox);
1387
        }
1388
1389
        if (hbox->cur_type == PF_COND_HEADER)
1390
                prefs_filter_edit_cond_hbox_select
1391
                        (hbox, hbox->cur_type, hbox->cur_header_name);
1392
}
1393
1394
static void prefs_filter_edit_activate_cond_header(FilterCondEdit *cond_edit,
1395
                                                   const gchar *header)
1396
{
1397
        gint index;
1398
        CondHBox *hbox;
1399
        GtkWidget *menu;
1400
        GtkWidget *menuitem;
1401
        GList *cur;
1402
        gchar *menu_header;
1403
1404
        g_return_if_fail(header != NULL);
1405
        g_return_if_fail(cond_edit != NULL);
1406
        g_return_if_fail(cond_edit->cond_hbox_list != NULL);
1407
1408
        hbox = (CondHBox *)cond_edit->cond_hbox_list->data;
1409
        menu = gtk_option_menu_get_menu
1410
                (GTK_OPTION_MENU(hbox->cond_type_optmenu));
1411
1412
        for (cur = GTK_MENU_SHELL(menu)->children, index = 0;
1413
             cur != NULL; cur = cur->next, index++) {
1414
                menuitem = GTK_WIDGET(cur->data);
1415
                menu_header = g_object_get_data(G_OBJECT(menuitem),
1416
                                                "header_str");
1417
                if (!menu_header)
1418
                        break;
1419
                if (!g_ascii_strcasecmp(menu_header, header)) {
1420
                        gtk_option_menu_set_history
1421
                                (GTK_OPTION_MENU(hbox->cond_type_optmenu),
1422
                                 index);
1423
                        gtk_menu_item_activate(GTK_MENU_ITEM(menuitem));
1424
                        break;
1425
                }
1426
        }
1427
}
1428
1429
static gint edit_header_list_dialog_deleted(GtkWidget *widget,
1430
                                            GdkEventAny *event, gpointer data)
1431
{
1432
        edit_header_list_dialog.finished = TRUE;
1433
        return TRUE;
1434
}
1435
1436
static gboolean edit_header_list_dialog_key_pressed(GtkWidget *widget,
1437
                                                    GdkEventKey *event,
1438
                                                    gpointer data)
1439
{
1440
        if (event && event->keyval == GDK_Escape)
1441
                edit_header_list_dialog.finished = TRUE;
1442
        return FALSE;
1443
}
1444
1445
static void edit_header_list_dialog_add(void)
1446
{
1447
        GtkCList *clist = GTK_CLIST(edit_header_list_dialog.clist);
1448
        const gchar *text;
1449
        gchar *ctext[1];
1450
        gint row;
1451
        gchar *row_text;
1452
1453
        text = gtk_entry_get_text(GTK_ENTRY(edit_header_list_dialog.entry));
1454
        if (text[0] == '\0') return;
1455
1456
        for (row = 0; gtk_clist_get_text(clist, row, 0, &row_text) != 0;
1457
             row++) {
1458
                if (g_ascii_strcasecmp(row_text, text) == 0) return;
1459
        }
1460
1461
        ctext[0] = (gchar *)text;
1462
        gtk_clist_append(clist, ctext);
1463
}
1464
1465
static void edit_header_list_dialog_delete(void)
1466
{
1467
        GtkCList *clist = GTK_CLIST(edit_header_list_dialog.clist);
1468
        gint row;
1469
1470
        if (!clist->selection) return;
1471
1472
        row = GPOINTER_TO_INT(clist->selection->data);
1473
        gtk_clist_remove(clist, row);
1474
}
1475
1476
static void edit_header_list_dialog_ok(void)
1477
{
1478
        edit_header_list_dialog.finished = TRUE;
1479
        edit_header_list_dialog.ok = TRUE;
1480
}
1481
1482
static void edit_header_list_dialog_cancel(void)
1483
{
1484
        edit_header_list_dialog.finished = TRUE;
1485
}
1486
1487
static void prefs_filter_edit_edit_header_list_dialog_create(void)
1488
{
1489
        GtkWidget *window;
1490
        GtkWidget *vbox;
1491
        GtkWidget *hbox;
1492
1493
        GtkWidget *vbox2;
1494
        GtkWidget *scrwin;
1495
        GtkWidget *clist;
1496
1497
        GtkWidget *entry_hbox;
1498
        GtkWidget *label;
1499
        GtkWidget *entry;
1500
1501
        GtkWidget *btn_vbox;
1502
        GtkWidget *add_btn;
1503
        GtkWidget *del_btn;
1504
1505
        GtkWidget *confirm_area;
1506
        GtkWidget *ok_btn;
1507
        GtkWidget *cancel_btn;
1508
1509
        gchar *title[1];
1510
1511
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1512
        gtk_container_set_border_width(GTK_CONTAINER(window), 8);
1513
        gtk_window_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
1514
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);
1515
        gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE);
1516
        gtk_window_set_title(GTK_WINDOW(window), _("Edit header list"));
1517
1518
        g_signal_connect(G_OBJECT(window), "delete_event",
1519
                         G_CALLBACK(edit_header_list_dialog_deleted), NULL);
1520
        g_signal_connect(G_OBJECT(window), "key_press_event",
1521
                         G_CALLBACK(edit_header_list_dialog_key_pressed), NULL);
1522
1523
        vbox = gtk_vbox_new(FALSE, 6);
1524
        gtk_container_add(GTK_CONTAINER(window), vbox);
1525
1526
        hbox = gtk_hbox_new(FALSE, 8);
1527
        gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
1528
1529
        vbox2 = gtk_vbox_new(FALSE, 8);
1530
        gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0);
1531
1532
        scrwin = gtk_scrolled_window_new(NULL, NULL);
1533
        gtk_widget_set_size_request(scrwin, 120, 160);
1534
        gtk_box_pack_start(GTK_BOX(vbox2), scrwin, TRUE, TRUE, 0);
1535
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrwin),
1536
                                       GTK_POLICY_AUTOMATIC,
1537
                                       GTK_POLICY_AUTOMATIC);
1538
1539
        title[0] = _("Headers");
1540
        clist = gtk_clist_new_with_titles(1, title);
1541
        gtk_container_add(GTK_CONTAINER(scrwin), clist);
1542
        gtk_clist_set_column_width(GTK_CLIST(clist), 0, 80);
1543
        gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_BROWSE);
1544
        gtkut_clist_set_redraw(GTK_CLIST(clist));
1545
        GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[0].button,
1546
                               GTK_CAN_FOCUS);
1547
1548
        entry_hbox = gtk_hbox_new(FALSE, 8);
1549
        gtk_box_pack_start(GTK_BOX(vbox), entry_hbox, FALSE, TRUE, 0);
1550
1551
        label = gtk_label_new(_("Header:"));
1552
        gtk_box_pack_start(GTK_BOX(entry_hbox), label, FALSE, FALSE, 0);
1553
1554
        entry = gtk_entry_new();
1555
        gtk_box_pack_start(GTK_BOX(entry_hbox), entry, TRUE, TRUE, 0);
1556
1557
        btn_vbox = gtk_vbox_new(FALSE, 8);
1558
        gtk_box_pack_start(GTK_BOX(hbox), btn_vbox, FALSE, FALSE, 0);
1559
1560
        add_btn = gtk_button_new_with_label(_("Add"));
1561
        gtk_box_pack_start(GTK_BOX(btn_vbox), add_btn, FALSE, FALSE, 0);
1562
1563
        del_btn = gtk_button_new_with_label(_(" Delete "));
1564
        gtk_box_pack_start(GTK_BOX(btn_vbox), del_btn, FALSE, FALSE, 0);
1565
1566
        gtkut_stock_button_set_create(&confirm_area, &ok_btn, GTK_STOCK_OK,
1567
                                      &cancel_btn, GTK_STOCK_CANCEL,
1568
                                      NULL, NULL);
1569
        gtk_box_pack_end(GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
1570
        gtk_widget_grab_default(ok_btn);
1571
1572
        g_signal_connect(G_OBJECT(add_btn), "clicked",
1573
                         G_CALLBACK(edit_header_list_dialog_add), NULL);
1574
        g_signal_connect(G_OBJECT(del_btn), "clicked",
1575
                         G_CALLBACK(edit_header_list_dialog_delete), NULL);
1576
        g_signal_connect(G_OBJECT(ok_btn), "clicked",
1577
                         G_CALLBACK(edit_header_list_dialog_ok), NULL);
1578
        g_signal_connect(G_OBJECT(cancel_btn), "clicked",
1579
                         G_CALLBACK(edit_header_list_dialog_cancel), NULL);
1580
1581
        manage_window_set_transient(GTK_WINDOW(window));
1582
1583
        gtk_widget_show_all(window);
1584
1585
        edit_header_list_dialog.window = window;
1586
        edit_header_list_dialog.clist = clist;
1587
        edit_header_list_dialog.entry = entry;
1588
        edit_header_list_dialog.finished = FALSE;
1589
        edit_header_list_dialog.ok = FALSE;
1590
}
1591
1592
static void prefs_filter_edit_edit_header_list_dialog_set(void)
1593
{
1594
        GtkCList *clist = GTK_CLIST(edit_header_list_dialog.clist);
1595
        GSList *list;
1596
        GSList *cur;
1597
        gchar *text[1];
1598
1599
        gtk_clist_freeze(clist);
1600
1601
        list = prefs_filter_get_user_header_list();
1602
        for (cur = list; cur != NULL; cur = cur->next) {
1603
                Header *header = (Header *)cur->data;
1604
                text[0] = header->name;
1605
                gtk_clist_append(clist, text);
1606
        }
1607
1608
        gtk_clist_thaw(clist);
1609
}
1610
1611
static GSList *prefs_filter_edit_edit_header_list_dialog_get(void)
1612
{
1613
        GtkCList *clist = GTK_CLIST(edit_header_list_dialog.clist);
1614
        gint row;
1615
        gchar *text;
1616
        GSList *list = NULL;
1617
1618
        for (row = 0; gtk_clist_get_text(clist, row, 0, &text) != 0; row++)
1619
                list = procheader_add_header_list(list, text, NULL);
1620
1621
        return list;
1622
}
1623
1624
static void prefs_filter_edit_edit_header_list(FilterCondEdit *cond_edit)
1625
{
1626
        GSList *list;
1627
        GSList *cur;
1628
1629
        prefs_filter_edit_edit_header_list_dialog_create();
1630
        prefs_filter_edit_edit_header_list_dialog_set();
1631
1632
        while (edit_header_list_dialog.finished == FALSE)
1633
                gtk_main_iteration();
1634
1635
        if (edit_header_list_dialog.ok == TRUE) {
1636
                list = prefs_filter_edit_edit_header_list_dialog_get();
1637
                prefs_filter_set_user_header_list(list);
1638
                prefs_filter_edit_update_header_list(cond_edit);
1639
                for (cur = cond_edit->cond_hbox_list; cur != NULL;
1640
                     cur = cur->next) {
1641
                        CondHBox *hbox = (CondHBox *)cur->data;
1642
                        prefs_filter_edit_set_cond_header_menu(cond_edit, hbox);
1643
                }
1644
                prefs_filter_write_user_header_list();
1645
        }
1646
1647
        gtk_widget_destroy(edit_header_list_dialog.window);
1648
        edit_header_list_dialog.window = NULL;
1649
        edit_header_list_dialog.clist = NULL;
1650
        edit_header_list_dialog.entry = NULL;
1651
        edit_header_list_dialog.finished = FALSE;
1652
        edit_header_list_dialog.ok = FALSE;
1653
}
1654
1655
FilterCond *prefs_filter_edit_cond_hbox_to_cond(CondHBox *hbox,
1656
                                                gboolean case_sens,
1657
                                                gchar **error_msg)
1658
{
1659
        FilterCond *cond = NULL;
1660
        GtkWidget *cond_type_menuitem;
1661
        CondMenuType cond_menu_type;
1662
        MatchMenuType match_menu_type;
1663
        const gchar *header_name;
1664
        const gchar *key_str;
1665
        gint int_value;
1666
        FilterMatchType match_type = FLT_CONTAIN;
1667
        FilterMatchFlag match_flag = 0;
1668
        SizeMatchType size_type;
1669
        AgeMatchType age_type;
1670
        StatusMatchType status_type;
1671
        gchar *error_msg_ = NULL;
1672
1673
        cond_type_menuitem = gtk_menu_get_active
1674
                (GTK_MENU(gtk_option_menu_get_menu
1675
                        (GTK_OPTION_MENU(hbox->cond_type_optmenu))));
1676
        cond_menu_type = GPOINTER_TO_INT
1677
                (g_object_get_data(G_OBJECT(cond_type_menuitem), MENU_VAL_ID));
1678
1679
        match_menu_type = menu_get_option_menu_active_index
1680
                (GTK_OPTION_MENU(hbox->match_type_optmenu));
1681
1682
        key_str = gtk_entry_get_text(GTK_ENTRY(hbox->key_entry));
1683
1684
        switch (match_menu_type) {
1685
        case PF_MATCH_CONTAIN:
1686
                match_type = FLT_CONTAIN;
1687
                break;
1688
        case PF_MATCH_NOT_CONTAIN:
1689
                match_type = FLT_CONTAIN;
1690
                match_flag |= FLT_NOT_MATCH;
1691
                break;
1692
        case PF_MATCH_EQUAL:
1693
                match_type = FLT_EQUAL;
1694
                break;
1695
        case PF_MATCH_NOT_EQUAL:
1696
                match_type = FLT_EQUAL;
1697
                match_flag |= FLT_NOT_MATCH;
1698
                break;
1699
        case PF_MATCH_REGEX:
1700
                match_type = FLT_REGEX;
1701
                break;
1702
        case PF_MATCH_NOT_REGEX:
1703
                match_type = FLT_REGEX;
1704
                match_flag |= FLT_NOT_MATCH;
1705
                break;
1706
        default:
1707
                break;
1708
        }
1709
1710
        if (case_sens)
1711
                match_flag |= FLT_CASE_SENS;
1712
1713
        switch (cond_menu_type) {
1714
        case PF_COND_HEADER:
1715
                header_name = g_object_get_data
1716
                        (G_OBJECT(cond_type_menuitem), "header_str");
1717
                cond = filter_cond_new(FLT_COND_HEADER,
1718
                                       match_type, match_flag,
1719
                                       header_name, key_str);
1720
                break;
1721
        case PF_COND_TO_OR_CC:
1722
                cond = filter_cond_new(FLT_COND_TO_OR_CC, match_type,
1723
                                       match_flag, NULL, key_str);
1724
                break;
1725
        case PF_COND_ANY_HEADER:
1726
                cond = filter_cond_new(FLT_COND_ANY_HEADER, match_type,
1727
                                       match_flag, NULL, key_str);
1728
                break;
1729
        case PF_COND_BODY:
1730
                cond = filter_cond_new(FLT_COND_BODY, match_type,
1731
                                       match_flag, NULL, key_str);
1732
                break;
1733
        case PF_COND_CMD_TEST:
1734
                if (key_str && *key_str)
1735
                        cond = filter_cond_new(FLT_COND_CMD_TEST,
1736
                                               0, 0, NULL, key_str);
1737
                else
1738
                        error_msg_ = _("Command is not specified.");
1739
                break;
1740
        case PF_COND_SIZE:
1741
                size_type = menu_get_option_menu_active_index
1742
                         (GTK_OPTION_MENU(hbox->size_match_optmenu));
1743
                match_flag = size_type == PF_SIZE_LARGER ? 0 : FLT_NOT_MATCH;
1744
                int_value = gtk_spin_button_get_value_as_int
1745
                        (GTK_SPIN_BUTTON(hbox->spin_btn));
1746
                cond = filter_cond_new(FLT_COND_SIZE_GREATER,
1747
                                       0, match_flag, NULL, itos(int_value));
1748
                break;
1749
        case PF_COND_AGE:
1750
                age_type = menu_get_option_menu_active_index
1751
                         (GTK_OPTION_MENU(hbox->age_match_optmenu));
1752
                match_flag = age_type == PF_AGE_LONGER ? 0 : FLT_NOT_MATCH;
1753
                int_value = gtk_spin_button_get_value_as_int
1754
                        (GTK_SPIN_BUTTON(hbox->spin_btn));
1755
                cond = filter_cond_new(FLT_COND_AGE_GREATER,
1756
                                       0, match_flag, NULL, itos(int_value));
1757
                break;
1758
        case PF_COND_UNREAD:
1759
                status_type = menu_get_option_menu_active_index
1760
                        (GTK_OPTION_MENU(hbox->status_match_optmenu));
1761
                match_flag = status_type == PF_STATUS_MATCH ? 0 : FLT_NOT_MATCH;
1762
                cond = filter_cond_new(FLT_COND_UNREAD, 0, match_flag,
1763
                                       NULL, NULL);
1764
                break;
1765
        case PF_COND_MARK:
1766
                status_type = menu_get_option_menu_active_index
1767
                        (GTK_OPTION_MENU(hbox->status_match_optmenu));
1768
                match_flag = status_type == PF_STATUS_MATCH ? 0 : FLT_NOT_MATCH;
1769
                cond = filter_cond_new(FLT_COND_MARK, 0, match_flag,
1770
                                       NULL, NULL);
1771
                break;
1772
        case PF_COND_COLOR_LABEL:
1773
                status_type = menu_get_option_menu_active_index
1774
                        (GTK_OPTION_MENU(hbox->status_match_optmenu));
1775
                match_flag = status_type == PF_STATUS_MATCH ? 0 : FLT_NOT_MATCH;
1776
                cond = filter_cond_new(FLT_COND_COLOR_LABEL, 0, match_flag,
1777
                                       NULL, NULL);
1778
                break;
1779
        case PF_COND_MIME:
1780
                status_type = menu_get_option_menu_active_index
1781
                        (GTK_OPTION_MENU(hbox->status_match_optmenu));
1782
                match_flag = status_type == PF_STATUS_MATCH ? 0 : FLT_NOT_MATCH;
1783
                cond = filter_cond_new(FLT_COND_MIME, 0, match_flag,
1784
                                       NULL, NULL);
1785
                break;
1786
        case PF_COND_ACCOUNT:
1787
        case PF_COND_EDIT_HEADER:
1788
        default:
1789
                break;
1790
        }
1791
1792
        if (error_msg)
1793
                *error_msg = error_msg_;
1794
1795
        return cond;
1796
}
1797
1798
FilterAction *prefs_filter_edit_action_hbox_to_action(ActionHBox *hbox,
1799
                                                      gchar **error_msg)
1800
{
1801
        FilterAction *action = NULL;
1802
        ActionMenuType action_menu_type;
1803
        const gchar *str;
1804
        guint color;
1805
        gchar *error_msg_ = NULL;
1806
1807
        action_menu_type = prefs_filter_edit_get_action_hbox_type(hbox);
1808
1809
        switch (action_menu_type) {
1810
        case PF_ACTION_MOVE:
1811
                str = gtk_entry_get_text(GTK_ENTRY(hbox->folder_entry));
1812
                if (str && *str)
1813
                        action = filter_action_new(FLT_ACTION_MOVE,
1814
                                                   str);
1815
                else
1816
                        error_msg_ = _("Destination folder is not specified.");
1817
                break;
1818
        case PF_ACTION_COPY:
1819
                str = gtk_entry_get_text(GTK_ENTRY(hbox->folder_entry));
1820
                if (str && *str)
1821
                        action = filter_action_new(FLT_ACTION_COPY, str);
1822
                else
1823
                        error_msg_ = _("Destination folder is not specified.");
1824
                break;
1825
        case PF_ACTION_NOT_RECEIVE:
1826
                action = filter_action_new(FLT_ACTION_NOT_RECEIVE, NULL);
1827
                break;
1828
        case PF_ACTION_DELETE:
1829
                action = filter_action_new(FLT_ACTION_DELETE, NULL);
1830
                break;
1831
        case PF_ACTION_EXEC:
1832
                str = gtk_entry_get_text(GTK_ENTRY(hbox->cmd_entry));
1833
                if (str && *str)
1834
                        action = filter_action_new(FLT_ACTION_EXEC, str);
1835
                else
1836
                        error_msg_ = _("Command is not specified.");
1837
                break;
1838
        case PF_ACTION_EXEC_ASYNC:
1839
                str = gtk_entry_get_text(GTK_ENTRY(hbox->cmd_entry));
1840
                if (str && *str)
1841
                        action = filter_action_new(FLT_ACTION_EXEC_ASYNC, str);
1842
                else
1843
                        error_msg_ = _("Command is not specified.");
1844
                break;
1845
        case PF_ACTION_MARK:
1846
                action = filter_action_new(FLT_ACTION_MARK, NULL);
1847
                break;
1848
        case PF_ACTION_COLOR_LABEL:
1849
                color = colorlabel_get_color_menu_active_item
1850
                        (gtk_option_menu_get_menu
1851
                         (GTK_OPTION_MENU(hbox->clabel_optmenu)));
1852
                action = filter_action_new(FLT_ACTION_COLOR_LABEL,
1853
                                           itos(color));
1854
                break;
1855
        case PF_ACTION_MARK_READ:
1856
                action = filter_action_new(FLT_ACTION_MARK_READ, NULL);
1857
                break;
1858
        case PF_ACTION_FORWARD:
1859
        case PF_ACTION_FORWARD_AS_ATTACHMENT:
1860
        case PF_ACTION_REDIRECT:
1861
                break;
1862
        case PF_ACTION_STOP_EVAL:
1863
                action = filter_action_new(FLT_ACTION_STOP_EVAL, NULL);
1864
                break;
1865
        case PF_ACTION_SEPARATOR:
1866
        default:
1867
                break;
1868
        }
1869
1870
        if (error_msg)
1871
                *error_msg = error_msg_;
1872
1873
        return action;
1874
}
1875
1876
GSList *prefs_filter_edit_cond_edit_to_list(FilterCondEdit *cond_edit,
1877
                                            gboolean case_sens)
1878
{
1879
        GSList *cur;
1880
        FilterCond *cond;
1881
        GSList *cond_list = NULL;
1882
1883
        for (cur = cond_edit->cond_hbox_list; cur != NULL; cur = cur->next) {
1884
                CondHBox *hbox = (CondHBox *)cur->data;
1885
                gchar *error_msg;
1886
1887
                cond = prefs_filter_edit_cond_hbox_to_cond(hbox, case_sens,
1888
                                                           &error_msg);
1889
                if (cond) {
1890
                        cond_list = g_slist_append(cond_list, cond);
1891
                } else {
1892
                        if (!error_msg)
1893
                                error_msg = _("Invalid condition exists.");
1894
                        alertpanel_error("%s", error_msg);
1895
                        filter_cond_list_free(cond_list);
1896
                        return NULL;
1897
                }
1898
        }
1899
1900
        return cond_list;
1901
}
1902
1903
static FilterRule *prefs_filter_edit_dialog_to_rule(void)
1904
{
1905
        FilterRule *rule = NULL;
1906
        GSList *cur;
1907
        const gchar *rule_name;
1908
        FilterBoolOp bool_op = FLT_OR;
1909
        GSList *cond_list = NULL;
1910
        GSList *action_list = NULL;
1911
        GtkWidget *bool_op_menuitem;
1912
        gchar *error_msg = NULL;
1913
1914
        rule_name = gtk_entry_get_text(GTK_ENTRY(rule_edit_window.name_entry));
1915
        if (!rule_name || *rule_name == '\0') {
1916
                error_msg = _("Rule name is not specified.");
1917
                goto error;
1918
        }
1919
1920
        bool_op_menuitem = gtk_menu_get_active
1921
                (GTK_MENU(gtk_option_menu_get_menu
1922
                        (GTK_OPTION_MENU(rule_edit_window.bool_op_optmenu))));
1923
        bool_op = GPOINTER_TO_INT
1924
                (g_object_get_data(G_OBJECT(bool_op_menuitem), MENU_VAL_ID));
1925
1926
        cond_list = prefs_filter_edit_cond_edit_to_list
1927
                (&rule_edit_window.cond_edit, FALSE);
1928
        if (!cond_list)
1929
                return NULL;
1930
1931
        for (cur = rule_edit_window.action_hbox_list; cur != NULL;
1932
             cur = cur->next) {
1933
                ActionHBox *hbox = (ActionHBox *)cur->data;
1934
                FilterAction *action;
1935
1936
                action = prefs_filter_edit_action_hbox_to_action(hbox,
1937
                                                                 &error_msg);
1938
                if (action)
1939
                        action_list = g_slist_append(action_list, action);
1940
                else {
1941
                        if (!error_msg)
1942
                                error_msg = _("Invalid action exists.");
1943
                        goto error;
1944
                }
1945
        }
1946
1947
error:
1948
        if (error_msg || !cond_list || !action_list) {
1949
                if (!error_msg) {
1950
                        if (!cond_list)
1951
                                error_msg = _("Condition not exist.");
1952
                        else
1953
                                error_msg = _("Action not exist.");
1954
                }
1955
                alertpanel_error("%s", error_msg);
1956
                if (cond_list)
1957
                        filter_cond_list_free(cond_list);
1958
                if (action_list)
1959
                        filter_action_list_free(action_list);
1960
                return NULL;
1961
        }
1962
1963
        rule = filter_rule_new(rule_name, bool_op, cond_list, action_list);
1964
1965
        return rule;
1966
}
1967
1968
/* callback functions */
1969
1970
static gint prefs_filter_edit_deleted(GtkWidget *widget, GdkEventAny *event,
1971
                                      gpointer data)
1972
{
1973
        prefs_filter_edit_cancel();
1974
        return TRUE;
1975
}
1976
1977
static gboolean prefs_filter_edit_key_pressed(GtkWidget *widget,
1978
                                              GdkEventKey *event,
1979
                                              gpointer data)
1980
{
1981
        if (event && event->keyval == GDK_Escape)
1982
                prefs_filter_edit_cancel();
1983
        return FALSE;
1984
}
1985
1986
static void prefs_filter_edit_ok(void)
1987
{
1988
        FilterRule *rule;
1989
1990
        rule = prefs_filter_edit_dialog_to_rule();
1991
        if (rule) {
1992
                rule_edit_window.new_rule = rule;
1993
                rule_edit_window.edit_finished = TRUE;
1994
        }
1995
}
1996
1997
static void prefs_filter_edit_cancel(void)
1998
{
1999
        rule_edit_window.new_rule = NULL;
2000
        rule_edit_window.edit_finished = TRUE;
2001
}
2002
2003
static void prefs_filter_cond_activated_cb(GtkWidget *widget, gpointer data)
2004
{
2005
        CondHBox *hbox = (CondHBox *)data;
2006
        FilterCondEdit *cond_edit = hbox->cond_edit;
2007
        CondMenuType type;
2008
2009
        type = GPOINTER_TO_INT
2010
                (g_object_get_data(G_OBJECT(widget), MENU_VAL_ID));
2011
2012
        if (type == PF_COND_EDIT_HEADER) {
2013
                prefs_filter_edit_edit_header_list(cond_edit);
2014
                prefs_filter_edit_cond_hbox_select
2015
                        (hbox, hbox->cur_type, hbox->cur_header_name);
2016
        } else {
2017
                hbox->cur_type = type;
2018
                g_free(hbox->cur_header_name);
2019
                hbox->cur_header_name = NULL;
2020
2021
                prefs_filter_edit_set_cond_hbox_widgets(hbox, type);
2022
                if (type == PF_COND_HEADER) {
2023
                        gchar *header_name;
2024
                        gchar *header_field;
2025
2026
                        header_name = (gchar *)g_object_get_data
2027
                                (G_OBJECT(widget), "header_str");
2028
                        header_field = prefs_filter_get_msg_header_field
2029
                                (header_name);
2030
                        if (header_field)
2031
                                gtk_entry_set_text(GTK_ENTRY(hbox->key_entry),
2032
                                                   header_field);
2033
                        hbox->cur_header_name = g_strdup(header_name);
2034
                }
2035
        }
2036
}
2037
2038
static void prefs_filter_action_activated_cb(GtkWidget *widget, gpointer data)
2039
{
2040
        ActionHBox *hbox = (ActionHBox *)data;
2041
        ActionMenuType type;
2042
2043
        type = GPOINTER_TO_INT
2044
                (g_object_get_data(G_OBJECT(widget), MENU_VAL_ID));
2045
        prefs_filter_edit_set_action_hbox_widgets(hbox, type);
2046
}
2047
2048
static void prefs_filter_action_select_dest_cb(GtkWidget *widget, gpointer data)
2049
{
2050
        ActionHBox *hbox = (ActionHBox *)data;
2051
2052
        FolderItem *dest;
2053
        gchar *id;
2054
2055
        dest = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL);
2056
        if (!dest || !dest->path) return;
2057
2058
        id = folder_item_get_identifier(dest);
2059
        if (id) {
2060
                gtk_entry_set_text(GTK_ENTRY(hbox->folder_entry), id);
2061
                g_free(id);
2062
        }
2063
}
2064
2065
static void prefs_filter_cond_del_cb(GtkWidget *widget, gpointer data)
2066
{
2067
        CondHBox *hbox = (CondHBox *)data;
2068
        FilterCondEdit *cond_edit = hbox->cond_edit;
2069
2070
        if (cond_edit->cond_hbox_list && cond_edit->cond_hbox_list->next)
2071
                prefs_filter_edit_remove_cond_hbox(cond_edit, hbox);
2072
}
2073
2074
static void prefs_filter_cond_add_cb(GtkWidget *widget, gpointer data)
2075
{
2076
        CondHBox *hbox = (CondHBox *)data;
2077
        CondHBox *new_hbox;
2078
        FilterCondEdit *cond_edit = hbox->cond_edit;
2079
        gint index;
2080
2081
        index = g_slist_index(cond_edit->cond_hbox_list, hbox);
2082
        g_return_if_fail(index >= 0);
2083
        new_hbox = prefs_filter_edit_cond_hbox_create(cond_edit);
2084
        prefs_filter_edit_set_cond_hbox_widgets(new_hbox, PF_COND_HEADER);
2085
        prefs_filter_edit_insert_cond_hbox(cond_edit, new_hbox, index + 1);
2086
        if (cond_edit->add_hbox)
2087
                cond_edit->add_hbox(new_hbox);
2088
}
2089
2090
static void prefs_filter_action_del_cb(GtkWidget *widget, gpointer data)
2091
{
2092
        ActionHBox *hbox = (ActionHBox *)data;
2093
2094
        if (rule_edit_window.action_hbox_list &&
2095
            rule_edit_window.action_hbox_list->next)
2096
                prefs_filter_edit_remove_action_hbox(hbox);
2097
}
2098
2099
static void prefs_filter_action_add_cb(GtkWidget *widget, gpointer data)
2100
{
2101
        ActionHBox *hbox = (ActionHBox *)data;
2102
        ActionHBox *new_hbox;
2103
        gboolean action_menu_selection[PF_ACTION_NONE];
2104
        gint index;
2105
2106
        prefs_filter_edit_get_action_hbox_menus_selection(action_menu_selection);
2107
2108
        index = g_slist_index(rule_edit_window.action_hbox_list, hbox);
2109
        g_return_if_fail(index >= 0);
2110
        new_hbox = prefs_filter_edit_action_hbox_create();
2111
        prefs_filter_edit_insert_action_hbox(new_hbox, index + 1);
2112
        if (action_menu_selection[PF_ACTION_MOVE] == TRUE ||
2113
            action_menu_selection[PF_ACTION_NOT_RECEIVE] == TRUE ||
2114
            action_menu_selection[PF_ACTION_DELETE] == TRUE)
2115
                prefs_filter_edit_set_action_hbox_widgets(new_hbox,
2116
                                                          PF_ACTION_COPY);
2117
        else
2118
                prefs_filter_edit_set_action_hbox_widgets(new_hbox,
2119
                                                          PF_ACTION_MOVE);
2120
}