From bb25fad9de068caf872f883c55fdbda988b3b899 Mon Sep 17 00:00:00 2001 From: Michael Mann Date: Wed, 23 Oct 2013 14:24:17 +0000 Subject: Add the ability to collapse subtrees with Shift+Left + additional menu items. Bug 9008 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9008). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently this is only for GTK, but allows users to test it to see if its worth adding to Qt (my personal opinion is yes). From Jiří Engelthaler svn path=/trunk/; revision=52790 --- doc/wireshark.pod.template | 4 +-- docbook/wsug_src/WSUG_chapter_use.xml | 8 +++++ docbook/wsug_src/WSUG_chapter_work.xml | 9 ++++++ ui/gtk/gui_utils.c | 54 +++++++++++++++++++++++++++++++--- ui/gtk/gui_utils.h | 7 +++++ ui/gtk/main.c | 25 +++++++++++++--- ui/gtk/main.h | 7 +++++ ui/gtk/main_menubar.c | 10 +++++++ 8 files changed, 114 insertions(+), 10 deletions(-) diff --git a/doc/wireshark.pod.template b/doc/wireshark.pod.template index 8c5365d6b8..c36c246821 100644 --- a/doc/wireshark.pod.template +++ b/doc/wireshark.pod.template @@ -1113,9 +1113,9 @@ Reset the zoom factor of zoom in / zoom out back to normal font size. Resize all columns to best fit the current packet display. -=item View:Expand Subtrees +=item View:Expand / Collapse Subtrees -Expands the currently selected item and it's subtrees in the packet details. +Expands / Collapses the currently selected item and it's subtrees in the packet details. =item View:Expand All diff --git a/docbook/wsug_src/WSUG_chapter_use.xml b/docbook/wsug_src/WSUG_chapter_use.xml index 6f7d234f08..9a0437437e 100644 --- a/docbook/wsug_src/WSUG_chapter_use.xml +++ b/docbook/wsug_src/WSUG_chapter_use.xml @@ -1148,6 +1148,14 @@ + Collapse Subtrees + Shift+Left + + This menu item collapses the currently selected subtree in the + packet details tree. + + + Expand All Ctrl+Right diff --git a/docbook/wsug_src/WSUG_chapter_work.xml b/docbook/wsug_src/WSUG_chapter_work.xml index c09d0281f7..bc3da31059 100644 --- a/docbook/wsug_src/WSUG_chapter_work.xml +++ b/docbook/wsug_src/WSUG_chapter_work.xml @@ -504,6 +504,15 @@ Expand the currently selected subtree. + + + + Collapse Subtrees + View + + + Collapse the currently selected subtree. + diff --git a/ui/gtk/gui_utils.c b/ui/gtk/gui_utils.c index 09b726617d..c08ba8a9a4 100644 --- a/ui/gtk/gui_utils.c +++ b/ui/gtk/gui_utils.c @@ -1135,6 +1135,47 @@ set_window_title(GtkWidget *win, g_free(title); } +/* + * Collapse row and his children + */ +static void +tree_collapse_row_with_children(GtkTreeView *tree_view, GtkTreeModel *model, GtkTreePath *path, + GtkTreeIter *iter) +{ + GtkTreeIter child; + + if (gtk_tree_view_row_expanded(tree_view, path)) { + if (gtk_tree_model_iter_children(model, &child, iter)) { + gtk_tree_path_down(path); + + do { + + if (gtk_tree_view_row_expanded(tree_view, path)) { + tree_collapse_row_with_children(tree_view, model, path, &child); + } + + gtk_tree_path_next(path); + } while (gtk_tree_model_iter_next(model, &child)); + + gtk_tree_path_up(path); + + gtk_tree_view_collapse_row(tree_view, path); + } + } +} + +void +tree_collapse_path_all(GtkTreeView *tree_view, GtkTreePath *path) +{ + GtkTreeIter iter; + GtkTreeModel *model; + + model = gtk_tree_view_get_model(tree_view); + gtk_tree_model_get_iter(model, &iter, path); + + tree_collapse_row_with_children(tree_view, model, path, &iter); +} + /* * This callback is invoked when keyboard focus is within either * the packetlist view or the detail view. The keystrokes processed @@ -1165,11 +1206,11 @@ tree_view_key_pressed_cb(GtkWidget *tree, GdkEventKey *event, gpointer user_data _U_) { - GtkTreeSelection* selection; + GtkTreeSelection *selection; GtkTreeIter iter; GtkTreeIter parent; - GtkTreeModel* model; - GtkTreePath* path; + GtkTreeModel *model; + GtkTreePath *path; gboolean expanded, expandable; int rc = FALSE; @@ -1195,7 +1236,12 @@ tree_view_key_pressed_cb(GtkWidget *tree, case GDK_Left: if(expanded) { /* Subtree is expanded. Collapse it. */ - gtk_tree_view_collapse_row(GTK_TREE_VIEW(tree), path); + if (event->state & GDK_SHIFT_MASK) + { + tree_collapse_row_with_children(GTK_TREE_VIEW(tree), model, path, &iter); + } + else + gtk_tree_view_collapse_row(GTK_TREE_VIEW(tree), path); rc = TRUE; break; } diff --git a/ui/gtk/gui_utils.h b/ui/gtk/gui_utils.h index eb9d524e5b..95248f18f3 100644 --- a/ui/gtk/gui_utils.h +++ b/ui/gtk/gui_utils.h @@ -311,6 +311,13 @@ extern gchar *create_user_window_title(const gchar *caption); */ extern void set_window_title(GtkWidget *win, const gchar *caption); +/** Collapses tree item and his expanded children + * + * @param tree_view A GtkTreeView + * @param path Path to the field + */ +extern void tree_collapse_path_all(GtkTreeView *tree_view, GtkTreePath *path); + /** Renders a float with two decimals precission, called from gtk_tree_view_column_set_cell_data_func(). * the user data must be the column number. * Present floats with two decimals diff --git a/ui/gtk/main.c b/ui/gtk/main.c index 2687815cc7..bad98e4873 100644 --- a/ui/gtk/main.c +++ b/ui/gtk/main.c @@ -878,12 +878,14 @@ tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_) proto_help_menu_modify(sel, &cfile); } -void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) { +void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) +{ if (cfile.edt->tree) collapse_all_tree(cfile.edt->tree, tree_view_gbl); } -void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) { +void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) +{ if (cfile.edt->tree) expand_all_tree(cfile.edt->tree, tree_view_gbl); } @@ -902,7 +904,8 @@ void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_) } } -void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) { +void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) +{ GtkTreePath *path; path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected); @@ -913,7 +916,21 @@ void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) { } } -void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) { +void collapse_tree_cb(GtkWidget *widget _U_, gpointer data _U_) +{ + GtkTreePath *path; + + path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected); + if(path) { + /* the mouse position is at an entry, expand that one */ + + tree_collapse_path_all(GTK_TREE_VIEW(tree_view_gbl), path); + gtk_tree_path_free(path); + } +} + +void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) +{ static const e_addr_resolve resolv_flags = {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE}; if (cfile.edt->tree) { diff --git a/ui/gtk/main.h b/ui/gtk/main.h index 3a5f511999..d880ddedae 100644 --- a/ui/gtk/main.h +++ b/ui/gtk/main.h @@ -238,6 +238,13 @@ extern void export_carrays_cmd_cb(GtkWidget *widget, gpointer data); */ extern void expand_tree_cb(GtkWidget *widget, gpointer data); +/** User requested "Collapse Tree" by menu. + * + * @param widget parent widget (unused) + * @param data unused + */ +extern void collapse_tree_cb(GtkWidget *widget, gpointer data); + /** User requested "Expand All" by menu. * * @param widget parent widget (unused) diff --git a/ui/gtk/main_menubar.c b/ui/gtk/main_menubar.c index 8f89964833..e30b1cdbb5 100644 --- a/ui/gtk/main_menubar.c +++ b/ui/gtk/main_menubar.c @@ -1085,6 +1085,7 @@ static const char *ui_desc_menubar = " \n" " \n" " \n" +" \n" " \n" " \n" " \n" @@ -1567,6 +1568,7 @@ static const GtkActionEntry main_menu_bar_entries[] = { { "/View/ResizeAllColumns", WIRESHARK_STOCK_RESIZE_COLUMNS, "Resize All Columns", "R", NULL, G_CALLBACK(packet_list_resize_columns_cb) }, { "/View/DisplayedColumns", NULL, "Displayed Columns", NULL, NULL, NULL }, { "/View/ExpandSubtrees", NULL, "E_xpand Subtrees", "Right", NULL, G_CALLBACK(expand_tree_cb) }, + { "/View/CollapseSubtrees", NULL, "Collapse Subtrees", "Left", NULL, G_CALLBACK(collapse_tree_cb) }, { "/View/ExpandAll", NULL, "_Expand All", "Right", NULL, G_CALLBACK(expand_all_cb) }, { "/View/CollapseAll", NULL, "Collapse _All", "Left", NULL, G_CALLBACK(collapse_all_cb) }, { "/View/ColorizeConversation", NULL, "Colorize Conversation",NULL, NULL, NULL }, @@ -2926,6 +2928,7 @@ static const char *ui_desc_tree_view_menu_popup = "\n" " \n" " \n" +" \n" " \n" " \n" " \n" @@ -2997,6 +3000,7 @@ static const char *ui_desc_tree_view_menu_popup = static const GtkActionEntry tree_view_menu_popup_action_entries[] = { { "/ExpandSubtrees", NULL, "Expand Subtrees", NULL, NULL, G_CALLBACK(expand_tree_cb) }, + { "/CollapseSubtrees", NULL, "Collapse Subtrees", NULL, NULL, G_CALLBACK(collapse_tree_cb) }, { "/ExpandAll", NULL, "Expand All", NULL, NULL, G_CALLBACK(expand_all_cb) }, { "/CollapseAll", NULL, "Collapse All", NULL, NULL, G_CALLBACK(collapse_all_cb) }, { "/Apply as Column", NULL, "Apply as Column", NULL, NULL, G_CALLBACK(apply_as_custom_column_cb) }, @@ -5616,6 +5620,8 @@ set_menus_for_selected_tree_row(capture_file *cf) (id == -1) ? FALSE : proto_can_toggle_protocol(id)); set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ExpandSubtrees", cf->finfo_selected->tree_type != -1); + set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/CollapseSubtrees", + cf->finfo_selected->tree_type != -1); set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/WikiProtocolPage", (id == -1) ? FALSE : TRUE); set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/FilterFieldReference", @@ -5640,6 +5646,8 @@ set_menus_for_selected_tree_row(capture_file *cf) proto_can_match_selected(cf->finfo_selected, cf->edt)); set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/ExpandSubtrees", cf->finfo_selected->tree_type != -1); + set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/CollapseSubtrees", + cf->finfo_selected->tree_type != -1); prev_abbrev = (char *)g_object_get_data(G_OBJECT(ui_manager_tree_view_menu), "menu_abbrev"); if (!prev_abbrev || (strcmp (prev_abbrev, abbrev) != 0)) { /* No previous protocol or protocol changed - update Protocol Preferences menu */ @@ -5661,6 +5669,7 @@ set_menus_for_selected_tree_row(capture_file *cf) FALSE); set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/DisableProtocol", FALSE); set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ExpandSubtrees", FALSE); + set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/CollapseSubtrees", FALSE); set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/WikiProtocolPage", FALSE); set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/FilterFieldReference", @@ -5677,6 +5686,7 @@ set_menus_for_selected_tree_row(capture_file *cf) set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/AnalyzeMenu/ApplyAsFilter", FALSE); set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/AnalyzeMenu/PrepareaFilter", FALSE); set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/ExpandSubtrees", FALSE); + set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/CollapseSubtrees", FALSE); } } -- cgit v1.2.1