2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2001 Hiroyuki Yamamoto
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.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #include <gdk/gdkkeysyms.h>
37 #include "prefs_matcher.h"
38 #include "prefs_scoring.h"
39 #include "prefs_common.h"
40 #include "mainwindow.h"
41 #include "foldersel.h"
42 #include "manage_window.h"
46 #include "alertpanel.h"
50 static struct Scoring {
54 GtkWidget *cond_entry;
55 GtkWidget *score_entry;
57 GtkWidget *cond_clist;
61 parameter name, default value, pointer to the prefs variable, data type,
62 pointer to the widget pointer,
63 pointer to the function for data setting,
64 pointer to the function for widget setting
68 #define VSPACING_NARROW 4
69 #define DEFAULT_ENTRY_WIDTH 80
70 #define PREFSBUFSIZE 1024
72 /* widget creating functions */
73 static void prefs_scoring_create (void);
75 static void prefs_scoring_set_dialog (ScoringProp * prop);
76 static void prefs_scoring_set_list (void);
78 /* callback functions */
79 /* static void prefs_scoring_select_dest_cb (void); */
80 static void prefs_scoring_register_cb (void);
81 static void prefs_scoring_substitute_cb (void);
82 static void prefs_scoring_delete_cb (void);
83 static void prefs_scoring_up (void);
84 static void prefs_scoring_down (void);
85 static void prefs_scoring_select (GtkCList *clist,
90 static gint prefs_scoring_deleted (GtkWidget *widget,
93 static void prefs_scoring_key_pressed (GtkWidget *widget,
96 static void prefs_scoring_cancel (void);
97 static void prefs_scoring_ok (void);
99 static void prefs_scoring_condition_define (void);
100 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop);
101 static void prefs_scoring_select_set_dialog(ScoringProp * prop);
102 static void prefs_scoring_reset_dialog(void);
104 void prefs_scoring_open(void)
106 inc_autocheck_timer_remove();
108 if (!scoring.window) {
109 prefs_scoring_create();
112 manage_window_set_transient(GTK_WINDOW(scoring.window));
113 gtk_widget_grab_focus(scoring.ok_btn);
115 prefs_scoring_set_dialog(NULL);
117 gtk_widget_show(scoring.window);
120 void prefs_scoring_open_with_scoring(ScoringProp * prop)
122 inc_autocheck_timer_remove();
124 if (!scoring.window) {
125 prefs_scoring_create();
128 manage_window_set_transient(GTK_WINDOW(scoring.window));
129 gtk_widget_grab_focus(scoring.ok_btn);
131 prefs_scoring_set_dialog(prop);
133 gtk_widget_show(scoring.window);
136 static void prefs_scoring_create(void)
141 GtkWidget *cancel_btn;
142 GtkWidget *confirm_area;
150 GtkWidget *cond_label;
151 GtkWidget *cond_entry;
153 GtkWidget *score_label;
154 GtkWidget *score_entry;
157 GtkWidget *subst_btn;
160 GtkWidget *cond_hbox;
161 GtkWidget *cond_scrolledwin;
162 GtkWidget *cond_clist;
168 gchar *title[] = {_("Registered rules")};
170 debug_print(_("Creating scoring setting window...\n"));
172 window = gtk_window_new (GTK_WINDOW_DIALOG);
173 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
174 gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
175 gtk_window_set_modal (GTK_WINDOW (window), TRUE);
176 gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
178 vbox = gtk_vbox_new (FALSE, 6);
179 gtk_widget_show (vbox);
180 gtk_container_add (GTK_CONTAINER (window), vbox);
182 gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
183 &cancel_btn, _("Cancel"), NULL, NULL);
184 gtk_widget_show (confirm_area);
185 gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
186 gtk_widget_grab_default (ok_btn);
188 gtk_window_set_title (GTK_WINDOW(window),
189 _("Scoring setting"));
190 gtk_signal_connect (GTK_OBJECT(window), "delete_event",
191 GTK_SIGNAL_FUNC(prefs_scoring_deleted), NULL);
192 gtk_signal_connect (GTK_OBJECT(window), "key_press_event",
193 GTK_SIGNAL_FUNC(prefs_scoring_key_pressed), NULL);
194 gtk_signal_connect (GTK_OBJECT(window), "focus_in_event",
195 GTK_SIGNAL_FUNC(manage_window_focus_in), NULL);
196 gtk_signal_connect (GTK_OBJECT(window), "focus_out_event",
197 GTK_SIGNAL_FUNC(manage_window_focus_out), NULL);
198 gtk_signal_connect (GTK_OBJECT(ok_btn), "clicked",
199 GTK_SIGNAL_FUNC(prefs_scoring_ok), NULL);
200 gtk_signal_connect (GTK_OBJECT(cancel_btn), "clicked",
201 GTK_SIGNAL_FUNC(prefs_scoring_cancel), NULL);
203 vbox1 = gtk_vbox_new (FALSE, VSPACING);
204 gtk_widget_show (vbox1);
205 gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
206 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
208 cond_label = gtk_label_new (_("Condition"));
209 gtk_widget_show (cond_label);
210 gtk_misc_set_alignment (GTK_MISC (cond_label), 0, 0.5);
211 gtk_box_pack_start (GTK_BOX (vbox1), cond_label, FALSE, FALSE, 0);
213 hbox1 = gtk_hbox_new (FALSE, VSPACING);
214 gtk_widget_show (vbox1);
215 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
216 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
218 cond_entry = gtk_entry_new ();
219 gtk_widget_show (cond_entry);
220 gtk_widget_set_usize (cond_entry, 300, -1);
221 gtk_box_pack_start (GTK_BOX (hbox1), cond_entry, TRUE, TRUE, 0);
223 cond_btn = gtk_button_new_with_label (_("Define ..."));
224 gtk_widget_show (cond_btn);
225 gtk_box_pack_start (GTK_BOX (hbox1), cond_btn, FALSE, FALSE, 0);
226 gtk_signal_connect (GTK_OBJECT (cond_btn), "clicked",
227 GTK_SIGNAL_FUNC (prefs_scoring_condition_define),
230 hbox1 = gtk_hbox_new (FALSE, VSPACING);
231 gtk_widget_show (vbox1);
232 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
233 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
235 score_label = gtk_label_new (_("Score"));
236 gtk_widget_show (score_label);
237 gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
238 gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
240 score_entry = gtk_entry_new ();
241 gtk_widget_show (score_entry);
242 gtk_widget_set_usize (score_entry, 50, -1);
243 gtk_box_pack_start (GTK_BOX (hbox1), score_entry, FALSE, FALSE, 0);
245 /* register / substitute / delete */
247 reg_hbox = gtk_hbox_new (FALSE, 4);
248 gtk_widget_show (reg_hbox);
249 gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
251 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
252 gtk_widget_show (arrow);
253 gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
254 gtk_widget_set_usize (arrow, -1, 16);
256 btn_hbox = gtk_hbox_new (TRUE, 4);
257 gtk_widget_show (btn_hbox);
258 gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
260 reg_btn = gtk_button_new_with_label (_("Register"));
261 gtk_widget_show (reg_btn);
262 gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
263 gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
264 GTK_SIGNAL_FUNC (prefs_scoring_register_cb), NULL);
266 subst_btn = gtk_button_new_with_label (_(" Substitute "));
267 gtk_widget_show (subst_btn);
268 gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
269 gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
270 GTK_SIGNAL_FUNC (prefs_scoring_substitute_cb),
273 del_btn = gtk_button_new_with_label (_("Delete"));
274 gtk_widget_show (del_btn);
275 gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
276 gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
277 GTK_SIGNAL_FUNC (prefs_scoring_delete_cb), NULL);
279 cond_hbox = gtk_hbox_new (FALSE, 8);
280 gtk_widget_show (cond_hbox);
281 gtk_box_pack_start (GTK_BOX (vbox1), cond_hbox, TRUE, TRUE, 0);
283 cond_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
284 gtk_widget_show (cond_scrolledwin);
285 gtk_widget_set_usize (cond_scrolledwin, -1, 150);
286 gtk_box_pack_start (GTK_BOX (cond_hbox), cond_scrolledwin,
288 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cond_scrolledwin),
289 GTK_POLICY_AUTOMATIC,
290 GTK_POLICY_AUTOMATIC);
292 cond_clist = gtk_clist_new_with_titles(1, title);
293 gtk_widget_show (cond_clist);
294 gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
295 gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
296 gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
297 GTK_SELECTION_BROWSE);
298 GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
300 gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
301 GTK_SIGNAL_FUNC (prefs_scoring_select), NULL);
303 btn_vbox = gtk_vbox_new (FALSE, 8);
304 gtk_widget_show (btn_vbox);
305 gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
307 up_btn = gtk_button_new_with_label (_("Up"));
308 gtk_widget_show (up_btn);
309 gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
310 gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
311 GTK_SIGNAL_FUNC (prefs_scoring_up), NULL);
313 down_btn = gtk_button_new_with_label (_("Down"));
314 gtk_widget_show (down_btn);
315 gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
316 gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
317 GTK_SIGNAL_FUNC (prefs_scoring_down), NULL);
319 gtk_widget_show_all(window);
321 scoring.window = window;
322 scoring.ok_btn = ok_btn;
324 scoring.cond_entry = cond_entry;
325 scoring.score_entry = score_entry;
327 scoring.cond_clist = cond_clist;
330 static void prefs_scoring_set_dialog(ScoringProp * cond)
332 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
336 prefs_scoring_reset_dialog();
338 prefs_scoring_select_set_dialog(cond);
340 gtk_clist_freeze(clist);
341 gtk_clist_clear(clist);
343 prefs_scoring_clist_set_row(-1, NULL);
344 for(cur = prefs_scoring ; cur != NULL ; cur = g_slist_next(cur)) {
345 ScoringProp * prop = (ScoringProp *) cur->data;
347 prefs_scoring_clist_set_row(-1, prop);
350 gtk_clist_thaw(clist);
353 static void prefs_scoring_reset_dialog(void)
355 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), "");
356 gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), "");
359 static void prefs_scoring_set_list(void)
367 for(cur = prefs_scoring ; cur != NULL ; cur = g_slist_next(cur))
368 scoringprop_free((ScoringProp *) cur->data);
369 g_slist_free(prefs_scoring);
370 prefs_scoring = NULL;
372 while (gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
373 row, 0, &scoring_str)) {
374 if (strcmp(scoring_str, _("(New)")) != 0) {
376 prop = scoringprop_parse(&tmp);
378 prefs_scoring = g_slist_append(prefs_scoring,
385 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop)
387 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
392 cond_str[0] = _("(New)");
393 return gtk_clist_append(clist, cond_str);
396 str = scoringprop_to_string(prop);
403 row = gtk_clist_append(clist, cond_str);
405 gtk_clist_set_text(clist, row, 0, cond_str[0]);
411 static void prefs_scoring_condition_define_done(MatcherList * matchers)
415 if (matchers == NULL)
418 str = matcherlist_to_string(matchers);
421 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), str);
426 static void prefs_scoring_condition_define(void)
429 MatcherList * matchers = NULL;
431 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
433 if (*cond_str != '\0') {
437 matchers = matcherlist_parse(&tmp);
439 alertpanel_error(_("Match string is not valid."));
442 prefs_matcher_open(matchers, prefs_scoring_condition_define_done);
444 if (matchers != NULL)
445 matcherlist_free(matchers);
449 /* register / substitute delete buttons */
451 static void prefs_scoring_register_cb(void)
460 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
461 if (*cond_str == '\0') {
462 alertpanel_error(_("Score is not set."));
466 score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
467 if (*score_str == '\0') {
468 alertpanel_error(_("Match string is not set."));
472 score = atoi(score_str);
474 cond = matcherlist_parse(&tmp);
477 alertpanel_error(_("Match string is not valid."));
481 prop = scoringprop_new(cond, score);
483 prefs_scoring_clist_set_row(-1, prop);
485 scoringprop_free(prop);
487 prefs_scoring_reset_dialog();
490 static void prefs_scoring_substitute_cb(void)
492 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
501 if (!clist->selection) return;
503 row = GPOINTER_TO_INT(clist->selection->data);
504 if (row == 0) return;
506 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
507 if (*cond_str == '\0') {
508 alertpanel_error(_("Score is not set."));
512 score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
513 if (*score_str == '\0') {
514 alertpanel_error(_("Match string is not set."));
518 score = atoi(score_str);
520 cond = matcherlist_parse(&tmp);
523 alertpanel_error(_("Match string is not valid."));
527 prop = scoringprop_new(cond, score);
529 prefs_scoring_clist_set_row(row, prop);
531 scoringprop_free(prop);
533 prefs_scoring_reset_dialog();
536 static void prefs_scoring_delete_cb(void)
538 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
541 if (!clist->selection) return;
542 row = GPOINTER_TO_INT(clist->selection->data);
543 if (row == 0) return;
545 if (alertpanel(_("Delete rule"),
546 _("Do you really want to delete this rule?"),
547 _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
550 gtk_clist_remove(clist, row);
553 static void prefs_scoring_up(void)
555 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
558 if (!clist->selection) return;
560 row = GPOINTER_TO_INT(clist->selection->data);
562 gtk_clist_row_move(clist, row, row - 1);
566 static void prefs_scoring_down(void)
568 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
571 if (!clist->selection) return;
573 row = GPOINTER_TO_INT(clist->selection->data);
574 if (row > 0 && row < clist->rows - 1) {
575 gtk_clist_row_move(clist, row, row + 1);
579 static void prefs_scoring_select_set_dialog(ScoringProp * prop)
587 matcher_str = matcherlist_to_string(prop->matchers);
588 if (matcher_str == NULL) {
589 scoringprop_free(prop);
593 score_str = itos(prop->score);
595 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), matcher_str);
596 gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
601 static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
610 prefs_scoring_reset_dialog();
614 if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
615 row, 0, &scoring_str))
619 prop = scoringprop_parse(&tmp);
623 prefs_scoring_select_set_dialog(prop);
625 scoringprop_free(prop);
628 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
631 prefs_scoring_cancel();
635 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
638 if (event && event->keyval == GDK_Escape)
639 prefs_scoring_cancel();
642 static void prefs_scoring_ok(void)
644 prefs_scoring_set_list();
645 prefs_scoring_write_config();
646 gtk_widget_hide(scoring.window);
649 static void prefs_scoring_cancel(void)
651 prefs_scoring_read_config();
652 gtk_widget_hide(scoring.window);