aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2015-06-11 15:53:51 -0700
committerGerald Combs <gerald@wireshark.org>2015-07-16 22:57:31 +0000
commit255d53dfc11fa49eadd30fefe3ed5950b03e6659 (patch)
tree1404c49ffb41d4f1245889f24e0e260e4cc011fd /ui
parent3e059c9d1fedf9c890f910fa88cc2ef99fb1e470 (diff)
Draw packet colors in the packet list scrollbar.
Inspired by (but not as fancy as) Packet Fence, an enhancement written for Ethereal a loooong time ago by Martin Visser: https://www.wireshark.org/lists/ethereal-dev/200011/msg00122.html Several text editors call this a "minimap". Color each scrollbar raster line to match the color of up to 7 packets. Note in the comments why this number was chosen. If we have any flagged frames (marked, ignored, time ref) indicate them on either side of the scrolbar. Handle HiDPI (retina) displays. This means that your window size depends on the height of your scrollbar *and* your monitor resolution. Qt's idea of the slider rect doesn't match up with the slider on OS X. This might be local to my build -- I can replicate it Qt Creator. Change-Id: Ia089d2d766ce37bab11e22d1a5721b4908935304 Reviewed-on: https://code.wireshark.org/review/8982 Reviewed-by: Gerald Combs <gerald@wireshark.org> Tested-by: Gerald Combs <gerald@wireshark.org>
Diffstat (limited to 'ui')
-rw-r--r--ui/qt/CMakeLists.txt2
-rw-r--r--ui/qt/Makefile.common3
-rw-r--r--ui/qt/Wireshark.pro2
-rw-r--r--ui/qt/color_utils.cpp2
-rw-r--r--ui/qt/color_utils.h2
-rw-r--r--ui/qt/overlay_scroll_bar.cpp158
-rw-r--r--ui/qt/overlay_scroll_bar.h62
-rw-r--r--ui/qt/packet_list.cpp232
-rw-r--r--ui/qt/packet_list.h15
-rw-r--r--ui/qt/packet_list_model.cpp18
-rw-r--r--ui/qt/packet_list_model.h1
-rw-r--r--ui/qt/packet_list_record.h1
12 files changed, 483 insertions, 15 deletions
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index 35b2d2e2f4..43bfd7bbd8 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -81,6 +81,7 @@ set(WIRESHARK_QT_HEADERS
main_window_preferences_frame.h
manage_interfaces_dialog.h
module_preferences_scroll_area.h
+ overlay_scroll_bar.h
packet_comment_dialog.h
packet_dialog.h
packet_format_group_box.h
@@ -206,6 +207,7 @@ set(WIRESHARK_QT_SRC
main_window_slots.cpp
manage_interfaces_dialog.cpp
module_preferences_scroll_area.cpp
+ overlay_scroll_bar.cpp
packet_comment_dialog.cpp
packet_dialog.cpp
packet_format_group_box.cpp
diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common
index c1a7479e54..5264100aec 100644
--- a/ui/qt/Makefile.common
+++ b/ui/qt/Makefile.common
@@ -65,6 +65,7 @@ NODIST_GENERATED_HEADER_FILES = \
ui_main_window_preferences_frame.h \
ui_manage_interfaces_dialog.h \
ui_module_preferences_scroll_area.h \
+ ui_overlay_scroll_bar.h \
ui_packet_comment_dialog.h \
ui_packet_dialog.h \
ui_packet_format_group_box.h \
@@ -190,6 +191,7 @@ MOC_HDRS = \
main_window_preferences_frame.h \
manage_interfaces_dialog.h \
module_preferences_scroll_area.h \
+ overlay_scroll_bar.h \
packet_comment_dialog.h \
packet_dialog.h \
packet_format_group_box.h \
@@ -421,6 +423,7 @@ WIRESHARK_QT_SRC = \
main_window_slots.cpp \
manage_interfaces_dialog.cpp \
module_preferences_scroll_area.cpp \
+ overlay_scroll_bar.cpp \
packet_comment_dialog.cpp \
packet_dialog.cpp \
packet_format_group_box.cpp \
diff --git a/ui/qt/Wireshark.pro b/ui/qt/Wireshark.pro
index 3aadf34e63..d2fb545d02 100644
--- a/ui/qt/Wireshark.pro
+++ b/ui/qt/Wireshark.pro
@@ -314,6 +314,7 @@ HEADERS += $$HEADERS_WS_C \
main_window_preferences_frame.h \
manage_interfaces_dialog.h \
module_preferences_scroll_area.h \
+ overlay_scroll_bar.h \
packet_comment_dialog.h \
packet_dialog.h \
packet_format_group_box.h \
@@ -692,6 +693,7 @@ SOURCES += \
main_window_slots.cpp \
manage_interfaces_dialog.cpp \
module_preferences_scroll_area.cpp \
+ overlay_scroll_bar.cpp \
packet_comment_dialog.cpp \
packet_dialog.cpp \
packet_format_group_box.cpp \
diff --git a/ui/qt/color_utils.cpp b/ui/qt/color_utils.cpp
index f63b2a0378..dbb93530f5 100644
--- a/ui/qt/color_utils.cpp
+++ b/ui/qt/color_utils.cpp
@@ -76,7 +76,7 @@ ColorUtils::ColorUtils(QObject *parent) :
{
}
-QColor ColorUtils::fromColorT (color_t *color) {
+QColor ColorUtils::fromColorT (const color_t *color) {
if (!color) return QColor();
return QColor(color->red >> 8, color->green >> 8, color->blue >> 8);
}
diff --git a/ui/qt/color_utils.h b/ui/qt/color_utils.h
index a263f76d23..30f8b170fd 100644
--- a/ui/qt/color_utils.h
+++ b/ui/qt/color_utils.h
@@ -38,7 +38,7 @@ class ColorUtils : public QObject
public:
explicit ColorUtils(QObject *parent = 0);
- static QColor fromColorT(color_t *color);
+ static QColor fromColorT(const color_t *color);
static QColor fromColorT(color_t color);
static const color_t toColorT(const QColor color);
static QRgb alphaBlend(const QColor &color1, const QColor &color2, qreal alpha);
diff --git a/ui/qt/overlay_scroll_bar.cpp b/ui/qt/overlay_scroll_bar.cpp
new file mode 100644
index 0000000000..6990bd57cb
--- /dev/null
+++ b/ui/qt/overlay_scroll_bar.cpp
@@ -0,0 +1,158 @@
+/* overlay_scroll_bar.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "overlay_scroll_bar.h"
+
+#include <QPainter>
+#include <QResizeEvent>
+#include <QStyle>
+#include <QStyleOptionSlider>
+
+// To do:
+// - The slider hole doesn't match up with the slider on OS X + Qt 5.3.2.
+
+OverlayScrollBar::OverlayScrollBar(Qt::Orientation orientation, QWidget *parent) :
+ QScrollBar(orientation, parent = 0),
+ near_overlay_(QImage()),
+ far_overlay_(QImage())
+{}
+
+QSize OverlayScrollBar::sizeHint() const
+{
+ return QSize(QScrollBar::sizeHint().width() + (far_overlay_.width() * 2), QScrollBar::sizeHint().height());
+}
+
+void OverlayScrollBar::setNearOverlayImage(QImage &overlay_image)
+{
+ near_overlay_ = overlay_image;
+ update();
+}
+
+void OverlayScrollBar::setFarOverlayImage(QImage &overlay_image)
+{
+ int old_width = far_overlay_.width();
+ far_overlay_ = overlay_image;
+ if (old_width != far_overlay_.width()) {
+ updateGeometry();
+ }
+ update();
+}
+
+QRect OverlayScrollBar::grooveRect()
+{
+ QStyleOptionSlider opt;
+ initStyleOption(&opt);
+
+ return style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarGroove, this);
+}
+
+void OverlayScrollBar::paintEvent(QPaintEvent *event)
+{
+ QScrollBar::paintEvent(event);
+ if (!near_overlay_.isNull()) {
+ QRect groove_rect = grooveRect();
+ QSize gr_size = groove_rect.size();
+#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
+ gr_size *= devicePixelRatio();
+#endif
+ QImage groove_overlay(gr_size, QImage::Format_ARGB32_Premultiplied);
+ groove_overlay.fill(Qt::transparent);
+
+ // Draw the image supplied by the packet list and apply a mask.
+ QPainter go_painter(&groove_overlay);
+ go_painter.setPen(Qt::NoPen);
+
+ int fo_width = far_overlay_.width();
+ QRect near_dest(fo_width, 0, gr_size.width() - (fo_width * 2), gr_size.height());
+ go_painter.drawImage(near_dest, near_overlay_.scaled(near_dest.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+ if (fo_width > 0) {
+ QRect far_dest(0, 0, fo_width, gr_size.height());
+ go_painter.drawImage(far_dest, far_overlay_);
+ far_dest.moveLeft(gr_size.width() - fo_width);
+ go_painter.drawImage(far_dest, far_overlay_.mirrored(true, false));
+ }
+ QRect near_outline(near_dest);
+ near_outline.adjust(0, 0, -1, -1);
+ go_painter.save();
+ QColor no_fg(palette().text().color());
+ no_fg.setAlphaF(0.25);
+ go_painter.setPen(no_fg);
+ go_painter.drawRect(near_outline);
+ go_painter.restore();
+
+#if 0
+ // Fade in from the left and right.
+ go_painter.save();
+ go_painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
+ QLinearGradient fade(0, 0, groove_overlay.width(), 0);
+ fade.setColorAt(0, Qt::transparent);
+ fade.setColorAt(0.2, Qt::white);
+ fade.setColorAt(0.8, Qt::white);
+ fade.setColorAt(1, Qt::transparent);
+
+ go_painter.setBrush(fade);
+ go_painter.drawRect(groove_overlay.rect());
+ go_painter.restore();
+#endif
+
+ // Punch a hole for the slider.
+ QStyleOptionSlider opt;
+ initStyleOption(&opt);
+
+ QRect slider_rect = style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarSlider, this);
+#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
+ slider_rect.setHeight(slider_rect.height() * devicePixelRatio());
+ slider_rect.setWidth(slider_rect.width() * devicePixelRatio());
+ slider_rect.moveTop((slider_rect.top() - groove_rect.top()) * devicePixelRatio());
+#else
+ slider_rect.moveTop(slider_rect.top() - groove_rect.top());
+#endif
+ slider_rect.adjust(fo_width + 1, 1, -1 - fo_width, -1);
+
+ go_painter.save();
+ go_painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
+ QColor slider_hole(Qt::white);
+ slider_hole.setAlphaF(0.1);
+ go_painter.setBrush(slider_hole);
+ go_painter.drawRect(slider_rect);
+ go_painter.restore();
+
+ // Draw over the groove.
+ QPainter painter(this);
+#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
+ groove_overlay.setDevicePixelRatio(devicePixelRatio());
+#endif
+ painter.drawImage(groove_rect.topLeft(), groove_overlay);
+ }
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/qt/overlay_scroll_bar.h b/ui/qt/overlay_scroll_bar.h
new file mode 100644
index 0000000000..76e7612292
--- /dev/null
+++ b/ui/qt/overlay_scroll_bar.h
@@ -0,0 +1,62 @@
+/* overlay_scroll_bar.h
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __OVERLAY_SCROLL_BAR_H__
+#define __OVERLAY_SCROLL_BAR_H__
+
+#include <QScrollBar>
+
+class OverlayScrollBar : public QScrollBar
+{
+ Q_OBJECT
+
+public:
+ OverlayScrollBar(Qt::Orientation orientation, QWidget * parent = 0);
+
+ virtual QSize sizeHint() const;
+
+ // Images are assumed to be 1 pixel wide and grooveRect.height() high.
+ void setNearOverlayImage(QImage &overlay_image);
+ void setFarOverlayImage(QImage &overlay_image);
+ QRect grooveRect();
+
+protected:
+ virtual void paintEvent(QPaintEvent * event);
+
+private:
+ QImage near_overlay_;
+ QImage far_overlay_;
+};
+
+#endif // __OVERLAY_SCROLL_BAR_H__
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp
index 4f295971d0..8aee922ace 100644
--- a/ui/qt/packet_list.cpp
+++ b/ui/qt/packet_list.cpp
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include "packet_list.h"
+
#include "config.h"
#include <glib.h>
@@ -30,16 +32,10 @@
#include <epan/column-info.h>
#include <epan/column.h>
+#include <epan/ipproto.h>
#include <epan/packet.h>
#include <epan/prefs.h>
-#include "packet_list.h"
-#include "proto_tree.h"
-#include "wireshark_application.h"
-#include "epan/ipproto.h"
-
-#include "qt_ui_utils.h"
-
#include "ui/main_statusbar.h"
#include "ui/packet_list_utils.h"
#include "ui/preference_utils.h"
@@ -47,17 +43,30 @@
#include "ui/recent_utils.h"
#include "ui/ui_util.h"
#include "ui/utf8_entities.h"
+#include "ui/util.h"
#include "wsutil/str_util.h"
+#include "color.h"
+#include "color_filters.h"
#include "frame_tvbuff.h"
+#include "color_utils.h"
+#include "overlay_scroll_bar.h"
+#include "proto_tree.h"
+#include "qt_ui_utils.h"
+#include "wireshark_application.h"
+
#include <QAction>
#include <QActionGroup>
#include <QContextMenuEvent>
+#include <QtCore/qmath.h>
+#include <QElapsedTimer>
#include <QFontMetrics>
#include <QHeaderView>
#include <QMessageBox>
+#include <QPainter>
+#include <QScreen>
#include <QScrollBar>
#include <QTabWidget>
#include <QTextEdit>
@@ -74,6 +83,7 @@ static PacketList *gbl_cur_packet_list = NULL;
const int max_comments_to_fetch_ = 20000000; // Arbitrary
const int tail_update_interval_ = 100; // Milliseconds.
+const int overlay_update_interval_ = 100; // 250; // Milliseconds.
guint
packet_list_append(column_info *, frame_data *fdata)
@@ -224,6 +234,8 @@ PacketList::PacketList(QWidget *parent) :
cap_file_(NULL),
decode_as_(NULL),
ctx_column_(-1),
+ create_near_overlay_(true),
+ create_far_overlay_(true),
capture_in_progress_(false),
tail_timer_id_(0),
rows_inserted_(false)
@@ -237,6 +249,10 @@ PacketList::PacketList(QWidget *parent) :
setAccessibleName("Packet list");
setItemDelegateForColumn(0, &related_packet_delegate_);
+ overlay_sb_ = new OverlayScrollBar(Qt::Vertical, this);
+ setVerticalScrollBar(overlay_sb_);
+ overlay_timer_id_ = startTimer(overlay_update_interval_);
+
packet_list_model_ = new PacketListModel(this, cap_file_);
setModel(packet_list_model_);
sortByColumn(-1, Qt::AscendingOrder);
@@ -578,15 +594,27 @@ void PacketList::timerEvent(QTimerEvent *event)
{
QTreeView::timerEvent(event);
- if (rows_inserted_
- && event->timerId() == tail_timer_id_
+ if (event->timerId() == tail_timer_id_
+ && rows_inserted_
&& capture_in_progress_
&& tail_at_end_) {
scrollToBottom();
rows_inserted_ = false;
+ } else if (event->timerId() == overlay_timer_id_ && !capture_in_progress_) {
+ if (create_near_overlay_) drawNearOverlay();
+ if (create_far_overlay_) drawFarOverlay();
}
}
+void PacketList::paintEvent(QPaintEvent *event)
+{
+ // XXX This is overkill, but there are quite a few events that
+ // require a new overlay, e.g. page up/down, scrolling, column
+ // resizing, etc.
+ create_near_overlay_ = true;
+ QTreeView::paintEvent(event);
+}
+
void PacketList::setColumnVisibility()
{
for (int i = 0; i < prefs.num_cols; i++) {
@@ -671,6 +699,7 @@ void PacketList::columnsChanged()
build_column_format_array(&cap_file_->cinfo, prefs.num_cols, FALSE);
packet_list_model_->recreateVisibleRows(); // Calls PacketListRecord::resetColumns
setColumnVisibility();
+ create_far_overlay_ = true;
redrawVisiblePackets();
}
@@ -761,6 +790,12 @@ void PacketList::clear() {
proto_tree_->clear();
byte_view_tab_->clear();
+ QImage overlay;
+ overlay_sb_->setNearOverlayImage(overlay);
+ overlay_sb_->setFarOverlayImage(overlay);
+ create_near_overlay_ = true;
+ create_far_overlay_ = true;
+
/* XXX is this correct in all cases?
* Reset the sort column, use packetlist as model in case the list is frozen.
*/
@@ -859,6 +894,12 @@ QString &PacketList::getFilterFromRowAndColumn()
return filter;
}
+void PacketList::resetColorized()
+{
+ packet_list_model_->resetColorized();
+ update();
+}
+
QString PacketList::packetComment()
{
int row = currentIndex().row();
@@ -936,6 +977,7 @@ void PacketList::setCaptureFile(capture_file *cf)
}
cap_file_ = cf;
packet_list_model_->setCaptureFile(cf);
+ create_near_overlay_ = true;
}
void PacketList::setMonospaceFont(const QFont &mono_font)
@@ -1004,6 +1046,7 @@ void PacketList::markFrame()
if (!cap_file_ || !packet_list_model_) return;
packet_list_model_->toggleFrameMark(currentIndex());
+ create_far_overlay_ = true;
packets_bar_update();
}
@@ -1012,6 +1055,7 @@ void PacketList::markAllDisplayedFrames(bool set)
if (!cap_file_ || !packet_list_model_) return;
packet_list_model_->setDisplayedFrameMark(set);
+ create_far_overlay_ = true;
packets_bar_update();
}
@@ -1020,6 +1064,7 @@ void PacketList::ignoreFrame()
if (!cap_file_ || !packet_list_model_) return;
packet_list_model_->toggleFrameIgnore(currentIndex());
+ create_far_overlay_ = true;
int sb_val = verticalScrollBar()->value(); // Surely there's a better way to keep our position?
setUpdatesEnabled(false);
emit packetDissectionChanged();
@@ -1032,6 +1077,7 @@ void PacketList::ignoreAllDisplayedFrames(bool set)
if (!cap_file_ || !packet_list_model_) return;
packet_list_model_->setDisplayedFrameIgnore(set);
+ create_far_overlay_ = true;
emit packetDissectionChanged();
}
@@ -1039,12 +1085,14 @@ void PacketList::setTimeReference()
{
if (!cap_file_ || !packet_list_model_) return;
packet_list_model_->toggleFrameRefTime(currentIndex());
+ create_far_overlay_ = true;
}
void PacketList::unsetAllTimeReferences()
{
if (!cap_file_ || !packet_list_model_) return;
packet_list_model_->unsetAllFrameRefTime();
+ create_far_overlay_ = true;
}
void PacketList::showHeaderMenu(QPoint pos)
@@ -1223,6 +1271,172 @@ void PacketList::vScrollBarActionTriggered(int)
}
}
+// Goal: Overlay the packet list scroll bar with the colors of all of the
+// packets.
+// Try 1: Average packet colors in each scroll bar raster line. This has
+// two problems: It's easy to wash out colors and we dissect every packet.
+// Try 2: Color across a 5000 or 10000 packet window. We still end up washing
+// out colors.
+// Try 3: One packet per vertical scroll bar pixel. This seems to work best
+// but has the smallest window.
+// Try 4: Use a multiple of the scroll bar heigh and scale the image down
+// using Qt::SmoothTransformation. This gives us more packets per raster
+// line.
+
+// Odd (prime?) numbers resulted in fewer scaling artifacts. A multiplier
+// of 9 washed out colors a little too much.
+const int height_multiplier_ = 7;
+void PacketList::drawNearOverlay()
+{
+ if (!cap_file_ || cap_file_->state != FILE_READ_DONE) return;
+
+ if (create_near_overlay_) {
+ create_near_overlay_ = false;
+ }
+
+ qreal dp_ratio = 1.0;
+#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
+ dp_ratio = overlay_sb_->devicePixelRatio();
+#endif
+ int o_height = overlay_sb_->height() * dp_ratio * height_multiplier_;
+ int o_rows = qMin(packet_list_model_->rowCount(), o_height);
+
+ if (recent.packet_list_colorize && o_rows > 0) {
+ QImage overlay(1, o_height, QImage::Format_ARGB32_Premultiplied);
+
+ QPainter painter(&overlay);
+#if 0
+ QElapsedTimer timer;
+ timer.start();
+#endif
+
+ overlay.fill(Qt::transparent);
+
+ int cur_line = 0;
+ int start = 0;
+
+ if (packet_list_model_->rowCount() > o_height) {
+ start += ((double) overlay_sb_->value() / overlay_sb_->maximum()) * (packet_list_model_->rowCount() - o_rows);
+ }
+ int end = start + o_rows;
+ for (int row = start; row < end; row++) {
+ packet_list_model_->ensureRowColorized(row);
+
+#if 0
+ // Try to remain responsive for large captures.
+ if (timer.elapsed() > update_time_) {
+ wsApp->processEvents();
+ if (!cap_file_ || cap_file_->state != FILE_READ_DONE) {
+ create_overlay_ = true;
+ return;
+ }
+ timer.restart();
+ }
+#endif
+
+ frame_data *fdata = packet_list_model_->getRowFdata(row);
+ const color_t *bgcolor = NULL;
+ if (fdata->color_filter) {
+ const color_filter_t *color_filter = (const color_filter_t *) fdata->color_filter;
+ bgcolor = &color_filter->bg_color;
+ }
+
+ int next_line = (row - start) * o_height / o_rows;
+ if (bgcolor) {
+ QColor color(ColorUtils::fromColorT(bgcolor));
+
+ painter.setPen(color);
+ painter.drawLine(0, cur_line, 0, next_line);
+ }
+ cur_line = next_line;
+ }
+
+ overlay_sb_->setNearOverlayImage(overlay);
+ } else {
+ QImage overlay;
+ overlay_sb_->setNearOverlayImage(overlay);
+ }
+}
+
+void PacketList::drawFarOverlay()
+{
+ if (!cap_file_ || cap_file_->state != FILE_READ_DONE) return;
+
+ if (create_far_overlay_) {
+ create_far_overlay_ = false;
+ }
+
+ qreal dp_ratio = 1.0;
+#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
+ dp_ratio = overlay_sb_->devicePixelRatio();
+#endif
+ int o_width = 2 * dp_ratio;
+ int o_height = overlay_sb_->height() * dp_ratio;
+ int pl_rows = packet_list_model_->rowCount();
+
+ if (recent.packet_list_colorize && pl_rows > 0) {
+ // Create a tall image here. OverlayScrollBar will scale it to fit.
+ QImage overlay(o_width, o_height, QImage::Format_ARGB32_Premultiplied);
+
+ QPainter painter(&overlay);
+ painter.setRenderHint(QPainter::Antialiasing);
+#if 0
+ QElapsedTimer timer;
+ timer.start();
+#endif
+
+ // The default "marked" background is black and the default "ignored"
+ // background is white. Instead of trying to figure out if our
+ // available colors will show up, just use the palette's background
+ // here and foreground below.
+ overlay.fill(palette().base().color());
+ QColor arrow_fg = palette().text().color();
+ arrow_fg.setAlphaF(0.3);
+ painter.setPen(arrow_fg);
+ painter.setBrush(arrow_fg);
+
+ bool have_far = false;
+ for (int row = 0; row < pl_rows; row++) {
+#if 0
+ // Try to remain responsive for large captures.
+ if (timer.elapsed() > update_time_) {
+ wsApp->processEvents();
+ if (!cap_file_ || cap_file_->state != FILE_READ_DONE) {
+ create_overlay_ = true;
+ return;
+ }
+ timer.restart();
+ }
+#endif
+
+ frame_data *fdata = packet_list_model_->getRowFdata(row);
+ bool marked = false;
+ if (fdata->flags.marked || fdata->flags.ref_time || fdata->flags.ignored) {
+ marked = true;
+ }
+
+ if (marked) {
+ int new_line = (row) * o_height / pl_rows;
+
+ QPointF points[3] = {
+ QPointF(o_width, new_line),
+ QPointF(0, new_line - (o_width * 0.7)),
+ QPointF(0, new_line + (o_width * 0.7))
+ };
+ painter.drawPolygon(points, 3);
+ have_far = true;
+ }
+ }
+
+ if (have_far) {
+ overlay_sb_->setFarOverlayImage(overlay);
+ return;
+ }
+ QImage null_overlay;
+ overlay_sb_->setFarOverlayImage(null_overlay);
+ }
+}
+
void PacketList::rowsInserted(const QModelIndex &parent, int start, int end)
{
QTreeView::rowsInserted(parent, start, end);
diff --git a/ui/qt/packet_list.h b/ui/qt/packet_list.h
index d1059aabc1..ae7b751281 100644
--- a/ui/qt/packet_list.h
+++ b/ui/qt/packet_list.h
@@ -33,6 +33,8 @@
#include <QTime>
#include <QTreeView>
+class OverlayScrollBar;
+
class QAction;
class QTimerEvent;
@@ -62,6 +64,7 @@ public:
void writeRecent(FILE *rf);
bool contextMenuActive();
QString &getFilterFromRowAndColumn();
+ void resetColorized();
QString packetComment();
void setPacketComment(QString new_comment);
QString allPacketComments();
@@ -70,10 +73,11 @@ public:
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 showEvent(QShowEvent *);
+ void selectionChanged(const QItemSelection & selected, const QItemSelection & deselected);
void contextMenuEvent(QContextMenuEvent *event);
void timerEvent(QTimerEvent *event);
+ void paintEvent(QPaintEvent *event);
protected slots:
void rowsInserted(const QModelIndex &parent, int start, int end);
@@ -89,6 +93,11 @@ private:
QAction *decode_as_;
int ctx_column_;
QByteArray column_state_;
+ OverlayScrollBar *overlay_sb_;
+ int overlay_timer_id_;
+ bool create_near_overlay_;
+ bool create_far_overlay_;
+ QVector<QRgb> overlay_colors_;
RelatedPacketDelegate related_packet_delegate_;
QMenu header_ctx_menu_;
@@ -142,6 +151,8 @@ private slots:
void sectionResized(int col, int, int new_width);
void sectionMoved(int, int, int);
void vScrollBarActionTriggered(int);
+ void drawFarOverlay();
+ void drawNearOverlay();
};
#endif // PACKET_LIST_H
diff --git a/ui/qt/packet_list_model.cpp b/ui/qt/packet_list_model.cpp
index 3de636d947..5fb77eecbc 100644
--- a/ui/qt/packet_list_model.cpp
+++ b/ui/qt/packet_list_model.cpp
@@ -34,7 +34,9 @@
#include "color_filters.h"
#include "frame_tvbuff.h"
+#include "color_utils.h"
#include "wireshark_application.h"
+
#include <QColor>
#include <QFontMetrics>
#include <QModelIndex>
@@ -398,7 +400,7 @@ QVariant PacketListModel::data(const QModelIndex &d_index, int role) const
} else {
return QVariant();
}
- return QColor(color->red >> 8, color->green >> 8, color->blue >> 8);
+ return ColorUtils::fromColorT(color);
case Qt::ForegroundRole:
if (fdata->flags.ignored) {
color = &prefs.gui_ignored_fg;
@@ -410,7 +412,7 @@ QVariant PacketListModel::data(const QModelIndex &d_index, int role) const
} else {
return QVariant();
}
- return QColor(color->red >> 8, color->green >> 8, color->blue >> 8);
+ return ColorUtils::fromColorT(color);
case Qt::DisplayRole:
{
int column = d_index.column();
@@ -485,6 +487,18 @@ frame_data *PacketListModel::getRowFdata(int row) {
return record->frameData();
}
+void PacketListModel::ensureRowColorized(int row)
+{
+ if (row < 0 || row >= visible_rows_.count())
+ return;
+ PacketListRecord *record = visible_rows_[row];
+ if (!record)
+ return;
+ if (!record->colorized()) {
+ record->columnString(cap_file_, 1);
+ }
+}
+
int PacketListModel::visibleIndexOf(frame_data *fdata) const
{
int row = 0;
diff --git a/ui/qt/packet_list_model.h b/ui/qt/packet_list_model.h
index 0c7772fef5..20733f2a5c 100644
--- a/ui/qt/packet_list_model.h
+++ b/ui/qt/packet_list_model.h
@@ -59,6 +59,7 @@ public:
gint appendPacket(frame_data *fdata);
frame_data *getRowFdata(int row);
+ void ensureRowColorized(int row);
int visibleIndexOf(frame_data *fdata) const;
void resetColumns();
void resetColorized();
diff --git a/ui/qt/packet_list_record.h b/ui/qt/packet_list_record.h
index 085c96c7d4..17d7c6ae82 100644
--- a/ui/qt/packet_list_record.h
+++ b/ui/qt/packet_list_record.h
@@ -46,6 +46,7 @@ public:
frame_data *frameData() const { return fdata_; }
// packet_list->col_to_text in gtk/packet_list_store.c
static int textColumn(int column) { return cinfo_column_.value(column, -1); }
+ bool colorized() { return colorized_; }
struct conversation *conversation() { return conv_; }
int columnTextSize(const char *str);