[PATCH (Experimental)] : find/find again for Balsa
- From: Emmanuel <e allaud wanadoo fr>
- To: balsa-list gnome org
- Subject: [PATCH (Experimental)] : find/find again for Balsa
- Date: Sun, 11 Nov 2001 14:14:15 +0100
Hi all,
here a patch that provides a find/find again capability to Balsa. Consider
it as a proof of concept or some sort :)
I mean that this patch may look as an ugly hack (and it is :), it is by no
mean in final state (in particular it touches a lot of files, and it'd be
better had a new source file to implement part of the patch).
But it works (at least for me).
You have to apply it AFTER filters-1.2.3-1.patch (bugzilla # 63459) (I
haven't posted it to bugzilla, it's too experimental for now).
Have fun
Comments welcome, like always. :)
Bye
Manu
diff -uN balsa-1.2.3-new/src/balsa-index.c balsa-1.2.3-dev/src/balsa-index.c
--- balsa-1.2.3-new/src/balsa-index.c Thu Nov 8 18:11:42 2001
+++ balsa-1.2.3-dev/src/balsa-index.c Sun Nov 11 13:28:49 2001
@@ -48,6 +48,10 @@
#include "sendmsg-window.h"
#include "store-address.h"
+#ifdef BALSA_SHOW_ALL
+#include "filter.h"
+#endif /* BALSA_SHOW_ALL */
+
/* constants */
#define BUFFER_SIZE 1024
@@ -97,7 +101,11 @@
gfloat row_align);
static GtkCTreeNode *balsa_index_find_node(BalsaIndex * bindex,
gboolean previous,
- LibBalsaMessageFlag flag);
+ LibBalsaMessageFlag flag
+#ifdef BALSA_SHOW_ALL
+ ,gint op,GSList * conditions
+#endif
+ );
static void balsa_index_transfer_messages(BalsaIndex * bindex,
LibBalsaMailbox * mailbox);
static void balsa_index_idle_remove(gpointer data);
@@ -511,7 +519,11 @@
balsa_index_set_first_new_message(BalsaIndex * bindex)
{
GtkCTreeNode *node =
- balsa_index_find_node(bindex, FALSE, LIBBALSA_MESSAGE_FLAG_NEW);
+ balsa_index_find_node(bindex, FALSE, LIBBALSA_MESSAGE_FLAG_NEW
+#ifdef BALSA_SHOW_ALL
+ , FILTER_NOOP, NULL
+#endif /* BALSA_SHOW_ALL */
+ );
if (node)
bindex->first_new_message =
LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data
@@ -528,6 +540,11 @@
GtkCTreeNode *next; /* returns first matching
after selection */
GtkCTreeNode *last; /* returns last matching */
+#ifdef BALSA_SHOW_ALL
+ gint conditions_op;
+ /* This list is not owned by the struct, so it is not its responsability to free it */
+ GSList * conditions;
+#endif /* BALSA_SHOW_ALL */
};
/*
@@ -932,12 +949,13 @@
} else {
LibBalsaMessage *message =
LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data(ctree, node));
- /* if we're not looking for flagged messages, we want only
+ /* if we're not looking for flagged messages or we are called by a search function, we want only
* viewable messages
* if we are looking for flagged messages, we want those
* that match, viewable or not */
- if ((b->flag == 0 && gtk_ctree_is_viewable(ctree, node))
- || (b->flag & message->flags)) {
+ if ((b->flag == 0 && !b->conditions && gtk_ctree_is_viewable(ctree, node))
+ || (b->flag & message->flags)
+ || (b->conditions && match_conditions(b->conditions_op,b->conditions,message))) {
if (b->first == NULL)
/* first matching message */
b->first = node;
@@ -978,7 +996,11 @@
*/
static GtkCTreeNode *
balsa_index_find_node(BalsaIndex * bindex, gboolean previous,
- LibBalsaMessageFlag flag)
+ LibBalsaMessageFlag flag
+#ifdef BALSA_SHOW_ALL
+ ,gint op,GSList * conditions
+#endif /* BALSA_SHOW_ALL */
+ )
{
GtkCTreeNode *node;
struct balsa_index_scan_info *bi;
@@ -990,6 +1012,10 @@
GTK_CLIST(bindex->ctree)->selection
? g_list_last(GTK_CLIST(bindex->ctree)->selection)->data : NULL;
bi->flag = flag;
+#ifdef BALSA_SHOW_ALL
+ bi->conditions_op=op;
+ bi->conditions=conditions;
+#endif /* BALSA_SHOW_ALL */
gtk_ctree_pre_recursive(bindex->ctree, NULL, (GtkCTreeFunc)
balsa_index_scan_node, bi);
node = previous ? bi->previous : bi->next;
@@ -1004,31 +1030,59 @@
void
balsa_index_select_next(BalsaIndex * bindex)
{
- balsa_index_select_node(bindex, balsa_index_find_node(bindex,
- FALSE, 0));
+ balsa_index_select_node(bindex,
+ balsa_index_find_node(bindex,
+ FALSE, 0
+#ifdef BALSA_SHOW_ALL
+ , FILTER_NOOP, NULL
+#endif /* BALSA_SHOW_ALL */
+ ));
}
void
balsa_index_select_previous(BalsaIndex * bindex)
{
- balsa_index_select_node(bindex, balsa_index_find_node(bindex,
- TRUE, 0));
+ balsa_index_select_node(bindex,
+ balsa_index_find_node(bindex,
+ TRUE, 0
+#ifdef BALSA_SHOW_ALL
+ , FILTER_NOOP, NULL
+#endif /* BALSA_SHOW_ALL */
+ ));
}
void
balsa_index_select_next_unread(BalsaIndex * bindex)
{
- balsa_index_select_node(bindex, balsa_index_find_node(bindex,
- FALSE, LIBBALSA_MESSAGE_FLAG_NEW));
+ balsa_index_select_node(bindex,
+ balsa_index_find_node(bindex,
+ FALSE, LIBBALSA_MESSAGE_FLAG_NEW
+#ifdef BALSA_SHOW_ALL
+ , FILTER_NOOP, NULL
+#endif /* BALSA_SHOW_ALL */
+ ));
}
void
balsa_index_select_next_flagged(BalsaIndex * bindex)
{
- balsa_index_select_node(bindex, balsa_index_find_node(bindex,
- FALSE, LIBBALSA_MESSAGE_FLAG_FLAGGED));
+ balsa_index_select_node(bindex,
+ balsa_index_find_node(bindex,
+ FALSE, LIBBALSA_MESSAGE_FLAG_FLAGGED
+#ifdef BALSA_SHOW_ALL
+ , FILTER_NOOP, NULL
+#endif /* BALSA_SHOW_ALL */
+ ));
+}
+
+#ifdef BALSA_SHOW_ALL
+
+void balsa_index_find(BalsaIndex * bindex,gint op,GSList * conditions,gboolean previous)
+{
+ balsa_index_select_node(bindex,balsa_index_find_node(bindex,previous,0,op,conditions));
}
+#endif /* BALSA_SHOW_ALL */
/* balsa_index_scan_selection:
* callback for pre-recursive search for next message after moving one
* or more message out of the mailbox
diff -uN balsa-1.2.3-new/src/balsa-index.h balsa-1.2.3-dev/src/balsa-index.h
--- balsa-1.2.3-new/src/balsa-index.h Thu Nov 8 18:11:42 2001
+++ balsa-1.2.3-dev/src/balsa-index.h Sun Nov 11 08:57:05 2001
@@ -101,6 +101,10 @@
void balsa_index_select_previous(BalsaIndex *);
void balsa_index_select_row(BalsaIndex * bindex, gint row);
+#ifdef BALSA_SHOW_ALL
+ void balsa_index_find(BalsaIndex * bindex,gint op,GSList * conditions,gboolean previous);
+#endif /* BALSA_SHOW_ALL */
+
/* retrieve the selection */
void balsa_index_get_selected_rows(BalsaIndex * bindex,
GtkCTreeNode *** rows,
diff -uN balsa-1.2.3-new/src/filter-run-callbacks.c balsa-1.2.3-dev/src/filter-run-callbacks.c
--- balsa-1.2.3-new/src/filter-run-callbacks.c Thu Nov 8 18:13:05 2001
+++ balsa-1.2.3-dev/src/filter-run-callbacks.c Sun Nov 11 12:59:05 2001
@@ -145,6 +145,7 @@
case 0: /* Apply button */
if (!run_filters_on_mailbox(p->selected_filters,p->mbox))
balsa_information(LIBBALSA_INFORMATION_ERROR,_("Error when applying filters"));
+ enable_empty_trash(TRASH_CHECK);
return;
case 1: /* OK button */
save_filters(p);
diff -uN balsa-1.2.3-new/src/filter-run-dialog.c balsa-1.2.3-dev/src/filter-run-dialog.c
--- balsa-1.2.3-new/src/filter-run-dialog.c Thu Nov 8 18:13:05 2001
+++ balsa-1.2.3-dev/src/filter-run-dialog.c Sun Nov 11 12:46:18 2001
@@ -256,7 +256,6 @@
| \---/ | \---/ |
\-----------------/
*/
-
gnome_dialog_append_buttons(GNOME_DIALOG(p),
GNOME_STOCK_BUTTON_APPLY,
GNOME_STOCK_BUTTON_OK,
diff -uN balsa-1.2.3-new/src/main-window.c balsa-1.2.3-dev/src/main-window.c
--- balsa-1.2.3-new/src/main-window.c Thu Nov 8 18:13:05 2001
+++ balsa-1.2.3-dev/src/main-window.c Sun Nov 11 14:03:40 2001
@@ -58,6 +58,11 @@
#include "threads.h"
#endif
+#ifdef BALSA_SHOW_ALL
+#include "filter.h"
+#include "filter-funcs.h"
+#endif
+
#include "libinit_balsa/init_balsa.h"
#define MAILBOX_DATA "mailbox_data"
@@ -200,6 +205,9 @@
static void select_part_cb(BalsaMessage * bm, gpointer data);
#ifdef BALSA_SHOW_ALL
+static void find_real(BalsaIndex * bindex,gboolean again);
+static void find_cb(GtkWidget * widget, gpointer data);
+static void find_again_cb(GtkWidget * widget, gpointer data);
static void filter_dlg_cb(GtkWidget * widget, gpointer data);
static void filter_export_cb(GtkWidget * widget, gpointer data);
#endif
@@ -332,10 +340,11 @@
GNOMEUIINFO_SEPARATOR,
#define MENU_FILE_ADDRESS_POS 9
{
- GNOME_APP_UI_ITEM, N_("_Address Book..."),
- N_("Open the address book"),
- address_book_cb, NULL, NULL, GNOME_APP_PIXMAP_STOCK,
- GNOME_STOCK_MENU_BOOK_RED, 'B', 0, NULL},
+ GNOME_APP_UI_ITEM, N_("_Address Book..."),
+ N_("Open the address book"),
+ address_book_cb, NULL, NULL, GNOME_APP_PIXMAP_STOCK,
+ GNOME_STOCK_MENU_BOOK_RED, 'B', 0, NULL
+ },
GNOMEUIINFO_SEPARATOR,
GNOMEUIINFO_MENU_EXIT_ITEM(balsa_quit_nicely, NULL),
@@ -344,21 +353,21 @@
static GnomeUIInfo edit_menu[] = {
/* FIXME: Features to hook up... */
- /* GNOMEUIINFO_MENU_UNDO_ITEM(NULL, NULL); */
- /* GNOMEUIINFO_MENU_REDO_ITEM(NULL, NULL); */
+ /* GNOMEUIINFO_MENU_UNDO_ITEM(NULL, NULL), */
+ /* GNOMEUIINFO_MENU_REDO_ITEM(NULL, NULL), */
/* GNOMEUIINFO_SEPARATOR, */
#define MENU_EDIT_COPY_POS 0
GNOMEUIINFO_MENU_COPY_ITEM(copy_cb, NULL),
#define MENU_EDIT_SELECT_ALL_POS 1
GNOMEUIINFO_MENU_SELECT_ALL_ITEM(select_all_cb, NULL),
- /* GNOMEUINFO_SEPARATOR, */
- /* GNOMEUIINFO_MENU_FIND_ITEM(NULL, NULL); */
- /* GNOMEUIINFO_MENU_FIND_AGAIN_ITEM(NULL, NULL); */
+#ifdef BALSA_SHOW_ALL
+ GNOMEUIINFO_SEPARATOR,
+ GNOMEUIINFO_MENU_FIND_ITEM(find_cb, NULL),
+ GNOMEUIINFO_MENU_FIND_AGAIN_ITEM(find_again_cb, NULL),
/* GNOMEUIINFO_MENU_REPLACE_ITEM(NULL, NULL); */
/* GNOMEUIINFO_SEPARATOR, */
/* #define MENU_EDIT_PREFERENCES_POS 3 */
/* GNOMEUIINFO_MENU_PREFERENCES_ITEM(open_preferences_manager, NULL), */
-#ifdef BALSA_SHOW_ALL
GNOMEUIINFO_SEPARATOR,
GNOMEUIINFO_ITEM_STOCK(N_("_Filters..."), N_("Manage filters"),
filter_dlg_cb, GNOME_STOCK_MENU_PROP),
@@ -2539,11 +2548,182 @@
}
#ifdef BALSA_SHOW_ALL
+
+static void
+find_real(BalsaIndex * bindex,gboolean again)
+{
+ /* FIXME : later we could do a search based on a complete filter */
+ static filter * f=NULL;
+ /* Condition set up for the search, it will be of type CONDITION_NONE if nothing has been set up */
+ static condition * cnd=NULL;
+ GSList * conditions;
+ static gboolean reverse=FALSE;
+
+ if (!cnd) {
+ cnd=condition_new();
+ if (!cnd) {
+ balsa_information(LIBBALSA_INFORMATION_ERROR,_("Not enough memory"));
+ return;
+ }
+ cnd->type=CONDITION_NONE;
+ }
+
+ /* first search, so set up the match rule(s) */
+ if (!again || (!f && cnd->type==CONDITION_NONE)) {
+ GnomeDialog * dia=GNOME_DIALOG(gnome_dialog_new(_("Search a message"),
+ GNOME_STOCK_BUTTON_OK,
+ GNOME_STOCK_BUTTON_CANCEL,
+ NULL));
+ GtkWidget * reverse_button,* search_entry, *w,* page, *table;
+ GtkWidget * matching_fields_body, *matching_fields_from,* matching_fields_to;
+ GtkWidget * matching_fields_cc,* matching_fields_subject;
+ gint ok;
+
+ gnome_dialog_close_hides(dia,TRUE);
+ /* FIXME : we'll set up this callback later when selecting filters has been enabled
+ gtk_signal_connect(GTK_OBJECT(dia),"clicked",find_dialog_button_cb,&f);
+ */
+ reverse_button = gtk_check_button_new_with_label(_("Reverse search"));
+
+ page=gtk_table_new(2, 1, FALSE);
+ w = gtk_label_new(_("Search for:"));
+ gtk_table_attach(GTK_TABLE(page),w,0, 1, 0, 1,
+ GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
+ search_entry = gtk_entry_new_with_max_length(30);
+ gtk_table_attach(GTK_TABLE(page),search_entry,1, 2, 0, 1,
+ GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
+ gtk_box_pack_start(GTK_BOX(dia->vbox), page, FALSE, FALSE, 2);
+
+ /* builds the toggle buttons to specify fields concerned by the search */
+ page = gtk_table_new(3, 7, FALSE);
+
+ w = gtk_frame_new(_("In:"));
+ gtk_frame_set_label_align(GTK_FRAME(w), GTK_POS_LEFT, GTK_POS_TOP);
+ gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_ETCHED_IN);
+ gtk_table_attach(GTK_TABLE(page),
+ w,
+ 0, 3, 0, 2,
+ GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 5, 5);
+
+ table = gtk_table_new(3, 3, TRUE);
+ gtk_container_add(GTK_CONTAINER(w), table);
+
+ matching_fields_body = gtk_check_button_new_with_label(_("Body"));
+ gtk_table_attach(GTK_TABLE(table),
+ matching_fields_body,
+ 0, 1, 0, 1,
+ GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
+ matching_fields_to = gtk_check_button_new_with_label(_("To:"));
+ gtk_table_attach(GTK_TABLE(table),
+ matching_fields_to,
+ 1, 2, 0, 1,
+ GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
+ matching_fields_from = gtk_check_button_new_with_label(_("From:"));
+ gtk_table_attach(GTK_TABLE(table),
+ matching_fields_from,
+ 1, 2, 1, 2,
+ GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
+ matching_fields_subject = gtk_check_button_new_with_label(_("Subject"));
+ gtk_table_attach(GTK_TABLE(table),
+ matching_fields_subject,
+ 2, 3, 0, 1,
+ GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
+ matching_fields_cc = gtk_check_button_new_with_label(_("Cc:"));
+ gtk_table_attach(GTK_TABLE(table),
+ matching_fields_cc,
+ 2, 3, 1, 2,
+ GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
+ gtk_box_pack_start(GTK_BOX(dia->vbox), page, FALSE, FALSE, 2);
+
+ gtk_box_pack_start(GTK_BOX(dia->vbox), gtk_hseparator_new(), FALSE, FALSE, 2);
+ gtk_box_pack_start(GTK_BOX(dia->vbox), reverse_button,TRUE,TRUE,0);
+ gtk_widget_show_all(dia->vbox);
+
+ if (cnd->match.string)
+ gtk_entry_set_text(GTK_ENTRY(search_entry),cnd->match.string);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(reverse_button),reverse);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matching_fields_body),
+ CONDITION_CHKMATCH(cnd,CONDITION_MATCH_BODY));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matching_fields_to),
+ CONDITION_CHKMATCH(cnd,CONDITION_MATCH_TO));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matching_fields_from),
+ CONDITION_CHKMATCH(cnd,CONDITION_MATCH_FROM));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matching_fields_subject),
+ CONDITION_CHKMATCH(cnd,CONDITION_MATCH_SUBJECT));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matching_fields_cc),
+ CONDITION_CHKMATCH(cnd,CONDITION_MATCH_CC));
+
+ do {
+ ok=gnome_dialog_run(dia);
+ if (ok==0) {
+ reverse=GTK_TOGGLE_BUTTON(reverse_button)->active;
+ g_free(cnd->match.string);
+ cnd->match.string=g_strdup(gtk_entry_get_text(GTK_ENTRY(search_entry)));
+ cnd->match_fields=CONDITION_EMPTY;
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(matching_fields_body)))
+ CONDITION_SETMATCH(cnd,CONDITION_MATCH_BODY);
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(matching_fields_to)))
+ CONDITION_SETMATCH(cnd,CONDITION_MATCH_TO);
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(matching_fields_subject)))
+ CONDITION_SETMATCH(cnd,CONDITION_MATCH_SUBJECT);
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(matching_fields_from)))
+ CONDITION_SETMATCH(cnd,CONDITION_MATCH_FROM);
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(matching_fields_cc)))
+ CONDITION_SETMATCH(cnd,CONDITION_MATCH_CC);
+ if (cnd->match_fields!=CONDITION_EMPTY && cnd->match.string[0])
+ /* FIXME : We should print error messages, but for that we should first make find dialog non-modal
+ * balsa_information(LIBBALSA_INFORMATION_ERROR,_("You must specify at least one field to look in"));
+ *balsa_information(LIBBALSA_INFORMATION_ERROR,_("You must provide a non-empty string")); */
+ ok=1;
+ else ok=-1;
+ }
+ else ok=-1;
+ }
+ while (ok==0);
+ gtk_widget_destroy(GTK_WIDGET(dia));
+ /* Here ok==1 means OK button was pressed, search is valid so let's go
+ * else cancel was pressed return */
+ if (ok!=1) return;
+ cnd->type=CONDITION_SIMPLE;
+ }
+
+ if (f) {
+ GSList * lst=g_slist_append(NULL,f);
+ if (!filters_prepare_to_run(lst)) return;
+ g_slist_free(lst);
+ conditions=f->conditions;
+ }
+ else conditions=g_slist_append(NULL,cnd);
+
+ balsa_index_find(bindex,f ? f->conditions_op : FILTER_OP_OR,conditions,reverse);
+
+ /* FIXME : See if this does not lead to a segfault because of balsa_index_scan_info */
+ if (!f) g_slist_free(conditions);
+}
+
+static void
+find_cb(GtkWidget * widget,gpointer data)
+{
+ GtkWidget * bindex;
+ if ((bindex=balsa_window_find_current_index(BALSA_WINDOW(data))))
+ find_real(BALSA_INDEX(bindex),FALSE);
+}
+
+static void
+find_again_cb(GtkWidget * widget,gpointer data)
+{
+ GtkWidget * bindex;
+ if ((bindex=balsa_window_find_current_index(BALSA_WINDOW(data))))
+ find_real(BALSA_INDEX(bindex),TRUE);
+}
+
static void
filter_dlg_cb(GtkWidget * widget, gpointer data)
{
filters_edit_dialog();
}
+
static void
filter_export_cb(GtkWidget * widget, gpointer data)
{
Common subdirectories: balsa-1.2.3-new/src/pixmaps and balsa-1.2.3-dev/src/pixmaps
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]