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 (_("Hide 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)
438 GSList * prefs_scoring;
440 if (cur_item == NULL)
441 prefs_scoring = global_scoring;
443 prefs_scoring = cur_item->prefs->scoring;
445 for(cur = prefs_scoring ; cur != NULL ;
446 cur = g_slist_next(cur))
447 scoringprop_free((ScoringProp *) cur->data);
448 g_slist_free(prefs_scoring);
449 prefs_scoring = NULL;
451 while (gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
452 row, 0, &scoring_str)) {
453 if (strcmp(scoring_str, _("(New)")) != 0) {
454 prop = matcher_parser_get_scoring(scoring_str);
456 prefs_scoring = g_slist_append(prefs_scoring,
462 cur_kill_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.kill_score_entry)));
463 cur_important_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.important_score_entry)));
465 if (cur_item == NULL) {
466 global_scoring = prefs_scoring;
467 prefs_common.kill_score = cur_kill_score;
468 prefs_common.important_score = cur_important_score;
471 cur_item->prefs->scoring = prefs_scoring;
472 cur_item->prefs->kill_score = cur_kill_score;
473 cur_item->prefs->important_score = cur_important_score;
477 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop)
479 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
484 cond_str[0] = _("(New)");
485 return gtk_clist_append(clist, cond_str);
488 str = scoringprop_to_string(prop);
495 row = gtk_clist_append(clist, cond_str);
497 gtk_clist_set_text(clist, row, 0, cond_str[0]);
503 static void prefs_scoring_condition_define_done(MatcherList * matchers)
507 if (matchers == NULL)
510 str = matcherlist_to_string(matchers);
513 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), str);
518 static void prefs_scoring_condition_define(void)
521 MatcherList * matchers = NULL;
523 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
525 if (*cond_str != '\0') {
526 matchers = matcher_parser_get_cond(cond_str);
527 if (matchers == NULL)
528 alertpanel_error(_("Match string is not valid."));
531 prefs_matcher_open(matchers, prefs_scoring_condition_define_done);
533 if (matchers != NULL)
534 matcherlist_free(matchers);
538 /* register / substitute delete buttons */
540 static void prefs_scoring_register_cb(void)
548 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
549 if (*cond_str == '\0') {
550 alertpanel_error(_("Score is not set."));
554 score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
555 if (*score_str == '\0') {
556 alertpanel_error(_("Match string is not set."));
560 score = atoi(score_str);
561 cond = matcher_parser_get_cond(cond_str);
564 alertpanel_error(_("Match string is not valid."));
568 prop = scoringprop_new(cond, score);
570 prefs_scoring_clist_set_row(-1, prop);
572 scoringprop_free(prop);
574 prefs_scoring_reset_dialog();
577 static void prefs_scoring_substitute_cb(void)
579 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
587 if (!clist->selection) return;
589 row = GPOINTER_TO_INT(clist->selection->data);
590 if (row == 0) return;
592 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
593 if (*cond_str == '\0') {
594 alertpanel_error(_("Score is not set."));
598 score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
599 if (*score_str == '\0') {
600 alertpanel_error(_("Match string is not set."));
604 score = atoi(score_str);
605 cond = matcher_parser_get_cond(cond_str);
608 alertpanel_error(_("Match string is not valid."));
612 prop = scoringprop_new(cond, score);
614 prefs_scoring_clist_set_row(row, prop);
616 scoringprop_free(prop);
618 prefs_scoring_reset_dialog();
621 static void prefs_scoring_delete_cb(void)
623 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
626 if (!clist->selection) return;
627 row = GPOINTER_TO_INT(clist->selection->data);
628 if (row == 0) return;
630 if (alertpanel(_("Delete rule"),
631 _("Do you really want to delete this rule?"),
632 _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
635 gtk_clist_remove(clist, row);
638 static void prefs_scoring_up(void)
640 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
643 if (!clist->selection) return;
645 row = GPOINTER_TO_INT(clist->selection->data);
647 gtk_clist_row_move(clist, row, row - 1);
648 if(gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL) {
649 gtk_clist_moveto(clist, row - 1, 0, 0, 0);
654 static void prefs_scoring_down(void)
656 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
659 if (!clist->selection) return;
661 row = GPOINTER_TO_INT(clist->selection->data);
662 if (row > 0 && row < clist->rows - 1) {
663 gtk_clist_row_move(clist, row, row + 1);
664 if(gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL) {
665 gtk_clist_moveto(clist, row + 1, 0, 1, 0);
670 static void prefs_scoring_select_set_dialog(ScoringProp * prop)
678 matcher_str = matcherlist_to_string(prop->matchers);
679 if (matcher_str == NULL) {
680 scoringprop_free(prop);
684 score_str = itos(prop->score);
686 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), matcher_str);
687 gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
692 static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
700 prefs_scoring_reset_dialog();
704 if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
705 row, 0, &scoring_str))
708 prop = matcher_parser_get_scoring(scoring_str);
712 prefs_scoring_select_set_dialog(prop);
714 scoringprop_free(prop);
717 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
720 prefs_scoring_cancel();
724 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
727 if (event && event->keyval == GDK_Escape)
728 prefs_scoring_cancel();
731 static void prefs_scoring_ok(void)
733 prefs_common_save_config();
734 prefs_scoring_set_list();
735 prefs_matcher_write_config();
736 if (cur_item != NULL)
737 prefs_folder_item_save_config(cur_item);
738 gtk_widget_hide(scoring.window);
742 static void prefs_scoring_cancel(void)
744 prefs_matcher_read_config();
745 gtk_widget_hide(scoring.window);