[PATCH]
- From: Emmanuel <e allaud wanadoo fr>
- To: ML de Balsa <balsa-list gnome org>
- Cc: Pawel Salek <pawsa theochem kth se>
- Subject: [PATCH]
- Date: Thu, 30 May 2002 15:27:42 +0200
Hi all,
I have done a patch to answer a request from Brian IIRC to add the
capability for filters to match on user headers. Ie now in the filters
edit dialog you have 2 new fields (I also have reorganized the dialog a
bit) in the matching fields frame to let you specify a user header name to
match on (it is done with a combo list so that it'll propose you the list
of the user headers already used in all filters).
I had a problem : I wanted to add a newly entered user string in the list
using gtk_combo_set_popdown_strings but this seemed to confuse gtk. So how
should I do it?
Please try and comment before I submit it to Pawel.
Thanks
Bye
Manu
diff -u /home/manu/prog/balsa-cvs/balsa/libbalsa/filter-file.c balsa-test/libbalsa/filter-file.c
--- /home/manu/prog/balsa-cvs/balsa/libbalsa/filter-file.c Mon Mar 18 16:05:31 2002
+++ balsa-test/libbalsa/filter-file.c Tue May 28 16:56:37 2002
@@ -72,6 +72,8 @@
newc->type = gnome_config_get_int("Type");
newc->condition_not = gnome_config_get_bool("Condition-not");
newc->match_fields = gnome_config_get_int("Match-fields");
+ if (CONDITION_CHKMATCH(newc,CONDITION_MATCH_US_HEAD))
+ newc->user_header = gnome_config_get_string("User-header");
switch(newc->type) {
case CONDITION_SIMPLE:
@@ -244,12 +246,10 @@
g_free(newf->sound);
newf->sound=NULL;
}
- else FILTER_SETFLAG(newf,FILTER_SOUND);
- if (newf->popup_text=='\0') {
+ if (newf->popup_text[0]=='\0') {
g_free(newf->popup_text);
newf->popup_text=NULL;
}
- else FILTER_SETFLAG(newf,FILTER_POPUP);
return newf;
}
@@ -277,6 +277,10 @@
gnome_config_clean_key("High-date");
}
if (cond->type!=CONDITION_FLAG) gnome_config_clean_key("Flags");
+ if (!CONDITION_CHKMATCH(cond,CONDITION_MATCH_US_HEAD))
+ gnome_config_clean_key("User-header");
+ else
+ gnome_config_set_string("User-header",cond->user_header);
switch(cond->type) {
case CONDITION_SIMPLE:
diff -u /home/manu/prog/balsa-cvs/balsa/libbalsa/filter-funcs.c balsa-test/libbalsa/filter-funcs.c
--- /home/manu/prog/balsa-cvs/balsa/libbalsa/filter-funcs.c Sun Feb 24 16:27:43 2002
+++ balsa-test/libbalsa/filter-funcs.c Tue May 28 16:56:37 2002
@@ -75,6 +75,8 @@
/* to avoid warnings */
break;
}
+ if (cond->user_header)
+ g_free(cond->user_header);
g_free(cond);
} /* end libbalsa_condition_free() */
@@ -96,8 +98,9 @@
newc->type = CONDITION_NONE;
newc->match_fields = CONDITION_EMPTY;
- newc->condition_not=FALSE;
+ newc->condition_not = FALSE;
newc->match.string = NULL;
+ newc->user_header = NULL;
filter_errno=FILTER_NOERR;
return newc;
@@ -132,6 +135,7 @@
new_cnd->condition_not = cnd->condition_not;
new_cnd->match_fields = cnd->match_fields;
new_cnd->type = cnd->type;
+ new_cnd->user_header = g_strdup(cnd->user_header);
switch (new_cnd->type) {
case CONDITION_SIMPLE:
new_cnd->match.string=g_strdup(cnd->match.string);
@@ -207,8 +211,8 @@
*
* Position filter_errno (by calling condition_regcomp)
*/
-static void
-condition_compile_regexs(LibBalsaCondition* cond)
+void
+libbalsa_condition_compile_regexs(LibBalsaCondition* cond)
{
GSList * regex;
@@ -231,6 +235,8 @@
filter_condition_validity(LibBalsaFilter* fil, LibBalsaCondition* cond)
{
/* Test validity of condition */
+ if (CONDITION_CHKMATCH(cond,CONDITION_MATCH_US_HEAD) && (!cond->user_header || cond->user_header[0]=='\0'))
+ FILTER_CLRFLAG(fil,FILTER_VALID);
switch (cond->type) {
case CONDITION_SIMPLE:
if (!cond->match.string)
@@ -281,7 +287,7 @@
if (fil->conditions) {
GSList * lst;
for (lst=fil->conditions;lst && filter_errno==FILTER_NOERR;lst=g_slist_next(lst))
- condition_compile_regexs((LibBalsaCondition*) lst->data);
+ libbalsa_condition_compile_regexs((LibBalsaCondition*) lst->data);
if (filter_errno != FILTER_NOERR) {
gchar * errorstring =
g_strdup_printf("Unable to compile filter %s", fil->name);
@@ -406,6 +412,7 @@
str=g_string_append(str,"\"Subject\"");
coma=TRUE;
}
+ /* FIXME : see how to export conditions matching user headers */
g_string_append(str,"] ");
if (str->len>3) {
gchar * temp=g_strdup_printf(str_format,"header",str->str);
diff -u /home/manu/prog/balsa-cvs/balsa/libbalsa/filter-funcs.h balsa-test/libbalsa/filter-funcs.h
--- /home/manu/prog/balsa-cvs/balsa/libbalsa/filter-funcs.h Mon Nov 26 10:07:00 2001
+++ balsa-test/libbalsa/filter-funcs.h Tue May 28 16:56:37 2002
@@ -44,7 +44,7 @@
LibBalsaCondition* libbalsa_condition_clone(LibBalsaCondition* cnd);
void libbalsa_condition_regex_free(LibBalsaConditionRegex *, gpointer);
void regexs_free(GSList *);
-
+void libbalsa_condition_compile_regexs(LibBalsaCondition* cond);
/* Filters */
/* Free a filter
* free_condition is a gint into a gpointer : if <>0 the function frees filter conditions also
diff -u /home/manu/prog/balsa-cvs/balsa/libbalsa/filter-private.h balsa-test/libbalsa/filter-private.h
--- /home/manu/prog/balsa-cvs/balsa/libbalsa/filter-private.h Mon Nov 26 10:07:00 2001
+++ balsa-test/libbalsa/filter-private.h Tue May 28 16:56:37 2002
@@ -50,6 +50,7 @@
#define CONDITION_MATCH_FROM 1<<1 /* match in the From: field */
#define CONDITION_MATCH_SUBJECT 1<<2 /* match in the Subject field */
#define CONDITION_MATCH_CC 1<<3 /* match in the cc: field */
+#define CONDITION_MATCH_US_HEAD 1<<4 /* match in a user header */
#define CONDITION_MATCH_BODY 1<<7 /* match in the body */
/* match_fields macros */
@@ -74,8 +75,6 @@
#define FILTER_VALID 1<<1 /* ready to filter (eg regex strings
have been compiled with regcomp(), with no errors...) */
#define FILTER_COMPILED 1<<2 /* the filter needs to be compiled (ie there are uncompiled regex) */
-#define FILTER_SOUND 1<<4 /* play a sound when matches */
-#define FILTER_POPUP 1<<5 /* popup text when matches */
/* flag operation macros */
#define FILTER_SETFLAG(x, y) ((((LibBalsaFilter*)(x))->flags) |= (y))
diff -u /home/manu/prog/balsa-cvs/balsa/libbalsa/filter.c balsa-test/libbalsa/filter.c
--- /home/manu/prog/balsa-cvs/balsa/libbalsa/filter.c Thu May 16 06:34:55 2002
+++ balsa-test/libbalsa/filter.c Tue May 28 16:56:37 2002
@@ -120,6 +120,18 @@
g_free(str);
if (match) break;
}
+ if (CONDITION_CHKMATCH(cond,CONDITION_MATCH_US_HEAD)) {
+ if (cond->user_header) {
+ GList * header =
+ libbalsa_message_find_user_hdr(message, cond->user_header);
+
+ if (header) {
+ gchar ** tmp = header->data;
+ match = in_string(tmp[1],cond->match.string);
+ if (match) break;
+ }
+ }
+ }
if (CONDITION_CHKMATCH(cond,CONDITION_MATCH_BODY)) {
gboolean is_new = (message->flags & LIBBALSA_MESSAGE_FLAG_NEW);
if (!libbalsa_message_body_ref(message)) {
@@ -166,6 +178,18 @@
g_free(str);
if (match) break;
}
+ if (CONDITION_CHKMATCH(cond,CONDITION_MATCH_US_HEAD)) {
+ if (cond->user_header) {
+ GList * header =
+ libbalsa_message_find_user_hdr(message, cond->user_header);
+
+ if (header) {
+ gchar ** tmp = header->data;
+ if (tmp[1] && (match=REGEXEC(*(regex->compiled),tmp[1])==0))
+ break;
+ }
+ }
+ }
if (CONDITION_CHKMATCH(cond,CONDITION_MATCH_BODY)) {
gboolean is_new = (message->flags & LIBBALSA_MESSAGE_FLAG_NEW);
if (!libbalsa_message_body_ref(message)) {
@@ -254,6 +278,7 @@
query = extend_query(query, "CC", cond->match.string, op);
if (CONDITION_CHKMATCH(cond,CONDITION_MATCH_BODY))
query = extend_query(query, "TEXT", cond->match.string, op);
+ /* FIXME : extend that for user headers matching */
}
str = query->str;
g_string_free(query, FALSE);
@@ -262,8 +287,6 @@
/*--------- Filtering functions -------------------------------*/
-/* FIXME : Add error reporting for each filter */
-
gint
filters_prepare_to_run(GSList * filters)
{
@@ -287,21 +310,18 @@
/*
* Run all filters until one matches (so order of filter is important)
* filters must be valid and compiled (ie filters_prepare_to_run have been called before)
- * Assume that all messages come from ONE mailbox
- * returns TRUE if the trash bin has been filled
- * FIXME : Should position filter_errno on errors (bad command action,bad destination mailbox...)
+ * In general you'll call this function with mailbox lock held (ie you locked the mailbox
+ * you're filtering before calling this function)
*/
-gboolean
-filters_run_on_messages(GSList * filter_list, GList * messages)
+void
+libbalsa_filter_match(GSList * filter_list, GList * messages)
{
gint match;
GSList * lst;
- GList * lst_messages;
LibBalsaFilter * filt=NULL;
- gboolean result=FALSE;
- if (!filter_list || ! messages) return FALSE;
+ if (!filter_list || ! messages) return;
for (;messages;messages=g_list_next(messages)) {
@@ -316,17 +336,38 @@
filt->matching_messages=g_list_prepend(filt->matching_messages,LIBBALSA_MESSAGE(messages->data));
}
}
+}
+
+void libbalsa_filter_match_mailbox(GSList * filter_list, LibBalsaMailbox * mbox)
+{
+ LOCK_MAILBOX(mbox);
+ libbalsa_filter_match(filter_list, mbox->message_list);
+ UNLOCK_MAILBOX(mbox);
+}
+
+/* Apply all filters on their matching messages (call libbalsa_filter_match before)
+ * returns TRUE if the trash bin has been filled
+ * FIXME : Should position filter_errno on errors (bad command action,bad destination mailbox...)
+ */
+
+gboolean
+libbalsa_filter_apply(GSList * filter_list)
+{
+ GSList * lst;
+ GList * lst_messages;
+ LibBalsaFilter * filt=NULL;
+ gboolean result=FALSE;
+ LibBalsaMailbox *mbox;
- /* OK we have done all the matching thing, now we take every action for matching messages */
+ if (!filter_list) return FALSE;
for (lst=filter_list;lst;lst=g_slist_next(lst)) {
- LibBalsaMailbox *mbox;
filt=(LibBalsaFilter*)lst->data;
- if (FILTER_CHKFLAG(filt,FILTER_SOUND)) {
+ if (filt->sound) {
/* FIXME : Emit sound */
}
- if (FILTER_CHKFLAG(filt,FILTER_POPUP)) {
+ if (filt->popup_text) {
/* FIXME : Print popup text */
}
if (filt->matching_messages) {
diff -u /home/manu/prog/balsa-cvs/balsa/libbalsa/filter.h balsa-test/libbalsa/filter.h
--- /home/manu/prog/balsa-cvs/balsa/libbalsa/filter.h Thu May 16 06:34:55 2002
+++ balsa-test/libbalsa/filter.h Tue May 28 16:56:37 2002
@@ -74,6 +74,8 @@
LibBalsaMessageFlag flags;
} match;
guint match_fields; /* Contains the flag mask for CONDITION_FLAG type */
+ gchar * user_header; /* This is !=NULL and gives the name of the user
+ header against which we make the match */
} LibBalsaCondition;
/* Filter definition :
@@ -178,13 +180,27 @@
gint filters_prepare_to_run(GSList * filters);
-/* filters_run_on_messages run all filters on the list of messages
+/* libbalsa_filter_match run all filters on the list of messages
+ each filter is stuffed with the list of its matching messages
+ you must call libbalsa_filter_apply after to make the filters
+ act on their matching messages (this split is needed for proper
+ locking)
+ */
+
+void libbalsa_filter_match(GSList * filter_list, GList * messages);
+
+/* Same but on mailbox, convenience function that locks the mailbox
+ before calling libbalsa_filter_match */
+
+void libbalsa_filter_match_mailbox(GSList * filter_list, LibBalsaMailbox * mbox);
+
+/* libbalsa_filter_apply will let all filters to apply on their
+ * matching messages (you must call libbalsa_filters_match before)
* It returns TRUE if the trash bin has been filled with something
* this is used to call enable_empty_trash after
- * FIXME : No locking is done for now
*/
-gboolean filters_run_on_messages(GSList * filter_list, GList * messages);
+gboolean libbalsa_filter_apply(GSList * filter_list);
/* libalsa_extract_new_messages : returns a sublist of the messages list containing all
"new" messages, ie just retrieved mails
diff -u /home/manu/prog/balsa-cvs/balsa/libbalsa/mailbox_local.c balsa-test/libbalsa/mailbox_local.c
--- /home/manu/prog/balsa-cvs/balsa/libbalsa/mailbox_local.c Fri May 17 08:15:11 2002
+++ balsa-test/libbalsa/mailbox_local.c Tue May 28 16:56:37 2002
@@ -239,14 +239,18 @@
FILTER_WHEN_INCOMING);
/* We apply filter if needed */
if (filters) {
+ LOCK_MAILBOX(mailbox);
new_messages=libbalsa_extract_new_messages(mailbox->message_list);
if (new_messages) {
- if (filters_prepare_to_run(filters))
- filters_run_on_messages(filters, new_messages);
- /* FIXME : do better error report */
- else g_warning("Filter error\n");
+ if (filters_prepare_to_run(filters)) {
+ libbalsa_filter_match(filters, new_messages);
+ UNLOCK_MAILBOX(mailbox);
+ libbalsa_filter_apply(filters);
+ }
+ else UNLOCK_MAILBOX(mailbox);
g_list_free(new_messages);
}
+ else UNLOCK_MAILBOX(mailbox);
g_slist_free(filters);
}
}
diff -u /home/manu/prog/balsa-cvs/balsa/libbalsa/mailbox_pop3.c balsa-test/libbalsa/mailbox_pop3.c
--- /home/manu/prog/balsa-cvs/balsa/libbalsa/mailbox_pop3.c Thu May 16 06:35:01 2002
+++ balsa-test/libbalsa/mailbox_pop3.c Tue May 28 16:56:37 2002
@@ -308,10 +308,10 @@
filters = libbalsa_mailbox_filters_when(mailbox->filters,
FILTER_WHEN_INCOMING);
if (filters) {
- if (filters_prepare_to_run(filters))
- filters_run_on_messages(filters, tmp_mailbox->message_list);
- /* FIXME : do better error report */
- else g_warning("Filter error\n");
+ if (filters_prepare_to_run(filters)) {
+ libbalsa_filter_match(filters, tmp_mailbox->message_list);
+ libbalsa_filter_apply(filters);
+ }
g_slist_free(filters);
}
diff -u /home/manu/prog/balsa-cvs/balsa/src/filter-edit-callbacks.c balsa-test/src/filter-edit-callbacks.c
--- /home/manu/prog/balsa-cvs/balsa/src/filter-edit-callbacks.c Wed May 8 08:49:07 2002
+++ balsa-test/src/filter-edit-callbacks.c Thu May 30 15:21:03 2002
@@ -43,10 +43,14 @@
extern option_list fe_search_type[4];
extern GtkWidget * build_option_menu(option_list options[], gint num,
GtkSignalFunc func);
+extern GList * fe_user_headers_list;
+
static void fe_add_pressed(GtkWidget * widget, gpointer throwaway);
static void fe_remove_pressed(GtkWidget * widget, gpointer throwaway);
static void fe_regexs_select_row(GtkWidget * widget, gint row, gint column,
GdkEventButton * bevent, gpointer data);
+static void fe_free_associated_filters(void);
+static void fe_free_associated_conditions(void);
/* The dialog widget (we need it to be able to close dialog on error) */
@@ -74,6 +78,9 @@
GtkWidget *fe_matching_fields_from;
GtkWidget *fe_matching_fields_subject;
GtkWidget *fe_matching_fields_cc;
+/* Combo list for user headers and check button*/
+GtkCombo * fe_user_header;
+GtkWidget * fe_matching_fields_us_head;
/* widget for the conditions */
extern GtkCList *fe_conditions_list;
@@ -155,6 +162,28 @@
*/
static GList * new_filters_names=NULL;
+/* Free filters associated with clist row */
+static void
+fe_free_associated_filters(void)
+{
+ gint row;
+
+ for (row=0;row<fe_filters_list->rows;row++)
+ libbalsa_filter_free((LibBalsaFilter*)
+ gtk_clist_get_row_data(fe_filters_list,row),
+ GINT_TO_POINTER(TRUE));
+}
+
+static void
+fe_free_associated_conditions(void)
+{
+ gint row;
+
+ for (row=0; row<fe_conditions_list->rows; row++)
+ libbalsa_condition_free((LibBalsaCondition *)
+ gtk_clist_get_row_data(fe_conditions_list,row));
+}
+
/*
* unique_filter_name()
*
@@ -325,14 +354,21 @@
gboolean active=GPOINTER_TO_INT(data)!=3; /* 3== uncheck all buttons */
condition_has_changed=TRUE;
- if (!active || GPOINTER_TO_INT(data)==1) /* 1== check all buttons */
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fe_matching_fields_body),active);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fe_matching_fields_body),active);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fe_matching_fields_to),active);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fe_matching_fields_from),active);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fe_matching_fields_subject),active);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fe_matching_fields_cc),active);
} /* end fe_match_fields_buttons_cb */
+static void
+fe_match_field_user_header_cb(GtkWidget * widget)
+{
+ gtk_widget_set_sensitive(GTK_WIDGET(fe_user_header),
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fe_matching_fields_us_head)));
+ condition_has_changed=TRUE;
+}
+
/* FIXME : to insure consistency and keep it simple I use a modal dialog box for condition edition/creation
* but I have to avoid libbalsa_information (this is not modal and does not get the focus because mine is modal
* so you end up with the small info box floating around and insensitive), so I use this function
@@ -348,6 +384,20 @@
gnome_dialog_run(err_dia);
}
+void
+fe_add_new_user_header(const gchar * str)
+{
+ GList * lst = fe_user_headers_list;
+
+ for (;lst;lst=g_list_next(lst))
+ if (g_strcasecmp(str,(gchar *)lst->data)==0) return;
+
+ /* It's a new string, add it */
+ fe_user_headers_list=g_list_insert_sorted(fe_user_headers_list,
+ g_strdup(str),
+ (GCompareFunc)g_strcasecmp);
+}
+
/* conditon_validate is responsible of validating
* the changes to the current condition, according to the widgets
* Performs sanity check on the widgets
@@ -363,6 +413,7 @@
gchar * str,* p;
gint match,row,col;
struct tm date;
+ GList * lst;
/* Sanity checks, prevent "empty" condition */
@@ -380,7 +431,24 @@
CONDITION_SETMATCH(new_cnd,CONDITION_MATCH_FROM);
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fe_matching_fields_cc)))
CONDITION_SETMATCH(new_cnd,CONDITION_MATCH_CC);
- if (new_cnd->match_fields==CONDITION_EMPTY) {
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fe_matching_fields_us_head))) {
+ CONDITION_SETMATCH(new_cnd,CONDITION_MATCH_US_HEAD);
+ str=gtk_entry_get_text(GTK_ENTRY(fe_user_header->entry));
+ if (!str[0]) {
+ condition_error(_("You must specify the name of the user header to match on"));
+ return FALSE;
+ }
+ fe_add_new_user_header(str);
+ /* Update combo */
+ /* FIXME : this piece of code is supposed to replace the combo list
+ by a new one that contains the new string the user has entered
+ but this seems to confuse the whole thing
+ gtk_combo_set_popdown_strings(fe_user_header,fe_user_headers_list);
+ gtk_entry_set_text(GTK_ENTRY(fe_user_header->entry),str);
+ for (lst=fe_user_headers_list;lst;lst=g_list_next(lst))
+ g_print("String = %s\n",(gchar*) lst->data);*/
+ }
+ else if (new_cnd->match_fields==CONDITION_EMPTY) {
condition_error(_("You must specify at least one field for matching"));
return FALSE;
}
@@ -439,7 +507,8 @@
/* Sanity checks OK, retrieve datas from widgets */
new_cnd->condition_not=condition_not;
-
+ if (CONDITION_CHKMATCH(new_cnd,CONDITION_MATCH_US_HEAD))
+ new_cnd->user_header=g_strdup(gtk_entry_get_text(GTK_ENTRY(fe_user_header->entry)));
/* Set the type specific fields of the condition */
switch (new_cnd->type) {
case CONDITION_SIMPLE:
@@ -527,6 +596,16 @@
CONDITION_CHKMATCH(cnd,CONDITION_MATCH_SUBJECT) && andmask);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fe_matching_fields_cc),
CONDITION_CHKMATCH(cnd,CONDITION_MATCH_CC) && andmask);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fe_matching_fields_us_head),
+ CONDITION_CHKMATCH(cnd,CONDITION_MATCH_US_HEAD) && andmask);
+ if (CONDITION_CHKMATCH(cnd,CONDITION_MATCH_US_HEAD) && andmask) {
+ gtk_widget_set_sensitive(GTK_WIDGET(fe_user_header),TRUE);
+ gtk_entry_set_text(GTK_ENTRY(fe_user_header->entry),cnd->user_header ? cnd->user_header : "");
+ }
+ else {
+ gtk_widget_set_sensitive(GTK_WIDGET(fe_user_header),FALSE);
+ gtk_entry_set_text(GTK_ENTRY(fe_user_header->entry),"");
+ }
/* Next update type specific fields */
switch (cnd->type) {
case CONDITION_SIMPLE:
@@ -636,7 +715,7 @@
GtkWidget *button;
gint row,col;
static gchar * flag_names[]=
- {N_("New"), N_("Deleted"), N_("Replied"), N_("Flagged")};
+ {N_("Unread"), N_("Deleted"), N_("Replied"), N_("Flagged")};
/* The notebook */
@@ -814,7 +893,7 @@
{
GtkWidget * table,* frame,* button,* page,* box;
- page = gtk_table_new(3, 7, FALSE);
+ page = gtk_table_new(7, 2, FALSE);
/* builds the toggle buttons to specify fields concerned by the conditions of
* the filter */
@@ -824,32 +903,24 @@
gtk_frame_set_shadow_type(GTK_FRAME(fe_match_frame), GTK_SHADOW_ETCHED_IN);
gtk_table_attach(GTK_TABLE(page),
fe_match_frame,
- 0, 3, 0, 2,
+ 0, 2, 0, 2,
GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 5, 5);
- table = gtk_table_new(3, 3, TRUE);
+ table = gtk_table_new(5, 2, TRUE);
gtk_container_add(GTK_CONTAINER(fe_match_frame), table);
button = gtk_button_new_with_label(_("All"));
gtk_table_attach(GTK_TABLE(table),
button,
- 0, 1, 2, 3,
+ 0, 1, 4, 5,
GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
gtk_signal_connect(GTK_OBJECT(button),"clicked",
GTK_SIGNAL_FUNC(fe_match_fields_buttons_cb),
GINT_TO_POINTER(1));
- button = gtk_button_new_with_label(_("All headers"));
- gtk_table_attach(GTK_TABLE(table),
- button,
- 1, 2, 2, 3,
- GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
- gtk_signal_connect(GTK_OBJECT(button),"clicked",
- GTK_SIGNAL_FUNC(fe_match_fields_buttons_cb),
- GINT_TO_POINTER(2));
button = gtk_button_new_with_label(_("Clear"));
gtk_table_attach(GTK_TABLE(table),
button,
- 2, 3, 2, 3,
+ 1, 2, 4, 5,
GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
gtk_signal_connect(GTK_OBJECT(button),"clicked",
GTK_SIGNAL_FUNC(fe_match_fields_buttons_cb),
@@ -867,7 +938,7 @@
fe_matching_fields_to = gtk_check_button_new_with_label(_("To:"));
gtk_table_attach(GTK_TABLE(table),
fe_matching_fields_to,
- 1, 2, 0, 1,
+ 0, 1, 1, 2,
GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
gtk_signal_connect(GTK_OBJECT(fe_matching_fields_to),
"toggled",
@@ -885,7 +956,7 @@
fe_matching_fields_subject = gtk_check_button_new_with_label(_("Subject"));
gtk_table_attach(GTK_TABLE(table),
fe_matching_fields_subject,
- 2, 3, 0, 1,
+ 0, 1, 2, 3,
GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
gtk_signal_connect(GTK_OBJECT(fe_matching_fields_subject),
"toggled",
@@ -894,20 +965,40 @@
fe_matching_fields_cc = gtk_check_button_new_with_label(_("Cc:"));
gtk_table_attach(GTK_TABLE(table),
fe_matching_fields_cc,
- 2, 3, 1, 2,
+ 1, 2, 2, 3,
GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
gtk_signal_connect(GTK_OBJECT(fe_matching_fields_cc),
"toggled",
GTK_SIGNAL_FUNC(fe_condition_changed_cb),
NULL);
-
+ fe_matching_fields_us_head = gtk_check_button_new_with_label(_("User header:"));
+ gtk_table_attach(GTK_TABLE(table),
+ fe_matching_fields_us_head,
+ 0, 1, 3, 4,
+ GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
+ gtk_signal_connect(GTK_OBJECT(fe_matching_fields_us_head),
+ "toggled",
+ GTK_SIGNAL_FUNC(fe_match_field_user_header_cb),
+ NULL);
+ fe_user_header = GTK_COMBO(gtk_combo_new());
+ gtk_combo_set_value_in_list(fe_user_header,FALSE,FALSE);
+ gtk_combo_set_case_sensitive(fe_user_header,FALSE);
+ gtk_combo_set_popdown_strings(fe_user_header,fe_user_headers_list);
+ gtk_signal_connect(GTK_OBJECT(fe_user_header->entry),
+ "changed", GTK_SIGNAL_FUNC(fe_condition_changed_cb),
+ NULL);
+ gtk_table_attach(GTK_TABLE(table),
+ GTK_WIDGET(fe_user_header),
+ 1, 2, 3, 4,
+ GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
+
frame = gtk_frame_new(_("Selected condition search type:"));
gtk_frame_set_label_align(GTK_FRAME(frame), GTK_POS_LEFT, GTK_POS_TOP);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
gtk_table_attach(GTK_TABLE(page),
frame,
- 0, 3, 2, 3,
+ 0, 2, 2, 3,
GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 5, 5);
box = gtk_hbox_new(FALSE, 5);
gtk_container_add(GTK_CONTAINER(frame), box);
@@ -920,7 +1011,7 @@
build_type_notebook();
gtk_table_attach(GTK_TABLE(page),
fe_type_notebook,
- 0, 3, 3, 7,
+ 0, 2, 3, 7,
GTK_FILL | GTK_SHRINK | GTK_EXPAND,
GTK_FILL | GTK_SHRINK | GTK_EXPAND, 5, 5);
gtk_box_pack_start(GTK_BOX(condition_dialog->vbox),page,FALSE,FALSE,2);
@@ -939,10 +1030,10 @@
LibBalsaCondition* cnd=NULL;
gint row=-1;
- if (!fe_filters_list->selection ||
- (!is_new_cnd && !fe_conditions_list->selection)) return;
-
is_new_condition=GPOINTER_TO_INT(is_new_cnd);
+
+ if (!fe_filters_list->selection && !is_new_condition) return;
+
if (!is_new_condition) {
row=GPOINTER_TO_INT(fe_conditions_list->selection->data);
cnd=(LibBalsaCondition*)gtk_clist_get_row_data(fe_conditions_list,row);
@@ -1124,6 +1215,11 @@
new_filters_names=NULL;
fe_already_open=FALSE;
+
+ /* free all strings in fe_user_headers_list */
+ g_list_foreach(fe_user_headers_list,(GFunc)g_free,NULL);
+ g_list_free(fe_user_headers_list);
+ fe_user_headers_list = NULL;
}
/*
@@ -1502,38 +1598,30 @@
if (fil->action!=FILTER_TRASH)
fil->action_string=g_strdup(mailbox_name);
- if (GTK_TOGGLE_BUTTON(fe_popup_button)->active) {
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fe_popup_button))) {
static gchar defstring[19] = N_("Filter has matched");
gchar *tmpstr;
- FILTER_SETFLAG(fil, FILTER_POPUP);
tmpstr = gtk_entry_get_text(GTK_ENTRY(fe_popup_entry));
fil->popup_text=g_strdup(((!tmpstr)
|| (tmpstr[0] ==
'\0')) ? _(defstring) : tmpstr);
}
- else {
- g_free(fil->popup_text);
- fil->popup_text=NULL;
- }
#ifdef HAVE_LIBESD
- if (GTK_TOGGLE_BUTTON(fe_sound_button)->active) {
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fe_sound_button))) {
gchar *tmpstr;
FILTER_SETFLAG(fil, FILTER_SOUND);
tmpstr = gtk_entry_get_text(GTK_ENTRY(fe_sound_entry));
if ((!tmpstr) || (tmpstr[0] == '\0')) {
libbalsa_filter_free(fil, GINT_TO_POINTER(TRUE));
- /* FIXME error_dialog("You must provide a sound to play") */
+ balsa_information(LIBBALSA_INFORMATION_ERROR,
+ _("You must provide a sound to play"));
return;
}
- fil->popup_sound(tmpstr);
- }
- else {
- g_free(fil->sound);
- fil->sound=NULL;
+ fil->sound=g_strdup(tmpstr);
}
#endif
/* New filter is OK, we replace the old one */
@@ -1590,14 +1678,14 @@
/* Populate all fields with filter data */
gtk_entry_set_text(GTK_ENTRY(fe_name_entry),fil->name);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fe_popup_button),
- FILTER_CHKFLAG(fil,FILTER_POPUP));
+ fil->popup_text!=NULL);
gtk_entry_set_text(GTK_ENTRY(fe_popup_entry),
- FILTER_CHKFLAG(fil,FILTER_POPUP)
+ fil->popup_text!=NULL
? fil->popup_text : "");
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fe_sound_button),
- FILTER_CHKFLAG(fil,FILTER_SOUND));
+ fil->sound!=NULL);
gtk_entry_set_text(GTK_ENTRY(gnome_file_entry_gtk_entry(GNOME_FILE_ENTRY(fe_sound_entry))),
- FILTER_CHKFLAG(fil,FILTER_SOUND) ? fil->sound : "");
+ fil->sound!=NULL ? fil->sound : "");
gtk_option_menu_set_history(GTK_OPTION_MENU(fe_action_option_menu),
fil->action-1);
@@ -1653,4 +1741,3 @@
gtk_widget_set_sensitive(fe_revert_button, TRUE);
fe_enable_right_page(TRUE);
} /* end fe_clist_select_row */
-
diff -u /home/manu/prog/balsa-cvs/balsa/src/filter-edit-dialog.c balsa-test/src/filter-edit-dialog.c
--- /home/manu/prog/balsa-cvs/balsa/src/filter-edit-dialog.c Sat May 18 14:29:10 2002
+++ balsa-test/src/filter-edit-dialog.c Tue May 28 16:56:37 2002
@@ -57,6 +57,9 @@
/* widget for the conditions */
GtkCList *fe_conditions_list;
+/* List of strings in the combo of user headers name */
+GList * fe_user_headers_list;
+
/* notification field */
GtkWidget *fe_sound_button;
GtkWidget *fe_sound_entry;
@@ -156,28 +159,6 @@
return (option_menu);
} /* end build_option_menu */
-/* Free filters associated with clist row */
-void
-fe_free_associated_filters(void)
-{
- gint row;
-
- for (row=0;row<fe_filters_list->rows;row++)
- libbalsa_filter_free((LibBalsaFilter*)
- gtk_clist_get_row_data(fe_filters_list,row),
- GINT_TO_POINTER(TRUE));
-}
-
-void
-fe_free_associated_conditions(void)
-{
- gint row;
-
- for (row=0; row<fe_conditions_list->rows; row++)
- libbalsa_condition_free((LibBalsaCondition *)
- gtk_clist_get_row_data(fe_conditions_list,row));
-}
-
static void
fe_clist_unselect_row(GtkWidget * widget, gint row, gint column,
GdkEventButton *event, gpointer data)
@@ -416,8 +397,9 @@
gtk_frame_set_label_align(GTK_FRAME(frame), GTK_POS_LEFT, GTK_POS_TOP);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
gtk_box_pack_start(GTK_BOX(page), frame, FALSE, FALSE, 2);
+ gtk_container_set_border_width(GTK_CONTAINER(frame), 3);
- table = gtk_table_new(2, 2, FALSE);
+ table = gtk_table_new(3, 2, FALSE);
gtk_container_add(GTK_CONTAINER(frame), table);
/* Notification buttons */
@@ -587,6 +569,7 @@
gtk_widget_set_sensitive(fe_right_page, FALSE);
gtk_box_pack_start(GTK_BOX(hbox), piece, TRUE, TRUE, 2);
+ fe_user_headers_list=NULL;
/* Populate the clist of filters */
for(filter_list=balsa_app.filters;
@@ -618,6 +601,12 @@
LibBalsaCondition *c = (LibBalsaCondition*)cnds->data;
cpfil->conditions =
g_slist_prepend(cpfil->conditions,libbalsa_condition_clone(c));
+
+ /* If this condition is a match on a user header,
+ add the user header name to the combo list */
+ if (CONDITION_CHKMATCH(c,CONDITION_MATCH_US_HEAD) &&
+ c->user_header && c->user_header[0])
+ fe_add_new_user_header(c->user_header);
}
cpfil->conditions=g_slist_reverse(cpfil->conditions);
@@ -631,6 +620,8 @@
gtk_clist_set_row_data(fe_filters_list,row,(gpointer)cpfil);
}
+ /* To make sure we have at least one item in the combo list */
+ fe_add_new_user_header("X-Mailer");
if (filter_errno!=FILTER_NOERR) {
filter_perror(filter_strerror(filter_errno));
gnome_dialog_close(fe_window);
diff -u /home/manu/prog/balsa-cvs/balsa/src/filter-edit.h balsa-test/src/filter-edit.h
--- /home/manu/prog/balsa-cvs/balsa/src/filter-edit.h Wed May 8 08:49:12 2002
+++ balsa-test/src/filter-edit.h Tue May 28 16:56:37 2002
@@ -47,9 +47,6 @@
GtkWidget *widget;
} option_list;
-/* Free filters associated with filters clist row */
-void fe_free_associated_filters(void);
-
/* destroy calback */
void fe_destroy_window_cb(GtkWidget *,gpointer);
@@ -77,9 +74,6 @@
/*op codes callback */
void fe_op_codes_toggled(GtkWidget * widget, gpointer data);
-/* Free copied conditions */
-void fe_free_associated_conditions(void);
-
/* Conditions callbacks */
void fe_conditions_select_row(GtkWidget * widget, gint row, gint column,
GdkEventButton * bevent, gpointer data);
@@ -90,4 +84,5 @@
void fe_action_selected(GtkWidget * widget, gpointer data);
void fe_enable_right_page(gboolean enabled);
+void fe_add_new_user_header(const gchar *);
#endif /*__FILTER_EDIT_H__ */
diff -u /home/manu/prog/balsa-cvs/balsa/src/filter-run-callbacks.c balsa-test/src/filter-run-callbacks.c
--- /home/manu/prog/balsa-cvs/balsa/src/filter-run-callbacks.c Sun Dec 16 10:29:21 2001
+++ balsa-test/src/filter-run-callbacks.c Tue May 28 16:56:37 2002
@@ -28,6 +28,7 @@
#include <gnome.h>
#include <string.h>
+
#include "mailbox-filter.h"
#include "filter-private.h"
#include "filter-funcs.h"
@@ -95,7 +96,8 @@
if (!filters_prepare_to_run(filters))
return FALSE;
gtk_clist_freeze(GTK_CLIST(balsa_app.mblist));
- if (filters_run_on_messages(filters,mbox->message_list))
+ libbalsa_filter_match_mailbox(filters,mbox);
+ if (libbalsa_filter_apply(filters))
enable_empty_trash(TRASH_FULL);
gtk_clist_thaw(GTK_CLIST(balsa_app.mblist));
g_slist_free(filters);
diff -u /home/manu/prog/balsa-cvs/balsa/src/sendmsg-window.c balsa-test/src/sendmsg-window.c
--- /home/manu/prog/balsa-cvs/balsa/src/sendmsg-window.c Wed May 29 19:21:08 2002
+++ balsa-test/src/sendmsg-window.c Tue May 28 16:56:28 2002
@@ -3516,6 +3516,9 @@
gboolean thereturn;
LibBalsaMessage *message;
+ if (!is_ready_to_send(bsmsg))
+ return;
+
message = bsmsg2message(bsmsg);
gtk_object_ref(GTK_OBJECT(message));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]