Statistics
| Revision:

root / src / prefs_filter_edit.c @ 1533

History | View | Annotate | Download (61.1 kB)

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