diff options
-rw-r--r-- | ui/qt/CMakeLists.txt | 2 | ||||
-rw-r--r-- | ui/qt/Makefile.common | 3 | ||||
-rw-r--r-- | ui/qt/Wireshark.pro | 2 | ||||
-rw-r--r-- | ui/qt/color_utils.cpp | 2 | ||||
-rw-r--r-- | ui/qt/color_utils.h | 2 | ||||
-rw-r--r-- | ui/qt/overlay_scroll_bar.cpp | 158 | ||||
-rw-r--r-- | ui/qt/overlay_scroll_bar.h | 62 | ||||
-rw-r--r-- | ui/qt/packet_list.cpp | 232 | ||||
-rw-r--r-- | ui/qt/packet_list.h | 15 | ||||
-rw-r--r-- | ui/qt/packet_list_model.cpp | 18 | ||||
-rw-r--r-- | ui/qt/packet_list_model.h | 1 | ||||
-rw-r--r-- | ui/qt/packet_list_record.h | 1 |
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); |