diff options
author | Michal Labedzki <michal.labedzki@tieto.com> | 2015-02-20 15:30:23 +0100 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2015-02-27 20:27:14 +0000 |
commit | 2d4817966ee88d2b163dca46e4df75e8f6262b7a (patch) | |
tree | d887a5bcee4b267d55556436f320bb32cd49c738 /ui | |
parent | 2462c0d35a113043b003a73b8b3fe31a674264bb (diff) | |
download | wireshark-2d4817966ee88d2b163dca46e4df75e8f6262b7a.tar.gz |
Qt: Automatically scroll the packet list.
Add an "Auto Scroll in Live Capture" action to the Go menu. It's in the
View menu in the GTK+ UI but it seems to make more sense as a navigation
item.
Use a timeout interval for automatic scrolling. I haven't run any tests
to see if this makes a difference but it would seem that the less
drawing we do during a high speed capture the better, particularly for
remote displays.
Update the x-stay-last icons.
Note that we might want to make prefs.capture_auto_scroll a "recent"
setting.
Mark auto_scroll_live and packet_list_check_end GTK+ only.
Bug: 10601
Co-authored-by: Gerald Combs <gerald@wireshark.org>
Change-Id: I645d27c0814f0e4a0d5b01ae68be366847e2522d
Reviewed-on: https://code.wireshark.org/review/7292
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Diffstat (limited to 'ui')
-rw-r--r-- | ui/preference_utils.h | 2 | ||||
-rw-r--r-- | ui/qt/capture_file.cpp | 1 | ||||
-rw-r--r-- | ui/qt/main_window.cpp | 14 | ||||
-rw-r--r-- | ui/qt/main_window.h | 3 | ||||
-rw-r--r-- | ui/qt/main_window.ui | 14 | ||||
-rw-r--r-- | ui/qt/main_window_slots.cpp | 10 | ||||
-rw-r--r-- | ui/qt/packet_list.cpp | 70 | ||||
-rw-r--r-- | ui/qt/packet_list.h | 16 | ||||
-rw-r--r-- | ui/ui_util.h | 2 |
9 files changed, 112 insertions, 20 deletions
diff --git a/ui/preference_utils.h b/ui/preference_utils.h index 074b974844..e4117d682e 100644 --- a/ui/preference_utils.h +++ b/ui/preference_utils.h @@ -70,7 +70,7 @@ extern void reset_stashed_pref(pref_t *pref); /** If autoscroll in live captures is active or not */ -extern gboolean auto_scroll_live; +extern gboolean auto_scroll_live; /* GTK+ only. */ /** Fill in capture options with values from the preferences */ diff --git a/ui/qt/capture_file.cpp b/ui/qt/capture_file.cpp index a32f225f15..a15e8ebdba 100644 --- a/ui/qt/capture_file.cpp +++ b/ui/qt/capture_file.cpp @@ -40,6 +40,7 @@ capture_file cfile; // To do: // - Add getters and (if needed) setters: // - Full filename +// - Capture state (stopped, prepared, running). QString CaptureFile::no_capture_file_ = QObject::tr("[no capture file]"); diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index c69d50a68d..7eb7b702b7 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -187,7 +187,6 @@ MainWindow::MainWindow(QWidget *parent) : setForCapturedPackets(false); setMenusForSelectedPacket(); setMenusForSelectedTreeRow(); - setForCaptureInProgress(false); setMenusForFileSet(false); interfaceSelectionChanged(); loadWindowGeometry(); @@ -202,7 +201,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(wsApp, SIGNAL(profileChanging()), this, SLOT(saveWindowGeometry())); connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(layoutPanes())); connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(layoutToolbars())); - connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(updateNameResolutionActions())); + connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(updatePreferenceActions())); connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(zoomText())); connect(wsApp, SIGNAL(updateRecentItemStatus(const QString &, qint64, bool)), this, SLOT(updateRecentFiles())); @@ -286,7 +285,8 @@ MainWindow::MainWindow(QWidget *parent) : initShowHideMainWidgets(); initTimeDisplayFormatMenu(); initTimePrecisionFormatMenu(); - updateNameResolutionActions(); + updatePreferenceActions(); + setForCaptureInProgress(false); connect(&capture_file_, SIGNAL(captureCapturePrepared(capture_session *)), this, SLOT(captureCapturePrepared(capture_session *))); @@ -388,6 +388,8 @@ MainWindow::MainWindow(QWidget *parent) : packet_list_, SLOT(redrawVisiblePackets())); connect(packet_list_, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(openPacketDialog())); + connect(packet_list_, SIGNAL(packetListScrolled(bool)), + main_ui_->actionGoAutoScroll, SLOT(setChecked(bool))); connect(proto_tree_, SIGNAL(protoItemSelected(QString&)), main_ui_->statusBar, SLOT(pushFieldStatus(QString&))); @@ -1420,6 +1422,7 @@ void MainWindow::initMainToolbarIcons() main_ui_->actionGoGoToPacket->setIcon(StockIcon("go-jump")); main_ui_->actionGoFirstPacket->setIcon(StockIcon("go-first")); main_ui_->actionGoLastPacket->setIcon(StockIcon("go-last")); + main_ui_->actionGoAutoScroll->setIcon(StockIcon("x-stay-last")); main_ui_->actionViewColorizePacketList->setIcon(StockIcon("x-colorize-packets")); main_ui_->actionViewColorizePacketList->setChecked(recent.packet_list_colorize); @@ -1818,11 +1821,12 @@ void MainWindow::setForCaptureInProgress(gboolean capture_in_progress) { setMenusForCaptureInProgress(capture_in_progress); -//#ifdef HAVE_LIBPCAP +#ifdef HAVE_LIBPCAP + packet_list_->setCaptureInProgress(capture_in_progress); // set_toolbar_for_capture_in_progress(capture_in_progress); // set_capture_if_dialog_for_capture_in_progress(capture_in_progress); -//#endif +#endif } /* diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 5310c00033..05f73e3f61 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -190,7 +190,7 @@ public slots: void layoutPanes(); void applyRecentPaneGeometry(); void layoutToolbars(); - void updateNameResolutionActions(); + void updatePreferenceActions(); void captureCapturePrepared(capture_session *); void captureCaptureUpdateStarted(capture_session *); @@ -324,6 +324,7 @@ private slots: void on_actionViewReload_triggered(); void on_actionGoGoToPacket_triggered(); + void on_actionGoAutoScroll_toggled(bool checked); void resetPreviousFocus(); #ifdef HAVE_LIBPCAP diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index 29a9efba84..6a9901a3a4 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -225,6 +225,8 @@ <addaction name="actionGoPreviousPacket"/> <addaction name="actionGoFirstPacket"/> <addaction name="actionGoLastPacket"/> + <addaction name="separator"/> + <addaction name="actionGoAutoScroll"/> </widget> <widget class="QMenu" name="menuView"> <property name="title"> @@ -568,6 +570,7 @@ <addaction name="actionGoGoToPacket"/> <addaction name="actionGoFirstPacket"/> <addaction name="actionGoLastPacket"/> + <addaction name="actionGoAutoScroll"/> <addaction name="separator"/> <addaction name="actionViewColorizePacketList"/> <addaction name="separator"/> @@ -2293,6 +2296,17 @@ <string>Show the linked packet in a separate window.</string> </property> </action> + <action name="actionGoAutoScroll"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Auto Scroll in Li&ve Capture</string> + </property> + <property name="toolTip"> + <string>Automatically scroll to the last packet during a live capture.</string> + </property> + </action> </widget> <layoutdefault spacing="6" margin="11"/> <customwidgets> diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 8291e0d3c8..bd366ae0e8 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -415,11 +415,14 @@ void MainWindow::layoutToolbars() main_ui_->mainToolBar->setToolButtonStyle(tbstyle); } -void MainWindow::updateNameResolutionActions() +void MainWindow::updatePreferenceActions() { main_ui_->actionViewNameResolutionPhysical->setChecked(gbl_resolv_flags.mac_name); main_ui_->actionViewNameResolutionNetwork->setChecked(gbl_resolv_flags.network_name); main_ui_->actionViewNameResolutionTransport->setChecked(gbl_resolv_flags.transport_name); + + // Should this be a "recent" setting? + main_ui_->actionGoAutoScroll->setChecked(prefs.capture_auto_scroll); } void MainWindow::filterAction(QString &action_filter, FilterAction::Action action, FilterAction::ActionType type) @@ -2693,6 +2696,11 @@ void MainWindow::on_actionGoGoToPacket_triggered() { main_ui_->goToLineEdit->setFocus(); } +void MainWindow::on_actionGoAutoScroll_toggled(bool checked) +{ + packet_list_->setAutoScroll(checked); +} + void MainWindow::resetPreviousFocus() { previous_focus_ = NULL; } diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp index 428a51f1f7..4d6e3905ac 100644 --- a/ui/qt/packet_list.cpp +++ b/ui/qt/packet_list.cpp @@ -60,11 +60,12 @@ #include <QScrollBar> #include <QTabWidget> #include <QTextEdit> +#include <QTimerEvent> #include <QTreeWidget> // To do: -// - Heading context menus // - Catch column reordering and rebuild the column list accoringly. +// - Use a timer to trigger automatic scrolling. // If we ever add the ability to open multiple capture files we might be // able to use something like QMap<capture_file *, PacketList *> to match @@ -72,6 +73,7 @@ static PacketList *gbl_cur_packet_list = NULL; const int max_comments_to_fetch_ = 20000000; // Arbitrary +const int tail_update_interval_ = 100; // Milliseconds. guint packet_list_append(column_info *cinfo, frame_data *fdata) @@ -135,13 +137,7 @@ packet_list_select_row_from_data(frame_data *fdata_needle) gboolean packet_list_check_end(void) { - if (gbl_cur_packet_list) { - QScrollBar *sb = gbl_cur_packet_list->verticalScrollBar(); - if (sb && sb->isVisible() && sb->value() == sb->maximum()) { - return TRUE; - } - } - return FALSE; + return FALSE; // GTK+ only. } void @@ -230,7 +226,9 @@ PacketList::PacketList(QWidget *parent) : byte_view_tab_(NULL), cap_file_(NULL), decode_as_(NULL), - ctx_column_(-1) + ctx_column_(-1), + capture_in_progress_(false), + tail_timer_id_(0) { QMenu *submenu, *subsubmenu; QAction *action; @@ -419,6 +417,8 @@ PacketList::PacketList(QWidget *parent) : connect(header(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(showHeaderMenu(QPoint))); connect(header(), SIGNAL(sectionResized(int,int,int)), this, SLOT(sectionResized(int,int,int))); + + connect(verticalScrollBar(), SIGNAL(actionTriggered(int)), this, SLOT(vScrollBarActionTriggered(int))); } void PacketList::setProtoTree (ProtoTree *proto_tree) { @@ -519,6 +519,27 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event) decode_as_->setData(QVariant()); } +// Auto scroll if: +// - We're not at the end +// - We are capturing +// - actionGoAutoScroll in the main UI is checked. +// - It's been more than tail_update_interval_ ms since we last scrolled +// - The last user-set vertical scrollbar position was at the end. + +// Using a timer assumes that we can save CPU overhead by updating +// periodically. If that's not the case we can dispense with it and call +// scrollToBottom() from rowsInserted(). +void PacketList::timerEvent(QTimerEvent *event) +{ + if (rows_inserted_ + && event->timerId() == tail_timer_id_ + && capture_in_progress_ + && tail_at_end_) { + scrollToBottom(); + rows_inserted_ = false; + } +} + void PacketList::markFramesReady() { packets_bar_update(); @@ -661,6 +682,18 @@ void PacketList::recolorPackets() redrawVisiblePackets(); } +void PacketList::setAutoScroll(bool enabled) +{ + tail_at_end_ = enabled; + if (enabled) { + scrollToBottom(); + if (tail_timer_id_ < 1) tail_timer_id_ = startTimer(tail_update_interval_); + } else if (tail_timer_id_ > 0) { + killTimer(tail_timer_id_); + tail_timer_id_ = 0; + } +} + void PacketList::freeze() { setUpdatesEnabled(false); @@ -1129,6 +1162,25 @@ void PacketList::sectionResized(int, int, int) } } +// We need to tell when the user has scrolled the packet list, either to +// the end or anywhere other than the end. +void PacketList::vScrollBarActionTriggered(int) +{ + // If we're scrolling with a mouse wheel or trackpad sliderPosition can end up + // past the end. + tail_at_end_ = (verticalScrollBar()->sliderPosition() >= verticalScrollBar()->maximum()); + + if (capture_in_progress_ && prefs.capture_auto_scroll) { + emit packetListScrolled(tail_at_end_); + } +} + +void PacketList::rowsInserted(const QModelIndex &parent, int start, int end) +{ + QTreeView::rowsInserted(parent, start, end); + rows_inserted_ = true; +} + /* * Editor modelines * diff --git a/ui/qt/packet_list.h b/ui/qt/packet_list.h index 04fcf74e2e..357533c67b 100644 --- a/ui/qt/packet_list.h +++ b/ui/qt/packet_list.h @@ -28,10 +28,12 @@ #include "proto_tree.h" #include "related_packet_delegate.h" -#include <QTreeView> #include <QMenu> +#include <QTime> +#include <QTreeView> class QAction; +class QTimerEvent; class PacketList : public QTreeView { @@ -63,12 +65,17 @@ public: void setPacketComment(QString new_comment); QString allPacketComments(); void recolorPackets(); + void setAutoScroll(bool enabled = true); + void setCaptureInProgress(bool in_progress = false) { capture_in_progress_ = in_progress; tail_at_end_ = in_progress; } protected: void showEvent (QShowEvent *); void selectionChanged (const QItemSelection & selected, const QItemSelection & deselected); void contextMenuEvent(QContextMenuEvent *event); + void timerEvent(QTimerEvent *event); +protected slots: + void rowsInserted(const QModelIndex &parent, int start, int end); private: PacketListModel *packet_list_model_; @@ -87,6 +94,10 @@ private: int header_ctx_column_; QAction *show_hide_separator_; QList<QAction *>show_hide_actions_; + bool capture_in_progress_; + int tail_timer_id_; + bool tail_at_end_; + bool rows_inserted_; void markFramesReady(); void setFrameMark(gboolean set, frame_data *fdata); @@ -94,12 +105,12 @@ private: void setFrameReftime(gboolean set, frame_data *fdata); void setColumnVisibility(); void initHeaderContextMenu(); - signals: void packetDissectionChanged(); void packetSelectionChanged(); void showPreferences(PreferencesDialog::PreferencesPane start_pane); void editColumn(int column); + void packetListScrolled(bool at_end); public slots: void setCaptureFile(capture_file *cf); @@ -124,6 +135,7 @@ private slots: void headerMenuTriggered(); void columnVisibilityTriggered(); void sectionResized(int, int, int); + void vScrollBarActionTriggered(int); }; #endif // PACKET_LIST_H diff --git a/ui/ui_util.h b/ui/ui_util.h index 7ebd59bd3d..b76e218951 100644 --- a/ui/ui_util.h +++ b/ui/ui_util.h @@ -74,7 +74,7 @@ void packet_list_queue_draw(void); void packet_list_select_first_row(void); void packet_list_select_last_row(void); void packet_list_moveto_end(void); -gboolean packet_list_check_end(void); +gboolean packet_list_check_end(void); /* GTK+ only */ gboolean packet_list_select_row_from_data(frame_data *fdata_needle); void packet_list_resize_column(gint col); |