aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ui/qt/byte_view_text.cpp61
-rw-r--r--ui/qt/byte_view_text.h12
-rw-r--r--ui/qt/color_utils.cpp20
-rw-r--r--ui/qt/color_utils.h5
4 files changed, 70 insertions, 28 deletions
diff --git a/ui/qt/byte_view_text.cpp b/ui/qt/byte_view_text.cpp
index 8c7e097a3a..809ff73c5a 100644
--- a/ui/qt/byte_view_text.cpp
+++ b/ui/qt/byte_view_text.cpp
@@ -26,6 +26,7 @@
#include <epan/charsets.h>
+#include "color_utils.h"
#include "wireshark_application.h"
#include <QMouseEvent>
@@ -34,7 +35,10 @@
// To do:
// - Bit view
-// - Fix sub-pixel text shifting in flushOffsetFragment.
+
+// We don't obey the gui.hex_dump_highlight_style preference. If you
+// would like to add support for this you'll probably have to call
+// QPainter::drawText for each individual character.
ByteViewText::ByteViewText(QWidget *parent, tvbuff_t *tvb, proto_tree *tree, QTreeWidget *tree_widget, packet_char_enc encoding) :
QAbstractScrollArea(parent),
@@ -60,7 +64,7 @@ ByteViewText::ByteViewText(QWidget *parent, tvbuff_t *tvb, proto_tree *tree, QTr
void ByteViewText::setEncoding(packet_char_enc encoding)
{
encoding_ = encoding;
- update();
+ viewport()->update();
}
bool ByteViewText::hasDataSource(const tvbuff_t *ds_tvb) {
@@ -94,19 +98,20 @@ void ByteViewText::setFieldAppendixHighlight(int start, int end)
void ByteViewText::setMonospaceFont(const QFont &mono_font)
{
- mono_normal_font_ = mono_font;
- mono_bold_font_ = QFont(mono_font);
- mono_bold_font_.setBold(true);
+ mono_font_ = mono_font;
+// mono_bold_font_ = QFont(mono_font);
+// mono_bold_font_.setBold(true);
const QFontMetricsF fm(mono_font);
font_width_ = fm.width('M');
+ line_spacing_ = fm.lineSpacing() + 0.5;
one_em_ = fm.height();
- margin_ = one_em_ / 2;
+ margin_ = fm.height() / 2;
setFont(mono_font);
updateScrollbars();
- update();
+ viewport()->update();
}
void ByteViewText::paintEvent(QPaintEvent *)
@@ -124,6 +129,9 @@ void ByteViewText::paintEvent(QPaintEvent *)
painter.fillRect(viewport()->rect(), palette().base());
// Offset background
+ offset_bg_.setColor(ColorUtils::alphaBlend(palette().text(), palette().base(), 0.2));
+ offset_normal_fg_.setColor(ColorUtils::alphaBlend(palette().text(), palette().base(), 0.5));
+ offset_field_fg_.setColor(ColorUtils::alphaBlend(palette().text(), palette().base(), 0.8));
if (show_offset_) {
QRect offset_rect = QRect(viewport()->rect());
offset_rect.setWidth(offsetPixels());
@@ -155,10 +163,10 @@ void ByteViewText::paintEvent(QPaintEvent *)
// Data rows
int widget_height = height();
painter.save();
- while(row_y + one_em_ < widget_height && offset < tvb_captured_length(tvb_)) {
+ while(row_y + line_spacing_ < widget_height && offset < tvb_captured_length(tvb_)) {
drawOffsetLine(painter, offset, row_y);
offset += row_width_;
- row_y += one_em_;
+ row_y += line_spacing_;
}
painter.restore();
}
@@ -174,7 +182,7 @@ void ByteViewText::mousePressEvent (QMouseEvent *event) {
}
QPoint pt = event->pos();
- int byte = (verticalScrollBar()->value() + (pt.y() / one_em_)) * row_width_;
+ int byte = (verticalScrollBar()->value() + (pt.y() / line_spacing_)) * row_width_;
int x = (horizontalScrollBar()->value() * font_width_) + pt.x();
int col = x_pos_to_column_.value(x, -1);
@@ -206,6 +214,10 @@ void ByteViewText::mousePressEvent (QMouseEvent *event) {
const int ByteViewText::separator_interval_ = 8; // Insert a space after this many bytes
+// Draw a line of byte view text for a given offset.
+// Text with different styles are split into fragments and passed to
+// flushOffsetFragment. Font character widths aren't necessarily whole
+// numbers so we track our X coordinate position using using floats.
void ByteViewText::drawOffsetLine(QPainter &painter, const guint offset, const int row_y)
{
if (!tvb_) {
@@ -221,14 +233,14 @@ void ByteViewText::drawOffsetLine(QPainter &painter, const guint offset, const i
QString text;
highlight_state state = StateNormal, offset_state = StateOffsetNormal;
- int hex_x = offsetPixels() + margin_;
- int ascii_x = offsetPixels() + hexPixels() + margin_;
+ qreal hex_x = offsetPixels() + margin_;
+ qreal ascii_x = offsetPixels() + hexPixels() + margin_;
// Hex
if (show_hex_) {
for (guint tvb_pos = offset; tvb_pos < max_pos; tvb_pos++) {
highlight_state hex_state = StateNormal;
- bool add_space = tvb_pos % row_width_ > 0;
+ bool add_space = tvb_pos != offset;
if ((tvb_pos >= f_start_ && tvb_pos < f_end_) || (tvb_pos >= fa_start_ && tvb_pos < fa_end_)) {
hex_state = StateField;
@@ -238,7 +250,7 @@ void ByteViewText::drawOffsetLine(QPainter &painter, const guint offset, const i
}
if (hex_state != state) {
- if (state != StateField && add_space) {
+ if ((state == StateNormal || (state == StateProtocol && hex_state == StateField)) && add_space) {
add_space = false;
text += ' ';
/* insert a space every separator_interval_ bytes */
@@ -278,7 +290,7 @@ void ByteViewText::drawOffsetLine(QPainter &painter, const guint offset, const i
if (show_ascii_) {
for (guint tvb_pos = offset; tvb_pos < max_pos; tvb_pos++) {
highlight_state ascii_state = StateNormal;
- bool add_space = tvb_pos % row_width_ > 0;
+ bool add_space = tvb_pos != offset;
if ((tvb_pos >= f_start_ && tvb_pos < f_end_) || (tvb_pos >= fa_start_ && tvb_pos < fa_end_)) {
ascii_state = StateField;
@@ -288,7 +300,7 @@ void ByteViewText::drawOffsetLine(QPainter &painter, const guint offset, const i
}
if (ascii_state != state) {
- if (state != StateField && add_space) {
+ if ((state == StateNormal || (state == StateProtocol && ascii_state == StateField)) && add_space) {
add_space = false;
/* insert a space every separator_interval_ bytes */
if ((tvb_pos % separator_interval_) == 0)
@@ -326,17 +338,18 @@ void ByteViewText::drawOffsetLine(QPainter &painter, const guint offset, const i
// Draws a fragment of byte view text at the specifiec location using colors
// for the specified state. Clears the text and returns the pixel width of the
// drawn text.
-int ByteViewText::flushOffsetFragment(QPainter &painter, int x, int y, highlight_state state, QString &text)
+qreal ByteViewText::flushOffsetFragment(QPainter &painter, qreal x, int y, highlight_state state, QString &text)
{
if (text.length() < 1) {
return 0;
}
- int width = text.length() * font_width_;
+ QFontMetricsF fm(mono_font_);
+ qreal width = fm.width(text);
// Background
if (state == StateField) {
- painter.fillRect(x, y, width, one_em_, palette().highlight());
+ painter.fillRect(QRectF(x, y, width, line_spacing_), palette().highlight());
} else if (state == StateProtocol) {
- painter.fillRect(x, y, width, one_em_, palette().button());
+ painter.fillRect(QRectF(x, y, width, line_spacing_), palette().button());
}
// Text
@@ -353,15 +366,15 @@ int ByteViewText::flushOffsetFragment(QPainter &painter, int x, int y, highlight
text_brush = palette().buttonText();
break;
case StateOffsetNormal:
- text_brush = palette().dark();
+ text_brush = offset_normal_fg_;
break;
case StateOffsetField:
- text_brush = palette().buttonText();
+ text_brush = offset_field_fg_;
break;
}
painter.setPen(QPen(text_brush.color()));
- painter.drawText(x, y, width, one_em_, Qt::AlignTop, text);
+ painter.drawText(QRectF(x, y, width, line_spacing_), Qt::AlignTop, text);
text.clear();
return width;
}
@@ -417,7 +430,7 @@ void ByteViewText::updateScrollbars()
if (tvb_) {
}
- qint64 maxval = length / row_width_ + ((length % row_width_) ? 1 : 0) - viewport()->height() / one_em_;
+ qint64 maxval = length / row_width_ + ((length % row_width_) ? 1 : 0) - viewport()->height() / line_spacing_;
verticalScrollBar()->setRange(0, qMax((qint64)0, maxval));
horizontalScrollBar()->setRange(0, qMax(0, static_cast<int>((totalPixels() - viewport()->width()) / font_width_)));
diff --git a/ui/qt/byte_view_text.h b/ui/qt/byte_view_text.h
index 24686e8ce8..e40c256ec3 100644
--- a/ui/qt/byte_view_text.h
+++ b/ui/qt/byte_view_text.h
@@ -72,7 +72,7 @@ private:
} highlight_state;
void drawOffsetLine(QPainter &painter, const guint offset, const int row_y);
- int flushOffsetFragment(QPainter &painter, int x, int y, highlight_state state, QString &text);
+ qreal flushOffsetFragment(QPainter &painter, qreal x, int y, highlight_state state, QString &text);
void scrollToByte(int byte);
int offsetChars();
int offsetPixels();
@@ -85,8 +85,13 @@ private:
tvbuff_t *tvb_;
proto_tree *proto_tree_;
QTreeWidget *tree_widget_;
- QFont mono_normal_font_;
- QFont mono_bold_font_;
+
+ // Fonts and colors
+ QFont mono_font_;
+// QFont mono_bold_font_;
+ QBrush offset_bg_;
+ QBrush offset_normal_fg_;
+ QBrush offset_field_fg_;
gboolean bold_highlight_;
@@ -105,6 +110,7 @@ private:
guint row_width_; // Number of bytes per line
int one_em_; // Font character height
qreal font_width_; // Font character width
+ int line_spacing_; // Font line spacing
int margin_; // Text margin
// Data selection
diff --git a/ui/qt/color_utils.cpp b/ui/qt/color_utils.cpp
index 0603a26b98..4210d29734 100644
--- a/ui/qt/color_utils.cpp
+++ b/ui/qt/color_utils.cpp
@@ -60,6 +60,26 @@ QColor ColorUtils::fromColorT(color_t color)
return fromColorT(&color);
}
+QRgb ColorUtils::alphaBlend(const QColor &color1, const QColor &color2, qreal alpha)
+{
+ alpha = qBound(0.0, alpha, 1.0);
+
+ int r1 = color1.red() * alpha;
+ int g1 = color1.green() * alpha;
+ int b1 = color1.blue() * alpha;
+ int r2 = color2.red() * (1 - alpha);
+ int g2 = color2.green() * (1 - alpha);
+ int b2 = color2.blue() * (1 - alpha);
+
+ QColor alpha_color(r1 + r2, g1 + g2, b1 + b2);
+ return alpha_color.rgb();
+}
+
+QRgb ColorUtils::alphaBlend(const QBrush &brush1, const QBrush &brush2, qreal alpha)
+{
+ return alphaBlend(brush1.color(), brush2.color(), alpha);
+}
+
/*
* Editor modelines
*
diff --git a/ui/qt/color_utils.h b/ui/qt/color_utils.h
index 484001ddf4..abbd4497a2 100644
--- a/ui/qt/color_utils.h
+++ b/ui/qt/color_utils.h
@@ -28,8 +28,9 @@
#include "color.h"
-#include <QObject>
+#include <QBrush>
#include <QColor>
+#include <QObject>
class ColorUtils : public QObject
{
@@ -39,6 +40,8 @@ public:
static QColor fromColorT(color_t *color);
static QColor fromColorT(color_t color);
+ static QRgb alphaBlend(const QColor &color1, const QColor &color2, qreal alpha);
+ static QRgb alphaBlend(const QBrush &brush1, const QBrush &brush2, qreal alpha);
signals: