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 #include "matcher_parser.h"
52 static struct Scoring {
56 GtkWidget *cond_entry;
57 GtkWidget *score_entry;
58 GtkWidget *kill_score_label;
59 GtkWidget *kill_score_entry;
60 GtkWidget *important_score_entry;
62 GtkWidget *cond_clist;
66 parameter name, default value, pointer to the prefs variable, data type,
67 pointer to the widget pointer,
68 pointer to the function for data setting,
69 pointer to the function for widget setting
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);
105 static FolderItem * cur_item = NULL;
106 static gint cur_important_score;
107 static gint cur_kill_score;
109 void prefs_scoring_open(FolderItem * item)
111 if (prefs_rc_is_readonly(SCORING_RC))
116 if (!scoring.window) {
117 prefs_scoring_create();
120 manage_window_set_transient(GTK_WINDOW(scoring.window));
121 gtk_widget_grab_focus(scoring.ok_btn);
125 prefs_scoring_set_dialog(NULL);
127 gtk_widget_show(scoring.window);
130 void prefs_scoring_open_with_scoring(ScoringProp * prop)
134 if (!scoring.window) {
135 prefs_scoring_create();
138 manage_window_set_transient(GTK_WINDOW(scoring.window));
139 gtk_widget_grab_focus(scoring.ok_btn);
141 prefs_scoring_set_dialog(prop);
143 gtk_widget_show(scoring.window);
146 static void prefs_scoring_create(void)
151 GtkWidget *cancel_btn;
152 GtkWidget *confirm_area;
160 GtkWidget *cond_label;
161 GtkWidget *cond_entry;
163 GtkWidget *score_label;
164 GtkWidget *score_entry;
167 GtkWidget *subst_btn;
170 GtkWidget *cond_hbox;
171 GtkWidget *cond_scrolledwin;
172 GtkWidget *cond_clist;
178 GtkWidget *important_score_entry;
179 GtkWidget *kill_score_entry;
180 GtkWidget *kill_score_label;
184 debug_print(_("Creating scoring setting window...\n"));
186 window = gtk_window_new (GTK_WINDOW_DIALOG);
187 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
188 gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
189 gtk_window_set_modal (GTK_WINDOW (window), TRUE);
190 gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
192 vbox = gtk_vbox_new (FALSE, 6);
193 gtk_widget_show (vbox);
194 gtk_container_add (GTK_CONTAINER (window), vbox);
196 gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
197 &cancel_btn, _("Cancel"), NULL, NULL);
198 gtk_widget_show (confirm_area);
199 gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
200 gtk_widget_grab_default (ok_btn);
202 gtk_window_set_title (GTK_WINDOW(window),
203 _("Scoring setting"));
204 gtk_signal_connect (GTK_OBJECT(window), "delete_event",
205 GTK_SIGNAL_FUNC(prefs_scoring_deleted), NULL);
206 gtk_signal_connect (GTK_OBJECT(window), "key_press_event",
207 GTK_SIGNAL_FUNC(prefs_scoring_key_pressed), NULL);
208 MANAGE_WINDOW_SIGNALS_CONNECT (window);
209 gtk_signal_connect (GTK_OBJECT(ok_btn), "clicked",
210 GTK_SIGNAL_FUNC(prefs_scoring_ok), NULL);
211 gtk_signal_connect (GTK_OBJECT(cancel_btn), "clicked",
212 GTK_SIGNAL_FUNC(prefs_scoring_cancel), NULL);
214 vbox1 = gtk_vbox_new (FALSE, VSPACING);
215 gtk_widget_show (vbox1);
216 gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
217 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
219 cond_label = gtk_label_new (_("Condition"));
220 gtk_widget_show (cond_label);
221 gtk_misc_set_alignment (GTK_MISC (cond_label), 0, 0.5);
222 gtk_box_pack_start (GTK_BOX (vbox1), cond_label, FALSE, FALSE, 0);
224 hbox1 = gtk_hbox_new (FALSE, VSPACING);
225 gtk_widget_show (vbox1);
226 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
227 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
229 cond_entry = gtk_entry_new ();
230 gtk_widget_show (cond_entry);
231 gtk_widget_set_usize (cond_entry, 300, -1);
232 gtk_box_pack_start (GTK_BOX (hbox1), cond_entry, TRUE, TRUE, 0);
234 cond_btn = gtk_button_new_with_label (_("Define ..."));
235 gtk_widget_show (cond_btn);
236 gtk_box_pack_start (GTK_BOX (hbox1), cond_btn, FALSE, FALSE, 0);
237 gtk_signal_connect (GTK_OBJECT (cond_btn), "clicked",
238 GTK_SIGNAL_FUNC (prefs_scoring_condition_define),
241 hbox1 = gtk_hbox_new (FALSE, VSPACING);
242 gtk_widget_show (vbox1);
243 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
244 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
246 score_label = gtk_label_new (_("Score"));
247 gtk_widget_show (score_label);
248 gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
249 gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
251 score_entry = gtk_entry_new ();
252 gtk_widget_show (score_entry);
253 gtk_widget_set_usize (score_entry, 50, -1);
254 gtk_box_pack_start (GTK_BOX (hbox1), score_entry, FALSE, FALSE, 0);
256 /* register / substitute / delete */
258 reg_hbox = gtk_hbox_new (FALSE, 4);
259 gtk_widget_show (reg_hbox);
260 gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
262 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
263 gtk_widget_show (arrow);
264 gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
265 gtk_widget_set_usize (arrow, -1, 16);
267 btn_hbox = gtk_hbox_new (TRUE, 4);
268 gtk_widget_show (btn_hbox);
269 gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
271 reg_btn = gtk_button_new_with_label (_("Register"));
272 gtk_widget_show (reg_btn);
273 gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
274 gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
275 GTK_SIGNAL_FUNC (prefs_scoring_register_cb), NULL);
277 subst_btn = gtk_button_new_with_label (_(" Substitute "));
278 gtk_widget_show (subst_btn);
279 gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
280 gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
281 GTK_SIGNAL_FUNC (prefs_scoring_substitute_cb),
284 del_btn = gtk_button_new_with_label (_("Delete"));
285 gtk_widget_show (del_btn);
286 gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
287 gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
288 GTK_SIGNAL_FUNC (prefs_scoring_delete_cb), NULL);
290 cond_hbox = gtk_hbox_new (FALSE, 8);
291 gtk_widget_show (cond_hbox);
292 gtk_box_pack_start (GTK_BOX (vbox1), cond_hbox, TRUE, TRUE, 0);
294 cond_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
295 gtk_widget_show (cond_scrolledwin);
296 gtk_widget_set_usize (cond_scrolledwin, -1, 150);
297 gtk_box_pack_start (GTK_BOX (cond_hbox), cond_scrolledwin,
299 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cond_scrolledwin),
300 GTK_POLICY_AUTOMATIC,
301 GTK_POLICY_AUTOMATIC);
303 title[0] = ("Registered rules");
304 cond_clist = gtk_clist_new_with_titles(1, title);
305 gtk_widget_show (cond_clist);
306 gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
307 gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
308 gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
309 GTK_SELECTION_BROWSE);
310 GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
312 gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
313 GTK_SIGNAL_FUNC (prefs_scoring_select), NULL);
315 btn_vbox = gtk_vbox_new (FALSE, 8);
316 gtk_widget_show (btn_vbox);
317 gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
319 up_btn = gtk_button_new_with_label (_("Up"));
320 gtk_widget_show (up_btn);
321 gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
322 gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
323 GTK_SIGNAL_FUNC (prefs_scoring_up), NULL);
325 down_btn = gtk_button_new_with_label (_("Down"));
326 gtk_widget_show (down_btn);
327 gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
328 gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
329 GTK_SIGNAL_FUNC (prefs_scoring_down), NULL);
331 hbox1 = gtk_hbox_new (FALSE, 8);
332 gtk_widget_show (hbox1);
333 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
335 kill_score_label = gtk_label_new (_("Kill score"));
336 gtk_widget_show (kill_score_label);
337 gtk_misc_set_alignment (GTK_MISC (kill_score_label), 0, 0.5);
338 gtk_box_pack_start (GTK_BOX (hbox1), kill_score_label,
341 kill_score_entry = gtk_entry_new ();
342 gtk_widget_show (kill_score_entry);
343 gtk_widget_set_usize (kill_score_entry, 50, -1);
344 gtk_box_pack_start (GTK_BOX (hbox1), kill_score_entry,
347 score_label = gtk_label_new (_("Important score"));
348 gtk_widget_show (score_label);
349 gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
350 gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
352 important_score_entry = gtk_entry_new ();
353 gtk_widget_show (important_score_entry);
354 gtk_widget_set_usize (important_score_entry, 50, -1);
355 gtk_box_pack_start (GTK_BOX (hbox1), important_score_entry,
358 gtk_widget_show_all(window);
360 scoring.window = window;
361 scoring.ok_btn = ok_btn;
363 scoring.cond_entry = cond_entry;
364 scoring.score_entry = score_entry;
365 scoring.kill_score_entry = kill_score_entry;
366 scoring.kill_score_label = kill_score_label;
367 scoring.important_score_entry = important_score_entry;
369 scoring.cond_clist = cond_clist;
372 static void prefs_scoring_set_dialog(ScoringProp * cond)
374 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
376 GSList * prefs_scoring;
380 prefs_scoring_reset_dialog();
382 prefs_scoring_select_set_dialog(cond);
384 gtk_clist_freeze(clist);
385 gtk_clist_clear(clist);
387 prefs_scoring_clist_set_row(-1, NULL);
388 if (cur_item == NULL) {
389 prefs_scoring = global_scoring;
390 cur_kill_score = prefs_common.kill_score;
391 cur_important_score = prefs_common.important_score;
392 gtk_widget_show(scoring.kill_score_label);
393 gtk_widget_show(scoring.kill_score_entry);
396 prefs_scoring = cur_item->prefs->scoring;
397 cur_kill_score = cur_item->prefs->kill_score;
398 cur_important_score = cur_item->prefs->important_score;
399 if (cur_item->folder->type != F_NEWS) {
400 gtk_widget_hide(scoring.kill_score_label);
401 gtk_widget_hide(scoring.kill_score_entry);
404 gtk_widget_show(scoring.kill_score_label);
405 gtk_widget_show(scoring.kill_score_entry);
409 for(cur = prefs_scoring ; cur != NULL ;
410 cur = g_slist_next(cur)) {
411 ScoringProp * prop = (ScoringProp *) cur->data;
413 prefs_scoring_clist_set_row(-1, prop);
416 score_str = itos(cur_kill_score);
417 gtk_entry_set_text(GTK_ENTRY(scoring.kill_score_entry),
419 score_str = itos(cur_important_score);
420 gtk_entry_set_text(GTK_ENTRY(scoring.important_score_entry),
423 gtk_clist_thaw(clist);
426 static void prefs_scoring_reset_dialog(void)
428 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), "");
429 gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), "");
432 static void prefs_scoring_set_list(void)
439 GSList * prefs_scoring;
441 if (cur_item == NULL)
442 prefs_scoring = global_scoring;
444 prefs_scoring = cur_item->prefs->scoring;
446 for(cur = prefs_scoring ; cur != NULL ;
447 cur = g_slist_next(cur))
448 scoringprop_free((ScoringProp *) cur->data);
449 g_slist_free(prefs_scoring);
450 prefs_scoring = NULL;
452 while (gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
453 row, 0, &scoring_str)) {
454 if (strcmp(scoring_str, _("(New)")) != 0) {
455 prop = matcher_parser_get_scoring(scoring_str);
457 prefs_scoring = g_slist_append(prefs_scoring,
463 cur_kill_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.kill_score_entry)));
464 cur_important_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.important_score_entry)));
466 if (cur_item == NULL) {
467 global_scoring = prefs_scoring;
468 prefs_common.kill_score = cur_kill_score;
469 prefs_common.important_score = cur_important_score;
472 cur_item->prefs->scoring = prefs_scoring;
473 cur_item->prefs->kill_score = cur_kill_score;
474 cur_item->prefs->important_score = cur_important_score;
478 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop)
480 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
485 cond_str[0] = _("(New)");
486 return gtk_clist_append(clist, cond_str);
489 str = scoringprop_to_string(prop);
496 row = gtk_clist_append(clist, cond_str);
498 gtk_clist_set_text(clist, row, 0, cond_str[0]);
504 static void prefs_scoring_condition_define_done(MatcherList * matchers)
508 if (matchers == NULL)
511 str = matcherlist_to_string(matchers);
514 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), str);
519 static void prefs_scoring_condition_define(void)
522 MatcherList * matchers = NULL;
524 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
526 if (*cond_str != '\0') {
529 matchers = matcher_parser_get_cond(cond_str);
530 if (matchers == NULL)
531 alertpanel_error(_("Match string is not valid."));
534 prefs_matcher_open(matchers, prefs_scoring_condition_define_done);
536 if (matchers != NULL)
537 matcherlist_free(matchers);
541 /* register / substitute delete buttons */
543 static void prefs_scoring_register_cb(void)
552 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
553 if (*cond_str == '\0') {
554 alertpanel_error(_("Score is not set."));
558 score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
559 if (*score_str == '\0') {
560 alertpanel_error(_("Match string is not set."));
564 score = atoi(score_str);
565 cond = matcher_parser_get_cond(cond_str);
568 alertpanel_error(_("Match string is not valid."));
572 prop = scoringprop_new(cond, score);
574 prefs_scoring_clist_set_row(-1, prop);
576 scoringprop_free(prop);
578 prefs_scoring_reset_dialog();
581 static void prefs_scoring_substitute_cb(void)
583 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
592 if (!clist->selection) return;
594 row = GPOINTER_TO_INT(clist->selection->data);
595 if (row == 0) return;
597 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
598 if (*cond_str == '\0') {
599 alertpanel_error(_("Score is not set."));
603 score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
604 if (*score_str == '\0') {
605 alertpanel_error(_("Match string is not set."));
609 score = atoi(score_str);
610 cond = matcher_parser_get_cond(cond_str);
613 alertpanel_error(_("Match string is not valid."));
617 prop = scoringprop_new(cond, score);
619 prefs_scoring_clist_set_row(row, prop);
621 scoringprop_free(prop);
623 prefs_scoring_reset_dialog();
626 static void prefs_scoring_delete_cb(void)
628 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
631 if (!clist->selection) return;
632 row = GPOINTER_TO_INT(clist->selection->data);
633 if (row == 0) return;
635 if (alertpanel(_("Delete rule"),
636 _("Do you really want to delete this rule?"),
637 _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
640 gtk_clist_remove(clist, row);
643 static void prefs_scoring_up(void)
645 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
648 if (!clist->selection) return;
650 row = GPOINTER_TO_INT(clist->selection->data);
652 gtk_clist_row_move(clist, row, row - 1);
653 if(gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL) {
654 gtk_clist_moveto(clist, row - 1, 0, 0, 0);
659 static void prefs_scoring_down(void)
661 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
664 if (!clist->selection) return;
666 row = GPOINTER_TO_INT(clist->selection->data);
667 if (row > 0 && row < clist->rows - 1) {
668 gtk_clist_row_move(clist, row, row + 1);
669 if(gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL) {
670 gtk_clist_moveto(clist, row + 1, 0, 1, 0);
675 static void prefs_scoring_select_set_dialog(ScoringProp * prop)
683 matcher_str = matcherlist_to_string(prop->matchers);
684 if (matcher_str == NULL) {
685 scoringprop_free(prop);
689 score_str = itos(prop->score);
691 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), matcher_str);
692 gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
697 static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
706 prefs_scoring_reset_dialog();
710 if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
711 row, 0, &scoring_str))
714 prop = matcher_parser_get_scoring(scoring_str);
718 prefs_scoring_select_set_dialog(prop);
720 scoringprop_free(prop);
723 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
726 prefs_scoring_cancel();
730 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
733 if (event && event->keyval == GDK_Escape)
734 prefs_scoring_cancel();
737 static void prefs_scoring_ok(void)
739 prefs_common_save_config();
740 prefs_scoring_set_list();
741 prefs_matcher_write_config();
742 if (cur_item != NULL)
743 prefs_folder_item_save_config(cur_item);
744 gtk_widget_hide(scoring.window);
748 static void prefs_scoring_cancel(void)
750 prefs_matcher_read_config();
751 gtk_widget_hide(scoring.window);