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 | |
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>
-rw-r--r-- | epan/prefs.c | 1 | ||||
-rw-r--r-- | file.c | 2 | ||||
-rw-r--r-- | image/toolbar/16x16/x-stay-last.png | bin | 267 -> 303 bytes | |||
-rw-r--r-- | image/toolbar/16x16/x-stay-last.svg | 44 | ||||
-rw-r--r-- | image/toolbar/16x16/x-stay-last@2x.png | bin | 425 -> 380 bytes | |||
-rw-r--r-- | image/toolbar/24x24/x-stay-last.png | bin | 295 -> 313 bytes | |||
-rw-r--r-- | image/toolbar/24x24/x-stay-last.svg | 46 | ||||
-rw-r--r-- | image/toolbar/24x24/x-stay-last@2x.png | bin | 479 -> 408 bytes | |||
-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 |
17 files changed, 177 insertions, 48 deletions
diff --git a/epan/prefs.c b/epan/prefs.c index 7c90d8570d..00890d9c66 100644 --- a/epan/prefs.c +++ b/epan/prefs.c @@ -2416,6 +2416,7 @@ prefs_register_modules(void) prefs_register_bool_preference(capture_module, "real_time_update", "Update packet list in real time during capture", "Update packet list in real time during capture?", &prefs.capture_real_time); + /* We might want to make this a "recent" setting. */ prefs_register_bool_preference(capture_module, "auto_scroll", "Scroll packet list during capture", "Scroll packet list during capture?", &prefs.capture_auto_scroll); @@ -102,7 +102,7 @@ #endif #ifdef HAVE_LIBPCAP -gboolean auto_scroll_live; +gboolean auto_scroll_live; /* GTK+ only? */ #endif static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt, diff --git a/image/toolbar/16x16/x-stay-last.png b/image/toolbar/16x16/x-stay-last.png Binary files differindex e5bb6ea5b5..68629cc289 100644 --- a/image/toolbar/16x16/x-stay-last.png +++ b/image/toolbar/16x16/x-stay-last.png diff --git a/image/toolbar/16x16/x-stay-last.svg b/image/toolbar/16x16/x-stay-last.svg index acec8379f7..2962556869 100644 --- a/image/toolbar/16x16/x-stay-last.svg +++ b/image/toolbar/16x16/x-stay-last.svg @@ -14,7 +14,7 @@ id="svg2" version="1.1" inkscape:version="0.48.2 r9819" - sodipodi:docname="x-colorize-packets.svg" + sodipodi:docname="x-stay-last.svg" inkscape:export-filename="x-colorize-packets.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90"> @@ -27,16 +27,16 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="34.9375" - inkscape:cx="7.7733362" + inkscape:zoom="39.25" + inkscape:cx="8" inkscape:cy="8" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" - inkscape:window-width="1028" - inkscape:window-height="728" - inkscape:window-x="283" - inkscape:window-y="792" + inkscape:window-width="1263" + inkscape:window-height="799" + inkscape:window-x="65" + inkscape:window-y="1" inkscape:window-maximized="0"> <inkscape:grid type="xygrid" @@ -54,7 +54,7 @@ <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> + <dc:title /> </cc:Work> </rdf:RDF> </metadata> @@ -95,7 +95,7 @@ id="path4099" inkscape:connector-curvature="0" /> <path - style="fill:#204a87;stroke:#ef2929;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" + style="fill:#204a87;stroke:#babdb6;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" d="m 1.4821429,1040.8622 c 13.0357141,0 13.0357141,0 13.0357141,0" id="path4103" inkscape:connector-curvature="0" /> @@ -103,12 +103,12 @@ inkscape:connector-curvature="0" id="path4105" d="m 1.5185185,1043.8622 c 12.9629625,0 12.9629625,0 12.9629625,0" - style="fill:none;stroke:#3465a4;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" /> + style="fill:none;stroke:#babdb6;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" /> <path inkscape:connector-curvature="0" id="path4109" d="m 1.5185185,1046.8622 c 12.9629625,0 12.9629625,0 12.9629625,0" - style="fill:none;stroke:#75507b;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" /> + style="fill:none;stroke:#babdb6;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" /> <path style="fill:none;stroke:#2e3436;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" d="m 1.5,1050.8622 c 13,0 13,0 13,0" @@ -116,7 +116,7 @@ inkscape:connector-curvature="0" /> <path sodipodi:type="star" - style="fill:#c4a000;fill-opacity:1;stroke:#725000;stroke-width:3.77809595999999992;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + style="fill:#c4a000;fill-opacity:1;stroke:#725000;stroke-width:3.77809596;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" id="path4205" sodipodi:sides="3" sodipodi:cx="28" @@ -129,7 +129,25 @@ inkscape:rounded="1" inkscape:randomized="0" d="M 28,14 C 17.607695,14 17.607695,14 22.803847,5.0000001 28,-4 28,-4 33.196152,4.9999999 38.392305,14 38.392305,14 28,14 z" - transform="matrix(-0.36780134,0,0,-0.19047619,21.631938,1050.5289)" + transform="matrix(-0.36780134,0,0,-0.19047619,33.631938,1050.5289)" inkscape:transform-center-y="0.35714706" /> + <path + inkscape:transform-center-x="-3.8849402e-05" + transform="matrix(-0.40653866,0,0,-0.25396825,22.383082,1050.4178)" + d="M 28,14 C 17.607695,14 17.607695,14 22.803847,5.0000001 28,-4 28,-4 33.196152,4.9999999 38.392305,14 38.392305,14 28,14 z" + inkscape:randomized="0" + inkscape:rounded="1" + inkscape:flatsided="true" + sodipodi:arg2="2.6179939" + sodipodi:arg1="1.5707963" + sodipodi:r2="3" + sodipodi:r1="6" + sodipodi:cy="8" + sodipodi:cx="28" + sodipodi:sides="3" + id="path4590" + style="fill:#3465a4;fill-opacity:1;stroke:#3465a4;stroke-width:3.11214161;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + sodipodi:type="star" + inkscape:transform-center-y="0.47633785" /> </g> </svg> diff --git a/image/toolbar/16x16/x-stay-last@2x.png b/image/toolbar/16x16/x-stay-last@2x.png Binary files differindex cb8ee9eb88..23c73aab9a 100644 --- a/image/toolbar/16x16/x-stay-last@2x.png +++ b/image/toolbar/16x16/x-stay-last@2x.png diff --git a/image/toolbar/24x24/x-stay-last.png b/image/toolbar/24x24/x-stay-last.png Binary files differindex 06b9d30bcd..9c04995d80 100644 --- a/image/toolbar/24x24/x-stay-last.png +++ b/image/toolbar/24x24/x-stay-last.png diff --git a/image/toolbar/24x24/x-stay-last.svg b/image/toolbar/24x24/x-stay-last.svg index 06ce2fdc8b..2bbd401b6f 100644 --- a/image/toolbar/24x24/x-stay-last.svg +++ b/image/toolbar/24x24/x-stay-last.svg @@ -27,16 +27,16 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="23.291667" - inkscape:cx="10.503891" + inkscape:zoom="23.369223" + inkscape:cx="15.441568" inkscape:cy="12" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" - inkscape:window-width="1028" - inkscape:window-height="728" - inkscape:window-x="132" - inkscape:window-y="821" + inkscape:window-width="1300" + inkscape:window-height="732" + inkscape:window-x="70" + inkscape:window-y="702" inkscape:window-maximized="0"> <inkscape:grid type="xygrid" @@ -54,7 +54,7 @@ <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> + <dc:title /> </cc:Work> </rdf:RDF> </metadata> @@ -97,9 +97,9 @@ inkscape:connector-curvature="0" id="path4115" d="m 1.5,1032.8622 c 21,0 21,0 21,0" - style="fill:#ef2929;stroke:#ef2929;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" /> + style="fill:#babdb6;stroke:#babdb6;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" /> <path - style="fill:none;stroke:#73d216;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" + style="fill:#babdb6;stroke:#babdb6;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" d="m 1.4999999,1038.8622 c 20.9999991,0 20.9999991,0 20.9999991,0" id="path4117" inkscape:connector-curvature="0" /> @@ -107,9 +107,9 @@ inkscape:connector-curvature="0" id="path4119" d="m 1.4999999,1035.8622 c 20.9999991,0 20.9999991,0 20.9999991,0" - style="fill:none;stroke:#3465a4;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" /> + style="fill:#babdb6;stroke:#babdb6;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" /> <path - style="fill:none;stroke:#3465a4;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" + style="fill:#babdb6;stroke:#babdb6;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" d="m 1.4999999,1041.8622 c 20.9999991,0 20.9999991,0 20.9999991,0" id="path4121" inkscape:connector-curvature="0" /> @@ -117,9 +117,9 @@ inkscape:connector-curvature="0" id="path4123" d="m 1.5,1047.8622 c 21,0 21,0 21,0" - style="fill:#f57900;stroke:#f57900;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" /> + style="fill:#babdb6;stroke:#babdb6;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" /> <path - style="fill:none;stroke:#75507b;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" + style="fill:#babdb6;stroke:#babdb6;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" d="m 1.4999999,1044.8622 c 20.9999991,0 20.9999991,0 20.9999991,0" id="path4125" inkscape:connector-curvature="0" /> @@ -143,7 +143,25 @@ inkscape:rounded="1" inkscape:randomized="0" d="M 28,14 C 17.607695,14 17.607695,14 22.803847,5.0000001 28,-4 28,-4 33.196152,4.9999999 38.392305,14 38.392305,14 28,14 z" - transform="matrix(0.58076952,0,0,-0.31746032,1.2384534,1050.3066)" + transform="matrix(0.58076952,0,0,-0.31746032,15.238453,1050.3066)" inkscape:transform-center-y="0.59532957" /> + <path + inkscape:transform-center-x="-6.9566908e-05" + transform="matrix(-0.58076952,0,0,-0.31746032,32.761547,1050.3066)" + d="M 28,14 C 17.607695,14 17.607695,14 22.803847,5.0000001 28,-4 28,-4 33.196152,4.9999999 38.392305,14 38.392305,14 28,14 z" + inkscape:randomized="0" + inkscape:rounded="1" + inkscape:flatsided="true" + sodipodi:arg2="2.6179939" + sodipodi:arg1="1.5707963" + sodipodi:r2="3" + sodipodi:r1="6" + sodipodi:cy="8" + sodipodi:cx="28" + sodipodi:sides="3" + id="path4550" + style="fill:#3465a4;fill-opacity:1;stroke:#3465a4;stroke-width:2.32891345;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + sodipodi:type="star" + inkscape:transform-center-y="0.5953435" /> </g> </svg> diff --git a/image/toolbar/24x24/x-stay-last@2x.png b/image/toolbar/24x24/x-stay-last@2x.png Binary files differindex fff5b22a0f..a66c2a8007 100644 --- a/image/toolbar/24x24/x-stay-last@2x.png +++ b/image/toolbar/24x24/x-stay-last@2x.png 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); |