From: Colin Leroy Date: Mon, 16 Jul 2007 17:13:43 +0000 (+0000) Subject: 2007-07-16 [colin] 2.10.0cvs30 X-Git-Tag: rel_3_0_0~166 X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=commitdiff_plain;h=72e57381b23be4bfa2a52fc670fd1b157a1713ee 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. --- diff --git a/ChangeLog b/ChangeLog index c30971b41..47b9b019a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +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 diff --git a/PATCHSETS b/PATCHSETS index 230c87ace..d94ae780b 100644 --- a/PATCHSETS +++ b/PATCHSETS @@ -2683,3 +2683,4 @@ ( 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 diff --git a/configure.ac b/configure.ac index 99a4a7a91..bbcc07929 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ MINOR_VERSION=10 MICRO_VERSION=0 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=29 +EXTRA_VERSION=30 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/edittags.c b/src/edittags.c index 141020ab9..6ec316bfe 100644 --- a/src/edittags.c +++ b/src/edittags.c @@ -577,3 +577,366 @@ gint prefs_tags_create_new(MainWindow *mainwin) 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); + } +} + diff --git a/src/edittags.h b/src/edittags.h index 7b02d064b..3d4fa30c8 100644 --- a/src/edittags.h +++ b/src/edittags.h @@ -25,4 +25,5 @@ void prefs_tags_open(MainWindow *mainwin); gint prefs_tags_create_new(MainWindow *mainwin); +void tag_apply_open(GSList *msglist); #endif diff --git a/src/gtk/gtkvscrollbutton.c b/src/gtk/gtkvscrollbutton.c index 9b495684a..005fed6af 100644 --- a/src/gtk/gtkvscrollbutton.c +++ b/src/gtk/gtkvscrollbutton.c @@ -114,32 +114,72 @@ static void gtk_vscrollbutton_class_init(GtkVScrollbuttonClass *class) { } +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), diff --git a/src/mainwindow.c b/src/mainwindow.c index 6fa82e6ce..c73ebf010 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -1021,7 +1021,11 @@ static void mainwindow_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item, 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); @@ -1045,34 +1049,53 @@ static void mainwindow_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item, (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)); @@ -1158,11 +1181,11 @@ static void mainwindow_colorlabel_menu_create(MainWindow *mainwin, gboolean refr 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); @@ -1171,11 +1194,7 @@ static void mainwindow_tags_menu_item_new_tag_activate_cb(GtkWidget *widget, "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) @@ -1220,14 +1239,20 @@ 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); @@ -3103,7 +3128,7 @@ static void main_window_set_widgets(MainWindow *mainwin, LayoutType layout_mode) 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); diff --git a/src/mimeview.c b/src/mimeview.c index fcd27e9b1..5eef45c03 100644 --- a/src/mimeview.c +++ b/src/mimeview.c @@ -126,6 +126,7 @@ static void mimeview_open_part_with (MimeView *mimeview, 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, @@ -139,8 +140,6 @@ static void icon_selected (MimeView *mimeview, 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, @@ -148,10 +147,8 @@ 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); @@ -182,6 +179,32 @@ static GtkTargetEntry mimeview_mime_types[] = 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; @@ -207,6 +230,9 @@ MimeView *mimeview_create(MainWindow *mainwin) 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); @@ -261,16 +287,30 @@ MimeView *mimeview_create(MainWindow *mainwin) 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); @@ -1236,39 +1276,43 @@ void mimeview_pass_key_press_event(MimeView *mimeview, GdkEventKey *event) 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); } } @@ -1284,7 +1328,6 @@ static gint mimeview_key_pressed(GtkWidget *widget, GdkEventKey *event, { SummaryView *summaryview; GtkCTree *ctree = GTK_CTREE(widget); - GtkCTreeNode *node; if (!event) return FALSE; if (!mimeview->opened) return FALSE; @@ -1299,13 +1342,9 @@ static gint mimeview_key_pressed(GtkWidget *widget, GdkEventKey *event, 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; @@ -1317,19 +1356,15 @@ static gint mimeview_key_pressed(GtkWidget *widget, GdkEventKey *event, 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(); @@ -1886,11 +1921,9 @@ static gboolean icon_clicked_cb (GtkWidget *button, GdkEventButton *event, MimeV 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; } @@ -1910,11 +1943,6 @@ void mimeview_select_mimepart_icon(MimeView *mimeview, MimeInfo *partinfo) 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) { @@ -1932,19 +1960,11 @@ static gint icon_key_pressed(GtkWidget *button, GdkEventKey *event, 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: @@ -1952,63 +1972,44 @@ static gint icon_key_pressed(GtkWidget *button, GdkEventKey *event, 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: @@ -2020,21 +2021,6 @@ static gint icon_key_pressed(GtkWidget *button, GdkEventKey *event, 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; @@ -2065,8 +2051,18 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo) 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", @@ -2228,53 +2224,11 @@ static void icon_list_clear (MimeView *mimeview) 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) { @@ -2318,11 +2272,41 @@ static void icon_list_create(MimeView *mimeview, MimeInfo *mimeinfo) } } -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); @@ -2354,9 +2338,8 @@ static void mime_toggle_button_cb (GtkWidget *button, MimeView *mimeview) 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) { diff --git a/src/mimeview.h b/src/mimeview.h index 4f110da8b..dae076b74 100644 --- a/src/mimeview.h +++ b/src/mimeview.h @@ -70,6 +70,7 @@ struct _MimeView GtkWidget *mime_toggle; GtkWidget *scrollbutton; MimeViewType type; + gboolean ctree_mode; GtkWidget *popupmenu; GtkItemFactory *popupfactory; diff --git a/src/stock_pixmap.c b/src/stock_pixmap.c index 4a28da9fd..12cb82953 100644 --- a/src/stock_pixmap.c +++ b/src/stock_pixmap.c @@ -736,6 +736,7 @@ GtkWidget *stock_pixmap_widget_with_overlay(GtkWidget *window, StockPixmap icon, 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; } diff --git a/src/summaryview.c b/src/summaryview.c index b2472b953..90bf2d83a 100644 --- a/src/summaryview.c +++ b/src/summaryview.c @@ -5389,6 +5389,11 @@ static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item, 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); @@ -5412,11 +5417,13 @@ static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item, (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; @@ -5425,33 +5432,49 @@ static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item, 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); @@ -5460,12 +5483,8 @@ static void summary_tags_menu_item_new_tag_activate_cb(GtkWidget *widget, 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) @@ -5510,14 +5529,20 @@ 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);