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 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 title[0] = ("Registered rules");
307 cond_clist = gtk_clist_new_with_titles(1, title);
308 gtk_widget_show (cond_clist);
309 gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
310 gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
311 gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
312 GTK_SELECTION_BROWSE);
313 GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
315 gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
316 GTK_SIGNAL_FUNC (prefs_scoring_select), NULL);
318 btn_vbox = gtk_vbox_new (FALSE, 8);
319 gtk_widget_show (btn_vbox);
320 gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
322 up_btn = gtk_button_new_with_label (_("Up"));
323 gtk_widget_show (up_btn);
324 gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
325 gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
326 GTK_SIGNAL_FUNC (prefs_scoring_up), NULL);
328 down_btn = gtk_button_new_with_label (_("Down"));
329 gtk_widget_show (down_btn);
330 gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
331 gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
332 GTK_SIGNAL_FUNC (prefs_scoring_down), NULL);
334 hbox1 = gtk_hbox_new (FALSE, 8);
335 gtk_widget_show (hbox1);
336 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
338 kill_score_label = gtk_label_new (_("Kill score"));
339 gtk_widget_show (kill_score_label);
340 gtk_misc_set_alignment (GTK_MISC (kill_score_label), 0, 0.5);
341 gtk_box_pack_start (GTK_BOX (hbox1), kill_score_label,
344 kill_score_entry = gtk_entry_new ();
345 gtk_widget_show (kill_score_entry);
346 gtk_widget_set_usize (kill_score_entry, 50, -1);
347 gtk_box_pack_start (GTK_BOX (hbox1), kill_score_entry,
350 score_label = gtk_label_new (_("Important score"));
351 gtk_widget_show (score_label);
352 gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
353 gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
355 important_score_entry = gtk_entry_new ();
356 gtk_widget_show (important_score_entry);
357 gtk_widget_set_usize (important_score_entry, 50, -1);
358 gtk_box_pack_start (GTK_BOX (hbox1), important_score_entry,
361 gtk_widget_show_all(window);
363 scoring.window = window;
364 scoring.ok_btn = ok_btn;
366 scoring.cond_entry = cond_entry;
367 scoring.score_entry = score_entry;
368 scoring.kill_score_entry = kill_score_entry;
369 scoring.kill_score_label = kill_score_label;
370 scoring.important_score_entry = important_score_entry;
372 scoring.cond_clist = cond_clist;
375 static void prefs_scoring_set_dialog(ScoringProp * cond)
377 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
379 GSList * prefs_scoring;
383 prefs_scoring_reset_dialog();
385 prefs_scoring_select_set_dialog(cond);
387 gtk_clist_freeze(clist);
388 gtk_clist_clear(clist);
390 prefs_scoring_clist_set_row(-1, NULL);
391 if (cur_item == NULL) {
392 prefs_scoring = global_scoring;
393 cur_kill_score = prefs_common.kill_score;
394 cur_important_score = prefs_common.important_score;
395 gtk_widget_show(scoring.kill_score_label);
396 gtk_widget_show(scoring.kill_score_entry);
399 prefs_scoring = cur_item->prefs->scoring;
400 cur_kill_score = cur_item->prefs->kill_score;
401 cur_important_score = cur_item->prefs->important_score;
402 if (cur_item->folder->type != F_NEWS) {
403 gtk_widget_hide(scoring.kill_score_label);
404 gtk_widget_hide(scoring.kill_score_entry);
407 gtk_widget_show(scoring.kill_score_label);
408 gtk_widget_show(scoring.kill_score_entry);
412 for(cur = prefs_scoring ; cur != NULL ;
413 cur = g_slist_next(cur)) {
414 ScoringProp * prop = (ScoringProp *) cur->data;
416 prefs_scoring_clist_set_row(-1, prop);
419 score_str = itos(cur_kill_score);
420 gtk_entry_set_text(GTK_ENTRY(scoring.kill_score_entry),
422 score_str = itos(cur_important_score);
423 gtk_entry_set_text(GTK_ENTRY(scoring.important_score_entry),
426 gtk_clist_thaw(clist);
429 static void prefs_scoring_reset_dialog(void)
431 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), "");
432 gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), "");
435 static void prefs_scoring_set_list(void)
442 GSList * prefs_scoring;
444 if (cur_item == NULL)
445 prefs_scoring = global_scoring;
447 prefs_scoring = cur_item->prefs->scoring;
449 for(cur = prefs_scoring ; cur != NULL ;
450 cur = g_slist_next(cur))
451 scoringprop_free((ScoringProp *) cur->data);
452 g_slist_free(prefs_scoring);
453 prefs_scoring = NULL;
455 while (gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
456 row, 0, &scoring_str)) {
457 if (strcmp(scoring_str, _("(New)")) != 0) {
458 prop = matcher_parser_get_scoring(scoring_str);
460 prefs_scoring = g_slist_append(prefs_scoring,
466 cur_kill_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.kill_score_entry)));
467 cur_important_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.important_score_entry)));
469 if (cur_item == NULL) {
470 global_scoring = prefs_scoring;
471 prefs_common.kill_score = cur_kill_score;
472 prefs_common.important_score = cur_important_score;
475 cur_item->prefs->scoring = prefs_scoring;
476 cur_item->prefs->kill_score = cur_kill_score;
477 cur_item->prefs->important_score = cur_important_score;
481 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop)
483 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
488 cond_str[0] = _("(New)");
489 return gtk_clist_append(clist, cond_str);
492 str = scoringprop_to_string(prop);
499 row = gtk_clist_append(clist, cond_str);
501 gtk_clist_set_text(clist, row, 0, cond_str[0]);
507 static void prefs_scoring_condition_define_done(MatcherList * matchers)
511 if (matchers == NULL)
514 str = matcherlist_to_string(matchers);
517 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), str);
522 static void prefs_scoring_condition_define(void)
525 MatcherList * matchers = NULL;
527 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
529 if (*cond_str != '\0') {
532 matchers = matcher_parser_get_cond(cond_str);
533 if (matchers == NULL)
534 alertpanel_error(_("Match string is not valid."));
537 prefs_matcher_open(matchers, prefs_scoring_condition_define_done);
539 if (matchers != NULL)
540 matcherlist_free(matchers);
544 /* register / substitute delete buttons */
546 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);
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);
613 cond = matcher_parser_get_cond(cond_str);
616 alertpanel_error(_("Match string is not valid."));
620 prop = scoringprop_new(cond, score);
622 prefs_scoring_clist_set_row(row, prop);
624 scoringprop_free(prop);
626 prefs_scoring_reset_dialog();
629 static void prefs_scoring_delete_cb(void)
631 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
634 if (!clist->selection) return;
635 row = GPOINTER_TO_INT(clist->selection->data);
636 if (row == 0) return;
638 if (alertpanel(_("Delete rule"),
639 _("Do you really want to delete this rule?"),
640 _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
643 gtk_clist_remove(clist, row);
646 static void prefs_scoring_up(void)
648 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
651 if (!clist->selection) return;
653 row = GPOINTER_TO_INT(clist->selection->data);
655 gtk_clist_row_move(clist, row, row - 1);
656 if(gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL) {
657 gtk_clist_moveto(clist, row - 1, 0, 0, 0);
662 static void prefs_scoring_down(void)
664 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
667 if (!clist->selection) return;
669 row = GPOINTER_TO_INT(clist->selection->data);
670 if (row > 0 && row < clist->rows - 1) {
671 gtk_clist_row_move(clist, row, row + 1);
672 if(gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL) {
673 gtk_clist_moveto(clist, row + 1, 0, 1, 0);
678 static void prefs_scoring_select_set_dialog(ScoringProp * prop)
686 matcher_str = matcherlist_to_string(prop->matchers);
687 if (matcher_str == NULL) {
688 scoringprop_free(prop);
692 score_str = itos(prop->score);
694 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), matcher_str);
695 gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
700 static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
709 prefs_scoring_reset_dialog();
713 if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
714 row, 0, &scoring_str))
717 prop = matcher_parser_get_scoring(scoring_str);
721 prefs_scoring_select_set_dialog(prop);
723 scoringprop_free(prop);
726 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
729 prefs_scoring_cancel();
733 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
736 if (event && event->keyval == GDK_Escape)
737 prefs_scoring_cancel();
740 static void prefs_scoring_ok(void)
742 prefs_common_save_config();
743 prefs_scoring_set_list();
744 prefs_matcher_write_config();
745 if (cur_item != NULL)
746 prefs_folder_item_save_config(cur_item);
747 gtk_widget_hide(scoring.window);
751 static void prefs_scoring_cancel(void)
753 prefs_matcher_read_config();
754 gtk_widget_hide(scoring.window);