/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2006 Hiroyuki Yamamoto and the Claws Mail team
+ * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
*
* 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
#include "sourcewindow.h"
#include "prefs_common.h"
#include "prefs_summary_column.h"
+#include "prefs_summary_open.h"
#include "prefs_filtering.h"
#include "account.h"
#include "compose.h"
#include "folderutils.h"
#include "quicksearch.h"
#include "partial_download.h"
+#include "tags.h"
#include "timing.h"
#include "gedit-print.h"
#include "log.h"
+#include "edittags.h"
#include "manual.h"
#define SUMMARY_COL_MARK_WIDTH 10
static void summary_set_column_titles (SummaryView *summaryview);
static void summary_set_ctree_from_list (SummaryView *summaryview,
GSList *mlist);
-static void summary_set_header (SummaryView *summaryview,
+static inline void summary_set_header (SummaryView *summaryview,
gchar *text[],
MsgInfo *msginfo);
static void summary_display_msg (SummaryView *summaryview,
static void summary_set_row_marks (SummaryView *summaryview,
GtkCTreeNode *row);
+static gboolean summary_set_row_tag (SummaryView *summaryview,
+ GtkCTreeNode *row,
+ gboolean refresh,
+ gboolean set,
+ gint id);
/* message handling */
static void summary_mark_row (SummaryView *summaryview,
GtkCTreeNode *row);
gpointer data);
static void summary_colorlabel_menu_create(SummaryView *summaryview,
gboolean refresh);
+static void summary_tags_menu_item_activate_cb
+ (GtkWidget *widget,
+ gpointer data);
+static void summary_tags_menu_item_activate_item_cb
+ (GtkMenuItem *label_menu_item,
+ gpointer data);
+static void summary_tags_menu_create(SummaryView *summaryview,
+ gboolean refresh);
static GtkWidget *summary_ctree_create (SummaryView *summaryview);
static gint summary_toggle_pressed (GtkWidget *eventbox,
GdkEventButton *event,
SummaryView *summaryview);
+#ifdef MAEMO
+static void summary_toggle_multiple_pressed
+ (GtkWidget *widget,
+ SummaryView *summaryview);
+#endif
+static gint summary_folder_eventbox_pressed
+ (GtkWidget *eventbox,
+ GdkEventButton *event,
+ SummaryView *summaryview);
static gboolean summary_button_pressed (GtkWidget *ctree,
GdkEventButton *event,
SummaryView *summaryview);
static gboolean summary_key_pressed (GtkWidget *ctree,
GdkEventKey *event,
SummaryView *summaryview);
-static void summary_open_row (GtkSCTree *sctree,
- SummaryView *summaryview);
static void summary_tree_expanded (GtkCTree *ctree,
GtkCTreeNode *node,
SummaryView *summaryview);
SummaryView *summaryview);
static void summary_locked_clicked (GtkWidget *button,
SummaryView *summaryview);
+static void summary_tags_clicked (GtkWidget *button,
+ SummaryView *summaryview);
static void summary_start_drag (GtkWidget *widget,
int button,
gint y,
guint time,
SummaryView *summaryview);
-
+static void summary_drag_end(GtkWidget *widget,
+ GdkDragContext *drag_context,
+ SummaryView *summaryview);
/* custom compare functions for sorting */
static gint summary_cmp_by_mark (GtkCList *clist,
static gint summary_cmp_by_date (GtkCList *clist,
gconstpointer ptr1,
gconstpointer ptr2);
+static gint summary_cmp_by_thread_date (GtkCList *clist,
+ gconstpointer ptr1,
+ gconstpointer ptr2);
static gint summary_cmp_by_from (GtkCList *clist,
gconstpointer ptr1,
gconstpointer ptr2);
static gint summary_cmp_by_locked (GtkCList *clist,
gconstpointer ptr1,
gconstpointer ptr2);
+static gint summary_cmp_by_tags (GtkCList *clist,
+ gconstpointer ptr1,
+ gconstpointer ptr2);
static void quicksearch_execute_cb (QuickSearch *quicksearch,
gpointer data);
MsgInfo *msg);
static gboolean summary_update_msg (gpointer source, gpointer data);
-static gboolean summary_update_folder_item_name(gpointer source, gpointer data);
+static gboolean summary_update_folder_item_hook(gpointer source, gpointer data);
+static gboolean summary_update_folder_hook(gpointer source, gpointer data);
GtkTargetEntry summary_drag_types[2] =
{
{N_("/_Mark/Lock"), NULL, summary_msgs_lock, 0, NULL},
{N_("/_Mark/Unlock"), NULL, summary_msgs_unlock, 0, NULL},
{N_("/Color la_bel"), NULL, NULL, 0, NULL},
+ {N_("/Ta_gs"), NULL, NULL, 0, NULL},
{"/---", NULL, NULL, 0, "<Separator>"},
{N_("/Add sender to address boo_k"),
N_("#"), /* S_COL_NUMBER */
N_("Score"), /* S_COL_SCORE */
"", /* S_COL_LOCKED */
+ N_("Tags"), /* S_COL_TAGS */
};
void summary_freeze(SummaryView *summaryview)
GtkWidget *ctree;
GtkWidget *hbox;
GtkWidget *hbox_l;
+ GtkWidget *stat_box;
+ GtkWidget *stat_box2;
+ GtkWidget *stat_vbox;
GtkWidget *statlabel_folder;
GtkWidget *statlabel_select;
GtkWidget *statlabel_msgs;
GtkWidget *hbox_spc;
GtkWidget *toggle_eventbox;
+#ifdef MAEMO
+ GtkWidget *multiple_sel_togbtn;
+#endif
GtkWidget *toggle_arrow;
GtkWidget *popupmenu;
GtkWidget *toggle_search;
- GtkTooltips *search_tip;
GtkItemFactory *popupfactory;
gint n_entries;
QuickSearch *quicksearch;
debug_print("Creating summary view...\n");
summaryview = g_new0(SummaryView, 1);
+ summaryview->tips = gtk_tooltips_new();
#define SUMMARY_VBOX_SPACING 3
vbox = gtk_vbox_new(FALSE, SUMMARY_VBOX_SPACING);
hbox = gtk_hbox_new(FALSE, 0);
gtk_widget_show(hbox);
- search_tip = gtk_tooltips_new();
+ stat_vbox = gtk_vbox_new(FALSE, 0);
+ gtk_widget_show(stat_vbox);
+
+ stat_box = gtk_hbox_new(FALSE, 0);
+ gtk_widget_show(stat_box);
+
+ stat_box2 = gtk_hbox_new(FALSE, 0);
+ gtk_widget_show(stat_box2);
+
toggle_search = gtk_toggle_button_new();
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_search),
prefs_common.show_searchbar);
gtk_widget_show(toggle_search);
- gtk_tooltips_set_tip(GTK_TOOLTIPS(search_tip),
+ gtk_tooltips_set_tip(GTK_TOOLTIPS(summaryview->tips),
toggle_search,
_("Toggle quick search bar"), NULL);
gtk_box_pack_start(GTK_BOX(hbox), toggle_search, FALSE, FALSE, 2);
+ gtk_box_pack_start(GTK_BOX(hbox), stat_vbox, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(stat_vbox), stat_box, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(stat_vbox), stat_box2, TRUE, TRUE, 0);
+
hbox_l = gtk_hbox_new(FALSE, 0);
gtk_widget_show(hbox_l);
- gtk_box_pack_start(GTK_BOX(hbox), hbox_l, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(stat_box), hbox_l, TRUE, TRUE, 0);
statlabel_folder = gtk_label_new("");
gtk_widget_show(statlabel_folder);
/* toggle view button */
toggle_eventbox = gtk_event_box_new();
gtk_widget_show(toggle_eventbox);
+
gtk_box_pack_end(GTK_BOX(hbox), toggle_eventbox, FALSE, FALSE, 4);
+
toggle_arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
gtk_widget_show(toggle_arrow);
gtk_container_add(GTK_CONTAINER(toggle_eventbox), toggle_arrow);
g_signal_connect(G_OBJECT(toggle_eventbox), "button_press_event",
G_CALLBACK(summary_toggle_pressed),
summaryview);
-
+
+#ifdef MAEMO
+ multiple_sel_togbtn = gtk_toggle_button_new();
+ gtk_widget_show(multiple_sel_togbtn);
+ gtk_box_pack_end(GTK_BOX(hbox), multiple_sel_togbtn, FALSE, FALSE, 4);
+ gtk_tooltips_set_tip(GTK_TOOLTIPS(summaryview->tips),
+ multiple_sel_togbtn,
+ _("Toggle multiple selection"), NULL);
+ g_signal_connect(G_OBJECT(multiple_sel_togbtn), "toggled",
+ G_CALLBACK(summary_toggle_multiple_pressed),
+ summaryview);
+#endif
statlabel_msgs = gtk_label_new("");
gtk_widget_show(statlabel_msgs);
- gtk_box_pack_end(GTK_BOX(hbox), statlabel_msgs, FALSE, FALSE, 4);
+ gtk_box_pack_end(GTK_BOX(stat_box), statlabel_msgs, FALSE, FALSE, 4);
hbox_spc = gtk_hbox_new(FALSE, 0);
gtk_widget_show(hbox_spc);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
+#ifndef MAEMO
gtk_box_pack_start(GTK_BOX(vbox), scrolledwin, TRUE, TRUE, 0);
+#endif
gtk_widget_set_size_request(vbox,
prefs_common.summaryview_width,
prefs_common.summaryview_height);
gtk_container_add(GTK_CONTAINER(scrolledwin), ctree);
/* status label */
+ gtk_widget_show_all(stat_vbox);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
/* quick search */
quicksearch = quicksearch_new();
gtk_box_pack_start(GTK_BOX(vbox), quicksearch_get_widget(quicksearch), FALSE, FALSE, 0);
+#ifdef MAEMO
+ gtk_box_pack_start(GTK_BOX(vbox), scrolledwin, TRUE, TRUE, 0);
+#endif
quicksearch_set_execute_callback(quicksearch, quicksearch_execute_cb, summaryview);
g_signal_connect (G_OBJECT(toggle_search), "toggled",
summaryview->ctree = ctree;
summaryview->hbox = hbox;
summaryview->hbox_l = hbox_l;
+ summaryview->hbox_spc = hbox_spc;
+ summaryview->stat_box = stat_box;
+ summaryview->stat_box2 = stat_box2;
summaryview->statlabel_folder = statlabel_folder;
summaryview->statlabel_select = statlabel_select;
summaryview->statlabel_msgs = statlabel_msgs;
summaryview->toggle_eventbox = toggle_eventbox;
summaryview->toggle_arrow = toggle_arrow;
+#ifdef MAEMO
+ summaryview->multiple_sel_togbtn = multiple_sel_togbtn;
+#endif
summaryview->toggle_search = toggle_search;
summaryview->popupmenu = popupmenu;
summaryview->popupfactory = popupfactory;
hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, summary_update_msg, (gpointer) summaryview);
summaryview->folder_item_update_callback_id =
hooks_register_hook(FOLDER_ITEM_UPDATE_HOOKLIST,
- summary_update_folder_item_name,
+ summary_update_folder_item_hook,
+ (gpointer) summaryview);
+ summaryview->folder_update_callback_id =
+ hooks_register_hook(FOLDER_UPDATE_HOOKLIST,
+ summary_update_folder_hook,
(gpointer) summaryview);
summaryview->target_list = gtk_target_list_new(summary_drag_types, 2);
else
quicksearch_hide(quicksearch);
+ if (prefs_common.layout_mode == WIDE_MSGLIST_LAYOUT ||
+ prefs_common.layout_mode == SMALL_LAYOUT)
+ gtk_widget_hide(summaryview->toggle_eventbox);
+
return summaryview;
}
+void summary_relayout(SummaryView *summaryview)
+{
+ gtk_widget_realize(summaryview->stat_box);
+
+ gtk_widget_ref(summaryview->hbox_l);
+ gtk_widget_ref(summaryview->statlabel_msgs);
+
+ gtkut_container_remove(GTK_CONTAINER(summaryview->hbox_l->parent), summaryview->hbox_l);
+ gtkut_container_remove(GTK_CONTAINER(summaryview->statlabel_msgs->parent), summaryview->statlabel_msgs);
+
+ switch (prefs_common.layout_mode) {
+ case NORMAL_LAYOUT:
+ case WIDE_LAYOUT:
+ case WIDE_MSGLIST_LAYOUT:
+ gtk_box_pack_start(GTK_BOX(summaryview->stat_box), summaryview->hbox_l, TRUE, TRUE, 0);
+ gtk_box_pack_end(GTK_BOX(summaryview->stat_box), summaryview->statlabel_msgs, FALSE, FALSE, 4);
+ gtk_widget_show_all(summaryview->stat_box);
+ gtk_widget_show_all(summaryview->stat_box2);
+ if (prefs_common.layout_mode == WIDE_MSGLIST_LAYOUT ||
+ prefs_common.layout_mode == SMALL_LAYOUT)
+ gtk_widget_hide(summaryview->toggle_eventbox);
+ else
+ gtk_widget_show(summaryview->toggle_eventbox);
+ break;
+ case VERTICAL_LAYOUT:
+ case SMALL_LAYOUT:
+ gtk_box_pack_start(GTK_BOX(summaryview->stat_box), summaryview->hbox_l, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(summaryview->stat_box2), summaryview->statlabel_msgs, FALSE, FALSE, 4);
+ gtk_widget_show_all(summaryview->stat_box);
+ gtk_widget_show_all(summaryview->stat_box2);
+ if (prefs_common.layout_mode == SMALL_LAYOUT)
+ gtk_widget_hide(summaryview->toggle_eventbox);
+ else
+ gtk_widget_show(summaryview->toggle_eventbox);
+
+ break;
+ }
+ gtk_widget_unref(summaryview->hbox_l);
+ gtk_widget_unref(summaryview->statlabel_msgs);
+ quicksearch_relayout(summaryview->quicksearch);
+}
+
static void summary_set_fonts(SummaryView *summaryview)
{
PangoFontDescription *font_desc;
gtk_widget_modify_font(summaryview->statlabel_folder, font_desc);
gtk_widget_modify_font(summaryview->statlabel_select, font_desc);
gtk_widget_modify_font(summaryview->statlabel_msgs, font_desc);
+ /* ici */
pango_font_description_free(font_desc);
}
+static void summary_set_folder_pixmap(SummaryView *summaryview, StockPixmap icon)
+{
+ GtkWidget *pixmap;
+ if (!summaryview->folder_pixmap_eventbox) {
+ summaryview->folder_pixmap_eventbox = gtk_event_box_new();
+ gtk_widget_show(summaryview->folder_pixmap_eventbox);
+ gtk_box_pack_start(GTK_BOX(summaryview->hbox_l), summaryview->folder_pixmap_eventbox, FALSE, FALSE, 4);
+ gtk_box_reorder_child(GTK_BOX(summaryview->hbox_l), summaryview->folder_pixmap_eventbox, 0); /* search_toggle before */
+ g_signal_connect(G_OBJECT(summaryview->folder_pixmap_eventbox), "button_press_event",
+ G_CALLBACK(summary_folder_eventbox_pressed),
+ summaryview);
+ }
+ if (summaryview->folder_pixmap)
+ gtk_widget_destroy(summaryview->folder_pixmap);
+
+ pixmap = stock_pixmap_widget(summaryview->hbox_l, icon);
+ gtk_container_add(GTK_CONTAINER(summaryview->folder_pixmap_eventbox), pixmap);
+ gtk_widget_show(pixmap);
+ summaryview->folder_pixmap = pixmap;
+}
+
void summary_init(SummaryView *summaryview)
{
GtkWidget *pixmap;
summary_set_fonts(summaryview);
- pixmap = stock_pixmap_widget(summaryview->hbox_l, STOCK_PIXMAP_DIR_OPEN);
- gtk_box_pack_start(GTK_BOX(summaryview->hbox_l), pixmap, FALSE, FALSE, 4);
- gtk_box_reorder_child(GTK_BOX(summaryview->hbox_l), pixmap, 0);
- gtk_widget_show(pixmap);
- summaryview->folder_pixmap = pixmap;
+ summary_set_folder_pixmap(summaryview, STOCK_PIXMAP_DIR_OPEN);
pixmap = stock_pixmap_widget(summaryview->hbox, STOCK_PIXMAP_QUICKSEARCH);
gtk_container_add (GTK_CONTAINER(summaryview->toggle_search), pixmap);
gtk_widget_show(pixmap);
summaryview->quick_search_pixmap = pixmap;
+
+#ifdef MAEMO
+ pixmap = stock_pixmap_widget(summaryview->hbox, STOCK_PIXMAP_SELECTION);
+ gtk_container_add(GTK_CONTAINER(summaryview->multiple_sel_togbtn), pixmap);
+ gtk_widget_show(pixmap);
+ summaryview->multiple_sel_image = pixmap;
+#endif
/* Init summaryview prefs */
summaryview->sort_key = SORT_BY_NONE;
summary_clear_list(summaryview);
summary_set_column_titles(summaryview);
summary_colorlabel_menu_create(summaryview, FALSE);
+ summary_tags_menu_create(summaryview, FALSE);
main_create_mailing_list_menu (summaryview->mainwin, NULL);
summary_set_menu_sensitive(summaryview);
if (!item)
return;
- if(FOLDER_SHOWS_TO_HDR(item))
+ if (FOLDER_SHOWS_TO_HDR(item))
show_to = TRUE;
else
show_from = TRUE;
is_refresh = (item == summaryview->folder_item) ? TRUE : FALSE;
- if (!is_refresh)
+ if (!is_refresh) {
main_create_mailing_list_menu (summaryview->mainwin, NULL);
-
+ if (prefs_common.layout_mode == SMALL_LAYOUT) {
+ if (item) {
+ mainwindow_enter_folder(summaryview->mainwin);
+ gtk_widget_grab_focus(summaryview->ctree);
+ }
+ }
+ }
if (!prefs_common.summary_quicksearch_sticky
&& !prefs_common.summary_quicksearch_recurse
&& !quicksearch_is_running(summaryview->quicksearch)
gtk_ctree_node_moveto(ctree, node, 0, 0.5, 0);
}
} else {
- switch (prefs_common.select_on_entry) {
- case SELECTONENTRY_MNU:
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_MARKED, FALSE);
- if (node == NULL)
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_NEW, FALSE);
- if (node == NULL)
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_UNREAD, FALSE);
+ /* backward compat */
+ int i = 0;
+ gboolean set = FALSE, stop = FALSE;
+ for (i = 0; i < 6; i++) {
+ EntryAction act = prefs_common.summary_select_prio[i];
+
+ if (act != ACTION_UNSET) {
+ set = TRUE;
break;
- case SELECTONENTRY_MUN:
+ }
+ }
+ if (!set)
+ prefs_summary_open_set_defaults();
+
+ for (i = 0; i < 6 && node == NULL; i++) {
+ EntryAction act = prefs_common.summary_select_prio[i];
+
+ switch(act) {
+ case ACTION_MARKED:
node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_MARKED, FALSE);
- if (node == NULL)
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_UNREAD, FALSE);
- if (node == NULL)
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_NEW, FALSE);
+ MSG_MARKED, FALSE);
break;
- case SELECTONENTRY_NMU:
+ case ACTION_NEW:
node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_NEW, FALSE);
- if (node == NULL)
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_MARKED, FALSE);
- if (node == NULL)
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_UNREAD, FALSE);
+ MSG_NEW, FALSE);
break;
- case SELECTONENTRY_NUM:
+ case ACTION_UNREAD:
node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_NEW, FALSE);
- if (node == NULL)
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_UNREAD, FALSE);
- if (node == NULL)
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_MARKED, FALSE);
+ MSG_UNREAD, FALSE);
break;
- case SELECTONENTRY_UNM:
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_UNREAD, FALSE);
- if (node == NULL)
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_NEW, FALSE);
- if (node == NULL)
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_MARKED, FALSE);
+ case ACTION_LAST_OPENED:
+ if (summaryview->folder_item) {
+ node = summary_find_msg_by_msgnum(summaryview,
+ summaryview->folder_item->last_seen);
+ }
break;
- case SELECTONENTRY_UMN:
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_UNREAD, FALSE);
- if (node == NULL)
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_MARKED, FALSE);
- if (node == NULL)
- node = summary_find_next_flagged_msg(summaryview, NULL,
- MSG_NEW, FALSE);
+ case ACTION_LAST_LIST:
+ if (GTK_CLIST(ctree)->row_list != NULL) {
+ node = gtk_ctree_node_nth
+ (ctree,
+ item->sort_type == SORT_DESCENDING
+ ? 0 : GTK_CLIST(ctree)->rows - 1);
+ }
break;
- default:
+ case ACTION_NOTHING:
+ case ACTION_UNSET:
node = NULL;
- }
-
- if (node == NULL && GTK_CLIST(ctree)->row_list != NULL) {
- node = gtk_ctree_node_nth
- (ctree,
- item->sort_type == SORT_DESCENDING
- ? 0 : GTK_CLIST(ctree)->rows - 1);
+ stop = TRUE;
+ break;
+ }
+
+ if (stop || node)
+ break;
}
+
summary_unlock(summaryview);
- summary_select_node(summaryview, node,
+ if (node)
+ summary_select_node(summaryview, node,
prefs_common.always_show_msg,
TRUE);
summary_lock(summaryview);
return mlist;
}
-GSList *summary_get_msg_list(SummaryView *summaryview)
-{
- GSList *mlist = NULL;
- GtkCTree *ctree;
- GtkCTreeNode *node;
- MsgInfo *msginfo;
-
- ctree = GTK_CTREE(summaryview->ctree);
-
- for (node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
- node != NULL; node = gtkut_ctree_node_next(ctree, node)) {
- msginfo = GTKUT_CTREE_NODE_GET_ROW_DATA(node);
- mlist = g_slist_prepend(mlist, msginfo);
- }
-
- mlist = g_slist_reverse(mlist);
-
- return mlist;
-}
-
void summary_set_menu_sensitive(SummaryView *summaryview)
{
GtkItemFactory *ifactory = summaryview->popupfactory;
{"/Mark/Mark as spam" , M_TARGET_EXIST|M_CAN_LEARN_SPAM},
{"/Mark/Mark as ham" , M_TARGET_EXIST|M_CAN_LEARN_SPAM},
{"/Color label" , M_TARGET_EXIST},
+ {"/Tags" , M_TARGET_EXIST},
{"/Add sender to address book" , M_SINGLE_TARGET_EXIST},
{"/Create filter rule" , M_SINGLE_TARGET_EXIST|M_UNLOCKED},
SORT_BY_SIZE,
SORT_BY_NUMBER,
SORT_BY_SCORE,
- SORT_BY_LOCKED
+ SORT_BY_LOCKED,
+ SORT_BY_TAGS
};
for (pos = 0; pos < N_SUMMARY_COLS; pos++) {
case S_COL_DATE:
case S_COL_NUMBER:
if(type == S_COL_FROM && item != NULL &&
- FOLDER_SHOWS_TO_HDR(item))
+ FOLDER_SHOWS_TO_HDR(item) &&
+ !summaryview->col_state[summaryview->col_pos[S_COL_TO]].visible)
type = S_COL_TO;
- if (prefs_common.trans_hdr)
+ if(type == S_COL_NUMBER)
title = gettext(col_label[type]);
else
- title = col_label[type];
+ title = prefs_common_translated_header_name(col_label[type]);
break;
default:
title = gettext(col_label[type]);
}
}
+void summary_reflect_tags_changes(SummaryView *summaryview)
+{
+ GtkMenuShell *menu;
+ GList *cur;
+ GtkCTreeNode *node;
+ GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+ gboolean froze = FALSE;
+ gboolean redisplay = FALSE;
+
+ /* re-create colorlabel submenu */
+ menu = GTK_MENU_SHELL(summaryview->tags_menu);
+ g_return_if_fail(menu != NULL);
+
+ /* clear items. get item pointers. */
+ for (cur = menu->children; cur != NULL && cur->data != NULL; cur = cur->next) {
+ gtk_menu_item_remove_submenu(GTK_MENU_ITEM(cur->data));
+ }
+ summary_tags_menu_create(summaryview, TRUE);
+
+ START_LONG_OPERATION(summaryview, TRUE);
+ for (node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list); node != NULL;
+ node = gtkut_ctree_node_next(ctree, node)) {
+ redisplay |= summary_set_row_tag(summaryview,
+ node, TRUE, FALSE, 0);
+ }
+ END_LONG_OPERATION(summaryview);
+ if (redisplay)
+ summary_redisplay_msg(summaryview);
+}
+
+
void summary_reflect_prefs(void)
{
static gchar *last_font = NULL;
case SORT_BY_DATE:
cmp_func = (GtkCListCompareFunc)summary_cmp_by_date;
break;
+ case SORT_BY_THREAD_DATE:
+ cmp_func = (GtkCListCompareFunc)summary_cmp_by_thread_date;
+ break;
case SORT_BY_FROM:
cmp_func = (GtkCListCompareFunc)summary_cmp_by_from;
break;
case SORT_BY_LOCKED:
cmp_func = (GtkCListCompareFunc)summary_cmp_by_locked;
break;
+ case SORT_BY_TAGS:
+ cmp_func = (GtkCListCompareFunc)summary_cmp_by_tags;
+ break;
case SORT_BY_NONE:
break;
default:
END_TIMING();
}
-gboolean summary_insert_gnode_func(GtkCTree *ctree, guint depth, GNode *gnode,
+static gboolean summary_update_thread_age(GNode *node, gpointer data)
+{
+ MsgInfo *msginfo = node->data;
+ time_t *most_recent = (time_t *)data;
+
+ if (msginfo->date_t > *most_recent) {
+ *most_recent = msginfo->date_t;
+ }
+ return FALSE;
+}
+
+static void summary_find_thread_age(GNode *gnode)
+{
+ MsgInfo *msginfo = (MsgInfo *)gnode->data;
+ time_t most_recent;
+
+ if (!msginfo)
+ return;
+ most_recent = msginfo->thread_date = msginfo->date_t;
+
+ g_node_traverse(gnode, G_IN_ORDER, G_TRAVERSE_ALL, -1, summary_update_thread_age, &most_recent);
+
+ msginfo->thread_date = most_recent;
+}
+
+static gboolean summary_insert_gnode_func(GtkCTree *ctree, guint depth, GNode *gnode,
GtkCTreeNode *cnode, gpointer data)
{
SummaryView *summaryview = (SummaryView *)data;
SET_TEXT(S_COL_FROM);
if (summaryview->col_state[summaryview->col_pos[S_COL_TO]].visible)
SET_TEXT(S_COL_TO);
+ if (summaryview->col_state[summaryview->col_pos[S_COL_TAGS]].visible)
+ SET_TEXT(S_COL_TAGS);
#undef SET_TEXT
if (!mlist) return;
- debug_print("\tSetting summary from message data...");
+ debug_print("\tSetting summary from message data...\n");
STATUSBAR_PUSH(summaryview->mainwin,
_("Setting summary from message data..."));
gdk_flush();
START_TIMING("threaded");
root = procmsg_get_thread_tree(mlist);
+
for (gnode = root->children; gnode != NULL;
gnode = gnode->next) {
+ summary_find_thread_age(gnode);
node = gtk_sctree_insert_gnode
(ctree, NULL, node, gnode,
summary_insert_gnode_func, summaryview);
return res;
}
-static void summary_set_header(SummaryView *summaryview, gchar *text[],
+static inline void summary_set_header(SummaryView *summaryview, gchar *text[],
MsgInfo *msginfo)
{
static gchar date_modified[80];
static gchar col_score[11];
- static gchar buf[BUFFSIZE];
+ static gchar buf[BUFFSIZE], tmp1[BUFFSIZE], tmp2[BUFFSIZE], tmp3[BUFFSIZE];
gint *col_pos = summaryview->col_pos;
- gchar *from_text = NULL, *to_text = NULL;
+ gchar *from_text = NULL, *to_text = NULL, *tags_text = NULL;
gboolean should_swap = FALSE;
text[col_pos[S_COL_FROM]] = "";
text[col_pos[S_COL_MIME]] = "";
text[col_pos[S_COL_LOCKED]] = "";
text[col_pos[S_COL_DATE]] = "";
+ text[col_pos[S_COL_TAGS]] = "";
if (summaryview->col_state[summaryview->col_pos[S_COL_NUMBER]].visible)
text[col_pos[S_COL_NUMBER]] = itos(msginfo->msgnum);
else
else
text[col_pos[S_COL_SCORE]] = "";
+ if (summaryview->col_state[summaryview->col_pos[S_COL_TAGS]].visible) {
+ tags_text = procmsg_msginfo_get_tags_str(msginfo);
+ if (!tags_text) {
+ text[col_pos[S_COL_TAGS]] = "-";
+ } else {
+ strncpy2(tmp1, tags_text, sizeof(tmp1));
+ tmp1[sizeof(tmp1)-1]='\0';
+ g_free(tags_text);
+ text[col_pos[S_COL_TAGS]] = tmp1;
+ }
+ } else
+ text[col_pos[S_COL_TAGS]] = "";
+
/* slow! */
if (summaryview->col_state[summaryview->col_pos[S_COL_DATE]].visible) {
if (msginfo->date_t) {
msginfo->fromname :
_("(No From)");
} else {
- gchar buf[BUFFSIZE];
gchar *tmp = summary_complete_address(msginfo->from);
if (tmp) {
strncpy2(buf, tmp, sizeof(buf));
if (!should_swap) {
text[col_pos[S_COL_FROM]] = from_text;
} else {
- gchar tmp[BUFFSIZE];
- snprintf(tmp, BUFFSIZE-1, "--> %s", to_text);
- tmp[BUFFSIZE-1]='\0';
- text[col_pos[S_COL_FROM]] = tmp;
+ snprintf(tmp2, BUFFSIZE-1, "--> %s", to_text);
+ tmp2[BUFFSIZE-1]='\0';
+ text[col_pos[S_COL_FROM]] = tmp2;
}
if (summaryview->simplify_subject_preg != NULL)
text[col_pos[S_COL_SUBJECT]] = msginfo->subject ?
- string_remove_match(buf, BUFFSIZE, msginfo->subject,
+ string_remove_match(tmp3, BUFFSIZE, msginfo->subject,
summaryview->simplify_subject_preg) :
_("(No Subject)");
else
typedef struct {
MsgInfo *msginfo;
SummaryView *summaryview;
- GtkCTreeNode *row;
} MarkAsReadData;
static int msginfo_mark_as_read_timeout(void *data)
if (mdata->msginfo == summary_get_selected_msg(mdata->summaryview))
msginfo_mark_as_read(mdata->summaryview, mdata->msginfo,
- mdata->row);
+ mdata->summaryview->selected);
g_free(mdata);
if (!new_window) {
if (summaryview->displayed == row)
return;
- else
+ else if (summaryview->messageview)
summaryview->messageview->filtered = FALSE;
}
g_return_if_fail(row != NULL);
g_return_if_fail(msginfo);
- if (new_window) {
+ if (new_window && prefs_common.layout_mode != SMALL_LAYOUT) {
MessageView *msgview;
msgview = messageview_create_with_new_window(summaryview->mainwin);
} else {
MessageView *msgview;
- msgview = summaryview->messageview;
- summaryview->last_displayed = summaryview->displayed;
- summaryview->displayed = row;
- if (!messageview_is_visible(msgview)) {
- main_window_toggle_message_view(summaryview->mainwin);
- GTK_EVENTS_FLUSH();
+ if (prefs_common.layout_mode == SMALL_LAYOUT) {
+ if (summaryview->ext_messageview == NULL)
+ summaryview->ext_messageview = messageview_create_with_new_window(summaryview->mainwin);
+ else
+ gtkut_window_popup(summaryview->ext_messageview->window);
+ msgview = summaryview->ext_messageview;
+ summaryview->last_displayed = summaryview->displayed;
+ summaryview->displayed = row;
+ val = messageview_show(msgview, msginfo, all_headers);
+ if (GTK_CLIST(msgview->mimeview->ctree)->row_list == NULL)
+ gtk_widget_grab_focus(summaryview->ctree);
+ gtkut_ctree_node_move_if_on_the_edge(ctree, row,
+ GTK_CLIST(summaryview->ctree)->focus_row);
+ } else {
+ msgview = summaryview->messageview;
+ summaryview->last_displayed = summaryview->displayed;
+ summaryview->displayed = row;
+ if (!messageview_is_visible(msgview)) {
+ main_window_toggle_message_view(summaryview->mainwin);
+ GTK_EVENTS_FLUSH();
+ }
+ val = messageview_show(msgview, msginfo, all_headers);
+ if (GTK_CLIST(msgview->mimeview->ctree)->row_list == NULL)
+ gtk_widget_grab_focus(summaryview->ctree);
+ gtkut_ctree_node_move_if_on_the_edge(ctree, row,
+ GTK_CLIST(summaryview->ctree)->focus_row);
}
- val = messageview_show(msgview, msginfo, all_headers);
- if (GTK_CLIST(msgview->mimeview->ctree)->row_list == NULL)
- gtk_widget_grab_focus(summaryview->ctree);
- gtkut_ctree_node_move_if_on_the_edge(ctree, row,
- GTK_CLIST(summaryview->ctree)->focus_row);
}
if (val == 0 && MSG_IS_UNREAD(msginfo->flags)) {
MarkAsReadData *data = g_new0(MarkAsReadData, 1);
data->summaryview = summaryview;
data->msginfo = msginfo;
- data->row = row;
- gtk_timeout_add(prefs_common.mark_as_read_delay * 1000,
+ g_timeout_add(prefs_common.mark_as_read_delay * 1000,
msginfo_mark_as_read_timeout, data);
} else if (new_window || !prefs_common.mark_as_read_on_new_window) {
msginfo_mark_as_read(summaryview, msginfo, row);
/* CLAWS: if separate message view, don't open a new window
* but rather use the current separated message view */
- summary_display_msg_full(summaryview, summaryview->selected,
- prefs_common.sep_msg ? FALSE : TRUE,
- FALSE);
+ summary_display_msg_full(summaryview, summaryview->selected,
+ TRUE, FALSE);
}
void summary_view_source(SummaryView * summaryview)
msginfo = gtk_ctree_node_get_row_data(ctree, summaryview->selected);
source_window_show_msg(srcwin, msginfo);
source_window_show(srcwin);
+#ifdef MAEMO
+ maemo_window_full_screen_if_needed(GTK_WINDOW(srcwin->window));
+ maemo_connect_key_press_to_mainwindow(GTK_WINDOW(srcwin->window));
+#endif
}
void summary_reedit(SummaryView *summaryview)
void summary_toggle_view(SummaryView *summaryview)
{
+ if (prefs_common.layout_mode == SMALL_LAYOUT)
+ return;
if (!messageview_is_visible(summaryview->messageview) &&
summaryview->selected)
summary_display_msg(summaryview,
msginfo->msgnum);
}
-void summary_mark_as_read
-(SummaryView *summaryview)
+void summary_mark_as_read(SummaryView *summaryview)
{
GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
GList *cur;
continue;
if (is_spam) {
summary_msginfo_change_flags(msginfo, MSG_SPAM, 0, MSG_NEW|MSG_UNREAD, 0);
- if (procmsg_spam_get_folder() != summaryview->folder_item) {
- summary_move_row_to(summaryview, row, procmsg_spam_get_folder());
+ if (procmsg_spam_get_folder(msginfo) != summaryview->folder_item) {
+ summary_move_row_to(summaryview, row,
+ procmsg_spam_get_folder(msginfo));
moved = TRUE;
}
} else {
summary_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
}
+ summaryview->display_msg = prefs_common.always_show_msg;
+
summary_set_row_marks(summaryview, row);
}
} else {
- log_error(_("An error happened while learning.\n"));
+ log_error(LOG_PROTOCOL, _("An error happened while learning.\n"));
}
prefs_common.immediate_exec = immediate_exec;
if (!summaryview->folder_item) return;
if (!prefs_common.live_dangerously) {
+ gchar *buf = NULL;
+ int num = g_list_length(GTK_CLIST(summaryview->ctree)->selection);
+ if (num == 1)
+ buf = g_strdup_printf(_(
+ "Do you really want to delete the selected message?"));
+ else
+ buf = g_strdup_printf(_(
+ "Do you really want to delete the %d selected messages?"),
+ num);
aval = alertpanel(_("Delete message(s)"),
- _("Do you really want to delete selected message(s)?"),
+ buf,
GTK_STOCK_CANCEL, "+"GTK_STOCK_DELETE, NULL);
+ g_free(buf);
if (aval != G_ALERTALTERNATE) return;
}
summary_status_show(summaryview);
}
-void summary_select_thread(SummaryView *summaryview)
+void summary_select_thread(SummaryView *summaryview, gboolean delete_thread)
{
GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
- GtkCTreeNode *node = summaryview->selected;
-
- if (!node) return;
+ GtkCTreeNode *node = NULL;
+ gboolean froze = FALSE;
+ GList *cur = NULL;
+ GList *copy = NULL;
+ if (!GTK_CLIST(summaryview->ctree)->selection)
+ return;
- while (GTK_CTREE_ROW(node)->parent != NULL)
- node = GTK_CTREE_ROW(node)->parent;
- if (node != summaryview->selected)
- summary_select_node
- (summaryview, node,
- messageview_is_visible(summaryview->messageview),
- FALSE);
+ START_LONG_OPERATION(summaryview, FALSE);
+ copy = g_list_copy(GTK_CLIST(summaryview->ctree)->selection);
+ for (cur = copy; cur != NULL && cur->data != NULL;
+ cur = cur->next) {
+ node = GTK_CTREE_NODE(cur->data);
+ if (!node)
+ continue;
+ while (GTK_CTREE_ROW(node)->parent != NULL)
+ node = GTK_CTREE_ROW(node)->parent;
- gtk_ctree_select_recursive(ctree, node);
+ gtk_ctree_select_recursive(ctree, node);
+ }
+ g_list_free(copy);
+ END_LONG_OPERATION(summaryview);
+ if (delete_thread) {
+ if (FOLDER_TYPE(summaryview->folder_item->folder) == F_NEWS)
+ summary_delete(summaryview);
+ else
+ summary_delete_trash(summaryview);
+ }
summary_status_show(summaryview);
}
Xstrdup_a(filename, msginfo->subject, return);
subst_for_filename(filename);
}
- if (g_getenv ("G_BROKEN_FILENAMES") &&
- filename && !g_utf8_validate(filename, -1, NULL)) {
+ if (filename && !g_utf8_validate(filename, -1, NULL)) {
gchar *oldstr = filename;
filename = conv_codeset_strdup(filename,
conv_get_locale_charset_str(),
CS_UTF_8);
if (!filename) {
- g_warning("summary_save_as(): faild to convert character set.");
+ g_warning("summary_save_as(): failed to convert character set.");
filename = g_strdup(oldstr);
}
dest = filesel_select_file_save(_("Save as"), filename);
MsgInfo *msginfo = gtk_ctree_node_get_row_data(
GTK_CTREE(summaryview->ctree),
node);
- messageview_print(msginfo, summaryview->messageview->all_headers);
+ gint sel_start = -1, sel_end = -1, partnum = 0;
+
+ if (node == summaryview->displayed) {
+ partnum = mimeview_get_selected_part_num(summaryview->messageview->mimeview);
+ textview_get_selection_offsets(summaryview->messageview->mimeview->textview,
+ &sel_start, &sel_end);
+ }
+ messageview_print(msginfo, summaryview->messageview->all_headers,
+ sel_start, sel_end, partnum);
}
#endif
}
gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
}
-void account_rules_radio_button_toggled_cb(GtkToggleButton *btn, gpointer data)
+static void account_rules_radio_button_toggled_cb(GtkToggleButton *btn, gpointer data)
{
prefs_common.apply_per_account_filtering_rules = GPOINTER_TO_INT(data);
}
-gboolean summary_filter_get_mode(void)
+static gboolean summary_filter_get_mode(void)
/* ask what to do w/ them: skip them, apply them regardless to the account,
use the current account */
{
_("Filtering"),
_("There are some filtering rules that belong to an account.\n"
"Please choose what to do with these rules:"),
- GTK_STOCK_CANCEL, _("+_Filter"), NULL, TRUE, vbox);
- if ((val & ~G_ALERTDISABLE) == G_ALERTDEFAULT) {
+ GTK_STOCK_CANCEL, _("_Filter"), NULL, TRUE, G_ALERTALTERNATE, vbox);
+
+ if ((val & ~G_ALERTDISABLE) != G_ALERTALTERNATE) {
return FALSE;
} else if (val & G_ALERTDISABLE)
prefs_common.ask_apply_per_account_filtering_rules = FALSE;
if (hooks_invoke(MAIL_MANUAL_FILTERING_HOOKLIST, &mail_filtering_data))
return;
- filter_message_by_msginfo(filtering_rules, msginfo, NULL);
+ filter_message_by_msginfo(filtering_rules, msginfo, NULL,
+ FILTERING_MANUALLY, NULL);
}
void summary_msginfo_filter_open(FolderItem * item, MsgInfo *msginfo,
style->fg[GTK_STATE_NORMAL] = color;
/* get the average of label color and selected fg color
for visibility */
- style->fg[GTK_STATE_SELECTED].red = (color.red + ctree_style->fg[GTK_STATE_SELECTED].red ) / 2;
- style->fg[GTK_STATE_SELECTED].green = (color.green + ctree_style->fg[GTK_STATE_SELECTED].green) / 2;
- style->fg[GTK_STATE_SELECTED].blue = (color.blue + ctree_style->fg[GTK_STATE_SELECTED].blue ) / 2;
+ style->fg[GTK_STATE_SELECTED].red = (color.red + 3*ctree_style->fg[GTK_STATE_SELECTED].red ) / 4;
+ style->fg[GTK_STATE_SELECTED].green = (color.green + 3*ctree_style->fg[GTK_STATE_SELECTED].green) / 4;
+ style->fg[GTK_STATE_SELECTED].blue = (color.blue + 3*ctree_style->fg[GTK_STATE_SELECTED].blue ) / 4;
}
gtk_ctree_node_set_row_style(ctree, node, style);
END_LONG_OPERATION(summaryview);
}
+static gboolean summary_set_row_tag(SummaryView *summaryview, GtkCTreeNode *row, gboolean refresh, gboolean set, gint id)
+{
+ GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+ MsgInfo *msginfo;
+ gchar *tags_str = NULL;
+ msginfo = gtk_ctree_node_get_row_data(ctree, row);
+ g_return_val_if_fail(msginfo, FALSE);
+
+ procmsg_msginfo_update_tags(msginfo, set, id);
+
+
+ if (summaryview->col_state[summaryview->col_pos[S_COL_TAGS]].visible) {
+ tags_str = procmsg_msginfo_get_tags_str(msginfo);
+ gtk_ctree_node_set_text(ctree, row,
+ summaryview->col_pos[S_COL_TAGS],
+ tags_str?tags_str:"-");
+ g_free(tags_str);
+ }
+
+ summary_set_row_marks(summaryview, row);
+ if (row == summaryview->displayed) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void summary_set_tag(SummaryView *summaryview, gint tag_id,
+ GtkWidget *widget)
+{
+ GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+ GList *cur;
+ gboolean set = tag_id > 0;
+ gint real_id = set? tag_id:-tag_id;
+ gboolean froze = FALSE;
+ gboolean redisplay = FALSE;
+ START_LONG_OPERATION(summaryview, FALSE);
+ for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next) {
+ redisplay |= summary_set_row_tag(summaryview,
+ GTK_CTREE_NODE(cur->data), FALSE, set, real_id);
+ }
+ END_LONG_OPERATION(summaryview);
+ if (redisplay)
+ summary_redisplay_msg(summaryview);
+}
+
+static void summary_tags_menu_item_activate_cb(GtkWidget *widget,
+ gpointer data)
+{
+ gint id = GPOINTER_TO_INT(data);
+ gboolean set = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
+ SummaryView *summaryview;
+
+ summaryview = g_object_get_data(G_OBJECT(widget), "summaryview");
+ g_return_if_fail(summaryview != NULL);
+
+ /* "dont_toggle" state set? */
+ if (g_object_get_data(G_OBJECT(summaryview->tags_menu),
+ "dont_toggle"))
+ return;
+
+ if (!set)
+ id = -id;
+ summary_set_tag(summaryview, id, NULL);
+}
+
static void summary_colorlabel_menu_item_activate_item_cb(GtkMenuItem *menu_item,
gpointer data)
{
summaryview->colorlabel_menu = menu;
}
+static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item,
+ gpointer data)
+{
+ GtkMenuShell *menu;
+ GList *cur;
+ GList *sel;
+ GHashTable *menu_table = g_hash_table_new_full(
+ g_direct_hash,
+ g_direct_equal,
+ NULL, NULL);
+ SummaryView *summaryview = (SummaryView *)data;
+ g_return_if_fail(summaryview != NULL);
+
+ sel = GTK_CLIST(summaryview->ctree)->selection;
+ if (!sel) return;
+
+ menu = GTK_MENU_SHELL(summaryview->tags_menu);
+ g_return_if_fail(menu != NULL);
+
+ /* NOTE: don't return prematurely because we set the "dont_toggle"
+ * state for check menu items */
+ g_object_set_data(G_OBJECT(menu), "dont_toggle",
+ GINT_TO_POINTER(1));
+
+ /* clear items. get item pointers. */
+ for (cur = menu->children; cur != NULL && cur->data != NULL; cur = cur->next) {
+ if (GTK_IS_CHECK_MENU_ITEM(cur->data)) {
+ gint id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cur->data),
+ "tag_id"));
+ gtk_check_menu_item_set_active
+ (GTK_CHECK_MENU_ITEM(cur->data), FALSE);
+
+ g_hash_table_insert(menu_table, GINT_TO_POINTER(id), GTK_CHECK_MENU_ITEM(cur->data));
+ }
+ }
+
+ /* iterate all messages and set the state of the appropriate
+ * items */
+ for (; sel != NULL; sel = sel->next) {
+ MsgInfo *msginfo;
+ GSList *tags = NULL;
+ gint id;
+ GtkCheckMenuItem *item;
+ msginfo = gtk_ctree_node_get_row_data
+ (GTK_CTREE(summaryview->ctree),
+ GTK_CTREE_NODE(sel->data));
+ if (msginfo) {
+ tags = msginfo->tags;
+ if (!tags)
+ continue;
+
+ for (; tags; tags = tags->next) {
+ id = GPOINTER_TO_INT(tags->data);
+ item = g_hash_table_lookup(menu_table, GINT_TO_POINTER(tags->data));
+ if (item && !item->active)
+ gtk_check_menu_item_set_active
+ (item, TRUE);
+ }
+ }
+ }
+
+ g_hash_table_destroy(menu_table);
+ /* reset "dont_toggle" state */
+ g_object_set_data(G_OBJECT(menu), "dont_toggle",
+ GINT_TO_POINTER(0));
+
+}
+
+static void summary_tags_menu_item_new_tag_activate_cb(GtkWidget *widget,
+ gpointer data)
+{
+ SummaryView *summaryview;
+ gint id;
+
+ summaryview = g_object_get_data(G_OBJECT(widget), "summaryview");
+ g_return_if_fail(summaryview != NULL);
+
+ /* "dont_toggle" state set? */
+ if (g_object_get_data(G_OBJECT(summaryview->tags_menu),
+ "dont_toggle"))
+ return;
+
+ id = prefs_tags_create_new(summaryview->mainwin);
+ if (id != -1) {
+ summary_set_tag(summaryview, id, NULL);
+ main_window_reflect_tags_changes(mainwindow_get_mainwindow());
+ }
+}
+
+static void summary_tags_menu_create(SummaryView *summaryview, gboolean refresh)
+{
+ GtkWidget *label_menuitem;
+ GtkWidget *menu;
+ GtkWidget *item;
+ GSList *cur = tags_get_list();
+ GSList *orig = cur;
+ gboolean existing_tags = FALSE;
+
+ label_menuitem = gtk_item_factory_get_item(summaryview->popupfactory,
+ "/Tags");
+ g_signal_connect(G_OBJECT(label_menuitem), "activate",
+ G_CALLBACK(summary_tags_menu_item_activate_item_cb),
+ summaryview);
+
+ gtk_widget_show(label_menuitem);
+
+ menu = gtk_menu_new();
+
+ /* create tags menu items */
+ for (; cur; cur = cur->next) {
+ gint id = GPOINTER_TO_INT(cur->data);
+ const gchar *tag = tags_get_tag(id);
+
+ item = gtk_check_menu_item_new_with_label(tag);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ g_signal_connect(G_OBJECT(item), "activate",
+ G_CALLBACK(summary_tags_menu_item_activate_cb),
+ GINT_TO_POINTER(id));
+ g_object_set_data(G_OBJECT(item), "summaryview",
+ summaryview);
+ g_object_set_data(G_OBJECT(item), "tag_id",
+ GINT_TO_POINTER(id));
+ gtk_widget_show(item);
+ existing_tags = TRUE;
+ }
+ if (existing_tags) {
+ /* separator */
+ item = gtk_menu_item_new();
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ gtk_widget_show(item);
+ }
+ item = gtk_menu_item_new_with_label(_("New tag..."));
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ g_signal_connect(G_OBJECT(item), "activate",
+ G_CALLBACK(summary_tags_menu_item_new_tag_activate_cb),
+ NULL);
+ g_object_set_data(G_OBJECT(item), "summaryview",
+ summaryview);
+ gtk_widget_show(item);
+ g_slist_free(orig);
+ gtk_widget_show(menu);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(label_menuitem), menu);
+ summaryview->tags_menu = menu;
+}
+
static gboolean summary_popup_menu(GtkWidget *widget, gpointer data)
{
SummaryView *summaryview = (SummaryView *)data;
prefs_common.summary_col_size[S_COL_NUMBER]);
gtk_clist_set_column_width(GTK_CLIST(ctree), col_pos[S_COL_SCORE],
prefs_common.summary_col_size[S_COL_SCORE]);
+ gtk_clist_set_column_width(GTK_CLIST(ctree), col_pos[S_COL_TAGS],
+ prefs_common.summary_col_size[S_COL_TAGS]);
if (prefs_common.enable_dotted_lines) {
gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_DOTTED);
CLIST_BUTTON_SIGNAL_CONNECT(S_COL_SUBJECT, summary_subject_clicked);
CLIST_BUTTON_SIGNAL_CONNECT(S_COL_SCORE, summary_score_clicked);
CLIST_BUTTON_SIGNAL_CONNECT(S_COL_LOCKED, summary_locked_clicked);
+ CLIST_BUTTON_SIGNAL_CONNECT(S_COL_TAGS, summary_tags_clicked);
#undef CLIST_BUTTON_SIGNAL_CONNECT
g_signal_connect(G_OBJECT(ctree), "button_press_event",
G_CALLBACK(summary_button_pressed),
summaryview);
+#ifndef MAEMO
g_signal_connect(G_OBJECT(ctree), "popup-menu",
G_CALLBACK(summary_popup_menu), summaryview);
+#else
+ gtk_widget_tap_and_hold_setup(GTK_WIDGET(ctree), NULL, NULL,
+ GTK_TAP_AND_HOLD_NONE | GTK_TAP_AND_HOLD_NO_INTERNALS);
+ g_signal_connect(G_OBJECT(ctree), "tap-and-hold",
+ G_CALLBACK(summary_popup_menu), summaryview);
+#endif
g_signal_connect(G_OBJECT(ctree), "button_release_event",
G_CALLBACK(summary_button_released),
summaryview);
g_signal_connect(G_OBJECT(ctree), "drag_data_get",
G_CALLBACK(summary_drag_data_get),
summaryview);
+ g_signal_connect(G_OBJECT(ctree), "drag_end",
+ G_CALLBACK(summary_drag_end),
+ summaryview);
gtk_drag_dest_set(ctree, GTK_DEST_DEFAULT_ALL & ~GTK_DEST_DEFAULT_HIGHLIGHT,
summary_drag_types, 2,
/* callback functions */
+static gint summary_folder_eventbox_pressed(GtkWidget *eventbox, GdkEventButton *event,
+ SummaryView *summaryview)
+{
+ if (event) {
+ gtk_widget_grab_focus(summaryview->folderview->ctree);
+ mainwindow_exit_folder(summaryview->mainwin);
+ }
+ return TRUE;
+}
+
static gint summary_toggle_pressed(GtkWidget *eventbox, GdkEventButton *event,
SummaryView *summaryview)
{
summary_toggle_view(summaryview);
return TRUE;
}
-
+#ifdef MAEMO
+static void summary_toggle_multiple_pressed(GtkWidget *widget,
+ SummaryView *summaryview)
+{
+ GTK_SCTREE(summaryview->ctree)->force_additive_sel =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+}
+#endif
static gboolean summary_button_pressed(GtkWidget *ctree, GdkEventButton *event,
SummaryView *summaryview)
{
switch (event->keyval) {
case GDK_space: /* Page down or go to the next */
handled = TRUE;
+ if (event->state & GDK_CONTROL_MASK)
+ event->state &= ~GDK_CONTROL_MASK;
if (event->state & GDK_SHIFT_MASK)
mimeview_scroll_page(messageview->mimeview, TRUE);
else {
mimeview_scroll_page(messageview->mimeview, TRUE);
break;
case GDK_Return: /* Scroll up/down one line */
+ case GDK_KP_Enter:
handled = TRUE;
if (summaryview->displayed != summaryview->selected) {
summary_display_msg(summaryview,
/* FALLTHROUGH */
case GDK_Escape:
gtk_widget_grab_focus(summaryview->folderview->ctree);
+ mainwindow_exit_folder(summaryview->mainwin);
return TRUE;
case GDK_Home:
case GDK_End:
case GDK_t:
case GDK_l:
case GDK_c:
+ case GDK_a:
if ((event->state & (GDK_MOD1_MASK|GDK_CONTROL_MASK)) == 0) {
g_signal_stop_emission_by_name(G_OBJECT(widget),
"key_press_event");
}
}
-void summaryview_activate_quicksearch(SummaryView *summaryview)
+void summaryview_activate_quicksearch(SummaryView *summaryview, gboolean show)
{
+ prefs_common.show_searchbar = show;
gtk_toggle_button_set_active(
GTK_TOGGLE_BUTTON(summaryview->toggle_search),
- TRUE);
- quicksearch_show(summaryview->quicksearch);
+ show);
+ if (show) {
+ quicksearch_show(summaryview->quicksearch);
+ } else {
+ quicksearch_hide(summaryview->quicksearch);
+ summary_grab_focus(summaryview);
+ }
}
-static void summary_open_row(GtkSCTree *sctree, SummaryView *summaryview)
+void summary_open_row(GtkSCTree *sctree, SummaryView *summaryview)
{
if (FOLDER_SHOWS_TO_HDR(summaryview->folder_item))
summary_reedit(summaryview);
if (summary_is_locked(summaryview)
&& !GTK_SCTREE(ctree)->selecting_range
+ && summaryview->messageview
&& summaryview->messageview->mimeview
&& summaryview->messageview->mimeview->type == MIMEVIEW_TEXT
&& summaryview->messageview->mimeview->textview->loading) {
if (procmsg_spam_learner_learn(msginfo, NULL, FALSE) == 0)
summary_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
else
- log_error(_("An error happened while learning.\n"));
+ log_error(LOG_PROTOCOL, _("An error happened while learning.\n"));
} else if (!MSG_IS_REPLIED(msginfo->flags) &&
!MSG_IS_FORWARDED(msginfo->flags)) {
marked_unread = TRUE;
summary_sort_by_column_click(summaryview, SORT_BY_LOCKED);
}
+static void summary_tags_clicked(GtkWidget *button,
+ SummaryView *summaryview)
+{
+ summary_sort_by_column_click(summaryview, SORT_BY_TAGS);
+}
+
static void summary_start_drag(GtkWidget *widget, gint button, GdkEvent *event,
SummaryView *summaryview)
{
context = gtk_drag_begin(widget, summaryview->target_list,
GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_DEFAULT, button, event);
gtk_drag_set_icon_default(context);
+ if (prefs_common.layout_mode == SMALL_LAYOUT) {
+ GtkWidget *paned = GTK_WIDGET_PTR(summaryview)->parent;
+ if (paned && GTK_IS_PANED(paned)) {
+ mainwindow_reset_paned(GTK_PANED(paned));
+ }
+ }
+}
+
+static gboolean summary_return_to_list(void *data)
+{
+ SummaryView *summaryview = (SummaryView *)data;
+ mainwindow_enter_folder(summaryview->mainwin);
+ return FALSE;
+}
+
+static void summary_drag_end (GtkWidget *widget,
+ GdkDragContext *drag_context,
+ SummaryView *summaryview)
+{
+ if (prefs_common.layout_mode == SMALL_LAYOUT) {
+ g_timeout_add(250, summary_return_to_list, summaryview);
+ }
}
static void summary_drag_data_get(GtkWidget *widget,
CMP_FUNC_DEF(summary_cmp_by_mark,
MSG_IS_MARKED(msginfo1->flags) - MSG_IS_MARKED(msginfo2->flags))
CMP_FUNC_DEF(summary_cmp_by_status,
- MSG_IS_UNREAD(msginfo1->flags) - MSG_IS_UNREAD(msginfo2->flags))
+ (-(MSG_IS_SPAM(msginfo1->flags))+(MSG_IS_UNREAD(msginfo1->flags)<<1)+(MSG_IS_NEW(msginfo1->flags)<<2))
+ - (-(MSG_IS_SPAM(msginfo2->flags))+(MSG_IS_UNREAD(msginfo2->flags)<<1)+(MSG_IS_NEW(msginfo2->flags)<<2)) )
CMP_FUNC_DEF(summary_cmp_by_mime,
MSG_IS_WITH_ATTACHMENT(msginfo1->flags) - MSG_IS_WITH_ATTACHMENT(msginfo2->flags))
CMP_FUNC_DEF(summary_cmp_by_label,
(msginfo1->subject, msginfo2->subject);
}
+static gint summary_cmp_by_thread_date(GtkCList *clist,
+ gconstpointer ptr1,
+ gconstpointer ptr2)
+{
+ MsgInfo *msginfo1 = ((GtkCListRow *)ptr1)->data;
+ MsgInfo *msginfo2 = ((GtkCListRow *)ptr2)->data;
+ gint thread_diff = msginfo1->thread_date - msginfo2->thread_date;
+
+ if (msginfo1->thread_date > 0 && msginfo2->thread_date > 0)
+ return thread_diff;
+ else
+ return msginfo1->date_t - msginfo2->date_t;
+}
+
static gint summary_cmp_by_from(GtkCList *clist, gconstpointer ptr1,
gconstpointer ptr2)
{
return g_utf8_collate(str1, str2);
}
+static gint summary_cmp_by_tags(GtkCList *clist, gconstpointer ptr1,
+ gconstpointer ptr2)
+{
+ const gchar *str1, *str2;
+ const GtkCListRow *r1 = (const GtkCListRow *) ptr1;
+ const GtkCListRow *r2 = (const GtkCListRow *) ptr2;
+ const SummaryView *sv = g_object_get_data(G_OBJECT(clist), "summaryview");
+ gint res;
+ g_return_val_if_fail(sv, -1);
+
+ str1 = GTK_CELL_TEXT(r1->cell[sv->col_pos[S_COL_TAGS]])->text;
+ str2 = GTK_CELL_TEXT(r2->cell[sv->col_pos[S_COL_TAGS]])->text;
+
+ if (!str1)
+ return str2 != NULL;
+
+ if (!str2)
+ return -1;
+
+ res = g_utf8_collate(str1, str2);
+ return (res != 0)? res: summary_cmp_by_date(clist, ptr1, ptr2);
+}
+
static gint summary_cmp_by_simplified_subject
(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
{
GtkWidget *ctree = summaryview->ctree;
GtkWidget *pixmap;
- gtk_widget_destroy(summaryview->folder_pixmap);
-
stock_pixmap_gdk(ctree, STOCK_PIXMAP_MARK, &markxpm, &markxpmmask);
stock_pixmap_gdk(ctree, STOCK_PIXMAP_DELETED, &deletedxpm, &deletedxpmmask);
stock_pixmap_gdk(ctree, STOCK_PIXMAP_NEW, &newxpm, &newxpmmask);
stock_pixmap_gdk(ctree, STOCK_PIXMAP_MOVED, &movedxpm, &movedxpmmask);
stock_pixmap_gdk(ctree, STOCK_PIXMAP_COPIED, &copiedxpm, &copiedxpmmask);
- pixmap = stock_pixmap_widget(summaryview->hbox, STOCK_PIXMAP_DIR_OPEN);
- gtk_box_pack_start(GTK_BOX(summaryview->hbox), pixmap, FALSE, FALSE, 4);
- gtk_box_reorder_child(GTK_BOX(summaryview->hbox), pixmap, 1); /* search_toggle before */
- gtk_widget_show(pixmap);
- summaryview->folder_pixmap = pixmap;
+ summary_set_folder_pixmap(summaryview, STOCK_PIXMAP_DIR_OPEN);
pixmap = stock_pixmap_widget(summaryview->hbox, STOCK_PIXMAP_QUICKSEARCH);
gtk_container_remove (GTK_CONTAINER(summaryview->toggle_search),
gtk_widget_show(pixmap);
summaryview->quick_search_pixmap = pixmap;
+#ifdef MAEMO
+ pixmap = stock_pixmap_widget(summaryview->hbox, STOCK_PIXMAP_SELECTION);
+ gtk_container_remove (GTK_CONTAINER(summaryview->multiple_sel_togbtn),
+ summaryview->multiple_sel_image);
+ gtk_container_add(GTK_CONTAINER(summaryview->multiple_sel_togbtn), pixmap);
+ gtk_widget_show(pixmap);
+ summaryview->multiple_sel_togbtn = pixmap;
+#endif
+
folderview_unselect(summaryview->folderview);
folderview_select(summaryview->folderview, summaryview->folder_item);
summary_set_column_titles(summaryview);
summaryview->simplify_subject_preg = summary_compile_simplify_regexp(item->prefs->simplify_subject_regexp);
/* Sorting */
- if (folder_get_sort_type(item->folder, &sort_key, &sort_type)) {
- summaryview->sort_key = sort_key;
- summaryview->sort_type = sort_type;
- } else {
- summaryview->sort_key = item->sort_key;
- summaryview->sort_type = item->sort_type;
- }
+ sort_key = item->sort_key;
+ sort_type = item->sort_type;
+
+ folder_get_sort_type(item->folder, &sort_key, &sort_type);
+
+ summaryview->sort_key = sort_key;
+ summaryview->sort_type = sort_type;
+
/* Threading */
summaryview->threaded = item->threaded;
summaryview->thread_collapsed = item->thread_collapsed;
return FALSE;
}
-static gboolean summary_update_folder_item_name(gpointer source, gpointer data)
+void summary_update_unread(SummaryView *summaryview, FolderItem *removed_item)
+{
+ guint new, unread, unreadmarked, marked, total;
+ static gboolean tips_initialized = FALSE;
+
+ if (prefs_common.layout_mode != SMALL_LAYOUT) {
+ if (tips_initialized) {
+ summary_set_folder_pixmap(summaryview, STOCK_PIXMAP_DIR_OPEN);
+ gtk_tooltips_set_tip(GTK_TOOLTIPS(summaryview->tips),
+ summaryview->folder_pixmap_eventbox,
+ NULL, NULL);
+ tips_initialized = FALSE;
+ }
+ return;
+ }
+ folder_count_total_msgs(&new, &unread, &unreadmarked, &marked, &total);
+ if (removed_item) {
+ total -= removed_item->total_msgs;
+ new -= removed_item->new_msgs;
+ unread -= removed_item->unread_msgs;
+ }
+
+ if (new > 0 || unread > 0) {
+ tips_initialized = TRUE;
+ summary_set_folder_pixmap(summaryview, STOCK_PIXMAP_DIR_OPEN_HRM);
+ gtk_tooltips_set_tip(GTK_TOOLTIPS(summaryview->tips),
+ summaryview->folder_pixmap_eventbox,
+ _("Go back to the folder list (You have unread messages)"), NULL);
+ } else {
+ tips_initialized = TRUE;
+ summary_set_folder_pixmap(summaryview, STOCK_PIXMAP_DIR_OPEN);
+ gtk_tooltips_set_tip(GTK_TOOLTIPS(summaryview->tips),
+ summaryview->folder_pixmap_eventbox,
+ _("Go back to the folder list"), NULL);
+ }
+}
+
+static gboolean summary_update_folder_item_hook(gpointer source, gpointer data)
{
FolderItemUpdateData *hookdata = (FolderItemUpdateData *)source;
SummaryView *summaryview = (SummaryView *)data;
gtk_label_set_text(GTK_LABEL(summaryview->statlabel_folder), name);
g_free(name);
}
+ summary_update_unread(summaryview, NULL);
+
+ return FALSE;
+}
+
+static gboolean summary_update_folder_hook(gpointer source, gpointer data)
+{
+ FolderUpdateData *hookdata;
+ SummaryView *summaryview = (SummaryView *)data;
+ hookdata = source;
+ if (hookdata->update_flags & FOLDER_REMOVE_FOLDERITEM)
+ summary_update_unread(summaryview, hookdata->item);
+ else
+ summary_update_unread(summaryview, NULL);
return FALSE;
}