2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2002 Hiroyuki Yamamoto
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #include <gtk/gtkoptionmenu.h>
29 #include <gdk/gdkkeysyms.h>
39 #include "prefs_matcher.h"
40 #include "prefs_filtering.h"
41 #include "prefs_common.h"
42 #include "prefs_account.h"
44 #include "mainwindow.h"
45 #include "foldersel.h"
46 #include "manage_window.h"
47 #include "stock_pixmap.h"
51 #include "alertpanel.h"
54 #include "filtering.h"
55 #include "matcher_parser.h"
56 #include "selective_download.h"
57 #include "procheader.h"
63 GtkWidget *btn_getmail;
64 GtkWidget *btn_remove;
67 GtkWidget *label_account_name;
68 GtkWidget *label_mails;
71 GSList *header_item_list = NULL;
73 static GdkPixmap *checkboxonxpm;
74 static GdkPixmap *checkboxonxpmmask;
75 static GdkPixmap *checkboxoffxpm;
76 static GdkPixmap *checkboxoffxpmmask;
78 static void sd_window_create(MainWindow *mainwin);
79 static void sd_clist_set();
80 static void sd_remove_header_files();
83 void selective_download(MainWindow *mainwin)
85 PrefsAccount *account = cur_account;
87 summary_write_cache(mainwin->summaryview);
88 main_window_lock(mainwin);
90 sd_remove_header_files();
92 header_item_list = NULL;
94 sd_window_create(mainwin);
96 stock_pixmap_gdk(selective.clist, STOCK_PIXMAP_CHECKBOX_OFF,
97 &checkboxoffxpm, &checkboxoffxpmmask);
98 stock_pixmap_gdk(selective.clist, STOCK_PIXMAP_CHECKBOX_ON,
99 &checkboxonxpm, &checkboxonxpmmask);
101 gtk_label_set_text(GTK_LABEL(selective.label_account_name), account->account_name);
105 /* sd_remove_header_files()
107 * - removes any stale header files in HEADER_CACHE_DIR
110 static void sd_remove_header_files()
112 gchar *path = g_strconcat(get_header_cache_dir(), G_DIR_SEPARATOR_S, NULL);
114 remove_all_files(path);
119 /* sd_toggle_btn_remove()
121 * - checks whether at least on email is selected for deletion
122 * if so, untoggle remove button
124 static gboolean sd_toggle_btn_remove()
131 for (cur = header_item_list; cur != NULL; cur = cur->next) {
132 HeaderItems *item = (HeaderItems*)cur->data;
134 if (item->state == CHECKED) {
135 gtk_widget_set_sensitive (selective.btn_remove, TRUE);
141 gtk_widget_set_sensitive (selective.btn_remove, FALSE);
146 /* sd_header_filter(MsgInfo *msginfo)
148 * - parse header line and look for any applying filtering rules
149 * - if message matches other MATCHACTION --> return
152 gboolean sd_header_filter(MsgInfo *msginfo)
156 /* parse header line for line */
157 for (rules = global_processing; rules != NULL; rules = rules->next) {
159 FilteringProp *prop = (FilteringProp*) rules->data;
160 gchar line[POPBUFSIZE];
162 if ( matcherlist_match(prop->matchers, msginfo) ) {
163 if (prop->action->type == MATCHACTION_DELETE_ON_SERVER) {
175 /* sd_get_msginfo_from_file(const gchar *filename)
177 * - retrieve msginfo from saved header files
179 MsgInfo *sd_get_msginfo_from_file(const gchar *filename)
183 MsgInfo *msginfo = g_new0(MsgInfo, 1);
184 MsgFlags msgflags = { 0, 0 };
186 msginfo = (MsgInfo*) procheader_parse(filename, msgflags, TRUE, FALSE);
187 if ( (fp = fopen(filename, "r")) != NULL ) {
188 static HeaderEntry hentry[] = { { SIZE_HEADER, NULL, FALSE},
189 { NULL, NULL, FALSE} };
191 procheader_get_one_field (buf, sizeof(buf), fp, hentry);
196 msginfo->size = (off_t)atoi(buf + SIZE_HEADER_LEN);
206 * - fill clist and set toggle button accordingly
212 gchar *path = g_strconcat(get_header_cache_dir(), G_DIR_SEPARATOR_S, NULL);
213 gchar *filename = g_strdup_printf("%s%i", path, index);
215 while ( is_file_exist(filename) ) {
217 MsgInfo *msginfo = sd_get_msginfo_from_file(filename);
218 HeaderItems *line = g_new0 (HeaderItems, 1);
225 row[1] = line->from = msginfo->from;
226 row[2] = line->subject = msginfo->subject;
227 row[3] = line->size = to_human_readable(msginfo->size);
229 gtk_clist_append (GTK_CLIST(selective.clist), row);
231 msginfo->folder = folder_get_default_processing();
233 /* move msg file to drop folder */
234 if ((msginfo->msgnum = folder_item_add_msg(msginfo->folder,
235 filename, TRUE)) < 0) {
240 if (sd_header_filter(msginfo)) {
241 line->state = CHECKED;
242 gtk_clist_set_pixmap (GTK_CLIST (selective.clist), index - 1, 0,
243 checkboxonxpm, checkboxonxpmmask);
246 line->state = UNCHECKED;
247 gtk_clist_set_pixmap (GTK_CLIST (selective.clist), index - 1, 0,
248 checkboxoffxpm, checkboxoffxpmmask);
251 folder_item_remove_msg(msginfo->folder, msginfo->msgnum);
253 header_item_list = g_slist_append(header_item_list, line);
256 filename = g_strdup_printf("%s%i", path, index);
259 sd_toggle_btn_remove();
266 /* --- Callbacks -- */
267 static void sd_btn_remove_cb()
270 PrefsAccount *account = cur_account;
271 gboolean enable_dele = FALSE;
273 account->to_delete = NULL;
275 /* loop through list collecting mails marked for delete */
276 for (cur = header_item_list; cur != NULL; cur = cur->next) {
278 HeaderItems *items = (HeaderItems*)cur->data;
280 if (items->state == CHECKED) {
283 /* replace deleted Mail */
285 row[1] = items->from;
286 row[2] = items->subject;
287 row[3] = items->size;
289 account->to_delete = g_slist_append(account->to_delete,
290 GINT_TO_POINTER(items->index));
292 gtk_clist_remove(GTK_CLIST(selective.clist), items->index-1);
293 gtk_clist_insert(GTK_CLIST(selective.clist), items->index-1, row);
294 gtk_clist_set_selectable(GTK_CLIST(selective.clist),
295 items->index - 1, FALSE);
297 debug_print(_("marked to delete %i\n"),
300 items->state = UNCHECKED;
305 if (enable_dele == TRUE) {
306 inc_selective_download(selective.mainwin, DELE_HEADER);
309 sd_toggle_btn_remove();
311 g_slist_free(account->to_delete);
312 account->to_delete = NULL;
315 static void sd_btn_receive_cb()
318 manage_window_focus_in(selective.window, NULL, NULL);
320 inc_selective_download(selective.mainwin, RETR_HEADER);
322 gtk_clist_clear(GTK_CLIST(selective.clist));
326 static void sd_btn_done_cb()
328 sd_remove_header_files();
330 if (header_item_list)
331 slist_free_strings (header_item_list);
333 gtk_widget_hide(selective.window);
334 main_window_unlock(selective.mainwin);
337 static void sd_select_row_cb(GtkCList *clist, gint row, gint column,
338 GdkEvent *event, gpointer user_data)
341 if ((row >= 0) && (column >= 0)) {
342 HeaderItems *item = (HeaderItems*) g_slist_nth_data (header_item_list, row);
345 if (!gtk_clist_get_selectable(GTK_CLIST(selective.clist), row)) return;
347 if (item->state == UNCHECKED) {
348 item->state = CHECKED;
349 gtk_clist_set_pixmap (GTK_CLIST (selective.clist), row, 0,
350 checkboxonxpm, checkboxonxpmmask);
352 item->state = UNCHECKED;
353 gtk_clist_set_pixmap (GTK_CLIST (selective.clist), row, 0,
354 checkboxoffxpm, checkboxoffxpmmask);
356 sd_toggle_btn_remove();
360 static void sd_window_create(MainWindow *mainwin)
364 GtkWidget *label_mails;
365 GtkWidget *hbox_bottom;
366 GtkWidget *label_fixed;
367 GtkWidget *label_account_name;
368 GtkWidget *scrolledwindow;
370 GtkWidget *label_state;
371 GtkWidget *label_from;
372 GtkWidget *label_subject;
373 GtkWidget *label_size;
374 GtkWidget *hbox_toolbar;
376 GtkWidget *btn_receive;
377 GtkWidget *tmp_toolbar_icon;
378 GtkWidget *btn_remove;
381 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
382 gtk_object_set_data (GTK_OBJECT (window), "window", window);
383 gtk_window_set_title (GTK_WINDOW (window), _("Selective Download"));
384 gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
385 gtk_window_set_default_size (GTK_WINDOW (window), 450, 250);
387 table = gtk_table_new (2, 2, FALSE);
388 gtk_widget_ref (table);
389 gtk_object_set_data_full (GTK_OBJECT (window), "table", table,
390 (GtkDestroyNotify) gtk_widget_unref);
391 gtk_widget_show (table);
392 gtk_container_add (GTK_CONTAINER (window), table);
394 label_mails = gtk_label_new (_("0 Mail(s)"));
395 gtk_widget_ref (label_mails);
396 gtk_object_set_data_full (GTK_OBJECT (window), "label_mails", label_mails,
397 (GtkDestroyNotify) gtk_widget_unref);
398 gtk_widget_show (label_mails);
399 gtk_table_attach (GTK_TABLE (table), label_mails, 1, 2, 1, 2,
400 (GtkAttachOptions) (GTK_FILL),
401 (GtkAttachOptions) (0), 0, 0);
402 gtk_misc_set_alignment (GTK_MISC (label_mails), 0, 0.5);
404 hbox_bottom = gtk_hbox_new (FALSE, 0);
405 gtk_widget_ref (hbox_bottom);
406 gtk_object_set_data_full (GTK_OBJECT (window), "hbox_bottom", hbox_bottom,
407 (GtkDestroyNotify) gtk_widget_unref);
408 gtk_widget_show (hbox_bottom);
409 gtk_table_attach (GTK_TABLE (table), hbox_bottom, 0, 1, 1, 2,
410 (GtkAttachOptions) (GTK_FILL),
411 (GtkAttachOptions) (GTK_FILL), 0, 0);
413 label_fixed = gtk_label_new (_("current Account:"));
414 gtk_widget_ref (label_fixed);
415 gtk_object_set_data_full (GTK_OBJECT (window), "label_fixed", label_fixed,
416 (GtkDestroyNotify) gtk_widget_unref);
417 gtk_widget_show (label_fixed);
418 gtk_box_pack_start (GTK_BOX (hbox_bottom), label_fixed, FALSE, FALSE, 0);
420 label_account_name = gtk_label_new (_("none"));
421 gtk_widget_ref (label_account_name);
422 gtk_object_set_data_full (GTK_OBJECT (window), "label_account_name", label_account_name,
423 (GtkDestroyNotify) gtk_widget_unref);
424 gtk_widget_show (label_account_name);
425 gtk_box_pack_start (GTK_BOX (hbox_bottom), label_account_name, TRUE, FALSE, 0);
427 scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
428 gtk_widget_ref (scrolledwindow);
429 gtk_object_set_data_full (GTK_OBJECT (window), "scrolledwindow", scrolledwindow,
430 (GtkDestroyNotify) gtk_widget_unref);
431 gtk_widget_show (scrolledwindow);
432 gtk_table_attach (GTK_TABLE (table), scrolledwindow, 0, 1, 0, 1,
433 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
434 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
435 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
437 clist = gtk_clist_new (4);
438 gtk_widget_ref (clist);
439 gtk_object_set_data_full (GTK_OBJECT (window), "clist", clist,
440 (GtkDestroyNotify) gtk_widget_unref);
441 gtk_widget_show (clist);
442 gtk_container_add (GTK_CONTAINER (scrolledwindow), clist);
443 gtk_container_set_border_width (GTK_CONTAINER (clist), 5);
444 gtk_clist_set_column_width (GTK_CLIST (clist), 0, 21);
445 gtk_clist_set_column_width (GTK_CLIST (clist), 1, 143);
446 gtk_clist_set_column_width (GTK_CLIST (clist), 2, 158);
447 gtk_clist_set_column_width (GTK_CLIST (clist), 3, 15);
448 gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_BROWSE);
449 gtk_clist_column_titles_show (GTK_CLIST (clist));
451 label_state = gtk_label_new (_("#"));
452 gtk_widget_ref (label_state);
453 gtk_object_set_data_full (GTK_OBJECT (window), "label_state", label_state,
454 (GtkDestroyNotify) gtk_widget_unref);
455 gtk_widget_show (label_state);
456 gtk_clist_set_column_widget (GTK_CLIST (clist), 0, label_state);
458 label_from = gtk_label_new (_("From"));
459 gtk_widget_ref (label_from);
460 gtk_object_set_data_full (GTK_OBJECT (window), "label_from", label_from,
461 (GtkDestroyNotify) gtk_widget_unref);
462 gtk_widget_show (label_from);
463 gtk_clist_set_column_widget (GTK_CLIST (clist), 1, label_from);
465 label_subject = gtk_label_new (_("Subject"));
466 gtk_widget_ref (label_subject);
467 gtk_object_set_data_full (GTK_OBJECT (window), "label_subject", label_subject,
468 (GtkDestroyNotify) gtk_widget_unref);
469 gtk_widget_show (label_subject);
470 gtk_clist_set_column_widget (GTK_CLIST (clist), 2, label_subject);
472 label_size = gtk_label_new (_("Size"));
473 gtk_widget_ref (label_size);
474 gtk_object_set_data_full (GTK_OBJECT (window), "label_size", label_size,
475 (GtkDestroyNotify) gtk_widget_unref);
476 gtk_widget_show (label_size);
477 gtk_clist_set_column_widget (GTK_CLIST (clist), 3, label_size);
479 hbox_toolbar = gtk_hbox_new (FALSE, 0);
480 gtk_widget_ref (hbox_toolbar);
481 gtk_object_set_data_full (GTK_OBJECT (window), "hbox_toolbar", hbox_toolbar,
482 (GtkDestroyNotify) gtk_widget_unref);
483 gtk_widget_show (hbox_toolbar);
484 gtk_table_attach (GTK_TABLE (table), hbox_toolbar, 1, 2, 0, 1,
485 (GtkAttachOptions) (GTK_FILL),
486 (GtkAttachOptions) (GTK_FILL), 0, 0);
488 toolbar = gtk_toolbar_new (GTK_ORIENTATION_VERTICAL, GTK_TOOLBAR_BOTH);
489 gtk_widget_ref (toolbar);
490 gtk_object_set_data_full (GTK_OBJECT (window), "toolbar", toolbar,
491 (GtkDestroyNotify) gtk_widget_unref);
492 gtk_widget_show (toolbar);
493 gtk_box_pack_start (GTK_BOX (hbox_toolbar), toolbar, FALSE, FALSE, 0);
494 gtk_toolbar_set_space_size (GTK_TOOLBAR (toolbar), 20);
495 gtk_toolbar_set_space_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_SPACE_LINE);
497 tmp_toolbar_icon = stock_pixmap_widget(hbox_toolbar, STOCK_PIXMAP_MAIL_RECEIVE);
498 btn_receive = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
499 GTK_TOOLBAR_CHILD_BUTTON,
502 _("preview E-Mail"), NULL,
503 tmp_toolbar_icon, NULL, NULL);
504 gtk_widget_ref (btn_receive);
505 gtk_object_set_data_full (GTK_OBJECT (window), "btn_receive", btn_receive,
506 (GtkDestroyNotify) gtk_widget_unref);
507 gtk_widget_show (btn_receive);
509 gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
511 tmp_toolbar_icon = stock_pixmap_widget(hbox_toolbar, STOCK_PIXMAP_CONTINUE);
512 btn_remove = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
513 GTK_TOOLBAR_CHILD_BUTTON,
516 _("remove selected E-Mails"), NULL,
517 tmp_toolbar_icon, NULL, NULL);
518 gtk_widget_ref (btn_remove);
519 gtk_object_set_data_full (GTK_OBJECT (window), "btn_remove", btn_remove,
520 (GtkDestroyNotify) gtk_widget_unref);
521 gtk_widget_set_sensitive (btn_remove, FALSE);
523 gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
525 tmp_toolbar_icon = stock_pixmap_widget (hbox_toolbar, STOCK_PIXMAP_CLOSE);
526 btn_done = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
527 GTK_TOOLBAR_CHILD_BUTTON,
530 _("Exit Dialog"), NULL,
531 tmp_toolbar_icon, NULL, NULL);
532 gtk_widget_ref (btn_done);
533 gtk_object_set_data_full (GTK_OBJECT (window), "btn_done", btn_done,
534 (GtkDestroyNotify) gtk_widget_unref);
535 gtk_widget_show (btn_done);
537 gtk_signal_connect (GTK_OBJECT (window), "destroy",
538 GTK_SIGNAL_FUNC (sd_btn_done_cb),
540 gtk_signal_connect (GTK_OBJECT (btn_receive), "clicked",
541 GTK_SIGNAL_FUNC (sd_btn_receive_cb),
543 gtk_signal_connect (GTK_OBJECT (btn_remove), "clicked",
544 GTK_SIGNAL_FUNC (sd_btn_remove_cb),
546 gtk_signal_connect (GTK_OBJECT (btn_done), "clicked",
547 GTK_SIGNAL_FUNC (sd_btn_done_cb),
549 gtk_signal_connect (GTK_OBJECT (clist), "select_row",
550 GTK_SIGNAL_FUNC (sd_select_row_cb),
555 selective.mainwin = mainwin;
556 selective.window = window;
557 selective.btn_remove = btn_remove;
558 selective.btn_done = btn_done;
559 selective.clist = clist;
560 selective.label_account_name = label_account_name;
561 selective.label_mails = label_mails;
563 gtk_widget_show_all(window);