summaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
authorMichal Labedzki <michal.labedzki@tieto.com>2015-02-20 15:30:23 +0100
committerGerald Combs <gerald@wireshark.org>2015-02-27 20:27:14 +0000
commit2d4817966ee88d2b163dca46e4df75e8f6262b7a (patch)
treed887a5bcee4b267d55556436f320bb32cd49c738 /ui
parent2462c0d35a113043b003a73b8b3fe31a674264bb (diff)
downloadwireshark-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.h2
-rw-r--r--ui/qt/capture_file.cpp1
-rw-r--r--ui/qt/main_window.cpp14
-rw-r--r--ui/qt/main_window.h3
-rw-r--r--ui/qt/main_window.ui14
-rw-r--r--ui/qt/main_window_slots.cpp10
-rw-r--r--ui/qt/packet_list.cpp70
-rw-r--r--ui/qt/packet_list.h16
-rw-r--r--ui/ui_util.h2
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&amp;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);