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"
49 #include "matcher_parser.h"
51 static struct Scoring {
55 GtkWidget *cond_entry;
56 GtkWidget *score_entry;
57 GtkWidget *kill_score_label;
58 GtkWidget *kill_score_entry;
59 GtkWidget *important_score_entry;
61 GtkWidget *cond_clist;
65 parameter name, default value, pointer to the prefs variable, data type,
66 pointer to the widget pointer,
67 pointer to the function for data setting,
68 pointer to the function for widget setting
72 #define VSPACING_NARROW 4
73 #define DEFAULT_ENTRY_WIDTH 80
74 #define PREFSBUFSIZE 1024
76 /* widget creating functions */
77 static void prefs_scoring_create (void);
79 static void prefs_scoring_set_dialog (ScoringProp * prop);
80 static void prefs_scoring_set_list (void);
82 /* callback functions */
83 /* static void prefs_scoring_select_dest_cb (void); */
84 static void prefs_scoring_register_cb (void);
85 static void prefs_scoring_substitute_cb (void);
86 static void prefs_scoring_delete_cb (void);
87 static void prefs_scoring_up (void);
88 static void prefs_scoring_down (void);
89 static void prefs_scoring_select (GtkCList *clist,
94 static gint prefs_scoring_deleted (GtkWidget *widget,
97 static void prefs_scoring_key_pressed (GtkWidget *widget,
100 static void prefs_scoring_cancel (void);
101 static void prefs_scoring_ok (void);
103 static void prefs_scoring_condition_define (void);
104 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop);
105 static void prefs_scoring_select_set_dialog(ScoringProp * prop);
106 static void prefs_scoring_reset_dialog(void);
109 static FolderItem * cur_item = NULL;
110 static gint cur_important_score;
111 static gint cur_kill_score;
113 void prefs_scoring_open(FolderItem * item)
115 if (prefs_rc_is_readonly(SCORING_RC))
118 inc_autocheck_timer_remove();
120 if (!scoring.window) {
121 prefs_scoring_create();
124 manage_window_set_transient(GTK_WINDOW(scoring.window));
125 gtk_widget_grab_focus(scoring.ok_btn);
129 prefs_scoring_set_dialog(NULL);
131 gtk_widget_show(scoring.window);
134 void prefs_scoring_open_with_scoring(ScoringProp * prop)
136 inc_autocheck_timer_remove();
138 if (!scoring.window) {
139 prefs_scoring_create();
142 manage_window_set_transient(GTK_WINDOW(scoring.window));
143 gtk_widget_grab_focus(scoring.ok_btn);
145 prefs_scoring_set_dialog(prop);
147 gtk_widget_show(scoring.window);
150 static void prefs_scoring_create(void)
155 GtkWidget *cancel_btn;
156 GtkWidget *confirm_area;
164 GtkWidget *cond_label;
165 GtkWidget *cond_entry;
167 GtkWidget *score_label;
168 GtkWidget *score_entry;
171 GtkWidget *subst_btn;
174 GtkWidget *cond_hbox;
175 GtkWidget *cond_scrolledwin;
176 GtkWidget *cond_clist;
182 GtkWidget *important_score_entry;
183 GtkWidget *kill_score_entry;
184 GtkWidget *kill_score_label;
186 gchar *title[] = {_("Registered rules")};
188 debug_print(_("Creating scoring setting window...\n"));
190 window = gtk_window_new (GTK_WINDOW_DIALOG);
191 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
192 gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
193 gtk_window_set_modal (GTK_WINDOW (window), TRUE);
194 gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
196 vbox = gtk_vbox_new (FALSE, 6);
197 gtk_widget_show (vbox);
198 gtk_container_add (GTK_CONTAINER (window), vbox);
200 gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
201 &cancel_btn, _("Cancel"), NULL, NULL);
202 gtk_widget_show (confirm_area);
203 gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
204 gtk_widget_grab_default (ok_btn);
206 gtk_window_set_title (GTK_WINDOW(window),
207 _("Scoring setting"));
208 gtk_signal_connect (GTK_OBJECT(window), "delete_event",
209 GTK_SIGNAL_FUNC(prefs_scoring_deleted), NULL);
210 gtk_signal_connect (GTK_OBJECT(window), "key_press_event",
211 GTK_SIGNAL_FUNC(prefs_scoring_key_pressed), NULL);
212 gtk_signal_connect (GTK_OBJECT(window), "focus_in_event",
213 GTK_SIGNAL_FUNC(manage_window_focus_in), NULL);
214 gtk_signal_connect (GTK_OBJECT(window), "focus_out_event",
215 GTK_SIGNAL_FUNC(manage_window_focus_out), NULL);
216 gtk_signal_connect (GTK_OBJECT(ok_btn), "clicked",
217 GTK_SIGNAL_FUNC(prefs_scoring_ok), NULL);
218 gtk_signal_connect (GTK_OBJECT(cancel_btn), "clicked",
219 GTK_SIGNAL_FUNC(prefs_scoring_cancel), NULL);
221 vbox1 = gtk_vbox_new (FALSE, VSPACING);
222 gtk_widget_show (vbox1);
223 gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
224 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
226 cond_label = gtk_label_new (_("Condition"));
227 gtk_widget_show (cond_label);
228 gtk_misc_set_alignment (GTK_MISC (cond_label), 0, 0.5);
229 gtk_box_pack_start (GTK_BOX (vbox1), cond_label, FALSE, FALSE, 0);
231 hbox1 = gtk_hbox_new (FALSE, VSPACING);
232 gtk_widget_show (vbox1);
233 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
234 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
236 cond_entry = gtk_entry_new ();
237 gtk_widget_show (cond_entry);
238 gtk_widget_set_usize (cond_entry, 300, -1);
239 gtk_box_pack_start (GTK_BOX (hbox1), cond_entry, TRUE, TRUE, 0);
241 cond_btn = gtk_button_new_with_label (_("Define ..."));
242 gtk_widget_show (cond_btn);
243 gtk_box_pack_start (GTK_BOX (hbox1), cond_btn, FALSE, FALSE, 0);
244 gtk_signal_connect (GTK_OBJECT (cond_btn), "clicked",
245 GTK_SIGNAL_FUNC (prefs_scoring_condition_define),
248 hbox1 = gtk_hbox_new (FALSE, VSPACING);
249 gtk_widget_show (vbox1);
250 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
251 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
253 score_label = gtk_label_new (_("Score"));
254 gtk_widget_show (score_label);
255 gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
256 gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
258 score_entry = gtk_entry_new ();
259 gtk_widget_show (score_entry);
260 gtk_widget_set_usize (score_entry, 50, -1);
261 gtk_box_pack_start (GTK_BOX (hbox1), score_entry, FALSE, FALSE, 0);
263 /* register / substitute / delete */
265 reg_hbox = gtk_hbox_new (FALSE, 4);
266 gtk_widget_show (reg_hbox);
267 gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
269 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
270 gtk_widget_show (arrow);
271 gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
272 gtk_widget_set_usize (arrow, -1, 16);
274 btn_hbox = gtk_hbox_new (TRUE, 4);
275 gtk_widget_show (btn_hbox);
276 gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
278 reg_btn = gtk_button_new_with_label (_("Register"));
279 gtk_widget_show (reg_btn);
280 gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
281 gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
282 GTK_SIGNAL_FUNC (prefs_scoring_register_cb), NULL);
284 subst_btn = gtk_button_new_with_label (_(" Substitute "));
285 gtk_widget_show (subst_btn);
286 gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
287 gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
288 GTK_SIGNAL_FUNC (prefs_scoring_substitute_cb),
291 del_btn = gtk_button_new_with_label (_("Delete"));
292 gtk_widget_show (del_btn);
293 gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
294 gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
295 GTK_SIGNAL_FUNC (prefs_scoring_delete_cb), NULL);
297 cond_hbox = gtk_hbox_new (FALSE, 8);
298 gtk_widget_show (cond_hbox);
299 gtk_box_pack_start (GTK_BOX (vbox1), cond_hbox, TRUE, TRUE, 0);
301 cond_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
302 gtk_widget_show (cond_scrolledwin);
303 gtk_widget_set_usize (cond_scrolledwin, -1, 150);
304 gtk_box_pack_start (GTK_BOX (cond_hbox), cond_scrolledwin,
306 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cond_scrolledwin),
307 GTK_POLICY_AUTOMATIC,
308 GTK_POLICY_AUTOMATIC);
310 cond_clist = gtk_clist_new_with_titles(1, title);
311 gtk_widget_show (cond_clist);
312 gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
313 gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
314 gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
315 GTK_SELECTION_BROWSE);
316 GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
318 gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
319 GTK_SIGNAL_FUNC (prefs_scoring_select), NULL);
321 btn_vbox = gtk_vbox_new (FALSE, 8);
322 gtk_widget_show (btn_vbox);
323 gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
325 up_btn = gtk_button_new_with_label (_("Up"));
326 gtk_widget_show (up_btn);
327 gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
328 gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
329 GTK_SIGNAL_FUNC (prefs_scoring_up), NULL);
331 down_btn = gtk_button_new_with_label (_("Down"));
332 gtk_widget_show (down_btn);
333 gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
334 gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
335 GTK_SIGNAL_FUNC (prefs_scoring_down), NULL);
337 hbox1 = gtk_hbox_new (FALSE, 8);
338 gtk_widget_show (hbox1);
339 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
341 kill_score_label = gtk_label_new (_("Kill score"));
342 gtk_widget_show (kill_score_label);
343 gtk_misc_set_alignment (GTK_MISC (kill_score_label), 0, 0.5);
344 gtk_box_pack_start (GTK_BOX (hbox1), kill_score_label,
347 kill_score_entry = gtk_entry_new ();
348 gtk_widget_show (kill_score_entry);
349 gtk_widget_set_usize (kill_score_entry, 50, -1);
350 gtk_box_pack_start (GTK_BOX (hbox1), kill_score_entry,
353 score_label = gtk_label_new (_("Important score"));
354 gtk_widget_show (score_label);
355 gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
356 gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
358 important_score_entry = gtk_entry_new ();
359 gtk_widget_show (important_score_entry);
360 gtk_widget_set_usize (important_score_entry, 50, -1);
361 gtk_box_pack_start (GTK_BOX (hbox1), important_score_entry,
364 gtk_widget_show_all(window);
366 scoring.window = window;
367 scoring.ok_btn = ok_btn;
369 scoring.cond_entry = cond_entry;
370 scoring.score_entry = score_entry;
371 scoring.kill_score_entry = kill_score_entry;
372 scoring.kill_score_label = kill_score_label;
373 scoring.important_score_entry = important_score_entry;
375 scoring.cond_clist = cond_clist;
378 static void prefs_scoring_set_dialog(ScoringProp * cond)
380 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
382 GSList * prefs_scoring;
386 prefs_scoring_reset_dialog();
388 prefs_scoring_select_set_dialog(cond);
390 gtk_clist_freeze(clist);
391 gtk_clist_clear(clist);
393 prefs_scoring_clist_set_row(-1, NULL);
394 if (cur_item == NULL) {
395 prefs_scoring = global_scoring;
396 cur_kill_score = prefs_common.kill_score;
397 cur_important_score = prefs_common.important_score;
398 gtk_widget_show(scoring.kill_score_label);
399 gtk_widget_show(scoring.kill_score_entry);
402 prefs_scoring = cur_item->prefs->scoring;
403 cur_kill_score = cur_item->prefs->kill_score;
404 cur_important_score = cur_item->prefs->important_score;
405 if (cur_item->folder->type != F_NEWS) {
406 gtk_widget_hide(scoring.kill_score_label);
407 gtk_widget_hide(scoring.kill_score_entry);
410 gtk_widget_show(scoring.kill_score_label);
411 gtk_widget_show(scoring.kill_score_entry);
415 for(cur = prefs_scoring ; cur != NULL ;
416 cur = g_slist_next(cur)) {
417 ScoringProp * prop = (ScoringProp *) cur->data;
419 prefs_scoring_clist_set_row(-1, prop);
422 score_str = itos(cur_kill_score);
423 gtk_entry_set_text(GTK_ENTRY(scoring.kill_score_entry),
425 score_str = itos(cur_important_score);
426 gtk_entry_set_text(GTK_ENTRY(scoring.important_score_entry),
429 gtk_clist_thaw(clist);
432 static void prefs_scoring_reset_dialog(void)
434 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), "");
435 gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), "");
438 static void prefs_scoring_set_list(void)
444 GSList * prefs_scoring;
446 if (cur_item == NULL)
447 prefs_scoring = global_scoring;
449 prefs_scoring = cur_item->prefs->scoring;
451 for(cur = prefs_scoring ; cur != NULL ;
452 cur = g_slist_next(cur))
453 scoringprop_free((ScoringProp *) cur->data);
454 g_slist_free(prefs_scoring);
455 prefs_scoring = NULL;
457 while (gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
458 row, 0, &scoring_str)) {
459 if (strcmp(scoring_str, _("(New)")) != 0) {
460 prop = matcher_parser_get_scoring(scoring_str);
462 prefs_scoring = g_slist_append(prefs_scoring,
468 cur_kill_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.kill_score_entry)));
469 cur_important_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.important_score_entry)));
471 if (cur_item == NULL) {
472 global_scoring = prefs_scoring;
473 prefs_common.kill_score = cur_kill_score;
474 prefs_common.important_score = cur_important_score;
477 cur_item->prefs->scoring = prefs_scoring;
478 cur_item->prefs->kill_score = cur_kill_score;
479 cur_item->prefs->important_score = cur_important_score;
483 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop)
485 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
490 cond_str[0] = _("(New)");
491 return gtk_clist_append(clist, cond_str);
494 str = scoringprop_to_string(prop);
501 row = gtk_clist_append(clist, cond_str);
503 gtk_clist_set_text(clist, row, 0, cond_str[0]);
509 static void prefs_scoring_condition_define_done(MatcherList * matchers)
513 if (matchers == NULL)
516 str = matcherlist_to_string(matchers);
519 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), str);
524 static void prefs_scoring_condition_define(void)
527 MatcherList * matchers = NULL;
529 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
531 if (*cond_str != '\0') {
532 matchers = matcher_parser_get_cond(cond_str);
534 if (matchers == NULL)
535 alertpanel_error(_("Match string is not valid."));
538 prefs_matcher_open(matchers, prefs_scoring_condition_define_done);
540 if (matchers != NULL)
541 matcherlist_free(matchers);
545 /* register / substitute delete buttons */
547 static void prefs_scoring_register_cb(void)
555 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
556 if (*cond_str == '\0') {
557 alertpanel_error(_("Score is not set."));
561 score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
562 if (*score_str == '\0') {
563 alertpanel_error(_("Match string is not set."));
567 score = atoi(score_str);
568 cond = matcher_parser_get_cond(cond_str);
571 alertpanel_error(_("Match string is not valid."));
575 prop = scoringprop_new(cond, score);
577 prefs_scoring_clist_set_row(-1, prop);
579 scoringprop_free(prop);
581 prefs_scoring_reset_dialog();
584 static void prefs_scoring_substitute_cb(void)
586 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
594 if (!clist->selection) return;
596 row = GPOINTER_TO_INT(clist->selection->data);
597 if (row == 0) return;
599 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
600 if (*cond_str == '\0') {
601 alertpanel_error(_("Score is not set."));
605 score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
606 if (*score_str == '\0') {
607 alertpanel_error(_("Match string is not set."));
611 score = atoi(score_str);
612 cond = matcher_parser_get_cond(cond_str);
615 alertpanel_error(_("Match string is not valid."));
619 prop = scoringprop_new(cond, score);
621 prefs_scoring_clist_set_row(row, prop);
623 scoringprop_free(prop);
625 prefs_scoring_reset_dialog();
628 static void prefs_scoring_delete_cb(void)
630 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
633 if (!clist->selection) return;
634 row = GPOINTER_TO_INT(clist->selection->data);
635 if (row == 0) return;
637 if (alertpanel(_("Delete rule"),
638 _("Do you really want to delete this rule?"),
639 _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
642 gtk_clist_remove(clist, row);
645 static void prefs_scoring_up(void)
647 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
650 if (!clist->selection) return;
652 row = GPOINTER_TO_INT(clist->selection->data);
654 gtk_clist_row_move(clist, row, row - 1);
658 static void prefs_scoring_down(void)
660 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
663 if (!clist->selection) return;
665 row = GPOINTER_TO_INT(clist->selection->data);
666 if (row > 0 && row < clist->rows - 1) {
667 gtk_clist_row_move(clist, row, row + 1);
671 static void prefs_scoring_select_set_dialog(ScoringProp * prop)
679 matcher_str = matcherlist_to_string(prop->matchers);
680 if (matcher_str == NULL) {
681 scoringprop_free(prop);
685 score_str = itos(prop->score);
687 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), matcher_str);
688 gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
693 static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
701 prefs_scoring_reset_dialog();
705 if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
706 row, 0, &scoring_str))
709 prop = matcher_parser_get_scoring(scoring_str);
713 prefs_scoring_select_set_dialog(prop);
715 scoringprop_free(prop);
718 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
721 prefs_scoring_cancel();
725 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
728 if (event && event->keyval == GDK_Escape)
729 prefs_scoring_cancel();
732 static void prefs_scoring_ok(void)
734 prefs_scoring_set_list();
735 prefs_scoring_write_config();
736 if (cur_item != NULL)
737 prefs_folder_item_save_config(cur_item);
738 gtk_widget_hide(scoring.window);
741 static void prefs_scoring_cancel(void)
743 prefs_scoring_read_config();
744 gtk_widget_hide(scoring.window);