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;
56 GtkWidget *kill_score_label;
57 GtkWidget *kill_score_entry;
58 GtkWidget *important_score_entry;
60 GtkWidget *cond_clist;
64 parameter name, default value, pointer to the prefs variable, data type,
65 pointer to the widget pointer,
66 pointer to the function for data setting,
67 pointer to the function for widget setting
70 /* widget creating functions */
71 static void prefs_scoring_create (void);
73 static void prefs_scoring_set_dialog (ScoringProp * prop);
74 static void prefs_scoring_set_list (void);
76 /* callback functions */
77 /* static void prefs_scoring_select_dest_cb (void); */
78 static void prefs_scoring_register_cb (void);
79 static void prefs_scoring_substitute_cb (void);
80 static void prefs_scoring_delete_cb (void);
81 static void prefs_scoring_up (void);
82 static void prefs_scoring_down (void);
83 static void prefs_scoring_select (GtkCList *clist,
88 static gint prefs_scoring_deleted (GtkWidget *widget,
91 static void prefs_scoring_key_pressed (GtkWidget *widget,
94 static void prefs_scoring_cancel (void);
95 static void prefs_scoring_ok (void);
97 static void prefs_scoring_condition_define (void);
98 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop);
99 static void prefs_scoring_select_set_dialog(ScoringProp * prop);
100 static void prefs_scoring_reset_dialog(void);
103 static FolderItem * cur_item = NULL;
104 static gint cur_important_score;
105 static gint cur_kill_score;
107 void prefs_scoring_open(FolderItem * item)
109 if (prefs_rc_is_readonly(SCORING_RC))
112 inc_autocheck_timer_remove();
114 if (!scoring.window) {
115 prefs_scoring_create();
118 manage_window_set_transient(GTK_WINDOW(scoring.window));
119 gtk_widget_grab_focus(scoring.ok_btn);
123 prefs_scoring_set_dialog(NULL);
125 gtk_widget_show(scoring.window);
128 void prefs_scoring_open_with_scoring(ScoringProp * prop)
130 inc_autocheck_timer_remove();
132 if (!scoring.window) {
133 prefs_scoring_create();
136 manage_window_set_transient(GTK_WINDOW(scoring.window));
137 gtk_widget_grab_focus(scoring.ok_btn);
139 prefs_scoring_set_dialog(prop);
141 gtk_widget_show(scoring.window);
144 static void prefs_scoring_create(void)
149 GtkWidget *cancel_btn;
150 GtkWidget *confirm_area;
158 GtkWidget *cond_label;
159 GtkWidget *cond_entry;
161 GtkWidget *score_label;
162 GtkWidget *score_entry;
165 GtkWidget *subst_btn;
168 GtkWidget *cond_hbox;
169 GtkWidget *cond_scrolledwin;
170 GtkWidget *cond_clist;
176 GtkWidget *important_score_entry;
177 GtkWidget *kill_score_entry;
178 GtkWidget *kill_score_label;
180 gchar *title[] = {_("Registered rules")};
182 debug_print(_("Creating scoring setting window...\n"));
184 window = gtk_window_new (GTK_WINDOW_DIALOG);
185 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
186 gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
187 gtk_window_set_modal (GTK_WINDOW (window), TRUE);
188 gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
190 vbox = gtk_vbox_new (FALSE, 6);
191 gtk_widget_show (vbox);
192 gtk_container_add (GTK_CONTAINER (window), vbox);
194 gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
195 &cancel_btn, _("Cancel"), NULL, NULL);
196 gtk_widget_show (confirm_area);
197 gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
198 gtk_widget_grab_default (ok_btn);
200 gtk_window_set_title (GTK_WINDOW(window),
201 _("Scoring setting"));
202 gtk_signal_connect (GTK_OBJECT(window), "delete_event",
203 GTK_SIGNAL_FUNC(prefs_scoring_deleted), NULL);
204 gtk_signal_connect (GTK_OBJECT(window), "key_press_event",
205 GTK_SIGNAL_FUNC(prefs_scoring_key_pressed), NULL);
206 gtk_signal_connect (GTK_OBJECT(window), "focus_in_event",
207 GTK_SIGNAL_FUNC(manage_window_focus_in), NULL);
208 gtk_signal_connect (GTK_OBJECT(window), "focus_out_event",
209 GTK_SIGNAL_FUNC(manage_window_focus_out), NULL);
210 gtk_signal_connect (GTK_OBJECT(ok_btn), "clicked",
211 GTK_SIGNAL_FUNC(prefs_scoring_ok), NULL);
212 gtk_signal_connect (GTK_OBJECT(cancel_btn), "clicked",
213 GTK_SIGNAL_FUNC(prefs_scoring_cancel), NULL);
215 vbox1 = gtk_vbox_new (FALSE, VSPACING);
216 gtk_widget_show (vbox1);
217 gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
218 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
220 cond_label = gtk_label_new (_("Condition"));
221 gtk_widget_show (cond_label);
222 gtk_misc_set_alignment (GTK_MISC (cond_label), 0, 0.5);
223 gtk_box_pack_start (GTK_BOX (vbox1), cond_label, FALSE, FALSE, 0);
225 hbox1 = gtk_hbox_new (FALSE, VSPACING);
226 gtk_widget_show (vbox1);
227 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
228 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
230 cond_entry = gtk_entry_new ();
231 gtk_widget_show (cond_entry);
232 gtk_widget_set_usize (cond_entry, 300, -1);
233 gtk_box_pack_start (GTK_BOX (hbox1), cond_entry, TRUE, TRUE, 0);
235 cond_btn = gtk_button_new_with_label (_("Define ..."));
236 gtk_widget_show (cond_btn);
237 gtk_box_pack_start (GTK_BOX (hbox1), cond_btn, FALSE, FALSE, 0);
238 gtk_signal_connect (GTK_OBJECT (cond_btn), "clicked",
239 GTK_SIGNAL_FUNC (prefs_scoring_condition_define),
242 hbox1 = gtk_hbox_new (FALSE, VSPACING);
243 gtk_widget_show (vbox1);
244 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
245 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
247 score_label = gtk_label_new (_("Score"));
248 gtk_widget_show (score_label);
249 gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
250 gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
252 score_entry = gtk_entry_new ();
253 gtk_widget_show (score_entry);
254 gtk_widget_set_usize (score_entry, 50, -1);
255 gtk_box_pack_start (GTK_BOX (hbox1), score_entry, FALSE, FALSE, 0);
257 /* register / substitute / delete */
259 reg_hbox = gtk_hbox_new (FALSE, 4);
260 gtk_widget_show (reg_hbox);
261 gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
263 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
264 gtk_widget_show (arrow);
265 gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
266 gtk_widget_set_usize (arrow, -1, 16);
268 btn_hbox = gtk_hbox_new (TRUE, 4);
269 gtk_widget_show (btn_hbox);
270 gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
272 reg_btn = gtk_button_new_with_label (_("Register"));
273 gtk_widget_show (reg_btn);
274 gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
275 gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
276 GTK_SIGNAL_FUNC (prefs_scoring_register_cb), NULL);
278 subst_btn = gtk_button_new_with_label (_(" Substitute "));
279 gtk_widget_show (subst_btn);
280 gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
281 gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
282 GTK_SIGNAL_FUNC (prefs_scoring_substitute_cb),
285 del_btn = gtk_button_new_with_label (_("Delete"));
286 gtk_widget_show (del_btn);
287 gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
288 gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
289 GTK_SIGNAL_FUNC (prefs_scoring_delete_cb), NULL);
291 cond_hbox = gtk_hbox_new (FALSE, 8);
292 gtk_widget_show (cond_hbox);
293 gtk_box_pack_start (GTK_BOX (vbox1), cond_hbox, TRUE, TRUE, 0);
295 cond_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
296 gtk_widget_show (cond_scrolledwin);
297 gtk_widget_set_usize (cond_scrolledwin, -1, 150);
298 gtk_box_pack_start (GTK_BOX (cond_hbox), cond_scrolledwin,
300 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cond_scrolledwin),
301 GTK_POLICY_AUTOMATIC,
302 GTK_POLICY_AUTOMATIC);
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) {
456 prop = scoringprop_parse(&tmp);
458 prefs_scoring = g_slist_append(prefs_scoring,
464 cur_kill_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.kill_score_entry)));
465 cur_important_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.important_score_entry)));
467 if (cur_item == NULL) {
468 global_scoring = prefs_scoring;
469 prefs_common.kill_score = cur_kill_score;
470 prefs_common.important_score = cur_important_score;
473 cur_item->prefs->scoring = prefs_scoring;
474 cur_item->prefs->kill_score = cur_kill_score;
475 cur_item->prefs->important_score = cur_important_score;
479 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop)
481 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
486 cond_str[0] = _("(New)");
487 return gtk_clist_append(clist, cond_str);
490 str = scoringprop_to_string(prop);
497 row = gtk_clist_append(clist, cond_str);
499 gtk_clist_set_text(clist, row, 0, cond_str[0]);
505 static void prefs_scoring_condition_define_done(MatcherList * matchers)
509 if (matchers == NULL)
512 str = matcherlist_to_string(matchers);
515 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), str);
520 static void prefs_scoring_condition_define(void)
523 MatcherList * matchers = NULL;
525 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
527 if (*cond_str != '\0') {
531 matchers = matcherlist_parse(&tmp);
533 alertpanel_error(_("Match string is not valid."));
536 prefs_matcher_open(matchers, prefs_scoring_condition_define_done);
538 if (matchers != NULL)
539 matcherlist_free(matchers);
543 /* register / substitute delete buttons */
545 static void prefs_scoring_register_cb(void)
554 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
555 if (*cond_str == '\0') {
556 alertpanel_error(_("Score is not set."));
560 score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
561 if (*score_str == '\0') {
562 alertpanel_error(_("Match string is not set."));
566 score = atoi(score_str);
568 cond = matcherlist_parse(&tmp);
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);
595 if (!clist->selection) return;
597 row = GPOINTER_TO_INT(clist->selection->data);
598 if (row == 0) return;
600 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
601 if (*cond_str == '\0') {
602 alertpanel_error(_("Score is not set."));
606 score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
607 if (*score_str == '\0') {
608 alertpanel_error(_("Match string is not set."));
612 score = atoi(score_str);
614 cond = matcherlist_parse(&tmp);
617 alertpanel_error(_("Match string is not valid."));
621 prop = scoringprop_new(cond, score);
623 prefs_scoring_clist_set_row(row, prop);
625 scoringprop_free(prop);
627 prefs_scoring_reset_dialog();
630 static void prefs_scoring_delete_cb(void)
632 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
635 if (!clist->selection) return;
636 row = GPOINTER_TO_INT(clist->selection->data);
637 if (row == 0) return;
639 if (alertpanel(_("Delete rule"),
640 _("Do you really want to delete this rule?"),
641 _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
644 gtk_clist_remove(clist, row);
647 static void prefs_scoring_up(void)
649 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
652 if (!clist->selection) return;
654 row = GPOINTER_TO_INT(clist->selection->data);
656 gtk_clist_row_move(clist, row, row - 1);
657 if(gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL) {
658 gtk_clist_moveto(clist, row - 1, 0, 0, 0);
663 static void prefs_scoring_down(void)
665 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
668 if (!clist->selection) return;
670 row = GPOINTER_TO_INT(clist->selection->data);
671 if (row > 0 && row < clist->rows - 1) {
672 gtk_clist_row_move(clist, row, row + 1);
673 if(gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL) {
674 gtk_clist_moveto(clist, row + 1, 0, 1, 0);
679 static void prefs_scoring_select_set_dialog(ScoringProp * prop)
687 matcher_str = matcherlist_to_string(prop->matchers);
688 if (matcher_str == NULL) {
689 scoringprop_free(prop);
693 score_str = itos(prop->score);
695 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), matcher_str);
696 gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
701 static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
710 prefs_scoring_reset_dialog();
714 if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
715 row, 0, &scoring_str))
719 prop = scoringprop_parse(&tmp);
723 prefs_scoring_select_set_dialog(prop);
725 scoringprop_free(prop);
728 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
731 prefs_scoring_cancel();
735 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
738 if (event && event->keyval == GDK_Escape)
739 prefs_scoring_cancel();
742 static void prefs_scoring_ok(void)
744 prefs_scoring_set_list();
745 prefs_scoring_write_config();
746 if (cur_item != NULL)
747 prefs_folder_item_save_config(cur_item);
748 gtk_widget_hide(scoring.window);
751 static void prefs_scoring_cancel(void)
753 prefs_scoring_read_config();
754 gtk_widget_hide(scoring.window);