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
71 #define VSPACING_NARROW 4
72 #define DEFAULT_ENTRY_WIDTH 80
73 #define PREFSBUFSIZE 1024
75 /* widget creating functions */
76 static void prefs_scoring_create (void);
78 static void prefs_scoring_set_dialog (ScoringProp * prop);
79 static void prefs_scoring_set_list (void);
81 /* callback functions */
82 /* static void prefs_scoring_select_dest_cb (void); */
83 static void prefs_scoring_register_cb (void);
84 static void prefs_scoring_substitute_cb (void);
85 static void prefs_scoring_delete_cb (void);
86 static void prefs_scoring_up (void);
87 static void prefs_scoring_down (void);
88 static void prefs_scoring_select (GtkCList *clist,
93 static gint prefs_scoring_deleted (GtkWidget *widget,
96 static void prefs_scoring_key_pressed (GtkWidget *widget,
99 static void prefs_scoring_cancel (void);
100 static void prefs_scoring_ok (void);
102 static void prefs_scoring_condition_define (void);
103 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop);
104 static void prefs_scoring_select_set_dialog(ScoringProp * prop);
105 static void prefs_scoring_reset_dialog(void);
108 static FolderItem * cur_item = NULL;
109 static gint cur_important_score;
110 static gint cur_kill_score;
112 void prefs_scoring_open(FolderItem * item)
114 inc_autocheck_timer_remove();
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)
132 inc_autocheck_timer_remove();
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) {
458 prop = scoringprop_parse(&tmp);
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') {
533 matchers = matcherlist_parse(&tmp);
535 alertpanel_error(_("Match string is not valid."));
538 prefs_matcher_open(matchers, prefs_scoring_condition_define_done);
540 if (matchers != NULL)
541 matcherlist_free(matchers);
545 /* register / substitute delete buttons */
547 static void prefs_scoring_register_cb(void)
556 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
557 if (*cond_str == '\0') {
558 alertpanel_error(_("Score is not set."));
562 score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
563 if (*score_str == '\0') {
564 alertpanel_error(_("Match string is not set."));
568 score = atoi(score_str);
570 cond = matcherlist_parse(&tmp);
573 alertpanel_error(_("Match string is not valid."));
577 prop = scoringprop_new(cond, score);
579 prefs_scoring_clist_set_row(-1, prop);
581 scoringprop_free(prop);
583 prefs_scoring_reset_dialog();
586 static void prefs_scoring_substitute_cb(void)
588 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
597 if (!clist->selection) return;
599 row = GPOINTER_TO_INT(clist->selection->data);
600 if (row == 0) return;
602 cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
603 if (*cond_str == '\0') {
604 alertpanel_error(_("Score is not set."));
608 score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
609 if (*score_str == '\0') {
610 alertpanel_error(_("Match string is not set."));
614 score = atoi(score_str);
616 cond = matcherlist_parse(&tmp);
619 alertpanel_error(_("Match string is not valid."));
623 prop = scoringprop_new(cond, score);
625 prefs_scoring_clist_set_row(row, prop);
627 scoringprop_free(prop);
629 prefs_scoring_reset_dialog();
632 static void prefs_scoring_delete_cb(void)
634 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
637 if (!clist->selection) return;
638 row = GPOINTER_TO_INT(clist->selection->data);
639 if (row == 0) return;
641 if (alertpanel(_("Delete rule"),
642 _("Do you really want to delete this rule?"),
643 _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
646 gtk_clist_remove(clist, row);
649 static void prefs_scoring_up(void)
651 GtkCList *clist = GTK_CLIST(scoring.cond_clist);
654 if (!clist->selection) return;
656 row = GPOINTER_TO_INT(clist->selection->data);
658 gtk_clist_row_move(clist, row, row - 1);
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);
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))
715 prop = scoringprop_parse(&tmp);
719 prefs_scoring_select_set_dialog(prop);
721 scoringprop_free(prop);
724 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
727 prefs_scoring_cancel();
731 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
734 if (event && event->keyval == GDK_Escape)
735 prefs_scoring_cancel();
738 static void prefs_scoring_ok(void)
740 prefs_scoring_set_list();
741 prefs_scoring_write_config();
742 if (cur_item != NULL)
743 prefs_folder_item_save_config(cur_item);
744 gtk_widget_hide(scoring.window);
747 static void prefs_scoring_cancel(void)
749 prefs_scoring_read_config();
750 gtk_widget_hide(scoring.window);