+2007-07-16 [colin] 2.10.0cvs30
+
+ * src/edittags.c
+ * src/edittags.h
+ * src/mainwindow.c
+ * src/summaryview.c
+ Improve the tag interface - allow
+ to set/unset tags from a special
+ window.
+ * src/gtk/gtkvscrollbutton.c
+ * src/mimeview.c
+ * src/mimeview.h
+ * src/stock_pixmap.c
+ Fix Mimeview's ugly hacks in the
+ icon list.
+
2007-07-16 [paul] 2.10.0cvs29
* src/wizard.c
( cvs diff -u -r 1.83.2.109 -r 1.83.2.110 src/mimeview.c; cvs diff -u -r 1.5.2.9 -r 1.5.2.10 src/gtk/gtkvscrollbutton.c; ) > 2.10.0cvs27.patchset
( cvs diff -u -r 1.274.2.197 -r 1.274.2.198 src/mainwindow.c; ) > 2.10.0cvs28.patchset
( cvs diff -u -r 1.1.2.54 -r 1.1.2.55 src/wizard.c; cvs diff -u -r 1.1.2.14 -r 1.1.2.15 src/gtk/icon_legend.c; ) > 2.10.0cvs29.patchset
+( cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src/edittags.c; cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src/edittags.h; cvs diff -u -r 1.274.2.198 -r 1.274.2.199 src/mainwindow.c; cvs diff -u -r 1.83.2.110 -r 1.83.2.111 src/mimeview.c; cvs diff -u -r 1.20.2.21 -r 1.20.2.22 src/mimeview.h; cvs diff -u -r 1.25.2.41 -r 1.25.2.42 src/stock_pixmap.c; cvs diff -u -r 1.395.2.311 -r 1.395.2.312 src/summaryview.c; cvs diff -u -r 1.5.2.10 -r 1.5.2.11 src/gtk/gtkvscrollbutton.c; ) > 2.10.0cvs30.patchset
MICRO_VERSION=0
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=29
+EXTRA_VERSION=30
EXTRA_RELEASE=
EXTRA_GTK2_VERSION=
return id;
}
+
+enum {
+ TAG_SELECTED,
+ TAG_SELECTED_INCONSISTENT,
+ TAG_NAME,
+ TAG_DATA,
+ N_TAG_EDIT_COLUMNS
+};
+
+static void apply_window_create(void);
+
+static struct TagApplyWindow
+{
+ GtkWidget *window;
+ GtkWidget *hbox1;
+ GtkWidget *vbox1;
+ GtkWidget *label;
+ GtkWidget *taglist;
+ GtkWidget *close_btn;
+ GtkWidget *add_entry;
+ GtkWidget *add_btn;
+ GSList *msglist;
+} applywindow;
+
+static void apply_window_load_tags (void);
+
+void tag_apply_open(GSList *msglist)
+{
+ g_return_if_fail(msglist);
+
+ if (!applywindow.window)
+ apply_window_create();
+
+ manage_window_set_transient(GTK_WINDOW(applywindow.window));
+ gtk_widget_grab_focus(applywindow.close_btn);
+
+ applywindow.msglist = msglist;
+ apply_window_load_tags();
+
+ gtk_widget_show(applywindow.window);
+ gtk_widget_grab_focus(applywindow.taglist);
+ gtk_window_set_modal(GTK_WINDOW(applywindow.window), TRUE);
+}
+
+static GtkListStore* apply_window_create_data_store(void)
+{
+ return gtk_list_store_new(N_TAG_EDIT_COLUMNS,
+ G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN,
+ G_TYPE_STRING,
+ G_TYPE_POINTER,
+ -1);
+}
+
+static void tag_apply_selected_toggled(GtkCellRendererToggle *widget,
+ gchar *path,
+ GtkWidget *list_view);
+
+static void apply_window_create_list_view_columns(GtkWidget *list_view)
+{
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+
+ renderer = gtk_cell_renderer_toggle_new();
+ g_object_set(renderer,
+ "radio", FALSE,
+ "activatable", TRUE,
+ NULL);
+ column = gtk_tree_view_column_new_with_attributes
+ (_(""),
+ renderer,
+ "active", TAG_SELECTED,
+ "inconsistent", TAG_SELECTED_INCONSISTENT,
+ NULL);
+ gtk_tree_view_column_set_alignment (column, 0.5);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
+ g_signal_connect(G_OBJECT(renderer), "toggled",
+ G_CALLBACK(tag_apply_selected_toggled),
+ list_view);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes
+ (_("Tag"),
+ renderer,
+ "text", TAG_NAME,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+}
+
+static GtkWidget *apply_window_list_view_create (void)
+{
+ GtkTreeView *list_view;
+ GtkTreeSelection *selector;
+ GtkTreeModel *model;
+
+ model = GTK_TREE_MODEL(apply_window_create_data_store());
+ list_view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
+ g_object_unref(model);
+
+ gtk_tree_view_set_rules_hint(list_view, prefs_common.use_stripes_everywhere);
+
+ selector = gtk_tree_view_get_selection(list_view);
+ gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE);
+
+ /* create the columns */
+ apply_window_create_list_view_columns(GTK_WIDGET(list_view));
+
+ return GTK_WIDGET(list_view);
+
+}
+
+static void apply_window_close(void)
+{
+ g_slist_free(applywindow.msglist);
+ applywindow.msglist = NULL;
+ gtk_widget_hide(applywindow.window);
+}
+
+static void apply_window_close_cb(GtkWidget *widget,
+ gpointer data)
+{
+ apply_window_close();
+}
+
+static void apply_window_list_view_insert_tag(GtkWidget *list_view,
+ GtkTreeIter *row_iter,
+ gint tag);
+
+static void apply_window_add_tag(void)
+{
+ gchar *new_tag = gtk_editable_get_chars(GTK_EDITABLE(applywindow.add_entry), 0, -1);
+ if (new_tag) {
+ gint id = tags_get_id_for_str(new_tag);
+ if (id == -1) {
+ id = tags_add_tag(new_tag);
+ tags_write_tags();
+ if (mainwindow_get_mainwindow())
+ summary_set_tag(
+ mainwindow_get_mainwindow()->summaryview,
+ id, NULL);
+ main_window_reflect_tags_changes(mainwindow_get_mainwindow());
+ apply_window_list_view_insert_tag(applywindow.taglist, NULL, id);
+ }
+ g_free(new_tag);
+ }
+}
+
+static void apply_window_add_tag_cb(GtkWidget *widget,
+ gpointer data)
+{
+ apply_window_add_tag();
+}
+
+static gboolean apply_window_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ if (event && event->keyval == GDK_Escape)
+ apply_window_close();
+ return FALSE;
+}
+
+static gboolean apply_window_add_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ if (event && (event->keyval == GDK_KP_Enter || event->keyval == GDK_Return)) {
+ apply_window_add_tag();
+ gtk_entry_set_text(GTK_ENTRY(applywindow.add_entry), "");
+ gtk_widget_grab_focus(applywindow.taglist);
+ }
+
+ return FALSE;
+}
+
+static void apply_window_create(void)
+{
+ GtkWidget *window;
+ GtkWidget *hbox1;
+ GtkWidget *vbox1;
+ GtkWidget *label;
+ GtkWidget *taglist;
+ GtkWidget *close_btn;
+ GtkWidget *scrolledwin;
+ GtkWidget *new_tag_label;
+ GtkWidget *new_tag_entry;
+ GtkWidget *add_btn;
+
+ window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "tag_apply_window");
+ gtk_window_set_title (GTK_WINDOW(window),
+ Q_("Dialog title|Apply tags"));
+
+ gtk_container_set_border_width (GTK_CONTAINER (window), 8);
+ gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
+ gtk_window_set_resizable(GTK_WINDOW (window), TRUE);
+ g_signal_connect(G_OBJECT(window), "delete_event",
+ G_CALLBACK(apply_window_close_cb), NULL);
+ g_signal_connect(G_OBJECT(window), "key_press_event",
+ G_CALLBACK(apply_window_key_pressed), NULL);
+ MANAGE_WINDOW_SIGNALS_CONNECT (window);
+
+ vbox1 = gtk_vbox_new(FALSE, 6);
+ hbox1 = gtk_hbox_new(FALSE, 6);
+
+ new_tag_label = gtk_label_new(_("New tag:"));
+ gtk_misc_set_alignment(GTK_MISC(new_tag_label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox1), new_tag_label, FALSE, FALSE, 0);
+
+ new_tag_entry = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(hbox1), new_tag_entry, FALSE, FALSE, 0);
+ g_signal_connect(G_OBJECT(new_tag_entry), "key_press_event",
+ G_CALLBACK(apply_window_add_key_pressed), NULL);
+
+ add_btn = gtk_button_new_from_stock(GTK_STOCK_ADD);
+ gtk_box_pack_start(GTK_BOX(hbox1), add_btn, FALSE, FALSE, 0);
+
+ close_btn = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
+ gtk_box_pack_end(GTK_BOX(hbox1), close_btn, FALSE, FALSE, 0);
+
+ gtk_widget_show(new_tag_label);
+ gtk_widget_show(new_tag_entry);
+ gtk_widget_show(close_btn);
+ gtk_widget_show(add_btn);
+ g_signal_connect(G_OBJECT(close_btn), "clicked",
+ G_CALLBACK(apply_window_close_cb), NULL);
+ g_signal_connect(G_OBJECT(add_btn), "clicked",
+ G_CALLBACK(apply_window_add_tag_cb), NULL);
+
+ taglist = apply_window_list_view_create();
+
+ label = gtk_label_new(_("Please select tags to apply/remove. Changes are immediate."));
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(vbox1), label, FALSE, TRUE, 0);
+
+ scrolledwin = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+
+ gtk_widget_set_size_request(scrolledwin, 500, 250);
+
+ gtk_container_add(GTK_CONTAINER(scrolledwin), taglist);
+ gtk_box_pack_start(GTK_BOX(vbox1), scrolledwin, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
+
+ gtk_widget_show(label);
+ gtk_widget_show(scrolledwin);
+ gtk_widget_show(taglist);
+ gtk_widget_show(hbox1);
+ gtk_widget_show(vbox1);
+ gtk_widget_show(close_btn);
+ gtk_container_add(GTK_CONTAINER (window), vbox1);
+
+ applywindow.window = window;
+ applywindow.hbox1 = hbox1;
+ applywindow.vbox1 = vbox1;
+ applywindow.label = label;
+ applywindow.taglist = taglist;
+ applywindow.close_btn = close_btn;
+ applywindow.add_btn = add_btn;
+ applywindow.add_entry = new_tag_entry;
+}
+
+static void apply_window_list_view_clear_tags(GtkWidget *list_view)
+{
+ GtkListStore *list_store = GTK_LIST_STORE(gtk_tree_view_get_model
+ (GTK_TREE_VIEW(list_view)));
+ gtk_list_store_clear(list_store);
+}
+
+
+static void tag_apply_selected_toggled(GtkCellRendererToggle *widget,
+ gchar *path,
+ GtkWidget *list_view)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list_view));
+ gboolean enabled = TRUE, set = FALSE;
+ gpointer tmp;
+ gint tag_id;
+ SummaryView *summaryview = NULL;
+
+ if (mainwindow_get_mainwindow() != NULL)
+ summaryview = mainwindow_get_mainwindow()->summaryview;
+
+ if (!gtk_tree_model_get_iter_from_string(model, &iter, path))
+ return;
+
+ gtk_tree_model_get(model, &iter,
+ TAG_SELECTED, &enabled,
+ TAG_DATA, &tmp,
+ -1);
+
+ set = !enabled;
+ tag_id = GPOINTER_TO_INT(tmp);
+
+ gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+ TAG_SELECTED, set,
+ TAG_SELECTED_INCONSISTENT, FALSE,
+ -1);
+
+ if (summaryview)
+ summary_set_tag(summaryview, set ? tag_id : -tag_id, NULL);
+}
+
+static void apply_window_get_selected_state(gint tag, gboolean *selected, gboolean *selected_inconsistent)
+{
+ GSList *cur = applywindow.msglist;
+ gint num_mails = 0;
+ gint num_selected = 0;
+ for (; cur; cur = cur->next) {
+ MsgInfo *msginfo = (MsgInfo *)cur->data;
+ num_mails++;
+ if (msginfo->tags && g_slist_find(msginfo->tags, GINT_TO_POINTER(tag))) {
+ *selected = TRUE;
+ num_selected++;
+ }
+ }
+ if (num_selected > 0 && num_selected < num_mails)
+ *selected_inconsistent = TRUE;
+ else
+ *selected_inconsistent = FALSE;
+}
+
+static void apply_window_list_view_insert_tag(GtkWidget *list_view,
+ GtkTreeIter *row_iter,
+ gint tag)
+{
+ GtkTreeIter iter;
+ GtkListStore *list_store = GTK_LIST_STORE(gtk_tree_view_get_model
+ (GTK_TREE_VIEW(list_view)));
+ const gchar *name = tags_get_tag(tag);
+ gboolean selected = FALSE, selected_inconsistent = FALSE;
+
+ apply_window_get_selected_state(tag, &selected, &selected_inconsistent);
+ if (row_iter == NULL) {
+ /* append new */
+ gtk_list_store_append(list_store, &iter);
+ gtk_list_store_set(list_store, &iter,
+ TAG_SELECTED, selected,
+ TAG_SELECTED_INCONSISTENT, selected_inconsistent,
+ TAG_NAME, name,
+ TAG_DATA, GINT_TO_POINTER(tag),
+ -1);
+ } else {
+ gtk_list_store_set(list_store, row_iter,
+ TAG_SELECTED, selected,
+ TAG_SELECTED_INCONSISTENT, selected_inconsistent,
+ TAG_NAME, name,
+ TAG_DATA, GINT_TO_POINTER(tag),
+ -1);
+ }
+}
+
+static void apply_window_load_tags (void)
+{
+ GSList *cur;
+ GSList *tags = tags_get_list();
+ apply_window_list_view_clear_tags(applywindow.taglist);
+
+ cur = tags;
+ for (; cur; cur = cur->next) {
+ gint id = GPOINTER_TO_INT(cur->data);
+ apply_window_list_view_insert_tag(applywindow.taglist, NULL, id);
+ }
+}
+
void prefs_tags_open(MainWindow *mainwin);
gint prefs_tags_create_new(MainWindow *mainwin);
+void tag_apply_open(GSList *msglist);
#endif
{
}
+static GdkCursor *hand_cursor = NULL;
+
+static gboolean vscroll_visi_notify(GtkWidget *widget,
+ GdkEventVisibility *event,
+ gpointer data)
+{
+ gdk_window_set_cursor(widget->window, hand_cursor);
+ return FALSE;
+}
+
+static gboolean vscroll_leave_notify(GtkWidget *widget,
+ GdkEventCrossing *event,
+ gpointer data)
+{
+ gdk_window_set_cursor(widget->window, NULL);
+ return FALSE;
+}
+
+static gboolean vscroll_enter_notify(GtkWidget *widget,
+ GdkEventCrossing *event,
+ gpointer data)
+{
+ gdk_window_set_cursor(widget->window, hand_cursor);
+ return FALSE;
+}
+
+
static void gtk_vscrollbutton_init(GtkVScrollbutton *scrollbutton)
{
GtkWidget *arrow;
- scrollbutton->upbutton = gtk_button_new();
- scrollbutton->downbutton = gtk_button_new();
+
+ if (!hand_cursor)
+ hand_cursor = gdk_cursor_new(GDK_HAND2);
+
+ scrollbutton->upbutton = gtk_event_box_new();
+ scrollbutton->downbutton = gtk_event_box_new();
arrow = gtk_arrow_new(GTK_ARROW_UP, GTK_SHADOW_NONE);
gtk_widget_show(arrow);
gtk_container_add(GTK_CONTAINER(scrollbutton->upbutton), arrow);
-#ifndef MAEMO
gtk_widget_set_size_request(scrollbutton->upbutton, -1, 16);
-#else
- gtk_widget_set_size_request(scrollbutton->upbutton, -1, arrow->requisition.height + 8);
-#endif
arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
gtk_widget_show(arrow);
gtk_container_add(GTK_CONTAINER(scrollbutton->downbutton), arrow);
-#ifndef MAEMO
gtk_widget_set_size_request(scrollbutton->downbutton, -1, 16);
-#else
- gtk_widget_set_size_request(scrollbutton->downbutton, -1, arrow->requisition.height + 8);
-#endif
GTK_WIDGET_UNSET_FLAGS(scrollbutton->upbutton, GTK_CAN_FOCUS);
GTK_WIDGET_UNSET_FLAGS(scrollbutton->downbutton, GTK_CAN_FOCUS);
gtk_widget_show(scrollbutton->downbutton);
gtk_widget_show(scrollbutton->upbutton);
+ g_signal_connect(G_OBJECT(scrollbutton->upbutton), "visibility-notify-event",
+ G_CALLBACK(vscroll_visi_notify), NULL);
+ g_signal_connect(G_OBJECT(scrollbutton->upbutton), "motion-notify-event",
+ G_CALLBACK(vscroll_visi_notify), NULL);
+ g_signal_connect(G_OBJECT(scrollbutton->upbutton), "leave-notify-event",
+ G_CALLBACK(vscroll_leave_notify), NULL);
+ g_signal_connect(G_OBJECT(scrollbutton->upbutton), "enter-notify-event",
+ G_CALLBACK(vscroll_enter_notify), NULL);
+ g_signal_connect(G_OBJECT(scrollbutton->downbutton), "visibility-notify-event",
+ G_CALLBACK(vscroll_visi_notify), NULL);
+ g_signal_connect(G_OBJECT(scrollbutton->downbutton), "motion-notify-event",
+ G_CALLBACK(vscroll_visi_notify), NULL);
+ g_signal_connect(G_OBJECT(scrollbutton->downbutton), "leave-notify-event",
+ G_CALLBACK(vscroll_leave_notify), NULL);
+ g_signal_connect(G_OBJECT(scrollbutton->downbutton), "enter-notify-event",
+ G_CALLBACK(vscroll_enter_notify), NULL);
+
g_signal_connect(G_OBJECT(scrollbutton->upbutton),
"button_press_event",
G_CALLBACK(gtk_vscrollbutton_button_press),
g_direct_hash,
g_direct_equal,
NULL, NULL);
-
+ GHashTable *menu_allsel_table = g_hash_table_new_full(
+ g_direct_hash,
+ g_direct_equal,
+ NULL, NULL);
+ gint sel_len;
mainwin = (MainWindow *)data;
g_return_if_fail(mainwin != NULL);
(GTK_CHECK_MENU_ITEM(cur->data), FALSE);
g_hash_table_insert(menu_table, GINT_TO_POINTER(id), GTK_CHECK_MENU_ITEM(cur->data));
+ g_hash_table_insert(menu_allsel_table, GINT_TO_POINTER(id), GINT_TO_POINTER(0));
}
}
/* iterate all messages and set the state of the appropriate
* items */
+ sel_len = 0;
for (; sel != NULL; sel = sel->next) {
MsgInfo *msginfo;
GSList *tags = NULL;
gint id;
GtkCheckMenuItem *item;
msginfo = (MsgInfo *)sel->data;
+ sel_len++;
if (msginfo) {
tags = msginfo->tags;
if (!tags)
continue;
for (; tags; tags = tags->next) {
+ gint num_checked = GPOINTER_TO_INT(g_hash_table_lookup(menu_allsel_table, tags->data));
id = GPOINTER_TO_INT(tags->data);
item = g_hash_table_lookup(menu_table, GINT_TO_POINTER(tags->data));
- if (item && !item->active)
+ if (item && !item->active) {
gtk_check_menu_item_set_active
(item, TRUE);
+ }
+ num_checked++;
+ g_hash_table_replace(menu_allsel_table, tags->data, GINT_TO_POINTER(num_checked));
}
}
}
+ 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"));
+ gint num_checked = GPOINTER_TO_INT(g_hash_table_lookup(menu_allsel_table, GINT_TO_POINTER(id)));
+ if (num_checked < sel_len && num_checked > 0)
+ gtk_check_menu_item_set_inconsistent(GTK_CHECK_MENU_ITEM(cur->data), TRUE);
+ else
+ gtk_check_menu_item_set_inconsistent(GTK_CHECK_MENU_ITEM(cur->data), FALSE);
+ }
+ }
g_slist_free(sel);
g_hash_table_destroy(menu_table);
+ g_hash_table_destroy(menu_allsel_table);
/* reset "dont_toggle" state */
g_object_set_data(G_OBJECT(menu), "dont_toggle",
GINT_TO_POINTER(0));
mainwin->colorlabel_menu = menu;
}
-static void mainwindow_tags_menu_item_new_tag_activate_cb(GtkWidget *widget,
+static void mainwindow_tags_menu_item_apply_tags_activate_cb(GtkWidget *widget,
gpointer data)
{
MainWindow *mainwin;
- gint id;
+
mainwin = g_object_get_data(G_OBJECT(widget), "mainwin");
g_return_if_fail(mainwin != NULL);
"dont_toggle"))
return;
- id = prefs_tags_create_new(mainwin);
- if (id != -1) {
- summary_set_tag(mainwin->summaryview, id, NULL);
- main_window_reflect_tags_changes(mainwindow_get_mainwindow());
- }
+ tag_apply_open(summary_get_selection(mainwin->summaryview));
}
static void mainwindow_tags_menu_create(MainWindow *mainwin, gboolean refresh)
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
gtk_widget_show(item);
}
- item = gtk_menu_item_new_with_label(_("New tag..."));
+
+ item = gtk_menu_item_new_with_label(_("Apply tags..."));
+ gtk_widget_add_accelerator(item, "activate",
+ mainwin->menu_factory->accel_group,
+ GDK_T, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
+ GTK_ACCEL_LOCKED | GTK_ACCEL_VISIBLE);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
g_signal_connect(G_OBJECT(item), "activate",
- G_CALLBACK(mainwindow_tags_menu_item_new_tag_activate_cb),
+ G_CALLBACK(mainwindow_tags_menu_item_apply_tags_activate_cb),
NULL);
g_object_set_data(G_OBJECT(item), "mainwin",
mainwin);
gtk_widget_show(item);
+
g_slist_free(orig);
gtk_widget_show(menu);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(label_menuitem), menu);
gtk_widget_hide(GTK_WIDGET_PTR(mainwin->messageview->noticeview));
if (!noticeview_is_visible(mainwin->messageview->mimeview->siginfoview))
gtk_widget_hide(GTK_WIDGET_PTR(mainwin->messageview->mimeview->siginfoview));
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(mainwin->messageview->mimeview->mime_toggle)))
+ if (mainwin->messageview->mimeview->ctree_mode)
gtk_widget_hide(mainwin->messageview->mimeview->icon_mainbox);
else
gtk_widget_hide(mainwin->messageview->mimeview->ctree_mainbox);
MimeInfo *partinfo,
gboolean automatic);
static void mimeview_select_next_part (MimeView *mimeview);
+static void mimeview_select_prev_part (MimeView *mimeview);
static void mimeview_view_file (const gchar *filename,
MimeInfo *partinfo,
const gchar *cmd,
static gint icon_key_pressed (GtkWidget *button,
GdkEventKey *event,
MimeView *mimeview);
-static void toggle_icon (GtkToggleButton *button,
- MimeView *mimeview);
static void icon_list_append_icon (MimeView *mimeview,
MimeInfo *mimeinfo);
static void icon_list_create (MimeView *mimeview,
static void icon_list_clear (MimeView *mimeview);
static void icon_list_toggle_by_mime_info (MimeView *mimeview,
MimeInfo *mimeinfo);
-static gboolean icon_list_select_by_number(MimeView *mimeview,
- gint number);
-static void mime_toggle_button_cb (GtkWidget *button,
- MimeView *mimeview);
+static gint mime_toggle_button_cb(GtkWidget *button, GdkEventButton *event,
+ MimeView *mimeview);
static gboolean part_button_pressed (MimeView *mimeview,
GdkEventButton *event,
MimeInfo *partinfo);
GSList *mimeviewer_factories;
GSList *mimeviews;
+static GdkCursor *hand_cursor = NULL;
+
+static gboolean mimeview_visi_notify(GtkWidget *widget,
+ GdkEventVisibility *event,
+ MimeView *mimeview)
+{
+ gdk_window_set_cursor(widget->window, hand_cursor);
+ return FALSE;
+}
+
+static gboolean mimeview_leave_notify(GtkWidget *widget,
+ GdkEventCrossing *event,
+ MimeView *mimeview)
+{
+ gdk_window_set_cursor(widget->window, NULL);
+ return FALSE;
+}
+
+static gboolean mimeview_enter_notify(GtkWidget *widget,
+ GdkEventCrossing *event,
+ MimeView *mimeview)
+{
+ gdk_window_set_cursor(widget->window, hand_cursor);
+ return FALSE;
+}
+
MimeView *mimeview_create(MainWindow *mainwin)
{
MimeView *mimeview;
gint n_entries;
gint i;
+ if (!hand_cursor)
+ hand_cursor = gdk_cursor_new(GDK_HAND2);
+
debug_print("Creating MIME view...\n");
mimeview = g_new0(MimeView, 1);
g_signal_connect(G_OBJECT(icon_scroll), "scroll_event",
G_CALLBACK(mimeview_scrolled), mimeview);
- mime_toggle = gtk_toggle_button_new();
+ mime_toggle = gtk_event_box_new();
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(mime_toggle), FALSE);
+
+ g_signal_connect(G_OBJECT(mime_toggle), "visibility-notify-event",
+ G_CALLBACK(mimeview_visi_notify), mimeview);
+ g_signal_connect(G_OBJECT(mime_toggle), "motion-notify-event",
+ G_CALLBACK(mimeview_visi_notify), mimeview);
+ g_signal_connect(G_OBJECT(mime_toggle), "leave-notify-event",
+ G_CALLBACK(mimeview_leave_notify), mimeview);
+ g_signal_connect(G_OBJECT(mime_toggle), "enter-notify-event",
+ G_CALLBACK(mimeview_enter_notify), mimeview);
+
+ gtk_container_set_border_width(GTK_CONTAINER(mime_toggle), 2);
gtk_widget_show(mime_toggle);
+ mimeview->ctree_mode = FALSE;
arrow = gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_NONE);
gtk_widget_show(arrow);
gtk_container_add(GTK_CONTAINER(mime_toggle), arrow);
- g_signal_connect(G_OBJECT(mime_toggle), "toggled",
+ g_signal_connect(G_OBJECT(mime_toggle), "button_release_event",
G_CALLBACK(mime_toggle_button_cb), mimeview);
icon_mainbox = gtk_vbox_new(FALSE, 0);
gtk_widget_show(icon_mainbox);
+ gtk_widget_set_size_request(icon_mainbox, 32, -1);
gtk_box_pack_start(GTK_BOX(icon_mainbox), mime_toggle, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(icon_mainbox), icon_scroll, TRUE, TRUE, 3);
gtk_box_pack_end(GTK_BOX(icon_mainbox), scrollbutton, FALSE, FALSE, 0);
static void mimeview_select_next_part(MimeView *mimeview)
{
- gboolean is_next = FALSE;
+ GtkCTree *ctree = GTK_CTREE(mimeview->ctree);
+ GtkCTreeNode *node = mimeview->opened;
+ MimeInfo *partinfo = NULL;
+
+skip:
+ node = GTK_CTREE_NODE_NEXT(node);
+ if (!node)
+ node = gtk_ctree_node_nth(GTK_CTREE(ctree), 0);
- GList *child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
- for (; child != NULL; child = g_list_next(child)) {
- if (GTK_IS_TOGGLE_BUTTON(child->data) &&
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(child->data))) {
- is_next = TRUE;
- } else if (GTK_IS_TOGGLE_BUTTON(child->data) &&
- is_next) {
- toggle_icon(GTK_TOGGLE_BUTTON(child->data), mimeview);
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(child->data), TRUE);
- icon_selected(mimeview, -1,
- (MimeInfo *)g_object_get_data(G_OBJECT(child->data),
- "partinfo"));
- is_next = FALSE;
- break;
- }
+ if (node) {
+ partinfo = gtk_ctree_node_get_row_data(ctree, node);
+ if (partinfo->type == MIMETYPE_MULTIPART)
+ goto skip;
+ gtk_sctree_unselect_all(GTK_SCTREE(ctree));
+ gtk_sctree_select(GTK_SCTREE(ctree), node);
+ icon_list_toggle_by_mime_info(mimeview, partinfo);
}
- if (is_next) {
- /* we were on the last one, go to first */
- child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
- for (; child != NULL; child = g_list_next(child)) {
- if (GTK_IS_TOGGLE_BUTTON(child->data)) {
- toggle_icon(GTK_TOGGLE_BUTTON(child->data), mimeview);
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(child->data), TRUE);
- icon_selected(mimeview, -1,
- (MimeInfo *)g_object_get_data(G_OBJECT(child->data),
- "partinfo"));
- break;
- }
- }
+}
+
+static void mimeview_select_prev_part(MimeView *mimeview)
+{
+ GtkCTree *ctree = GTK_CTREE(mimeview->ctree);
+ GtkCTreeNode *node = mimeview->opened;
+ MimeInfo *partinfo = NULL;
+
+skip:
+ node = GTK_CTREE_NODE_PREV(node);
+ if (!node)
+ node = gtk_ctree_node_nth(GTK_CTREE(ctree), GTK_CLIST(ctree)->rows - 1);
+
+ if (node) {
+ partinfo = gtk_ctree_node_get_row_data(ctree, node);
+ if (partinfo->type == MIMETYPE_MULTIPART)
+ goto skip;
+ gtk_sctree_unselect_all(GTK_SCTREE(ctree));
+ gtk_sctree_select(GTK_SCTREE(ctree), node);
+ icon_list_toggle_by_mime_info(mimeview, partinfo);
}
}
{
SummaryView *summaryview;
GtkCTree *ctree = GTK_CTREE(widget);
- GtkCTreeNode *node;
if (!event) return FALSE;
if (!mimeview->opened) return FALSE;
if (mimeview_scroll_page(mimeview, FALSE))
return TRUE;
- node = GTK_CTREE_NODE_NEXT(mimeview->opened);
- if (node) {
- gtk_sctree_unselect_all(GTK_SCTREE(ctree));
- gtk_sctree_select(GTK_SCTREE(ctree), node);
- return TRUE;
- }
- break;
+ mimeview_select_next_part(mimeview);
+ return TRUE;
+
case GDK_BackSpace:
mimeview_scroll_page(mimeview, TRUE);
return TRUE;
case GDK_n:
case GDK_N:
BREAK_ON_MODIFIER_KEY();
- if (!GTK_CTREE_NODE_NEXT(mimeview->opened)) break;
- KEY_PRESS_EVENT_STOP();
- g_signal_emit_by_name(G_OBJECT(ctree), "scroll_vertical",
- GTK_SCROLL_STEP_FORWARD, 0.0);
+ mimeview_select_next_part(mimeview);
return TRUE;
+
case GDK_p:
case GDK_P:
BREAK_ON_MODIFIER_KEY();
- if (!GTK_CTREE_NODE_PREV(mimeview->opened)) break;
- KEY_PRESS_EVENT_STOP();
- g_signal_emit_by_name(G_OBJECT(ctree), "scroll_vertical",
- GTK_SCROLL_STEP_BACKWARD, 0.0);
+ mimeview_select_prev_part(mimeview);
return TRUE;
+
case GDK_y:
BREAK_ON_MODIFIER_KEY();
KEY_PRESS_EVENT_STOP();
if (event->button == 1) {
icon_selected(mimeview, num, partinfo);
gtk_widget_grab_focus(button);
- if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) {
- toggle_icon(GTK_TOGGLE_BUTTON(button), mimeview);
- }
}
part_button_pressed(mimeview, event, partinfo);
+ icon_list_toggle_by_mime_info(mimeview, partinfo);
return FALSE;
}
icon_selected(mimeview, -1, partinfo);
}
-#undef KEY_PRESS_EVENT_STOP
-#define KEY_PRESS_EVENT_STOP() \
- g_signal_stop_emission_by_name(G_OBJECT(button), \
- "key_press_event");
-
static gint icon_key_pressed(GtkWidget *button, GdkEventKey *event,
MimeView *mimeview)
{
switch (event->keyval) {
case GDK_space:
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) {
- /* stop the button being untoggled */
- KEY_PRESS_EVENT_STOP();
- if (mimeview_scroll_page(mimeview, FALSE))
- return TRUE;
-
- if (icon_list_select_by_number(mimeview, num + 1))
- return TRUE;
- } else {
- icon_selected(mimeview, num, partinfo);
- toggle_icon(GTK_TOGGLE_BUTTON(button), mimeview);
+ if (mimeview_scroll_page(mimeview, FALSE))
return TRUE;
- }
+
+ mimeview_select_next_part(mimeview);
+ return TRUE;
break;
case GDK_BackSpace:
return TRUE;
case GDK_Return:
case GDK_KP_Enter:
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) {
- KEY_PRESS_EVENT_STOP();
- mimeview_scroll_one_line(mimeview,
- (event->state & GDK_MOD1_MASK) != 0);
- return TRUE;
- } else {
- icon_selected(mimeview, num, partinfo);
- toggle_icon(GTK_TOGGLE_BUTTON(button), mimeview);
- return TRUE;
- }
+ mimeview_scroll_one_line(mimeview,
+ (event->state & GDK_MOD1_MASK) != 0);
+ return TRUE;
case GDK_n:
case GDK_N:
BREAK_ON_MODIFIER_KEY();
- if (icon_list_select_by_number(mimeview, num + 1)) {
- KEY_PRESS_EVENT_STOP();
- return TRUE;
- }
- break;
+ mimeview_select_next_part(mimeview);
+ return TRUE;
case GDK_p:
case GDK_P:
BREAK_ON_MODIFIER_KEY();
- if (icon_list_select_by_number(mimeview, num - 1)) {
- KEY_PRESS_EVENT_STOP();
- return TRUE;
- }
+ mimeview_select_prev_part(mimeview);
break;
case GDK_y:
BREAK_ON_MODIFIER_KEY();
- KEY_PRESS_EVENT_STOP();
mimeview_save_as(mimeview);
return TRUE;
case GDK_t:
BREAK_ON_MODIFIER_KEY();
- KEY_PRESS_EVENT_STOP();
mimeview_display_as_text(mimeview);
return TRUE;
case GDK_l:
BREAK_ON_MODIFIER_KEY();
- KEY_PRESS_EVENT_STOP();
mimeview_launch(mimeview, NULL);
return TRUE;
case GDK_o:
BREAK_ON_MODIFIER_KEY();
- KEY_PRESS_EVENT_STOP();
mimeview_open_with(mimeview);
return TRUE;
case GDK_c:
BREAK_ON_MODIFIER_KEY();
- KEY_PRESS_EVENT_STOP();
mimeview_check_signature(mimeview);
return TRUE;
case GDK_a:
BREAK_ON_MODIFIER_KEY();
- KEY_PRESS_EVENT_STOP();
mimeview_select_next_part(mimeview);
return TRUE;
default:
return summary_pass_key_press_event(summaryview, event);
}
-static void toggle_icon(GtkToggleButton *button, MimeView *mimeview)
-{
- GList *child;
-
- child = gtk_container_get_children(GTK_CONTAINER(mimeview->icon_vbox));
- for (; child != NULL; child = g_list_next(child)) {
- if (GTK_IS_TOGGLE_BUTTON(child->data) &&
- GTK_TOGGLE_BUTTON(child->data) != button &&
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(child->data)))
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(child->data),
- FALSE);
- }
-}
-
static gboolean icon_popup_menu(GtkWidget *widget, gpointer data)
{
MimeView *mimeview = (MimeView *)data;
vbox = mimeview->icon_vbox;
mimeview->icon_count++;
- button = gtk_toggle_button_new();
- gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
+ button = gtk_event_box_new();
+
+ g_signal_connect(G_OBJECT(button), "visibility-notify-event",
+ G_CALLBACK(mimeview_visi_notify), mimeview);
+ g_signal_connect(G_OBJECT(button), "motion-notify-event",
+ G_CALLBACK(mimeview_visi_notify), mimeview);
+ g_signal_connect(G_OBJECT(button), "leave-notify-event",
+ G_CALLBACK(mimeview_leave_notify), mimeview);
+ g_signal_connect(G_OBJECT(button), "enter-notify-event",
+ G_CALLBACK(mimeview_enter_notify), mimeview);
+
+ gtk_container_set_border_width(GTK_CONTAINER(button), 2);
g_object_set_data(G_OBJECT(button), "icon_number",
GINT_TO_POINTER(mimeview->icon_count));
g_object_set_data(G_OBJECT(button), "partinfo",
gtk_adjustment_set_value(adj, adj->lower);
}
-static void icon_list_toggle_by_mime_info(MimeView *mimeview,
- MimeInfo *mimeinfo)
-{
- GList *child;
-
- child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
- for (; child != NULL; child = g_list_next(child)) {
- if (GTK_IS_TOGGLE_BUTTON(child->data) &&
- g_object_get_data(G_OBJECT(child->data),
- "partinfo") == (gpointer)mimeinfo) {
- toggle_icon(GTK_TOGGLE_BUTTON(child->data), mimeview);
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(child->data), TRUE);
- }
- }
-}
-
/*!
*\brief Used to 'click' the next or previous icon.
*
*\return true if the icon 'number' exists and was selected.
*/
-static gboolean icon_list_select_by_number(MimeView *mimeview,
- gint number)
-{
- GList *child;
-
- if (number == 0) return FALSE;
- child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
- for (; child != NULL; child = g_list_next(child)) {
- if (GTK_IS_TOGGLE_BUTTON(child->data) &&
- GPOINTER_TO_INT(g_object_get_data(G_OBJECT(child->data),
- "icon_number")) == number) {
- icon_selected(mimeview, number,
- (MimeInfo*)g_object_get_data(G_OBJECT(child->data),
- "partinfo"));
- toggle_icon(GTK_TOGGLE_BUTTON(child->data), mimeview);
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(child->data), TRUE);
- gtk_widget_grab_focus(GTK_WIDGET(child->data));
-
- return TRUE;
- }
- }
- return FALSE;
-}
-
static void icon_scroll_size_allocate_cb(GtkWidget *widget,
GtkAllocation *size, MimeView *mimeview)
{
}
}
-static void mime_toggle_button_cb (GtkWidget *button, MimeView *mimeview)
+static void icon_list_toggle_by_mime_info (MimeView *mimeview,
+ MimeInfo *mimeinfo)
+{
+ GList *child;
+
+ child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
+ for (; child != NULL; child = g_list_next(child)) {
+ if (!GTK_IS_EVENT_BOX(child->data))
+ continue;
+ if(g_object_get_data(G_OBJECT(child->data),
+ "partinfo") == (gpointer)mimeinfo) {
+ gint *border_x = NULL;
+ GtkWidget *icon = gtk_bin_get_child(GTK_BIN(child->data));
+ border_x = g_object_get_data(G_OBJECT(icon), "border_x");
+ *border_x = 0;
+ gtk_widget_queue_draw(icon);
+ } else {
+ gint *border_x = NULL;
+ GtkWidget *icon = gtk_bin_get_child(GTK_BIN(child->data));
+ border_x = g_object_get_data(G_OBJECT(icon), "border_x");
+ *border_x = 6;
+ gtk_widget_queue_draw(icon);
+ }
+ }
+}
+
+static gint mime_toggle_button_cb(GtkWidget *button, GdkEventButton *event,
+ MimeView *mimeview)
{
gtk_widget_ref(button);
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) {
+ mimeview_leave_notify(button, NULL, NULL);
+
+ mimeview->ctree_mode = !mimeview->ctree_mode;
+ if (mimeview->ctree_mode) {
gtk_arrow_set(GTK_ARROW(GTK_BIN(button)->child), GTK_ARROW_RIGHT,
GTK_SHADOW_NONE);
gtk_widget_hide(mimeview->icon_mainbox);
gtk_paned_set_gutter_size(GTK_PANED(mimeview->paned), 0);
}
- gtk_widget_grab_focus(button);
gtk_widget_unref(button);
-
+ return TRUE;
}
void mimeview_update (MimeView *mimeview) {
GtkWidget *mime_toggle;
GtkWidget *scrollbutton;
MimeViewType type;
+ gboolean ctree_mode;
GtkWidget *popupmenu;
GtkItemFactory *popupfactory;
G_CALLBACK(pixmap_with_overlay_expose_event_cb), data);
g_signal_connect(G_OBJECT(widget), "destroy",
G_CALLBACK(pixmap_with_overlay_destroy_cb), data);
+ g_object_set_data(G_OBJECT(widget), "border_x", &(data->border_x));
return widget;
}
g_direct_hash,
g_direct_equal,
NULL, NULL);
+ GHashTable *menu_allsel_table = g_hash_table_new_full(
+ g_direct_hash,
+ g_direct_equal,
+ NULL, NULL);
+ gint sel_len;
SummaryView *summaryview = (SummaryView *)data;
g_return_if_fail(summaryview != NULL);
(GTK_CHECK_MENU_ITEM(cur->data), FALSE);
g_hash_table_insert(menu_table, GINT_TO_POINTER(id), GTK_CHECK_MENU_ITEM(cur->data));
+ g_hash_table_insert(menu_allsel_table, GINT_TO_POINTER(id), GINT_TO_POINTER(0));
}
}
/* iterate all messages and set the state of the appropriate
* items */
+ sel_len = 0;
for (; sel != NULL; sel = sel->next) {
MsgInfo *msginfo;
GSList *tags = NULL;
msginfo = gtk_ctree_node_get_row_data
(GTK_CTREE(summaryview->ctree),
GTK_CTREE_NODE(sel->data));
+ sel_len++;
if (msginfo) {
tags = msginfo->tags;
if (!tags)
continue;
for (; tags; tags = tags->next) {
+ gint num_checked = GPOINTER_TO_INT(g_hash_table_lookup(menu_allsel_table, tags->data));
id = GPOINTER_TO_INT(tags->data);
item = g_hash_table_lookup(menu_table, GINT_TO_POINTER(tags->data));
- if (item && !item->active)
+ if (item && !item->active) {
gtk_check_menu_item_set_active
(item, TRUE);
+ }
+ num_checked++;
+ g_hash_table_replace(menu_allsel_table, tags->data, GINT_TO_POINTER(num_checked));
}
}
}
+ 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"));
+ gint num_checked = GPOINTER_TO_INT(g_hash_table_lookup(menu_allsel_table, GINT_TO_POINTER(id)));
+ if (num_checked < sel_len && num_checked > 0)
+ gtk_check_menu_item_set_inconsistent(GTK_CHECK_MENU_ITEM(cur->data), TRUE);
+ else
+ gtk_check_menu_item_set_inconsistent(GTK_CHECK_MENU_ITEM(cur->data), FALSE);
+ }
+ }
g_hash_table_destroy(menu_table);
+ g_hash_table_destroy(menu_allsel_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,
+static void summary_tags_menu_item_apply_tags_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);
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());
- }
+
+ tag_apply_open(summary_get_selection(summaryview));
}
static void summary_tags_menu_create(SummaryView *summaryview, gboolean refresh)
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
gtk_widget_show(item);
}
- item = gtk_menu_item_new_with_label(_("New tag..."));
+
+ item = gtk_menu_item_new_with_label(_("Apply tags..."));
+ gtk_widget_add_accelerator(item, "activate",
+ summaryview->popupfactory->accel_group,
+ GDK_T, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
+ GTK_ACCEL_LOCKED | GTK_ACCEL_VISIBLE);
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),
+ G_CALLBACK(summary_tags_menu_item_apply_tags_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);