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;
182 gchar *title[] = {_("Registered rules")};
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 gtk_signal_connect (GTK_OBJECT(window), "focus_in_event",
209 GTK_SIGNAL_FUNC(manage_window_focus_in), NULL);
210 gtk_signal_connect (GTK_OBJECT(window), "focus_out_event",
211 GTK_SIGNAL_FUNC(manage_window_focus_out), NULL);
212 gtk_signal_connect (GTK_OBJECT(ok_btn), "clicked",
213 GTK_SIGNAL_FUNC(prefs_scoring_ok), NULL);
214 gtk_signal_connect (GTK_OBJECT(cancel_btn), "clicked",
215 GTK_SIGNAL_FUNC(prefs_scoring_cancel), NULL);
217 vbox1 = gtk_vbox_new (FALSE, VSPACING);
218 gtk_widget_show (vbox1);
219 gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
220 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
222 cond_label = gtk_label_new (_("Condition"));
223 gtk_widget_show (cond_label);
224 gtk_misc_set_alignment (GTK_MISC (cond_label), 0, 0.5);
225 gtk_box_pack_start (GTK_BOX (vbox1), cond_label, FALSE, FALSE, 0);
227 hbox1 = gtk_hbox_new (FALSE, VSPACING);
228 gtk_widget_show (vbox1);
229 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
230 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
232 cond_entry = gtk_entry_new ();
233 gtk_widget_show (cond_entry);
234 gtk_widget_set_usize (cond_entry, 300, -1);
235 gtk_box_pack_start (GTK_BOX (hbox1), cond_entry, TRUE, TRUE, 0);
237 cond_btn = gtk_button_new_with_label (_("Define ..."));
238 gtk_widget_show (cond_btn);
239 gtk_box_pack_start (GTK_BOX (hbox1), cond_btn, FALSE, FALSE, 0);
240 gtk_signal_connect (GTK_OBJECT (cond_btn), "clicked",
241 GTK_SIGNAL_FUNC (prefs_scoring_condition_define),
244 hbox1 = gtk_hbox_new (FALSE, VSPACING);
245 gtk_widget_show (vbox1);
246 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
247 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
249 score_label = gtk_label_new (_("Score"));
250 gtk_widget_show (score_label);
251 gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
252 gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
254 score_entry = gtk_entry_new ();
255 gtk_widget_show (score_entry);
256 gtk_widget_set_usize (score_entry, 50, -1);
257 gtk_box_pack_start (GTK_BOX (hbox1), score_entry, FALSE, FALSE, 0);
259 /* register / substitute / delete */
261 reg_hbox = gtk_hbox_new (FALSE, 4);
262 gtk_widget_show (reg_hbox);
263 gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
265 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
266 gtk_widget_show (arrow);
267 gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
268 gtk_widget_set_usize (arrow, -1, 16);
270 btn_hbox = gtk_hbox_new (TRUE, 4);
271 gtk_widget_show (btn_hbox);
272 gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
274 reg_btn = gtk_button_new_with_label (_("Register"));
275 gtk_widget_show (reg_btn);
276 gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
277 gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
278 GTK_SIGNAL_FUNC (prefs_scoring_register_cb), NULL);
280 subst_btn = gtk_button_new_with_label (_(" Substitute "));
281 gtk_widget_show (subst_btn);
282 gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
283 gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
284 GTK_SIGNAL_FUNC (prefs_scoring_substitute_cb),
287 del_btn = gtk_button_new_with_label (_("Delete"));
288 gtk_widget_show (del_btn);
289 gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
290 gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
291 GTK_SIGNAL_FUNC (prefs_scoring_delete_cb), NULL);
293 cond_hbox = gtk_hbox_new (FALSE, 8);
294 gtk_widget_show (cond_hbox);
295 gtk_box_pack_start (GTK_BOX (vbox1), cond_hbox, TRUE, TRUE, 0);
297 cond_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
298 gtk_widget_show (cond_scrolledwin);
299 gtk_widget_set_usize (cond_scrolledwin, -1, 150);
300 gtk_box_pack_start (GTK_BOX (cond_hbox), cond_scrolledwin,
302 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cond_scrolledwin),
303 GTK_POLICY_AUTOMATIC,
304 GTK_POLICY_AUTOMATIC);
306 cond_clist = gtk_clist_new_with_titles(1, title);
307 gtk_widget_show (cond_clist);
308 gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
309 gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
310 gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
311 GTK_SELECTION_BROWSE);
312 GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
314 gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
315 GTK_SIGNAL_FUNC (prefs_scoring_select), NULL);
317 btn_vbox = gtk_vbox_new (FALSE, 8);
318 gtk_widget_show (btn_vbox);
319 gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
321 up_btn = gtk_button_new_with_label (_("Up"));
322 gtk_widget_show (up_btn);
323 gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
324 gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
325 GTK_SIGNAL_FUNC (prefs_scoring_up), NULL);
327 down_btn = gtk_button_new_with_label (_("Down"));
328 gtk_widget_show (down_btn);
329 gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
330 gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
331 GTK_SIGNAL_FUNC (prefs_scoring_down), NULL);
333 hbox1 = gtk_hbox_new (FALSE, 8);
334 gtk_widget_show (hbox1);
335 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
337 kill_score_label = gtk_label_new (_("Kill score"));
338 gtk_widget_show (kill_score_label);
339 gtk_misc_set_alignment (GTK_MISC (kill_score_label), 0, 0.5);
340 gtk_box_pack_start (GTK_BOX (hbox1), kill_score_label,
343 kill_score_entry = gtk_entry_new ();
344 gtk_widget_show (kill_score_entry);
345 gtk_widget_set_usize (kill_score_entry, 50, -1);
346 gtk_box_pack_start (GTK_BOX (hbox1), kill_score_entry,
349 score_label = gtk_label_new (_("Important score"));
350 gtk_widget_show (score_label);
351 gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
352 gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
354 important_score_entry = gtk_entry_new ();
355 gtk_widget_show (important_score_entry);
356 gtk_widget_set_usize (important_score_entry, 50, -1);
357 gtk_box_pack_start (GTK_BOX (hbox1), important_score_entry,
360 gtk_widget_show_all(window);
362 scoring.window = window;
363 scoring.ok_btn = ok_btn;
365 scoring.cond_entry = cond_entry;
366 scoring.score_entry = score_entry;
367 scoring.kill_score_entry = kill_score_entry;
368 scoring.kill_score_label = kill_score_label;
369 scoring.important_score_entry = important_score_entry;
371 scoring.cond_clist = cond_clist;
374 static void prefs_scoring_set_dialog(ScoringProp * cond)
376 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
378 GSList * prefs_scoring;
382 prefs_scoring_reset_dialog();
384 prefs_scoring_select_set_dialog(cond);
386 gtk_clist_freeze(clist);
387 gtk_clist_clear(clist);
389 prefs_scoring_clist_set_row(-1, NULL);
390 if (cur_item == NULL) {
391 prefs_scoring = global_scoring;
392 cur_kill_score = prefs_common.kill_score;
393 cur_important_score = prefs_common.important_score;
394 gtk_widget_show(scoring.kill_score_label);
395 gtk_widget_show(scoring.kill_score_entry);
398 prefs_scoring = cur_item->prefs->scoring;
399 cur_kill_score = cur_item->prefs->kill_score;
400 cur_important_score = cur_item->prefs->important_score;
401 if (cur_item->folder->type != F_NEWS) {
402 gtk_widget_hide(scoring.kill_score_label);
403 gtk_widget_hide(scoring.kill_score_entry);
406 gtk_widget_show(scoring.kill_score_label);
407 gtk_widget_show(scoring.kill_score_entry);
411 for(cur = prefs_scoring ; cur != NULL ;
412 cur = g_slist_next(cur)) {
413 ScoringProp * prop = (ScoringProp *) cur->data;
415 prefs_scoring_clist_set_row(-1, prop);
418 score_str = itos(cur_kill_score);
419 gtk_entry_set_text(GTK_ENTRY(scoring.kill_score_entry),
421 score_str = itos(cur_important_score);
422 gtk_entry_set_text(GTK_ENTRY(scoring.important_score_entry),
425 gtk_clist_thaw(clist);
428 static void prefs_scoring_reset_dialog(void)
430 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), "");
431 gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), "");
434 static void prefs_scoring_set_list(void)
441 GSList * prefs_scoring;
443 if (cur_item == NULL)
444 prefs_scoring = global_scoring;
446 prefs_scoring = cur_item->prefs->scoring;
448 for(cur = prefs_scoring ; cur != NULL ;
449 cur = g_slist_next(cur))
450 scoringprop_free((ScoringProp *) cur->data);
451 g_slist_free(prefs_scoring);
452 prefs_scoring = NULL;
454 while (gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
455 row, 0, &scoring_str)) {
456 if (strcmp(scoring_str, _("(New)")) != 0) {
457 prop = matcher_parser_get_scoring(scoring_str);
459 prefs_scoring = g_slist_append(prefs_scoring,
465 cur_kill_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.kill_score_entry)));
466 cur_important_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.important_score_entry)));
468 if (cur_item == NULL) {
469 global_scoring = prefs_scoring;
470 prefs_common.kill_score = cur_kill_score;
471 prefs_common.important_score = cur_important_score;
474 cur_item->prefs->scoring = prefs_scoring;
475 cur_item->prefs->kill_score = cur_kill_score;
476 cur_item->prefs->important_score = cur_important_score;
480 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop)
482 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
487 cond_str[0] = _("(New)");
488 return gtk_clist_append(clist, cond_str);
491 str = scoringprop_to_string(prop);
498 row = gtk_clist_append(clist, cond_str);
500 gtk_clist_set_text(clist, row, 0, cond_str[0]);
506 static void prefs_scoring_condition_define_done(MatcherList * matchers)
510 if (matchers == NULL)
513 str = matcherlist_to_string(matchers);
516 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), str);
521 static void prefs_scoring_condition_define(void)
524 MatcherList * matchers = NULL;
526 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
528 if (*cond_str != '\0') {
531 matchers = matcher_parser_get_cond(cond_str);
532 if (matchers == NULL)
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);
567 cond = matcher_parser_get_cond(cond_str);
570 alertpanel_error(_("Match string is not valid."));
574 prop = scoringprop_new(cond, score);
576 prefs_scoring_clist_set_row(-1, prop);
578 scoringprop_free(prop);
580 prefs_scoring_reset_dialog();
583 static void prefs_scoring_substitute_cb(void)
585 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);
655 if(gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL) {
656 gtk_clist_moveto(clist, row - 1, 0, 0, 0);
661 static void prefs_scoring_down(void)
663 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
666 if (!clist->selection) return;
668 row = GPOINTER_TO_INT(clist->selection->data);
669 if (row > 0 && row < clist->rows - 1) {
670 gtk_clist_row_move(clist, row, row + 1);
671 if(gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL) {
672 gtk_clist_moveto(clist, row + 1, 0, 1, 0);
677 static void prefs_scoring_select_set_dialog(ScoringProp * prop)
685 matcher_str = matcherlist_to_string(prop->matchers);
686 if (matcher_str == NULL) {
687 scoringprop_free(prop);
691 score_str = itos(prop->score);
693 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), matcher_str);
694 gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
699 static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
708 prefs_scoring_reset_dialog();
712 if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
713 row, 0, &scoring_str))
716 prop = matcher_parser_get_scoring(scoring_str);
720 prefs_scoring_select_set_dialog(prop);
722 scoringprop_free(prop);
725 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
728 prefs_scoring_cancel();
732 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
735 if (event && event->keyval == GDK_Escape)
736 prefs_scoring_cancel();
739 static void prefs_scoring_ok(void)
741 prefs_common_save_config();
742 prefs_scoring_set_list();
743 prefs_matcher_write_config();
744 if (cur_item != NULL)
745 prefs_folder_item_save_config(cur_item);
746 gtk_widget_hide(scoring.window);
750 static void prefs_scoring_cancel(void)
752 prefs_matcher_read_config();
753 gtk_widget_hide(scoring.window);