From 9b8c98aff960fc12a1801588b35f3844b9095aec Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ho=C3=A0=20Vi=C3=AAt=20Dinh?= Date: Thu, 7 Aug 2003 13:30:23 +0000 Subject: [PATCH] several actions for each filtering rules can now be defined --- ChangeLog.claws | 14 + Makefile.am | 2 +- configure.ac | 2 +- src/Makefile.am | 2 + src/filtering.c | 134 +++- src/filtering.h | 5 +- src/matcher_parser.h | 1 + src/matcher_parser_parse.y | 108 ++- src/prefs_filtering.c | 726 +++++-------------- src/prefs_filtering_action.c | 1273 ++++++++++++++++++++++++++++++++++ src/prefs_filtering_action.h | 31 + 11 files changed, 1694 insertions(+), 604 deletions(-) create mode 100644 src/prefs_filtering_action.c create mode 100644 src/prefs_filtering_action.h diff --git a/ChangeLog.claws b/ChangeLog.claws index 721c11bf7..60bd2e8f0 100644 --- a/ChangeLog.claws +++ b/ChangeLog.claws @@ -1,3 +1,17 @@ +2003-08-07 [hoa] 0.9.4claws7 + + * src/filtering.[ch] + * src/matcher_parser.h + * src/matcher_parser_parse.y + can define several actions for each filtering rule + can import old versions of filtering rules + + * src/prefs_filtering.c + call to a new dialog box to define actions + + * src/prefs_filtering_action.[ch] + dialog box to define actions for filtering rules + 2003-08-06 [christoph] 0.9.4claws6 * src/imap.c diff --git a/Makefile.am b/Makefile.am index 59d283ff5..945e0e191 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = ac po intl src man manual faq tools config +SUBDIRS = ac po src man manual faq tools config intl EXTRA_DIST = \ ChangeLog.claws \ diff --git a/configure.ac b/configure.ac index d23fac3ed..7b250f8ba 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ MINOR_VERSION=9 MICRO_VERSION=4 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=6 +EXTRA_VERSION=7 if test $EXTRA_VERSION -eq 0; then VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}claws else diff --git a/src/Makefile.am b/src/Makefile.am index 025b878d6..25c6e6bdf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -82,6 +82,7 @@ sylpheed_SOURCES = \ prefs_customheader.c \ prefs_display_header.c \ prefs_filtering.c \ + prefs_filtering_action.c \ prefs_folder_item.c \ prefs_gtk.c \ prefs_matcher.c \ @@ -200,6 +201,7 @@ sylpheedinclude_HEADERS = \ prefs_customheader.h \ prefs_display_header.h \ prefs_filtering.h \ + prefs_filtering_action.h \ prefs_folder_item.h \ prefs_gtk.h \ prefs_matcher.h \ diff --git a/src/filtering.c b/src/filtering.c index 934eb08d4..2bba0912d 100644 --- a/src/filtering.c +++ b/src/filtering.c @@ -36,6 +36,8 @@ GSList * global_processing = NULL; +static gboolean filtering_is_final_action(FilteringAction *filtering_action); + #define STRLEN_WITH_CHECK(expr) \ strlen_with_check(#expr, __LINE__, expr) @@ -86,17 +88,38 @@ void filteringaction_free(FilteringAction * action) } FilteringProp * filteringprop_new(MatcherList * matchers, - FilteringAction * action) + GSList * action_list) { FilteringProp * filtering; filtering = g_new0(FilteringProp, 1); filtering->matchers = matchers; - filtering->action = action; + filtering->action_list = action_list; return filtering; } +static FilteringAction * filteringaction_copy(FilteringAction * src) +{ + FilteringAction * new; + + new = g_new0(FilteringAction, 1); + + new->type = src->type; + new->account_id = src->account_id; + if (src->destination) + new->destination = g_strdup(src->destination); + else + new->destination = NULL; + if (src->unesc_destination) + new->unesc_destination = g_strdup(src->unesc_destination); + else + new->unesc_destination = NULL; + new->labelcolor = src->labelcolor; + + return new; +} + FilteringProp * filteringprop_copy(FilteringProp *src) { FilteringProp * new; @@ -104,7 +127,11 @@ FilteringProp * filteringprop_copy(FilteringProp *src) new = g_new0(FilteringProp, 1); new->matchers = g_new0(MatcherList, 1); + +#if 0 new->action = g_new0(FilteringAction, 1); +#endif + for (tmp = src->matchers->matchers; tmp != NULL && tmp->data != NULL;) { MatcherProp *matcher = (MatcherProp *)tmp->data; @@ -112,7 +139,10 @@ FilteringProp * filteringprop_copy(FilteringProp *src) matcherprop_copy(matcher)); tmp = tmp->next; } + new->matchers->bool_and = src->matchers->bool_and; + +#if 0 new->action->type = src->action->type; new->action->account_id = src->action->account_id; if (src->action->destination) @@ -124,14 +154,31 @@ FilteringProp * filteringprop_copy(FilteringProp *src) else new->action->unesc_destination = NULL; new->action->labelcolor = src->action->labelcolor; +#endif + new->action_list = NULL; + + for (tmp = src->action_list ; tmp != NULL ; tmp = tmp->next) { + FilteringAction *filtering_action; + + filtering_action = tmp->data; + + new->action_list = g_slist_append(new->action_list, + filteringaction_copy(filtering_action)); + } + return new; } void filteringprop_free(FilteringProp * prop) { + GSList * tmp; + g_return_if_fail(prop); matcherlist_free(prop->matchers); - filteringaction_free(prop->action); + + for (tmp = prop->action_list ; tmp != NULL ; tmp = tmp->next) { + filteringaction_free(tmp->data); + } g_free(prop); } @@ -297,21 +344,35 @@ static gboolean filtering_match_condition(FilteringProp *filtering, MsgInfo *inf return matcherlist_match(filtering->matchers, info); } -static gboolean filtering_apply_rule(FilteringProp *filtering, MsgInfo *info) +static gboolean filtering_apply_rule(FilteringProp *filtering, MsgInfo *info, + gboolean * final) { gboolean result; gchar buf[50]; - - if (FALSE == (result = filteringaction_apply(filtering->action, info))) { - g_warning("action %s could not be applied", - filteringaction_to_string(buf, sizeof buf, filtering->action)); - } + GSList * tmp; + + * final = FALSE; + for (tmp = filtering->action_list ; tmp != NULL ; tmp = tmp->next) { + FilteringAction * action; + + action = tmp->data; + + if (FALSE == (result = filteringaction_apply(action, info))) { + g_warning("action %s could not be applied", + filteringaction_to_string(buf, sizeof buf, action)); + } + + if (filtering_is_final_action(action)) { + * final = TRUE; + break; + } + } return result; } -static gboolean filtering_is_final_action(FilteringProp *filtering) +static gboolean filtering_is_final_action(FilteringAction *filtering_action) { - switch(filtering->action->type) { + switch(filtering_action->type) { case MATCHACTION_MOVE: case MATCHACTION_DELETE: return TRUE; /* MsgInfo invalid for message */ @@ -344,9 +405,13 @@ static gboolean filter_msginfo(GSList * filtering_list, MsgInfo * info) FilteringProp * filtering = (FilteringProp *) l->data; if (filtering_match_condition(filtering, info)) { - applied = filtering_apply_rule(filtering, info); + applied = filtering_apply_rule(filtering, info, &final); +#if 0 if (TRUE == (final = filtering_is_final_action(filtering))) break; +#endif + if (final) + break; } } @@ -404,24 +469,57 @@ gchar *filteringaction_to_string(gchar *dest, gint destlen, FilteringAction *act } } +gchar * filteringaction_list_to_string(GSList * action_list) +{ + gchar *action_list_str; + gchar buf[256]; + GSList * tmp; + gchar *list_str; + + action_list_str = NULL; + for (tmp = action_list ; tmp != NULL ; tmp = tmp->next) { + gchar *action_str; + FilteringAction * action; + + action = tmp->data; + + action_str = filteringaction_to_string(buf, + sizeof buf, action); + + if (action_list_str != NULL) { + list_str = g_strconcat(action_list_str, " ", action_str, NULL); + g_free(action_list_str); + } + else { + list_str = g_strdup(action_str); + } + action_list_str = list_str; + } + + return action_list_str; +} + gchar * filteringprop_to_string(FilteringProp * prop) { gchar *list_str; - gchar *action_str; + gchar *action_list_str; gchar *filtering_str; - gchar buf[256]; + GSList * tmp; - action_str = filteringaction_to_string(buf, sizeof buf, prop->action); + action_list_str = filteringaction_list_to_string(prop->action_list); - if (action_str == NULL) + if (action_list_str == NULL) return NULL; list_str = matcherlist_to_string(prop->matchers); - if (list_str == NULL) + if (list_str == NULL) { + g_free(action_list_str); return NULL; + } - filtering_str = g_strconcat(list_str, " ", action_str, NULL); + filtering_str = g_strconcat(list_str, " ", action_list_str, NULL); + g_free(action_list_str); g_free(list_str); return filtering_str; diff --git a/src/filtering.h b/src/filtering.h index 0b8f5e6bd..bda6ca59d 100644 --- a/src/filtering.h +++ b/src/filtering.h @@ -37,7 +37,7 @@ typedef struct _FilteringAction FilteringAction; struct _FilteringProp { MatcherList * matchers; - FilteringAction * action; + GSList * action_list; }; typedef struct _FilteringProp FilteringProp; @@ -52,7 +52,7 @@ void filteringaction_free(FilteringAction *action); FilteringAction * filteringaction_parse(gchar **str); FilteringProp * filteringprop_new(MatcherList *matchers, - FilteringAction *action); + GSList *action_list); void filteringprop_free(FilteringProp *prop); FilteringProp * filteringprop_parse(gchar **str); @@ -63,6 +63,7 @@ gboolean filter_message_by_msginfo(GSList *flist, MsgInfo *info); gchar * filteringaction_to_string(gchar *dest, gint destlen, FilteringAction *action); void prefs_filtering_write_config(void); void prefs_filtering_read_config(void); +gchar * filteringaction_list_to_string(GSList * action_list); gchar * filteringprop_to_string(FilteringProp *prop); void prefs_filtering_clear(void); diff --git a/src/matcher_parser.h b/src/matcher_parser.h index ff2fbd864..f9bd43a43 100644 --- a/src/matcher_parser.h +++ b/src/matcher_parser.h @@ -35,5 +35,6 @@ MatcherList *matcher_parser_get_cond (gchar *str); MatcherProp *matcher_parser_get_prop (gchar *str); FilteringProp *matcher_parser_get_filtering (gchar *str); ScoringProp *matcher_parser_get_scoring (gchar *str); +GSList *matcher_parser_get_action_list(gchar *str); #endif diff --git a/src/matcher_parser_parse.y b/src/matcher_parser_parse.y index 559f680d6..bbe8a6d8c 100644 --- a/src/matcher_parser_parse.y +++ b/src/matcher_parser_parse.y @@ -46,6 +46,7 @@ static GSList *matchers_list = NULL; static MatcherList *cond; static gint score = 0; +static GSList *action_list = NULL; static FilteringAction *action = NULL; static FilteringProp *filtering; @@ -54,7 +55,19 @@ static ScoringProp *scoring = NULL; static GSList **prefs_scoring = NULL; static GSList **prefs_filtering = NULL; +#if 0 static int matcher_parser_dialog = 0; +#endif + +enum { + MATCHER_PARSE_NONE, + MATCHER_PARSE_NO_EOL, + MATCHER_PARSE_CONDITION, + MATCHER_PARSE_FILTERING_OR_SCORING, +}; + +static int matcher_parse_op = MATCHER_PARSE_NONE; + /* ******************************************************************** */ @@ -71,14 +84,14 @@ FilteringProp *matcher_parser_get_filtering(gchar *str) /* bad coding to enable the sub-grammar matching in yacc */ matcher_parserlineno = 1; - matcher_parser_dialog = 1; + matcher_parse_op = MATCHER_PARSE_NO_EOL; matcher_parserrestart(NULL); matcher_parser_init(); bufstate = matcher_parser_scan_string(str); matcher_parser_switch_to_buffer(bufstate); if (matcher_parserparse() != 0) filtering = NULL; - matcher_parser_dialog = 0; + matcher_parse_op = MATCHER_PARSE_NONE; matcher_parser_delete_buffer(bufstate); return filtering; } @@ -90,14 +103,14 @@ ScoringProp *matcher_parser_get_scoring(gchar *str) /* bad coding to enable the sub-grammar matching in yacc */ matcher_parserlineno = 1; - matcher_parser_dialog = 1; + matcher_parse_op = MATCHER_PARSE_NO_EOL; matcher_parserrestart(NULL); matcher_parser_init(); bufstate = matcher_parser_scan_string(str); matcher_parser_switch_to_buffer(bufstate); if (matcher_parserparse() != 0) scoring = NULL; - matcher_parser_dialog = 0; + matcher_parse_op = MATCHER_PARSE_NONE; matcher_parser_delete_buffer(bufstate); return scoring; } @@ -133,16 +146,38 @@ MatcherList *matcher_parser_get_cond(gchar *str) /* bad coding to enable the sub-grammar matching in yacc */ matcher_parserlineno = 1; - matcher_parser_dialog = 1; + matcher_parse_op = MATCHER_PARSE_CONDITION; matcher_parserrestart(NULL); matcher_parser_init(); bufstate = matcher_parser_scan_string(str); matcher_parserparse(); - matcher_parser_dialog = 0; + matcher_parse_op = MATCHER_PARSE_NONE; matcher_parser_delete_buffer(bufstate); return cond; } +GSList *matcher_parser_get_action_list(gchar *str) +{ + void *bufstate; + + if (!check_quote_symetry(str)) { + action_list = NULL; + return action_list; + } + + /* bad coding to enable the sub-grammar matching + in yacc */ + matcher_parserlineno = 1; + matcher_parse_op = MATCHER_PARSE_FILTERING_OR_SCORING; + matcher_parserrestart(NULL); + matcher_parser_init(); + bufstate = matcher_parser_scan_string(str); + matcher_parserparse(); + matcher_parse_op = MATCHER_PARSE_NONE; + matcher_parser_delete_buffer(bufstate); + return action_list; +} + MatcherProp *matcher_parser_get_prop(gchar *str) { MatcherList *list; @@ -233,7 +268,7 @@ int matcher_parserwrap(void) file: { - if (!matcher_parser_dialog) { + if (matcher_parse_op == MATCHER_PARSE_NONE) { prefs_scoring = &global_scoring; prefs_filtering = &global_processing; } @@ -248,7 +283,9 @@ file_line_list file_line: section_notification -| instruction +| +{ action_list = NULL; } +instruction | error MATCHER_EOL { yyerrok; @@ -260,7 +297,7 @@ MATCHER_SECTION MATCHER_EOL gchar *folder = $1; FolderItem *item = NULL; - if (!matcher_parser_dialog) { + if (matcher_parse_op == MATCHER_PARSE_NONE) { if (!strcmp(folder, "global")) { prefs_scoring = &global_scoring; prefs_filtering = &global_processing; @@ -279,43 +316,44 @@ MATCHER_SECTION MATCHER_EOL ; instruction: -condition end_instr_opt -| MATCHER_EOL -; - -end_instr_opt: -filtering_or_scoring end_action -| +condition filtering_or_scoring MATCHER_EOL +| condition filtering_or_scoring { - if (matcher_parser_dialog) + if (matcher_parse_op == MATCHER_PARSE_NO_EOL) YYACCEPT; else { matcher_parsererror("parse error"); YYERROR; } } -; - -end_action: -MATCHER_EOL -| +| condition +{ + if (matcher_parse_op == MATCHER_PARSE_CONDITION) + YYACCEPT; + else { + matcher_parsererror("parse error"); + YYERROR; + } +} +| filtering_action_list { - if (matcher_parser_dialog) + if (matcher_parse_op == MATCHER_PARSE_FILTERING_OR_SCORING) YYACCEPT; else { matcher_parsererror("parse error"); YYERROR; } } +| MATCHER_EOL ; filtering_or_scoring: -filtering_action +filtering_action_list { - filtering = filteringprop_new(cond, action); + filtering = filteringprop_new(cond, action_list); cond = NULL; - action = NULL; - if (!matcher_parser_dialog && (prefs_filtering != NULL)) { + action_list = NULL; + if ((matcher_parse_op == MATCHER_PARSE_NONE) && (prefs_filtering != NULL)) { *prefs_filtering = g_slist_append(*prefs_filtering, filtering); filtering = NULL; @@ -326,13 +364,27 @@ filtering_action scoring = scoringprop_new(cond, score); cond = NULL; score = 0; - if (!matcher_parser_dialog && (prefs_scoring != NULL)) { + if ((matcher_parse_op == MATCHER_PARSE_NONE) + && (prefs_scoring != NULL)) { *prefs_scoring = g_slist_append(*prefs_scoring, scoring); scoring = NULL; } } ; +filtering_action_list: +filtering_action_b filtering_action_list +| filtering_action_b +; + +filtering_action_b: +filtering_action +{ + action_list = g_slist_append(action_list, action); + action = NULL; +} +; + match_type: MATCHER_MATCHCASE { diff --git a/src/prefs_filtering.c b/src/prefs_filtering.c index 77cf6f0aa..900076f2b 100644 --- a/src/prefs_filtering.c +++ b/src/prefs_filtering.c @@ -58,25 +58,9 @@ static struct Filtering { GtkWidget *ok_btn; GtkWidget *cond_entry; - GtkWidget *action_list; - GtkWidget *action_combo; - GtkWidget *account_label; - GtkWidget *account_list; - GtkWidget *account_combo; - GtkWidget *dest_entry; - GtkWidget *dest_btn; - GtkWidget *dest_label; - GtkWidget *recip_label; - GtkWidget *exec_label; - GtkWidget *exec_btn; - - GtkWidget *color_label; - GtkWidget *color_optmenu; + GtkWidget *action_entry; GtkWidget *cond_clist; - - /* need this to make address completion entry work */ - gint current_action; } filtering; /* widget creating functions */ @@ -107,6 +91,7 @@ static void prefs_filtering_cancel (void); static void prefs_filtering_ok (void); static void prefs_filtering_condition_define (void); +static void prefs_filtering_action_define(void); static gint prefs_filtering_clist_set_row (gint row, FilteringProp * prop); static void prefs_filtering_select_dest (void); static void prefs_filtering_action_select (GtkList *list, @@ -312,19 +297,8 @@ static void prefs_filtering_create(void) GtkWidget *cond_entry; GtkWidget *cond_btn; GtkWidget *action_label; - GtkWidget *action_list; - GtkWidget *action_combo; - GtkWidget *account_label; - GtkWidget *account_list; - GtkWidget *account_combo; - GtkWidget *dest_label; - GtkWidget *recip_label; - GtkWidget *exec_label; - GtkWidget *dest_entry; - GtkWidget *dest_btn; - GtkWidget *exec_btn; - GtkWidget *color_label; - GtkWidget *color_optmenu; + GtkWidget *action_entry; + GtkWidget *action_btn; GtkWidget *reg_btn; GtkWidget *subst_btn; @@ -404,128 +378,25 @@ static void prefs_filtering_create(void) GTK_SIGNAL_FUNC (prefs_filtering_condition_define), NULL); - hbox1 = gtk_hbox_new (FALSE, VSPACING); - gtk_widget_show (hbox1); - gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2); - action_label = gtk_label_new (_("Action")); gtk_widget_show (action_label); gtk_misc_set_alignment (GTK_MISC (action_label), 0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox1), action_label, FALSE, FALSE, 0); - - action_combo = gtk_combo_new (); - gtk_widget_show (action_combo); - gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(action_combo)->entry), - FALSE); - - combo_items = NULL; - for (i = 0; i < sizeof action_text / sizeof action_text[0]; i++) - combo_items = g_list_append - (combo_items, (gpointer) _(action_text[i].text)); - gtk_combo_set_popdown_strings(GTK_COMBO(action_combo), combo_items); - - g_list_free(combo_items); - - gtk_box_pack_start (GTK_BOX (hbox1), action_combo, - TRUE, TRUE, 0); - action_list = GTK_COMBO(action_combo)->list; - gtk_signal_connect (GTK_OBJECT (action_list), "select-child", - GTK_SIGNAL_FUNC (prefs_filtering_action_select), - NULL); - - gtk_signal_connect(GTK_OBJECT(action_list), "selection-changed", - GTK_SIGNAL_FUNC(prefs_filtering_action_selection_changed), - NULL); - - /* accounts */ + gtk_box_pack_start (GTK_BOX (vbox1), action_label, FALSE, FALSE, 0); hbox1 = gtk_hbox_new (FALSE, VSPACING); gtk_widget_show (hbox1); gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2); - account_label = gtk_label_new (_("Account")); - gtk_widget_show (account_label); - gtk_misc_set_alignment (GTK_MISC (account_label), 0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox1), account_label, FALSE, FALSE, 0); + action_entry = gtk_entry_new (); + gtk_widget_show (action_entry); + gtk_box_pack_start (GTK_BOX (hbox1), action_entry, TRUE, TRUE, 0); - account_combo = gtk_combo_new (); - gtk_widget_show (account_combo); - - combo_items = NULL; - for (accounts = account_get_list() ; accounts != NULL; - accounts = accounts->next) { - PrefsAccount *ac = (PrefsAccount *)accounts->data; - gchar *name; - - name = g_strdup_printf("%s <%s> (%s)", - ac->name, ac->address, - ac->account_name); - combo_items = g_list_append(combo_items, (gpointer) name); - } - - gtk_combo_set_popdown_strings(GTK_COMBO(account_combo), combo_items); - - for(cur = g_list_first(combo_items) ; cur != NULL ; - cur = g_list_next(cur)) - g_free(cur->data); - g_list_free(combo_items); - - gtk_box_pack_start (GTK_BOX (hbox1), account_combo, - TRUE, TRUE, 0); - account_list = GTK_COMBO(account_combo)->list; - gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(account_combo)->entry), - FALSE); - - /* destination */ - - hbox1 = gtk_hbox_new (FALSE, VSPACING); - gtk_widget_show (hbox1); - gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2); - - dest_label = gtk_label_new (_("Destination")); - gtk_widget_show (dest_label); - gtk_misc_set_alignment (GTK_MISC (dest_label), 0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox1), dest_label, FALSE, FALSE, 0); - - recip_label = gtk_label_new (_("Recipient")); - gtk_widget_show (recip_label); - gtk_misc_set_alignment (GTK_MISC (recip_label), 0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox1), recip_label, FALSE, FALSE, 0); - - exec_label = gtk_label_new (_("Execute")); - gtk_widget_show (exec_label); - gtk_misc_set_alignment (GTK_MISC (exec_label), 0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox1), exec_label, FALSE, FALSE, 0); - - color_label = gtk_label_new (_("Color")); - gtk_widget_show(color_label); - gtk_misc_set_alignment(GTK_MISC(color_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(hbox1), color_label, FALSE, FALSE, 0); - - dest_entry = gtk_entry_new (); - gtk_widget_show (dest_entry); - gtk_box_pack_start (GTK_BOX (hbox1), dest_entry, TRUE, TRUE, 0); - - color_optmenu = gtk_option_menu_new(); - gtk_option_menu_set_menu(GTK_OPTION_MENU(color_optmenu), - colorlabel_create_color_menu()); - gtk_box_pack_start(GTK_BOX(hbox1), color_optmenu, TRUE, TRUE, 0); - - dest_btn = gtk_button_new_with_label (_("Select ...")); - gtk_widget_show (dest_btn); - gtk_box_pack_start (GTK_BOX (hbox1), dest_btn, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (dest_btn), "clicked", - GTK_SIGNAL_FUNC (prefs_filtering_select_dest), - NULL); - - exec_btn = gtk_button_new_with_label (_("Info ...")); - gtk_widget_show (exec_btn); - gtk_box_pack_start (GTK_BOX (hbox1), exec_btn, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (exec_btn), "clicked", - GTK_SIGNAL_FUNC (prefs_matcher_exec_info), + action_btn = gtk_button_new_with_label (_("Define ...")); + gtk_widget_show (action_btn); + gtk_box_pack_start (GTK_BOX (hbox1), action_btn, FALSE, FALSE, 0); + gtk_signal_connect (GTK_OBJECT (action_btn), "clicked", + GTK_SIGNAL_FUNC (prefs_filtering_action_define), NULL); /* register / substitute / delete */ @@ -611,22 +482,8 @@ static void prefs_filtering_create(void) filtering.ok_btn = ok_btn; filtering.cond_entry = cond_entry; - filtering.action_list = action_list; - filtering.action_combo = action_combo; - filtering.account_label = account_label; - filtering.account_list = account_list; - filtering.account_combo = account_combo; - filtering.dest_entry = dest_entry; - filtering.dest_btn = dest_btn; - filtering.dest_label = dest_label; - filtering.recip_label = recip_label; - filtering.exec_label = exec_label; - filtering.exec_btn = exec_btn; - + filtering.action_entry = action_entry; filtering.cond_clist = cond_clist; - - filtering.color_label = color_label; - filtering.color_optmenu = color_optmenu; } static void prefs_filtering_update_hscrollbar(void) @@ -663,6 +520,7 @@ static gboolean prefs_filtering_rename_path_func(GNode *node, gpointer data) gint prefixlen; gint oldpathlen; FolderItem *item; + GSList * action_cur; old_path = ((gchar **)data)[0]; new_path = ((gchar **)data)[1]; @@ -681,59 +539,66 @@ static gboolean prefs_filtering_rename_path_func(GNode *node, gpointer data) cur = item->prefs->processing; } + for (; cur != NULL; cur = cur->next) { FilteringProp *filtering = (FilteringProp *)cur->data; - FilteringAction *action = filtering->action; - - if (!action->destination) continue; - - destlen = strlen(action->destination); - - if (destlen > oldpathlen) { - prefixlen = destlen - oldpathlen; - suffix = action->destination + prefixlen; - - if (!strncmp(old_path, suffix, oldpathlen)) { - prefix = g_malloc0(prefixlen + 1); - strncpy2(prefix, action->destination, prefixlen); - - base = suffix + oldpathlen; - while (*base == G_DIR_SEPARATOR) base++; - if (*base == '\0') - dest_path = g_strconcat(prefix, - G_DIR_SEPARATOR_S, - new_path, NULL); - else - dest_path = g_strconcat(prefix, - G_DIR_SEPARATOR_S, - new_path, - G_DIR_SEPARATOR_S, - base, NULL); - - g_free(prefix); - g_free(action->destination); - action->destination = dest_path; - } else { /* for non-leaf folders */ - /* compare with trailing slash */ - if (!strncmp(old_path_with_sep, action->destination, oldpathlen+1)) { - - suffix = action->destination + oldpathlen + 1; - dest_path = g_strconcat(new_path, - G_DIR_SEPARATOR_S, - suffix, NULL); - g_free(action->destination); - action->destination = dest_path; - } - } - } else { - /* folder-moving a leaf */ - if (!strcmp(old_path, action->destination)) { - dest_path = g_strdup(new_path); - g_free(action->destination); - action->destination = dest_path; - } - } - } + + for(action_cur = filtering->action_list ; action_cur != NULL ; + action_cur = action_cur->next) { + + FilteringAction *action = action_cur->data; + + if (!action->destination) continue; + + destlen = strlen(action->destination); + + if (destlen > oldpathlen) { + prefixlen = destlen - oldpathlen; + suffix = action->destination + prefixlen; + + if (!strncmp(old_path, suffix, oldpathlen)) { + prefix = g_malloc0(prefixlen + 1); + strncpy2(prefix, action->destination, prefixlen); + + base = suffix + oldpathlen; + while (*base == G_DIR_SEPARATOR) base++; + if (*base == '\0') + dest_path = g_strconcat(prefix, + G_DIR_SEPARATOR_S, + new_path, NULL); + else + dest_path = g_strconcat(prefix, + G_DIR_SEPARATOR_S, + new_path, + G_DIR_SEPARATOR_S, + base, NULL); + + g_free(prefix); + g_free(action->destination); + action->destination = dest_path; + } else { /* for non-leaf folders */ + /* compare with trailing slash */ + if (!strncmp(old_path_with_sep, action->destination, oldpathlen+1)) { + + suffix = action->destination + oldpathlen + 1; + dest_path = g_strconcat(new_path, + G_DIR_SEPARATOR_S, + suffix, NULL); + g_free(action->destination); + action->destination = dest_path; + } + } + } else { + /* folder-moving a leaf */ + if (!strcmp(old_path, action->destination)) { + dest_path = g_strdup(new_path); + g_free(action->destination); + action->destination = dest_path; + } + } + } + } + g_free(old_path_with_sep); prefs_matcher_write_config(); @@ -755,13 +620,13 @@ void prefs_filtering_delete_path(const gchar *path) static gboolean prefs_filtering_delete_path_func(GNode *node, gpointer data) { GSList *cur, *orig; - GSList *next; gchar *path = (gchar *)data; gchar *suffix; gint destlen; gint prefixlen; gint pathlen; FolderItem *item; + GSList * action_cur; g_return_val_if_fail(path != NULL, FALSE); @@ -778,41 +643,43 @@ static gboolean prefs_filtering_delete_path_func(GNode *node, gpointer data) for (; cur != NULL; cur = cur->next) { FilteringProp *filtering = (FilteringProp *)cur->data; - FilteringAction *action; - if (!cur->data) - break; - - action = filtering->action; - next = cur->next; - - if (!action->destination) continue; - - destlen = strlen(action->destination); - - if (destlen > pathlen) { - prefixlen = destlen - pathlen; - suffix = action->destination + prefixlen; - - if (suffix && !strncmp(path, suffix, pathlen)) { - filteringprop_free(filtering); - orig = g_slist_remove(orig, filtering); - } - } else if (strcmp(action->destination, path) == 0) { - filteringprop_free(filtering); - orig = g_slist_remove(orig, filtering); - - } - } - - if (node == NULL) - global_processing = orig; - else { - item = node->data; - if (!item || !item->prefs) + + for(action_cur = filtering->action_list ; action_cur != NULL ; + action_cur = action_cur->next) { + + FilteringAction *action; + + action = action_cur->data; + + if (!action->destination) continue; + + destlen = strlen(action->destination); + + if (destlen > pathlen) { + prefixlen = destlen - pathlen; + suffix = action->destination + prefixlen; + + if (suffix && !strncmp(path, suffix, pathlen)) { + filteringprop_free(filtering); + orig = g_slist_remove(orig, filtering); + } + } else if (strcmp(action->destination, path) == 0) { + filteringprop_free(filtering); + orig = g_slist_remove(orig, filtering); + + } + } + } + + if (node == NULL) + global_processing = orig; + else { + item = node->data; + if (!item || !item->prefs) return FALSE; - item->prefs->processing = orig; - } - + item->prefs->processing = orig; + } + prefs_matcher_write_config(); return FALSE; @@ -865,10 +732,8 @@ static void prefs_filtering_set_dialog(const gchar *header, const gchar *key) static void prefs_filtering_reset_dialog(void) { - gtk_list_select_item(GTK_LIST(filtering.action_list), 0); - gtk_list_select_item(GTK_LIST(filtering.account_list), 0); - gtk_entry_set_text(GTK_ENTRY(filtering.dest_entry), ""); gtk_entry_set_text(GTK_ENTRY(filtering.cond_entry), ""); + gtk_entry_set_text(GTK_ENTRY(filtering.action_entry), ""); } static void prefs_filtering_set_list(void) @@ -892,7 +757,6 @@ static void prefs_filtering_set_list(void) while (gtk_clist_get_text(GTK_CLIST(filtering.cond_clist), row, 0, &filtering_str)) { if (strcmp(filtering_str, _("(New)")) != 0) { - /* tmp = filtering_str; */ prop = matcher_parser_get_filtering(filtering_str); if (prop != NULL) prefs_filtering = @@ -967,6 +831,45 @@ static void prefs_filtering_condition_define(void) matcherlist_free(matchers); } +static void prefs_filtering_action_define_done(GSList * action_list) +{ + gchar * str; + + if (action_list == NULL) + return; + + str = filteringaction_list_to_string(action_list); + + if (str != NULL) { + gtk_entry_set_text(GTK_ENTRY(filtering.action_entry), str); + g_free(str); + } +} + +static void prefs_filtering_action_define(void) +{ + gchar * action_str; + GSList * action_list = NULL; + + action_str = gtk_entry_get_text(GTK_ENTRY(filtering.action_entry)); + + if (*action_str != '\0') { + action_list = matcher_parser_get_action_list(action_str); + if (action_list == NULL) + alertpanel_error(_("Action string is not valid.")); + } + + prefs_filtering_action_open(action_list, + prefs_filtering_action_define_done); + + if (action_list != NULL) { + GSList * cur; + for(cur = action_list ; cur != NULL ; cur = cur->next) { + filteringaction_free(cur->data); + } + } +} + /* register / substitute delete buttons */ @@ -975,6 +878,7 @@ static FilteringProp * prefs_filtering_dialog_to_filtering(gboolean alert) { MatcherList * cond; gchar * cond_str; + gchar * action_str; FilteringProp * prop; FilteringAction * action; gint list_id; @@ -983,58 +887,35 @@ static FilteringProp * prefs_filtering_dialog_to_filtering(gboolean alert) gint account_id; gchar * destination; gint labelcolor = 0; - + GSList * action_list; + cond_str = gtk_entry_get_text(GTK_ENTRY(filtering.cond_entry)); if (*cond_str == '\0') { if(alert == TRUE) alertpanel_error(_("Condition string is empty.")); return NULL; } - action_id = get_sel_from_list(GTK_LIST(filtering.action_list)); - action_type = prefs_filtering_get_matching_from_action(action_id); - list_id = get_sel_from_list(GTK_LIST(filtering.account_list)); - account_id = get_account_id_from_list_id(list_id); - - switch (action_id) { - case ACTION_MOVE: - case ACTION_COPY: - case ACTION_EXECUTE: - destination = gtk_entry_get_text(GTK_ENTRY(filtering.dest_entry)); - if (*destination == '\0') { - if(alert == TRUE) alertpanel_error(_("Destination is not set.")); - return NULL; - } - break; - case ACTION_FORWARD: - case ACTION_FORWARD_AS_ATTACHMENT: - case ACTION_REDIRECT: - destination = gtk_entry_get_text(GTK_ENTRY(filtering.dest_entry)); - if (*destination == '\0') { - if(alert == TRUE) alertpanel_error(_("Recipient is not set.")); - return NULL; - } - break; - case ACTION_COLOR: - labelcolor = colorlabel_get_color_menu_active_item( - gtk_option_menu_get_menu(GTK_OPTION_MENU(filtering.color_optmenu))); - destination = NULL; - break; - default: - destination = NULL; - break; + action_str = gtk_entry_get_text(GTK_ENTRY(filtering.action_entry)); + if (*action_str == '\0') { + if(alert == TRUE) alertpanel_error(_("Action string is empty.")); + return NULL; } - - action = filteringaction_new(action_type, account_id, destination, labelcolor); cond = matcher_parser_get_cond(cond_str); if (cond == NULL) { if(alert == TRUE) alertpanel_error(_("Condition string is not valid.")); - filteringaction_free(action); return NULL; } + + action_list = matcher_parser_get_action_list(action_str); - prop = filteringprop_new(cond, action); + if (action_list == NULL) { + if(alert == TRUE) alertpanel_error(_("Action string is not valid.")); + return NULL; + } + + prop = filteringprop_new(cond, action_list); return prop; } @@ -1132,93 +1013,24 @@ static void prefs_filtering_select_set(FilteringProp *prop) FilteringAction *action; gchar *matcher_str; gint list_id; + gchar *action_str; prefs_filtering_reset_dialog(); - action = prop->action; - matcher_str = matcherlist_to_string(prop->matchers); if (matcher_str == NULL) { - filteringprop_free(prop); return; } gtk_entry_set_text(GTK_ENTRY(filtering.cond_entry), matcher_str); - - if (action->destination) - gtk_entry_set_text(GTK_ENTRY(filtering.dest_entry), action->destination); - else - gtk_entry_set_text(GTK_ENTRY(filtering.dest_entry), ""); - - switch(action->type) { - case MATCHACTION_MOVE: - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_MOVE); - break; - case MATCHACTION_COPY: - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_COPY); - break; - case MATCHACTION_DELETE: - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_DELETE); - break; - case MATCHACTION_MARK: - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_MARK); - break; - case MATCHACTION_UNMARK: - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_UNMARK); - break; - case MATCHACTION_LOCK: - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_LOCK); - break; - case MATCHACTION_UNLOCK: - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_UNLOCK); - break; - case MATCHACTION_MARK_AS_READ: - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_MARK_AS_READ); - break; - case MATCHACTION_MARK_AS_UNREAD: - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_MARK_AS_UNREAD); - break; - case MATCHACTION_FORWARD: - list_id = get_list_id_from_account_id(action->account_id); - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_FORWARD); - gtk_list_select_item(GTK_LIST(filtering.account_list), - list_id); - break; - case MATCHACTION_FORWARD_AS_ATTACHMENT: - list_id = get_list_id_from_account_id(action->account_id); - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_FORWARD_AS_ATTACHMENT); - gtk_list_select_item(GTK_LIST(filtering.account_list), - list_id); - break; - case MATCHACTION_REDIRECT: - list_id = get_list_id_from_account_id(action->account_id); - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_REDIRECT); - gtk_list_select_item(GTK_LIST(filtering.account_list), - list_id); - break; - case MATCHACTION_EXECUTE: - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_EXECUTE); - break; - case MATCHACTION_COLOR: - gtk_list_select_item(GTK_LIST(filtering.action_list), - ACTION_COLOR); - gtk_option_menu_set_history(GTK_OPTION_MENU(filtering.color_optmenu), action->labelcolor); - break; + + action_str = filteringaction_list_to_string(prop->action_list); + if (matcher_str == NULL) { + return; } + gtk_entry_set_text(GTK_ENTRY(filtering.action_entry), action_str); + g_free(action_str); g_free(matcher_str); } @@ -1246,200 +1058,6 @@ static void prefs_filtering_select(GtkCList *clist, gint row, gint column, filteringprop_free(prop); } -static void prefs_filtering_select_dest(void) -{ - FolderItem *dest; - gchar * path; - - dest = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL); - if (!dest) return; - - path = folder_item_get_identifier(dest); - - gtk_entry_set_text(GTK_ENTRY(filtering.dest_entry), path); - g_free(path); -} - -static void prefs_filtering_action_selection_changed(GtkList *list, - gpointer user_data) -{ - gint value; - - value = get_sel_from_list(GTK_LIST(filtering.action_list)); - - if (filtering.current_action != value) { - if (filtering.current_action == ACTION_FORWARD - || filtering.current_action == ACTION_FORWARD_AS_ATTACHMENT - || filtering.current_action == ACTION_REDIRECT) { - debug_print("unregistering address completion entry\n"); - address_completion_unregister_entry(GTK_ENTRY(filtering.dest_entry)); - } - if (value == ACTION_FORWARD || value == ACTION_FORWARD_AS_ATTACHMENT - || value == ACTION_REDIRECT) { - debug_print("registering address completion entry\n"); - address_completion_register_entry(GTK_ENTRY(filtering.dest_entry)); - } - filtering.current_action = value; - } -} - -static void prefs_filtering_action_select(GtkList *list, - GtkWidget *widget, - gpointer user_data) -{ - Action value; - - value = (Action) get_sel_from_list(GTK_LIST(filtering.action_list)); - - switch (value) { - case ACTION_MOVE: - gtk_widget_show(filtering.account_label); - gtk_widget_set_sensitive(filtering.account_label, FALSE); - gtk_widget_set_sensitive(filtering.account_combo, FALSE); - gtk_widget_show(filtering.dest_entry); - gtk_widget_set_sensitive(filtering.dest_entry, TRUE); - gtk_widget_show(filtering.dest_btn); - gtk_widget_set_sensitive(filtering.dest_btn, TRUE); - gtk_widget_show(filtering.dest_label); - gtk_widget_set_sensitive(filtering.dest_label, TRUE); - gtk_widget_hide(filtering.recip_label); - gtk_widget_hide(filtering.exec_label); - gtk_widget_hide(filtering.exec_btn); - gtk_widget_hide(filtering.color_optmenu); - gtk_widget_hide(filtering.color_label); - break; - case ACTION_COPY: - gtk_widget_show(filtering.account_label); - gtk_widget_set_sensitive(filtering.account_label, FALSE); - gtk_widget_set_sensitive(filtering.account_combo, FALSE); - gtk_widget_show(filtering.dest_entry); - gtk_widget_set_sensitive(filtering.dest_entry, TRUE); - gtk_widget_show(filtering.dest_btn); - gtk_widget_set_sensitive(filtering.dest_btn, TRUE); - gtk_widget_show(filtering.dest_label); - gtk_widget_set_sensitive(filtering.dest_label, TRUE); - gtk_widget_hide(filtering.recip_label); - gtk_widget_hide(filtering.exec_label); - gtk_widget_hide(filtering.exec_btn); - gtk_widget_hide(filtering.color_optmenu); - gtk_widget_hide(filtering.color_label); - break; - case ACTION_DELETE: - gtk_widget_show(filtering.account_label); - gtk_widget_set_sensitive(filtering.account_label, FALSE); - gtk_widget_set_sensitive(filtering.account_combo, FALSE); - gtk_widget_show(filtering.dest_entry); - gtk_widget_set_sensitive(filtering.dest_entry, FALSE); - gtk_widget_show(filtering.dest_btn); - gtk_widget_set_sensitive(filtering.dest_btn, FALSE); - gtk_widget_show(filtering.dest_label); - gtk_widget_set_sensitive(filtering.dest_label, FALSE); - gtk_widget_hide(filtering.recip_label); - gtk_widget_hide(filtering.exec_label); - gtk_widget_hide(filtering.exec_btn); - gtk_widget_hide(filtering.color_optmenu); - gtk_widget_hide(filtering.color_label); - break; - case ACTION_MARK: - case ACTION_UNMARK: - case ACTION_LOCK: - case ACTION_UNLOCK: - case ACTION_MARK_AS_READ: - case ACTION_MARK_AS_UNREAD: - gtk_widget_show(filtering.account_label); - gtk_widget_set_sensitive(filtering.account_label, FALSE); - gtk_widget_set_sensitive(filtering.account_combo, FALSE); - gtk_widget_show(filtering.dest_entry); - gtk_widget_set_sensitive(filtering.dest_entry, FALSE); - gtk_widget_show(filtering.dest_btn); - gtk_widget_set_sensitive(filtering.dest_btn, FALSE); - gtk_widget_show(filtering.dest_label); - gtk_widget_set_sensitive(filtering.dest_label, FALSE); - gtk_widget_hide(filtering.recip_label); - gtk_widget_hide(filtering.exec_label); - gtk_widget_hide(filtering.exec_btn); - gtk_widget_hide(filtering.color_optmenu); - gtk_widget_hide(filtering.color_label); - break; - case ACTION_FORWARD: - gtk_widget_show(filtering.account_label); - gtk_widget_set_sensitive(filtering.account_label, TRUE); - gtk_widget_set_sensitive(filtering.account_combo, TRUE); - gtk_widget_show(filtering.dest_entry); - gtk_widget_set_sensitive(filtering.dest_entry, TRUE); - gtk_widget_show(filtering.dest_btn); - gtk_widget_set_sensitive(filtering.dest_btn, FALSE); - gtk_widget_hide(filtering.dest_label); - gtk_widget_show(filtering.recip_label); - gtk_widget_set_sensitive(filtering.recip_label, TRUE); - gtk_widget_hide(filtering.exec_label); - gtk_widget_hide(filtering.exec_btn); - gtk_widget_hide(filtering.color_optmenu); - gtk_widget_hide(filtering.color_label); - break; - case ACTION_FORWARD_AS_ATTACHMENT: - gtk_widget_show(filtering.account_label); - gtk_widget_set_sensitive(filtering.account_label, TRUE); - gtk_widget_set_sensitive(filtering.account_combo, TRUE); - gtk_widget_show(filtering.dest_entry); - gtk_widget_set_sensitive(filtering.dest_entry, TRUE); - gtk_widget_show(filtering.dest_btn); - gtk_widget_set_sensitive(filtering.dest_btn, FALSE); - gtk_widget_hide(filtering.dest_label); - gtk_widget_show(filtering.recip_label); - gtk_widget_set_sensitive(filtering.recip_label, TRUE); - gtk_widget_hide(filtering.exec_label); - gtk_widget_hide(filtering.exec_btn); - gtk_widget_hide(filtering.color_optmenu); - gtk_widget_hide(filtering.color_label); - break; - case ACTION_REDIRECT: - gtk_widget_show(filtering.account_label); - gtk_widget_set_sensitive(filtering.account_label, TRUE); - gtk_widget_set_sensitive(filtering.account_combo, TRUE); - gtk_widget_show(filtering.dest_entry); - gtk_widget_set_sensitive(filtering.dest_entry, TRUE); - gtk_widget_show(filtering.dest_btn); - gtk_widget_set_sensitive(filtering.dest_btn, FALSE); - gtk_widget_hide(filtering.dest_label); - gtk_widget_show(filtering.recip_label); - gtk_widget_set_sensitive(filtering.recip_label, TRUE); - gtk_widget_hide(filtering.exec_label); - gtk_widget_hide(filtering.exec_btn); - gtk_widget_hide(filtering.color_optmenu); - gtk_widget_hide(filtering.color_label); - break; - case ACTION_EXECUTE: - gtk_widget_show(filtering.account_label); - gtk_widget_set_sensitive(filtering.account_label, FALSE); - gtk_widget_set_sensitive(filtering.account_combo, FALSE); - gtk_widget_show(filtering.dest_entry); - gtk_widget_set_sensitive(filtering.dest_entry, TRUE); - gtk_widget_hide(filtering.dest_btn); - gtk_widget_hide(filtering.dest_label); - gtk_widget_hide(filtering.recip_label); - gtk_widget_show(filtering.exec_label); - gtk_widget_set_sensitive(filtering.exec_btn, TRUE); - gtk_widget_show(filtering.exec_btn); - gtk_widget_hide(filtering.color_optmenu); - gtk_widget_hide(filtering.color_label); - break; - case ACTION_COLOR: - gtk_widget_show(filtering.account_label); - gtk_widget_set_sensitive(filtering.account_label, FALSE); - gtk_widget_set_sensitive(filtering.account_combo, FALSE); - gtk_widget_hide(filtering.dest_entry); - gtk_widget_hide(filtering.dest_btn); - gtk_widget_hide(filtering.dest_label); - gtk_widget_hide(filtering.recip_label); - gtk_widget_hide(filtering.exec_label); - gtk_widget_show(filtering.exec_btn); - gtk_widget_set_sensitive(filtering.exec_btn, FALSE); - gtk_widget_show(filtering.color_optmenu); - gtk_widget_show(filtering.color_label); - break; - } -} static gint prefs_filtering_deleted(GtkWidget *widget, GdkEventAny *event, gpointer data) diff --git a/src/prefs_filtering_action.c b/src/prefs_filtering_action.c new file mode 100644 index 000000000..1e10f3dce --- /dev/null +++ b/src/prefs_filtering_action.c @@ -0,0 +1,1273 @@ +/* + * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client + * Copyright (C) 1999-2001 Hiroyuki Yamamoto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "defs.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "intl.h" +#include "main.h" +#include "prefs_gtk.h" +#include "prefs_filtering_action.h" +#include "prefs_common.h" +#include "mainwindow.h" +#include "foldersel.h" +#include "manage_window.h" +#include "inc.h" +#include "matcher.h" +#include "utils.h" +#include "gtkutils.h" +#include "alertpanel.h" +#include "folder.h" +#include "description_window.h" + +#include "matcher_parser.h" +#include "colorlabel.h" + + +static void prefs_filtering_action_create(void); +static void prefs_filtering_action_delete_cb(void); +static void prefs_filtering_action_substitute_cb(void); +static void prefs_filtering_action_register_cb(void); +static void prefs_filtering_action_reset_dialog(void); +static void prefs_filtering_action_key_pressed(GtkWidget *widget, + GdkEventKey *event, gpointer data); +static void prefs_filtering_action_cancel(void); +static void prefs_filtering_action_ok(void); +static gint prefs_filtering_action_deleted(GtkWidget *widget, + GdkEventAny *event, gpointer data); +static void prefs_filtering_action_type_selection_changed(GtkList *list, + gpointer user_data); +static void prefs_filtering_action_type_select(GtkList *list, + GtkWidget *widget, gpointer user_data); +static void prefs_filtering_action_select_dest(void); +static void prefs_filtering_action_select(GtkCList *clist, + gint row, gint column, GdkEvent *event); +static void prefs_filtering_action_up(void); +static void prefs_filtering_action_down(void); +static void prefs_filtering_action_set_dialog(GSList *action_list); +static GSList *prefs_filtering_action_get_list(void); + + +/*! + *\brief UI data for matcher dialog + */ +static struct FilteringAction { + GtkWidget *window; + + GtkWidget *ok_btn; + + GtkWidget *action_clist; + GtkWidget *action_type_list; + GtkWidget *action_combo; + GtkWidget *account_label; + GtkWidget *account_list; + GtkWidget *account_combo; + GtkWidget *dest_entry; + GtkWidget *dest_btn; + GtkWidget *dest_label; + GtkWidget *recip_label; + GtkWidget *exec_label; + GtkWidget *exec_btn; + GtkWidget *color_label; + GtkWidget *color_optmenu; + + gint current_action; +} filtering_action; + + +typedef enum Action_ { + ACTION_MOVE, + ACTION_COPY, + ACTION_DELETE, + ACTION_MARK, + ACTION_UNMARK, + ACTION_LOCK, + ACTION_UNLOCK, + ACTION_MARK_AS_READ, + ACTION_MARK_AS_UNREAD, + ACTION_FORWARD, + ACTION_FORWARD_AS_ATTACHMENT, + ACTION_REDIRECT, + ACTION_EXECUTE, + ACTION_COLOR, + /* add other action constants */ +} Action; + +static struct { + gchar *text; + Action action; +} action_text [] = { + { N_("Move"), ACTION_MOVE }, + { N_("Copy"), ACTION_COPY }, + { N_("Delete"), ACTION_DELETE }, + { N_("Mark"), ACTION_MARK }, + { N_("Unmark"), ACTION_UNMARK }, + { N_("Lock"), ACTION_LOCK }, + { N_("Unlock"), ACTION_UNLOCK }, + { N_("Mark as read"), ACTION_MARK_AS_READ }, + { N_("Mark as unread"), ACTION_MARK_AS_UNREAD }, + { N_("Forward"), ACTION_FORWARD }, + { N_("Forward as attachment"), ACTION_FORWARD_AS_ATTACHMENT }, + { N_("Redirect"), ACTION_REDIRECT }, + { N_("Execute"), ACTION_EXECUTE }, + { N_("Color"), ACTION_COLOR } +}; + + +/*! + *\brief Hooks + */ +static PrefsFilteringActionSignal *filtering_action_callback; + +/*! + *\brief Find index of list selection + * + *\param list GTK list widget + * + *\return gint Selection index + */ +static gint get_sel_from_list(GtkList *list) +{ + gint row = 0; + void * sel; + GList * child; + + if (list->selection == NULL) + return -1; + + sel = list->selection->data; + for (child = list->children; child != NULL; child = g_list_next(child)) { + if (child->data == sel) + return row; + row ++; + } + + return row; +} + +/*! + *\brief Opens the filtering action dialog with a list of actions + * + *\param matchers List of conditions + *\param cb Callback + * + */ +void prefs_filtering_action_open(GSList *action_list, + PrefsFilteringActionSignal *cb) +{ + inc_lock(); + + if (!filtering_action.window) { + prefs_filtering_action_create(); + } + + manage_window_set_transient(GTK_WINDOW(filtering_action.window)); + gtk_widget_grab_focus(filtering_action.ok_btn); + + filtering_action_callback = cb; + + prefs_filtering_action_set_dialog(action_list); + + gtk_widget_show(filtering_action.window); +} + +/*! + *\brief Create the matcher dialog + */ +static void prefs_filtering_action_create(void) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *ok_btn; + GtkWidget *cancel_btn; + GtkWidget *confirm_area; + + GtkWidget *vbox1; + + GtkWidget *hbox1; + + GtkWidget *action_label; + GtkWidget *recip_label; + GtkWidget *action_combo; + GtkWidget *action_type_list; + GtkWidget *account_list; + GtkWidget *dest_label; + GtkWidget *exec_label; + GtkWidget *color_label; + GtkWidget *account_label; + GtkWidget *account_combo; + GtkWidget *dest_entry; + GtkWidget *dest_btn; + GList * cur; + + GtkWidget *reg_hbox; + GtkWidget *btn_hbox; + GtkWidget *arrow; + GtkWidget *reg_btn; + GtkWidget *subst_btn; + GtkWidget *del_btn; + + GtkWidget *action_hbox; + GtkWidget *action_scrolledwin; + GtkWidget *action_clist; + + GtkWidget *btn_vbox; + GtkWidget *up_btn; + GtkWidget *down_btn; + + GtkWidget *exec_btn; + + GtkWidget *color_optmenu; + + GList *combo_items; + gint i; + + gchar *title[1]; + GList * accounts; + + debug_print("Creating matcher configuration window...\n"); + + window = gtk_window_new(GTK_WINDOW_DIALOG); + gtk_container_set_border_width(GTK_CONTAINER(window), 8); + gtk_window_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + gtk_window_set_modal(GTK_WINDOW(window), TRUE); + gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE); + + vbox = gtk_vbox_new(FALSE, 6); + gtk_widget_show(vbox); + gtk_container_add(GTK_CONTAINER(window), vbox); + + gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"), + &cancel_btn, _("Cancel"), NULL, NULL); + gtk_widget_show(confirm_area); + gtk_box_pack_end(GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0); + gtk_widget_grab_default(ok_btn); + + gtk_window_set_title(GTK_WINDOW(window), + _("Filtering action configuration")); + gtk_signal_connect(GTK_OBJECT(window), "delete_event", + GTK_SIGNAL_FUNC(prefs_filtering_action_deleted), NULL); + gtk_signal_connect(GTK_OBJECT(window), "key_press_event", + GTK_SIGNAL_FUNC(prefs_filtering_action_key_pressed), NULL); + MANAGE_WINDOW_SIGNALS_CONNECT(window); + gtk_signal_connect(GTK_OBJECT(ok_btn), "clicked", + GTK_SIGNAL_FUNC(prefs_filtering_action_ok), NULL); + gtk_signal_connect(GTK_OBJECT(cancel_btn), "clicked", + GTK_SIGNAL_FUNC(prefs_filtering_action_cancel), NULL); + + vbox1 = gtk_vbox_new(FALSE, VSPACING); + gtk_widget_show(vbox1); + gtk_box_pack_start(GTK_BOX(vbox), vbox1, TRUE, TRUE, 0); + gtk_container_set_border_width(GTK_CONTAINER (vbox1), 2); + + /* action to be defined */ + + hbox1 = gtk_hbox_new (FALSE, VSPACING); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2); + + action_label = gtk_label_new (_("Action")); + gtk_widget_show (action_label); + gtk_misc_set_alignment (GTK_MISC (action_label), 0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox1), action_label, FALSE, FALSE, 0); + + action_combo = gtk_combo_new (); + gtk_widget_show (action_combo); + gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(action_combo)->entry), + FALSE); + + combo_items = NULL; + for (i = 0; i < sizeof action_text / sizeof action_text[0]; i++) + combo_items = g_list_append + (combo_items, (gpointer) _(action_text[i].text)); + gtk_combo_set_popdown_strings(GTK_COMBO(action_combo), combo_items); + + g_list_free(combo_items); + + gtk_box_pack_start (GTK_BOX (hbox1), action_combo, + TRUE, TRUE, 0); + action_type_list = GTK_COMBO(action_combo)->list; + gtk_signal_connect (GTK_OBJECT (action_type_list), "select-child", + GTK_SIGNAL_FUNC (prefs_filtering_action_type_select), + NULL); + + gtk_signal_connect(GTK_OBJECT(action_type_list), "selection-changed", + GTK_SIGNAL_FUNC(prefs_filtering_action_type_selection_changed), + NULL); + + /* accounts */ + + hbox1 = gtk_hbox_new (FALSE, VSPACING); + gtk_widget_show (vbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2); + + account_label = gtk_label_new (_("Account")); + gtk_widget_show (account_label); + gtk_misc_set_alignment (GTK_MISC (account_label), 0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox1), account_label, FALSE, FALSE, 0); + + account_combo = gtk_combo_new (); + gtk_widget_set_usize (account_combo, 150, -1); + gtk_widget_show (account_combo); + + combo_items = NULL; + for (accounts = account_get_list() ; accounts != NULL; + accounts = accounts->next) { + PrefsAccount *ac = (PrefsAccount *)accounts->data; + gchar *name; + + name = g_strdup_printf("%s <%s> (%s)", + ac->name, ac->address, + ac->account_name); + combo_items = g_list_append(combo_items, (gpointer) name); + } + + gtk_combo_set_popdown_strings(GTK_COMBO(account_combo), combo_items); + + for(cur = g_list_first(combo_items) ; cur != NULL ; + cur = g_list_next(cur)) + g_free(cur->data); + g_list_free(combo_items); + + gtk_box_pack_start (GTK_BOX (hbox1), account_combo, + TRUE, TRUE, 0); + account_list = GTK_COMBO(account_combo)->list; + gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(account_combo)->entry), + FALSE); + + /* destination */ + + hbox1 = gtk_hbox_new (FALSE, VSPACING); + gtk_widget_show (vbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2); + + dest_label = gtk_label_new (_("Destination")); + gtk_widget_show (dest_label); + gtk_misc_set_alignment (GTK_MISC (dest_label), 0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox1), dest_label, FALSE, FALSE, 0); + + recip_label = gtk_label_new (_("Recipient")); + gtk_widget_show (recip_label); + gtk_misc_set_alignment (GTK_MISC (recip_label), 0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox1), recip_label, FALSE, FALSE, 0); + + exec_label = gtk_label_new (_("Execute")); + gtk_widget_show (exec_label); + gtk_misc_set_alignment (GTK_MISC (exec_label), 0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox1), exec_label, FALSE, FALSE, 0); + + color_label = gtk_label_new (_("Color")); + gtk_widget_show(color_label); + gtk_misc_set_alignment(GTK_MISC(color_label), 0, 0.5); + gtk_box_pack_start(GTK_BOX(hbox1), color_label, FALSE, FALSE, 0); + + dest_entry = gtk_entry_new (); + gtk_widget_set_usize (dest_entry, 150, -1); + gtk_widget_show (dest_entry); + gtk_box_pack_start (GTK_BOX (hbox1), dest_entry, TRUE, TRUE, 0); + + color_optmenu = gtk_option_menu_new(); + gtk_option_menu_set_menu(GTK_OPTION_MENU(color_optmenu), + colorlabel_create_color_menu()); + gtk_box_pack_start(GTK_BOX(hbox1), color_optmenu, TRUE, TRUE, 0); + + dest_btn = gtk_button_new_with_label (_("Select ...")); + gtk_widget_show (dest_btn); + gtk_box_pack_start (GTK_BOX (hbox1), dest_btn, FALSE, FALSE, 0); + gtk_signal_connect (GTK_OBJECT (dest_btn), "clicked", + GTK_SIGNAL_FUNC (prefs_filtering_action_select_dest), + NULL); + + exec_btn = gtk_button_new_with_label (_("Info ...")); + gtk_widget_show (exec_btn); + gtk_box_pack_start (GTK_BOX (hbox1), exec_btn, FALSE, FALSE, 0); + gtk_signal_connect (GTK_OBJECT (exec_btn), "clicked", + GTK_SIGNAL_FUNC (prefs_filtering_action_exec_info), + NULL); + + /* register / substitute / delete */ + + reg_hbox = gtk_hbox_new(FALSE, 4); + gtk_widget_show(reg_hbox); + gtk_box_pack_start(GTK_BOX(vbox1), reg_hbox, FALSE, FALSE, 0); + + arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT); + gtk_widget_show(arrow); + gtk_box_pack_start(GTK_BOX(reg_hbox), arrow, FALSE, FALSE, 0); + gtk_widget_set_usize(arrow, -1, 16); + + btn_hbox = gtk_hbox_new(TRUE, 4); + gtk_widget_show(btn_hbox); + gtk_box_pack_start(GTK_BOX(reg_hbox), btn_hbox, FALSE, FALSE, 0); + + reg_btn = gtk_button_new_with_label(_("Add")); + gtk_widget_show(reg_btn); + gtk_box_pack_start(GTK_BOX(btn_hbox), reg_btn, FALSE, TRUE, 0); + gtk_signal_connect(GTK_OBJECT(reg_btn), "clicked", + GTK_SIGNAL_FUNC(prefs_filtering_action_register_cb), NULL); + + subst_btn = gtk_button_new_with_label(_(" Replace ")); + gtk_widget_show(subst_btn); + gtk_box_pack_start(GTK_BOX(btn_hbox), subst_btn, FALSE, TRUE, 0); + gtk_signal_connect(GTK_OBJECT(subst_btn), "clicked", + GTK_SIGNAL_FUNC(prefs_filtering_action_substitute_cb), + NULL); + + del_btn = gtk_button_new_with_label(_("Delete")); + gtk_widget_show(del_btn); + gtk_box_pack_start(GTK_BOX(btn_hbox), del_btn, FALSE, TRUE, 0); + gtk_signal_connect(GTK_OBJECT(del_btn), "clicked", + GTK_SIGNAL_FUNC(prefs_filtering_action_delete_cb), NULL); + + action_hbox = gtk_hbox_new(FALSE, 8); + gtk_widget_show(action_hbox); + gtk_box_pack_start(GTK_BOX(vbox1), action_hbox, TRUE, TRUE, 0); + + action_scrolledwin = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_show(action_scrolledwin); + gtk_widget_set_usize(action_scrolledwin, -1, 150); + gtk_box_pack_start(GTK_BOX(action_hbox), action_scrolledwin, + TRUE, TRUE, 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(action_scrolledwin), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + title[0] = _("Current action list"); + action_clist = gtk_clist_new_with_titles(1, title); + gtk_widget_show(action_clist); + gtk_container_add(GTK_CONTAINER(action_scrolledwin), action_clist); + gtk_clist_set_column_width(GTK_CLIST(action_clist), 0, 80); + gtk_clist_set_selection_mode(GTK_CLIST(action_clist), + GTK_SELECTION_BROWSE); + GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(action_clist)->column[0].button, + GTK_CAN_FOCUS); + gtk_signal_connect(GTK_OBJECT(action_clist), "select_row", + GTK_SIGNAL_FUNC(prefs_filtering_action_select), NULL); + + btn_vbox = gtk_vbox_new(FALSE, 8); + gtk_widget_show(btn_vbox); + gtk_box_pack_start(GTK_BOX(action_hbox), btn_vbox, FALSE, FALSE, 0); + + up_btn = gtk_button_new_with_label(_("Up")); + gtk_widget_show(up_btn); + gtk_box_pack_start(GTK_BOX(btn_vbox), up_btn, FALSE, FALSE, 0); + gtk_signal_connect(GTK_OBJECT(up_btn), "clicked", + GTK_SIGNAL_FUNC(prefs_filtering_action_up), NULL); + + down_btn = gtk_button_new_with_label(_("Down")); + gtk_widget_show(down_btn); + gtk_box_pack_start(GTK_BOX(btn_vbox), down_btn, FALSE, FALSE, 0); + gtk_signal_connect(GTK_OBJECT(down_btn), "clicked", + GTK_SIGNAL_FUNC(prefs_filtering_action_down), NULL); + + gtk_widget_show_all(window); + + filtering_action.window = window; + filtering_action.action_type_list = action_type_list; + filtering_action.action_combo = action_combo; + filtering_action.account_label = account_label; + filtering_action.account_list = account_list; + filtering_action.account_combo = account_combo; + filtering_action.dest_entry = dest_entry; + filtering_action.dest_btn = dest_btn; + filtering_action.dest_label = dest_label; + filtering_action.recip_label = recip_label; + filtering_action.exec_label = exec_label; + filtering_action.exec_btn = exec_btn; + filtering_action.color_label = color_label; + filtering_action.color_optmenu = color_optmenu; + filtering_action.ok_btn = ok_btn; + filtering_action.action_clist = action_clist; +} + +/*! + *\brief Set the contents of a row + * + *\param row Index of row to set + *\param prop Condition to set + * + *\return gint Row index \a prop has been added + */ +static gint prefs_filtering_action_clist_set_row(gint row, FilteringAction *action) +{ + GtkCList *clist = GTK_CLIST(filtering_action.action_clist); + gchar *action_tab_str[1]; + gchar *action_str; + gchar buf[256]; + + if (action == NULL) { + action_tab_str[0] = _("(New)"); + return gtk_clist_append(clist, action_tab_str); + } + + filteringaction_to_string(buf, sizeof buf, action); + action_str = g_strdup(buf); + + action_tab_str[0] = action_str; + if (row < 0) + row = gtk_clist_append(clist, action_tab_str); + else + gtk_clist_set_text(clist, row, 0, action_tab_str[0]); + g_free(action_str); + + return row; +} + +/*! + *\brief Update scrollbar + */ +static void prefs_filtering_action_update_hscrollbar(void) +{ + gint optwidth = gtk_clist_optimal_column_width(GTK_CLIST(filtering_action.action_clist), 0); + gtk_clist_set_column_width(GTK_CLIST(filtering_action.action_clist), 0, optwidth); +} + +/*! + *\brief Initializes dialog with a set of conditions + * + *\param matchers List of conditions + */ +static void prefs_filtering_action_set_dialog(GSList *action_list) +{ + GtkCList *clist = GTK_CLIST(filtering_action.action_clist); + GSList *cur; + + gtk_clist_freeze(clist); + gtk_clist_clear(clist); + + prefs_filtering_action_clist_set_row(-1, NULL); + if (action_list != NULL) { + for (cur = action_list; cur != NULL; + cur = g_slist_next(cur)) { + FilteringAction *action; + action = (FilteringAction *) cur->data; + prefs_filtering_action_clist_set_row(-1, action); + } + } + + prefs_filtering_action_update_hscrollbar(); + + gtk_clist_thaw(clist); + + prefs_filtering_action_reset_dialog(); +} + +/*! + *\brief Converts current actions in list box in + * an action list used by the filtering system. + * + *\return GSList * List of actions. + */ +static GSList *prefs_filtering_action_get_list(void) +{ + gchar *action_str; + FilteringAction *action; + gint row = 1; + GSList *action_list; + + action_list = NULL; + + while (gtk_clist_get_text(GTK_CLIST(filtering_action.action_clist), + row, 0, &action_str)) { + + if (strcmp(action_str, _("(New)")) != 0) { + GSList * tmp_action_list; + tmp_action_list = matcher_parser_get_action_list(action_str); + + if (tmp_action_list == NULL) + break; + + action_list = g_slist_concat(action_list, + tmp_action_list); + } + row ++; + } + + return action_list; +} + +/*! + *\brief Returns account ID from the given list index + * + *\return gint account ID + */ +static gint get_account_id_from_list_id(gint list_id) +{ + GList * accounts; + + for (accounts = account_get_list() ; accounts != NULL; + accounts = accounts->next) { + PrefsAccount *ac = (PrefsAccount *)accounts->data; + + if (list_id == 0) + return ac->account_id; + list_id--; + } + return 0; +} + +/*! + *\brief Returns list index from the given account ID + * + *\return gint list index + */ +static gint get_list_id_from_account_id(gint account_id) +{ + GList * accounts; + gint list_id = 0; + + for (accounts = account_get_list() ; accounts != NULL; + accounts = accounts->next) { + PrefsAccount *ac = (PrefsAccount *)accounts->data; + + if (account_id == ac->account_id) + return list_id; + list_id++; + } + return 0; +} + + +/*! + *\brief Returns parser action ID from internal action ID + * + *\return gint parser action ID + */ +static gint prefs_filtering_action_get_matching_from_action(Action action_id) +{ + switch (action_id) { + case ACTION_MOVE: + return MATCHACTION_MOVE; + case ACTION_COPY: + return MATCHACTION_COPY; + case ACTION_DELETE: + return MATCHACTION_DELETE; + case ACTION_MARK: + return MATCHACTION_MARK; + case ACTION_UNMARK: + return MATCHACTION_UNMARK; + case ACTION_LOCK: + return MATCHACTION_LOCK; + case ACTION_UNLOCK: + return MATCHACTION_UNLOCK; + case ACTION_MARK_AS_READ: + return MATCHACTION_MARK_AS_READ; + case ACTION_MARK_AS_UNREAD: + return MATCHACTION_MARK_AS_UNREAD; + case ACTION_FORWARD: + return MATCHACTION_FORWARD; + case ACTION_FORWARD_AS_ATTACHMENT: + return MATCHACTION_FORWARD_AS_ATTACHMENT; + case ACTION_REDIRECT: + return MATCHACTION_REDIRECT; + case ACTION_EXECUTE: + return MATCHACTION_EXECUTE; + case ACTION_COLOR: + return MATCHACTION_COLOR; + default: + return -1; + } +} + +/*! + *\brief Returns action from the content of the dialog + * + *\param alert specifies whether alert dialog boxes should be shown + * or not. + * + *\return FilteringAction * action entered in the dialog box. + */ +static FilteringAction * prefs_filtering_action_dialog_to_action(gboolean alert) +{ + Action action_id; + gint action_type; + gint list_id; + gint account_id; + gchar * destination; + gint labelcolor = 0; + FilteringAction * action; + + action_id = get_sel_from_list(GTK_LIST(filtering_action.action_type_list)); + action_type = prefs_filtering_action_get_matching_from_action(action_id); + list_id = get_sel_from_list(GTK_LIST(filtering_action.account_list)); + account_id = get_account_id_from_list_id(list_id); + + switch (action_id) { + case ACTION_MOVE: + case ACTION_COPY: + case ACTION_EXECUTE: + destination = gtk_entry_get_text(GTK_ENTRY(filtering_action.dest_entry)); + if (*destination == '\0') { + if (alert) + alertpanel_error(_("Destination is not set.")); + return NULL; + } + break; + case ACTION_FORWARD: + case ACTION_FORWARD_AS_ATTACHMENT: + case ACTION_REDIRECT: + destination = gtk_entry_get_text(GTK_ENTRY(filtering_action.dest_entry)); + if (*destination == '\0') { + if (alert) + alertpanel_error(_("Recipient is not set.")); + return NULL; + } + break; + case ACTION_COLOR: + labelcolor = colorlabel_get_color_menu_active_item( + gtk_option_menu_get_menu(GTK_OPTION_MENU(filtering_action.color_optmenu))); + destination = NULL; + break; + default: + destination = NULL; + break; + } + + action = filteringaction_new(action_type, account_id, destination, labelcolor); + + return action; +} + +/*! + *\brief Signal handler for register button + */ +static void prefs_filtering_action_register_cb(void) +{ + FilteringAction *action; + + action = prefs_filtering_action_dialog_to_action(TRUE); + if (action == NULL) + return; + + prefs_filtering_action_clist_set_row(-1, action); + + filteringaction_free(action); + + prefs_filtering_action_reset_dialog(); + prefs_filtering_action_update_hscrollbar(); +} + +/*! + *\brief Signal handler for substitute button + */ +static void prefs_filtering_action_substitute_cb(void) +{ + GtkCList *clist = GTK_CLIST(filtering_action.action_clist); + gint row; + FilteringAction *action; + + if (!clist->selection) return; + row = GPOINTER_TO_INT(clist->selection->data); + if (row == 0) + return; + + action = prefs_filtering_action_dialog_to_action(TRUE); + if (action == NULL) + return; + + prefs_filtering_action_clist_set_row(row, action); + + filteringaction_free(action); + + prefs_filtering_action_reset_dialog(); + + prefs_filtering_action_update_hscrollbar(); +} + +/*! + *\brief Signal handler for delete button + */ +static void prefs_filtering_action_delete_cb(void) +{ + GtkCList *clist = GTK_CLIST(filtering_action.action_clist); + gint row; + + if (!clist->selection) return; + row = GPOINTER_TO_INT(clist->selection->data); + if (row == 0) + return; + + gtk_clist_remove(clist, row); + + prefs_filtering_action_reset_dialog(); + + prefs_filtering_action_update_hscrollbar(); +} + +/*! + *\brief Signal handler for 'move up' button + */ +static void prefs_filtering_action_up(void) +{ + GtkCList *clist = GTK_CLIST(filtering_action.action_clist); + gint row; + + if (!clist->selection) return; + + row = GPOINTER_TO_INT(clist->selection->data); + if (row > 1) { + gtk_clist_row_move(clist, row, row - 1); + if (gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL) + gtk_clist_moveto(clist, row - 1, 0, 0, 0); + } +} + +/*! + *\brief Signal handler for 'move down' button + */ +static void prefs_filtering_action_down(void) +{ + GtkCList *clist = GTK_CLIST(filtering_action.action_clist); + gint row; + + if (!clist->selection) return; + + row = GPOINTER_TO_INT(clist->selection->data); + if (row >= 1 && row < clist->rows - 1) { + gtk_clist_row_move(clist, row, row + 1); + if (gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL) + gtk_clist_moveto(clist, row + 1, 0, 1, 0); + } +} + +/*! + *\brief Signal handler for select row. + * + *\param clist List widget + *\param row Selected row + *\param column Selected column + *\param event Event information + */ +static void prefs_filtering_action_select(GtkCList *clist, + gint row, gint column, GdkEvent *event) +{ + gchar *action_str; + FilteringAction *action; + GSList * action_list; + gint list_id; + + if (!gtk_clist_get_text(GTK_CLIST(filtering_action.action_clist), + row, 0, &action_str)) + return; + + if (row == 0) { + prefs_filtering_action_reset_dialog(); + return; + } + + action_list = matcher_parser_get_action_list(action_str); + if (action_list == NULL) + return; + + action = action_list->data; + g_slist_free(action_list); + + if (action->destination) + gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), action->destination); + else + gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), ""); + + switch(action->type) { + case MATCHACTION_MOVE: + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_MOVE); + break; + case MATCHACTION_COPY: + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_COPY); + break; + case MATCHACTION_DELETE: + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_DELETE); + break; + case MATCHACTION_MARK: + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_MARK); + break; + case MATCHACTION_UNMARK: + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_UNMARK); + break; + case MATCHACTION_LOCK: + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_LOCK); + break; + case MATCHACTION_UNLOCK: + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_UNLOCK); + break; + case MATCHACTION_MARK_AS_READ: + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_MARK_AS_READ); + break; + case MATCHACTION_MARK_AS_UNREAD: + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_MARK_AS_UNREAD); + break; + case MATCHACTION_FORWARD: + list_id = get_list_id_from_account_id(action->account_id); + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_FORWARD); + gtk_list_select_item(GTK_LIST(filtering_action.account_list), + list_id); + break; + case MATCHACTION_FORWARD_AS_ATTACHMENT: + list_id = get_list_id_from_account_id(action->account_id); + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_FORWARD_AS_ATTACHMENT); + gtk_list_select_item(GTK_LIST(filtering_action.account_list), + list_id); + break; + case MATCHACTION_REDIRECT: + list_id = get_list_id_from_account_id(action->account_id); + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_REDIRECT); + gtk_list_select_item(GTK_LIST(filtering_action.account_list), + list_id); + break; + case MATCHACTION_EXECUTE: + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_EXECUTE); + break; + case MATCHACTION_COLOR: + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), + ACTION_COLOR); + gtk_option_menu_set_history(GTK_OPTION_MENU(filtering_action.color_optmenu), action->labelcolor); + break; + } +} + +/*! + *\brief Handle key press + * + *\param widget Widget receiving key press + *\param event Key event + *\param data User data + */ +static void prefs_filtering_action_key_pressed(GtkWidget *widget, + GdkEventKey *event, gpointer data) +{ + if (event && event->keyval == GDK_Escape) + prefs_filtering_action_cancel(); +} + +/*! + *\brief Cancel matcher dialog + */ +static void prefs_filtering_action_cancel(void) +{ + gtk_widget_hide(filtering_action.window); + inc_unlock(); +} + +/*! + *\brief Accept current matchers + */ +static void prefs_filtering_action_ok(void) +{ + GSList * action_list; + GSList * cur; + + action_list = prefs_filtering_action_get_list(); + + if (action_list == NULL) { + alertpanel_error(_("No action was defined.")); + return; + } + + if (filtering_action_callback != NULL) + filtering_action_callback(action_list); + for(cur = action_list ; cur != NULL ; cur = cur->next) { + filteringaction_free(cur->data); + } + g_slist_free(action_list); + + gtk_widget_hide(filtering_action.window); + inc_unlock(); +} + +/*! + *\brief Called when closing dialog box + * + *\param widget Dialog widget + *\param event Event info + *\param data User data + * + *\return gint TRUE + */ +static gint prefs_filtering_action_deleted(GtkWidget *widget, + GdkEventAny *event, gpointer data) +{ + prefs_filtering_action_cancel(); + return TRUE; +} + +/* + * Strings describing exec format strings + * + * When adding new lines, remember to put 2 strings for each line + */ +static gchar *exec_desc_strings[] = { + "%%", "%", + "%s", N_("Subject"), + "%f", N_("From"), + "%t", N_("To"), + "%c", N_("Cc"), + "%d", N_("Date"), + "%i", N_("Message-ID"), + "%n", N_("Newsgroups"), + "%r", N_("References"), + "%F", N_("Filename - should not be modified"), + "\\n", N_("new line"), + "\\", N_("escape character for quotes"), + "\\\"",N_("quote character"), + NULL, NULL +}; + +static DescriptionWindow exec_desc_win = { + NULL, + 2, + N_("Description of symbols"), + exec_desc_strings +}; + + + +/*! + *\brief Show Execute action's info + */ +void prefs_filtering_action_exec_info(void) +{ + description_window_create(&exec_desc_win); +} + +static void prefs_filtering_action_select_dest(void) +{ + FolderItem *dest; + gchar * path; + + dest = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL); + if (!dest) return; + + path = folder_item_get_identifier(dest); + + gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), path); + g_free(path); +} + +static void prefs_filtering_action_type_selection_changed(GtkList *list, + gpointer user_data) +{ + gint value; + + value = get_sel_from_list(GTK_LIST(filtering_action.action_type_list)); + + if (filtering_action.current_action != value) { + if (filtering_action.current_action == ACTION_FORWARD + || filtering_action.current_action == ACTION_FORWARD_AS_ATTACHMENT + || filtering_action.current_action == ACTION_REDIRECT) { + debug_print("unregistering address completion entry\n"); + address_completion_unregister_entry(GTK_ENTRY(filtering_action.dest_entry)); + } + if (value == ACTION_FORWARD || value == ACTION_FORWARD_AS_ATTACHMENT + || value == ACTION_REDIRECT) { + debug_print("registering address completion entry\n"); + address_completion_register_entry(GTK_ENTRY(filtering_action.dest_entry)); + } + filtering_action.current_action = value; + } +} + +static void prefs_filtering_action_type_select(GtkList *list, + GtkWidget *widget, gpointer user_data) +{ + Action value; + + value = (Action) get_sel_from_list(GTK_LIST(filtering_action.action_type_list)); + + switch (value) { + case ACTION_MOVE: + gtk_widget_show(filtering_action.account_label); + gtk_widget_set_sensitive(filtering_action.account_label, FALSE); + gtk_widget_set_sensitive(filtering_action.account_combo, FALSE); + gtk_widget_show(filtering_action.dest_entry); + gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE); + gtk_widget_show(filtering_action.dest_btn); + gtk_widget_set_sensitive(filtering_action.dest_btn, TRUE); + gtk_widget_show(filtering_action.dest_label); + gtk_widget_set_sensitive(filtering_action.dest_label, TRUE); + gtk_widget_hide(filtering_action.recip_label); + gtk_widget_hide(filtering_action.exec_label); + gtk_widget_hide(filtering_action.exec_btn); + gtk_widget_hide(filtering_action.color_optmenu); + gtk_widget_hide(filtering_action.color_label); + break; + case ACTION_COPY: + gtk_widget_show(filtering_action.account_label); + gtk_widget_set_sensitive(filtering_action.account_label, FALSE); + gtk_widget_set_sensitive(filtering_action.account_combo, FALSE); + gtk_widget_show(filtering_action.dest_entry); + gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE); + gtk_widget_show(filtering_action.dest_btn); + gtk_widget_set_sensitive(filtering_action.dest_btn, TRUE); + gtk_widget_show(filtering_action.dest_label); + gtk_widget_set_sensitive(filtering_action.dest_label, TRUE); + gtk_widget_hide(filtering_action.recip_label); + gtk_widget_hide(filtering_action.exec_label); + gtk_widget_hide(filtering_action.exec_btn); + gtk_widget_hide(filtering_action.color_optmenu); + gtk_widget_hide(filtering_action.color_label); + break; + case ACTION_DELETE: + gtk_widget_show(filtering_action.account_label); + gtk_widget_set_sensitive(filtering_action.account_label, FALSE); + gtk_widget_set_sensitive(filtering_action.account_combo, FALSE); + gtk_widget_show(filtering_action.dest_entry); + gtk_widget_set_sensitive(filtering_action.dest_entry, FALSE); + gtk_widget_show(filtering_action.dest_btn); + gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE); + gtk_widget_show(filtering_action.dest_label); + gtk_widget_set_sensitive(filtering_action.dest_label, FALSE); + gtk_widget_hide(filtering_action.recip_label); + gtk_widget_hide(filtering_action.exec_label); + gtk_widget_hide(filtering_action.exec_btn); + gtk_widget_hide(filtering_action.color_optmenu); + gtk_widget_hide(filtering_action.color_label); + break; + case ACTION_MARK: + case ACTION_UNMARK: + case ACTION_LOCK: + case ACTION_UNLOCK: + case ACTION_MARK_AS_READ: + case ACTION_MARK_AS_UNREAD: + gtk_widget_show(filtering_action.account_label); + gtk_widget_set_sensitive(filtering_action.account_label, FALSE); + gtk_widget_set_sensitive(filtering_action.account_combo, FALSE); + gtk_widget_show(filtering_action.dest_entry); + gtk_widget_set_sensitive(filtering_action.dest_entry, FALSE); + gtk_widget_show(filtering_action.dest_btn); + gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE); + gtk_widget_show(filtering_action.dest_label); + gtk_widget_set_sensitive(filtering_action.dest_label, FALSE); + gtk_widget_hide(filtering_action.recip_label); + gtk_widget_hide(filtering_action.exec_label); + gtk_widget_hide(filtering_action.exec_btn); + gtk_widget_hide(filtering_action.color_optmenu); + gtk_widget_hide(filtering_action.color_label); + break; + case ACTION_FORWARD: + gtk_widget_show(filtering_action.account_label); + gtk_widget_set_sensitive(filtering_action.account_label, TRUE); + gtk_widget_set_sensitive(filtering_action.account_combo, TRUE); + gtk_widget_show(filtering_action.dest_entry); + gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE); + gtk_widget_show(filtering_action.dest_btn); + gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE); + gtk_widget_hide(filtering_action.dest_label); + gtk_widget_show(filtering_action.recip_label); + gtk_widget_set_sensitive(filtering_action.recip_label, TRUE); + gtk_widget_hide(filtering_action.exec_label); + gtk_widget_hide(filtering_action.exec_btn); + gtk_widget_hide(filtering_action.color_optmenu); + gtk_widget_hide(filtering_action.color_label); + break; + case ACTION_FORWARD_AS_ATTACHMENT: + gtk_widget_show(filtering_action.account_label); + gtk_widget_set_sensitive(filtering_action.account_label, TRUE); + gtk_widget_set_sensitive(filtering_action.account_combo, TRUE); + gtk_widget_show(filtering_action.dest_entry); + gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE); + gtk_widget_show(filtering_action.dest_btn); + gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE); + gtk_widget_hide(filtering_action.dest_label); + gtk_widget_show(filtering_action.recip_label); + gtk_widget_set_sensitive(filtering_action.recip_label, TRUE); + gtk_widget_hide(filtering_action.exec_label); + gtk_widget_hide(filtering_action.exec_btn); + gtk_widget_hide(filtering_action.color_optmenu); + gtk_widget_hide(filtering_action.color_label); + break; + case ACTION_REDIRECT: + gtk_widget_show(filtering_action.account_label); + gtk_widget_set_sensitive(filtering_action.account_label, TRUE); + gtk_widget_set_sensitive(filtering_action.account_combo, TRUE); + gtk_widget_show(filtering_action.dest_entry); + gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE); + gtk_widget_show(filtering_action.dest_btn); + gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE); + gtk_widget_hide(filtering_action.dest_label); + gtk_widget_show(filtering_action.recip_label); + gtk_widget_set_sensitive(filtering_action.recip_label, TRUE); + gtk_widget_hide(filtering_action.exec_label); + gtk_widget_hide(filtering_action.exec_btn); + gtk_widget_hide(filtering_action.color_optmenu); + gtk_widget_hide(filtering_action.color_label); + break; + case ACTION_EXECUTE: + gtk_widget_show(filtering_action.account_label); + gtk_widget_set_sensitive(filtering_action.account_label, FALSE); + gtk_widget_set_sensitive(filtering_action.account_combo, FALSE); + gtk_widget_show(filtering_action.dest_entry); + gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE); + gtk_widget_hide(filtering_action.dest_btn); + gtk_widget_hide(filtering_action.dest_label); + gtk_widget_hide(filtering_action.recip_label); + gtk_widget_show(filtering_action.exec_label); + gtk_widget_set_sensitive(filtering_action.exec_btn, TRUE); + gtk_widget_show(filtering_action.exec_btn); + gtk_widget_hide(filtering_action.color_optmenu); + gtk_widget_hide(filtering_action.color_label); + break; + case ACTION_COLOR: + gtk_widget_show(filtering_action.account_label); + gtk_widget_set_sensitive(filtering_action.account_label, FALSE); + gtk_widget_set_sensitive(filtering_action.account_combo, FALSE); + gtk_widget_hide(filtering_action.dest_entry); + gtk_widget_hide(filtering_action.dest_btn); + gtk_widget_hide(filtering_action.dest_label); + gtk_widget_hide(filtering_action.recip_label); + gtk_widget_hide(filtering_action.exec_label); + gtk_widget_show(filtering_action.exec_btn); + gtk_widget_set_sensitive(filtering_action.exec_btn, FALSE); + gtk_widget_show(filtering_action.color_optmenu); + gtk_widget_show(filtering_action.color_label); + break; + } +} + +static void prefs_filtering_action_reset_dialog(void) +{ + gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), 0); + gtk_list_select_item(GTK_LIST(filtering_action.account_list), 0); + gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), ""); +} diff --git a/src/prefs_filtering_action.h b/src/prefs_filtering_action.h new file mode 100644 index 000000000..01d11fcc5 --- /dev/null +++ b/src/prefs_filtering_action.h @@ -0,0 +1,31 @@ +/* + * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client + * Copyright (C) 1999-2001 Hiroyuki Yamamoto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PREFS_FILTERING_ACTION_H__ +#define __PREFS_FILTERING_ACTION_H__ + +#include "matcher.h" + +typedef void PrefsFilteringActionSignal (GSList *action_list); + +void prefs_filtering_action_open (GSList *action_list, + PrefsFilteringActionSignal *cb); +void prefs_filtering_action_exec_info (void); + +#endif /* __PREFS_FILTER_H__ */ -- 2.25.1