From 8e76cfbf54c209336d3aaf7e613e309675eebf38 Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Wed, 1 Mar 2017 10:03:17 -0600 Subject: [PATCH] Qt: Add selection history navigation. Add the ability to move back and forth in the packet selection history similar to GTK+. Update the documentation accordingly. Change-Id: If1fdc1e59b240c0588c292dc0f7f0a5f083c30e1 Reviewed-on: https://code.wireshark.org/review/20320 Petri-Dish: Anders Broman Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- docbook/release-notes.asciidoc | 1 + docbook/wsug_src/WSUG_chapter_use.asciidoc | 10 +-- ui/qt/main_window.cpp | 6 ++ ui/qt/main_window.ui | 24 +++++++ ui/qt/main_window_slots.cpp | 8 +++ ui/qt/packet_list.cpp | 81 +++++++++++++++++++++- ui/qt/packet_list.h | 7 ++ 7 files changed, 131 insertions(+), 6 deletions(-) diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc index df4e40900a..6a24a5f4a4 100644 --- a/docbook/release-notes.asciidoc +++ b/docbook/release-notes.asciidoc @@ -45,6 +45,7 @@ since version 2.2.0: A field can now automatically append "seconds" or "ms" to its value without additional printf-style APIs. * The Default profile can now be reset to default values. +* You can move back and forth in the selection history in the Qt UI. //=== Removed Dissectors diff --git a/docbook/wsug_src/WSUG_chapter_use.asciidoc b/docbook/wsug_src/WSUG_chapter_use.asciidoc index a2f335237d..ed9b9eabfc 100644 --- a/docbook/wsug_src/WSUG_chapter_use.asciidoc +++ b/docbook/wsug_src/WSUG_chapter_use.asciidoc @@ -95,8 +95,10 @@ a capture file. See <> for additional navigation keystrokes. |kbd:[Up] |Move to the previous packet or detail item. |kbd:[Ctrl+Down], kbd:[F8] |Move to the next packet, even if the packet list isn't focused. |kbd:[Ctrl+Up], kbd:[F7] |Move to the previous packet, even if the packet list isn't focused. -|kbd:[Ctrl+.] |Move to the next packet of the conversation (TCP, UDP or IP) -|kbd:[Ctrl+,] |Move to the previous packet of the conversation (TCP, UDP or IP) +|kbd:[Ctrl+.] |Move to the next packet of the conversation (TCP, UDP or IP). +|kbd:[Ctrl+,] |Move to the previous packet of the conversation (TCP, UDP or IP). +|kbd:[Alt+Right] or kbd:[Option+Right] (macOS) |Move to the next packet in the selection history. +|kbd:[Alt+Left] or kbd:[Option+Right] (macOS) |Move to the previous packet in the selection history. |kbd:[Left] |In the packet detail, closes the selected tree item. If it's already closed, jumps to the parent node. |kbd:[Right] |In the packet detail, opens the selected tree item. |kbd:[Shift+Right] |In the packet detail, opens the selected tree item and all of its subtrees. @@ -722,8 +724,8 @@ If you currently have a temporary capture file, the Save icon will be shown ins |image:wsug_graphics/toolbar/stock_refresh_24.png[{toolbar-icon-attrs}] |button:[Reload]|menu:View[Reload]| This item allows you to reload the current capture file. |image:wsug_graphics/toolbar/stock_print_24.png[{toolbar-icon-attrs}] |button:[Print...]|menu:File[Print...]| This item allows you to print all (or some of) the packets in the capture file. It pops up the Wireshark Print dialog box (which is discussed further in <>). |image:wsug_graphics/toolbar/stock_search_24.png[{toolbar-icon-attrs}] |button:[Find Packet...]|menu:Edit[Find Packet...]|This item brings up a dialog box that allows you to find a packet. There is further information on finding packets in <>. -|image:wsug_graphics/toolbar/stock_left_arrow_24.png[{toolbar-icon-attrs}] |button:[Go Back]|menu:Go[Go Back]|This item jumps back in the packet history. -|image:wsug_graphics/toolbar/stock_right_arrow_24.png[{toolbar-icon-attrs}] |button:[Go Forward]|menu:Go[Go Forward]|This item jumps forward in the packet history. +|image:wsug_graphics/toolbar/stock_left_arrow_24.png[{toolbar-icon-attrs}] |button:[Go Back]|menu:Go[Go Back]|This item jumps back in the packet history. Hold down the Alt key (Option on macOS) to go back in the selection history. +|image:wsug_graphics/toolbar/stock_right_arrow_24.png[{toolbar-icon-attrs}] |button:[Go Forward]|menu:Go[Go Forward]|This item jumps forward in the packet history. Hold down the Alt key (Option on macOS) to go forward in the selection history. |image:wsug_graphics/toolbar/stock_jump_to_24.png[{toolbar-icon-attrs}] |button:[Go to Packet...]|menu:Go[Go to Packet...]| This item brings up a dialog box that allows you to specify a packet number to go to that packet. |image:wsug_graphics/toolbar/stock_top_24.png[{toolbar-icon-attrs}] |button:[Go To First Packet]|menu:Go[First Packet]| This item jumps to the first packet of the capture file. |image:wsug_graphics/toolbar/stock_bottom_24.png[{toolbar-icon-attrs}] |button:[Go To Last Packet]|menu:Go[Last Packet]| This item jumps to the last packet of the capture file. diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 30f999e29b..4b23e92f69 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -652,6 +652,10 @@ MainWindow::MainWindow(QWidget *parent) : packet_list_, SLOT(goFirstPacket())); connect(main_ui_->actionGoLastPacket, SIGNAL(triggered()), packet_list_, SLOT(goLastPacket())); + connect(main_ui_->actionGoNextHistoryPacket, SIGNAL(triggered()), + packet_list_, SLOT(goNextHistoryPacket())); + connect(main_ui_->actionGoPreviousHistoryPacket, SIGNAL(triggered()), + packet_list_, SLOT(goPreviousHistoryPacket())); connect(main_ui_->actionViewExpandSubtrees, SIGNAL(triggered()), proto_tree_, SLOT(expandSubtrees())); @@ -1833,6 +1837,8 @@ void MainWindow::initMainToolbarIcons() main_ui_->actionGoPreviousConversationPacket->setShortcut(QKeySequence(Qt::META | Qt::Key_Comma)); main_ui_->actionGoNextConversationPacket->setShortcut(QKeySequence(Qt::META | Qt::Key_Period)); #endif + main_ui_->actionGoPreviousHistoryPacket->setIcon(StockIcon("go-previous")); + main_ui_->actionGoNextHistoryPacket->setIcon(StockIcon("go-next")); main_ui_->actionGoAutoScroll->setIcon(StockIcon("x-stay-last")); main_ui_->actionViewColorizePacketList->setIcon(StockIcon("x-colorize-packets")); diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index 0d66379c9f..b6fb96dd62 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -259,6 +259,8 @@ + + @@ -991,6 +993,28 @@ Ctrl+, + + + Next Packet In History + + + Go to the next packet in your selection history + + + Alt+Right + + + + + Previous Packet In History + + + Go to the previous packet in your selection history + + + Alt+Left + + First Packet diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index a90d59e82d..cefcd27b2b 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -1192,6 +1192,10 @@ void MainWindow::setMenusForSelectedPacket() bool have_frames = false; /* A frame is selected */ bool frame_selected = false; + /* A visible packet comes after this one in the selection history */ + bool next_selection_history = false; + /* A visible packet comes before this one in the selection history */ + bool previous_selection_history = false; /* We have marked frames. (XXX - why check frame_selected?) */ bool have_marked = false; /* We have a marked frame other than the current frame (i.e., @@ -1220,6 +1224,8 @@ void MainWindow::setMenusForSelectedPacket() if (capture_file_.capFile()) { frame_selected = capture_file_.capFile()->current_frame != NULL; + next_selection_history = packet_list_->haveNextHistory(); + previous_selection_history = packet_list_->havePreviousHistory(); have_frames = capture_file_.capFile()->count > 0; have_marked = frame_selected && capture_file_.capFile()->marked_count > 0; another_is_marked = have_marked && @@ -1266,6 +1272,8 @@ void MainWindow::setMenusForSelectedPacket() main_ui_->actionEditTimeShift->setEnabled(have_frames); main_ui_->actionGoGoToLinkedPacket->setEnabled(false); + main_ui_->actionGoNextHistoryPacket->setEnabled(next_selection_history); + main_ui_->actionGoPreviousHistoryPacket->setEnabled(previous_selection_history); main_ui_->actionAnalyzeAAFSelected->setEnabled(have_filter_expr); main_ui_->actionAnalyzeAAFNotSelected->setEnabled(have_filter_expr); diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp index 74049d084f..e3095fd3f8 100644 --- a/ui/qt/packet_list.cpp +++ b/ui/qt/packet_list.cpp @@ -247,7 +247,9 @@ PacketList::PacketList(QWidget *parent) : rows_inserted_(false), columns_changed_(false), set_column_visibility_(false), - frozen_row_(-1) + frozen_row_(-1), + cur_history_(-1), + in_history_(false) { QMenu *main_menu_item, *submenu; QAction *action; @@ -494,6 +496,13 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS cf_select_packet(cap_file_, row); } + if (!in_history_ && cap_file_->current_frame) { + cur_history_++; + selection_history_.resize(cur_history_); + selection_history_.append(cap_file_->current_frame->num); + } + in_history_ = false; + related_packet_delegate_.clear(); if (proto_tree_) proto_tree_->clear(); if (byte_view_tab_) byte_view_tab_->clear(); @@ -755,6 +764,42 @@ void PacketList::resetColumns() packet_list_model_->resetColumns(); } +// Return true if we have a visible packet further along in the history. +bool PacketList::haveNextHistory(bool update_cur) +{ + if (selection_history_.size() < 1 || cur_history_ >= selection_history_.size() - 1) { + return false; + } + + for (int i = cur_history_ + 1; i < selection_history_.size(); i++) { + if (packet_list_model_->packetNumberToRow(selection_history_.at(i)) >= 0) { + if (update_cur) { + cur_history_ = i; + } + return true; + } + } + return false; +} + +// Return true if we have a visible packet back in the history. +bool PacketList::havePreviousHistory(bool update_cur) +{ + if (selection_history_.size() < 1 || cur_history_ < 1) { + return false; + } + + for (int i = cur_history_ - 1; i >= 0; i--) { + if (packet_list_model_->packetNumberToRow(selection_history_.at(i)) >= 0) { + if (update_cur) { + cur_history_ = i; + } + return true; + } + } + return false; +} + // prefs.col_list has changed. void PacketList::columnsChanged() { @@ -916,12 +961,14 @@ void PacketList::thaw(bool restore_selection) } void PacketList::clear() { - // packet_history_clear(); related_packet_delegate_.clear(); selectionModel()->clear(); packet_list_model_->clear(); proto_tree_->clear(); byte_view_tab_->clear(); + selection_history_.clear(); + cur_history_ = -1; + in_history_ = false; QImage overlay; overlay_sb_->setNearOverlayImage(overlay); @@ -1121,6 +1168,12 @@ void PacketList::setMonospaceFont(const QFont &mono_font) } void PacketList::goNextPacket(void) { + if (QApplication::keyboardModifiers() | Qt::MetaModifier) { + // Alt+toolbar + goNextHistoryPacket(); + return; + } + if (selectionModel()->hasSelection()) { setCurrentIndex(moveCursor(MoveDown, Qt::NoModifier)); } else { @@ -1130,6 +1183,12 @@ void PacketList::goNextPacket(void) { } void PacketList::goPreviousPacket(void) { + if (QApplication::keyboardModifiers() | Qt::MetaModifier) { + // Alt+toolbar + goPreviousHistoryPacket(); + return; + } + if (selectionModel()->hasSelection()) { setCurrentIndex(moveCursor(MoveUp, Qt::NoModifier)); } else { @@ -1170,6 +1229,24 @@ void PacketList::goToPacket(int packet, int hf_id) proto_tree_->goToField(hf_id); } +void PacketList::goNextHistoryPacket() +{ + if (haveNextHistory(true)) { + in_history_ = true; + goToPacket(selection_history_.at(cur_history_)); + in_history_ = false; + } +} + +void PacketList::goPreviousHistoryPacket() +{ + if (havePreviousHistory(true)) { + in_history_ = true; + goToPacket(selection_history_.at(cur_history_)); + in_history_ = false; + } +} + void PacketList::markFrame() { if (!cap_file_ || !packet_list_model_) return; diff --git a/ui/qt/packet_list.h b/ui/qt/packet_list.h index 4f3d072831..9bb2139a1f 100644 --- a/ui/qt/packet_list.h +++ b/ui/qt/packet_list.h @@ -87,6 +87,8 @@ public: void setCaptureInProgress(bool in_progress = false) { capture_in_progress_ = in_progress; tail_at_end_ = in_progress; } void captureFileReadFinished(); void resetColumns(); + bool haveNextHistory(bool update_cur = false); + bool havePreviousHistory(bool update_cur = false); protected: void selectionChanged(const QItemSelection & selected, const QItemSelection & deselected); @@ -133,6 +135,9 @@ private: bool columns_changed_; bool set_column_visibility_; int frozen_row_; + QVector selection_history_; + int cur_history_; + bool in_history_; void setFrameReftime(gboolean set, frame_data *fdata); void setColumnVisibility(); @@ -160,6 +165,8 @@ public slots: void goLastPacket(); void goToPacket(int packet); void goToPacket(int packet, int hf_id); + void goNextHistoryPacket(); + void goPreviousHistoryPacket(); void markFrame(); void markAllDisplayedFrames(bool set); void ignoreFrame();