diff options
-rw-r--r-- | docbook/release-notes.asciidoc | 10 | ||||
-rw-r--r-- | ui/qt/byte_view_tab.cpp | 2 | ||||
-rw-r--r-- | ui/qt/byte_view_text.cpp | 548 | ||||
-rw-r--r-- | ui/qt/byte_view_text.h | 63 | ||||
-rw-r--r-- | ui/qt/proto_tree.cpp | 3 |
5 files changed, 331 insertions, 295 deletions
diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc index b47aafbed7..c49049de08 100644 --- a/docbook/release-notes.asciidoc +++ b/docbook/release-notes.asciidoc @@ -22,6 +22,16 @@ used for troubleshooting, analysis, development and education. === New and Updated Features The following features are new (or have been significantly updated) +since version 1.99.0: + +* Qt port: + +** You can now show and hide toolbars and major widgets using the View menu. +** You can now set the time display format and precision. +** The byte view widget is much faster, particularly when selecting large +reassembled packets. + +The following features are new (or have been significantly updated) since version 1.12.0: * The I/O Graph in the Gtk+ UI now supports an unlimited number of data points diff --git a/ui/qt/byte_view_tab.cpp b/ui/qt/byte_view_tab.cpp index 04b3008b13..61b3af1238 100644 --- a/ui/qt/byte_view_tab.cpp +++ b/ui/qt/byte_view_tab.cpp @@ -169,8 +169,6 @@ void ByteViewTab::protoTreeItemChanged(QTreeWidgetItem *current) { // Appendix (trailer) bytes byte_view_text->setFieldAppendixHighlight(fa_start, fa_end); - byte_view_text->renderBytes(); - setCurrentIndex(i); } byte_view_text = qobject_cast<ByteViewText*>(widget(++i)); diff --git a/ui/qt/byte_view_text.cpp b/ui/qt/byte_view_text.cpp index 7920b55d52..8c7e097a3a 100644 --- a/ui/qt/byte_view_text.cpp +++ b/ui/qt/byte_view_text.cpp @@ -19,21 +19,25 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +// Some code based on QHexView by Even Teran +// https://code.google.com/p/qhexview/ + #include "byte_view_text.h" #include <epan/charsets.h> #include "wireshark_application.h" -#include <QTextCursor> -#include <QTextBlock> -#include <QApplication> + #include <QMouseEvent> +#include <QPainter> +#include <QScrollBar> -// XXX - Use KHexEdit instead? -// http://api.kde.org/4.x-api/kdelibs-apidocs/interfaces/khexedit/html/index.html +// To do: +// - Bit view +// - Fix sub-pixel text shifting in flushOffsetFragment. ByteViewText::ByteViewText(QWidget *parent, tvbuff_t *tvb, proto_tree *tree, QTreeWidget *tree_widget, packet_char_enc encoding) : - QTextEdit(parent), + QAbstractScrollArea(parent), tvb_(tvb), proto_tree_(tree), tree_widget_(tree_widget), @@ -42,27 +46,24 @@ ByteViewText::ByteViewText(QWidget *parent, tvbuff_t *tvb, proto_tree *tree, QTr format_(BYTES_HEX), p_start_(-1), p_end_(-1), - f_start_(-1), - f_end_(-1), + f_start_(0), + f_end_(0), fa_start_(-1), fa_end_(-1), - per_line_(16), - offset_width_(4) + show_offset_(true), + show_hex_(true), + show_ascii_(true), + row_width_(16) { - setReadOnly(true); - setUndoRedoEnabled(false); - setLineWrapMode(QTextEdit::NoWrap); - setState(StateNormal); - - renderBytes(); } void ByteViewText::setEncoding(packet_char_enc encoding) { encoding_ = encoding; + update(); } -bool ByteViewText::hasDataSource(tvbuff_t *ds_tvb) { +bool ByteViewText::hasDataSource(const tvbuff_t *ds_tvb) { if (ds_tvb != NULL && ds_tvb == tvb_) return true; return false; @@ -70,347 +71,356 @@ bool ByteViewText::hasDataSource(tvbuff_t *ds_tvb) { void ByteViewText::setProtocolHighlight(int start, int end) { - p_start_ = start; - p_end_ = end; + p_start_ = qMax(0, start); + p_end_ = qMax(0, end); + viewport()->update(); } void ByteViewText::setFieldHighlight(int start, int end, guint32 mask, int mask_le) { Q_UNUSED(mask); Q_UNUSED(mask_le); - f_start_ = start; - f_end_ = end; + f_start_ = qMax(0, start); + f_end_ = qMax(0, end); + viewport()->update(); } void ByteViewText::setFieldAppendixHighlight(int start, int end) { - fa_start_ = start; - fa_end_ = end; + fa_start_ = qMax(0, start); + fa_end_ = qMax(0, end); + viewport()->update(); } -void ByteViewText::renderBytes() +void ByteViewText::setMonospaceFont(const QFont &mono_font) { - int length; - int start_byte = 0; + mono_normal_font_ = mono_font; + mono_bold_font_ = QFont(mono_font); + mono_bold_font_.setBold(true); - if (!tvb_) { - clear(); - return; - } + const QFontMetricsF fm(mono_font); + font_width_ = fm.width('M'); + one_em_ = fm.height(); + margin_ = one_em_ / 2; + + setFont(mono_font); + + updateScrollbars(); + update(); +} + +void ByteViewText::paintEvent(QPaintEvent *) +{ + QPainter painter(viewport()); + painter.translate(-horizontalScrollBar()->value() * font_width_, 0); + + // Pixel offset of this row + int row_y = 0; - // XXX Even with updates and undo disabled this is slow. Instead of clearing - // and filling in the text each time we should probably fill it in once and - // use setExtraSelections to set highlighting. - setUpdatesEnabled(false); + // Starting byte offset + guint offset = (guint) verticalScrollBar()->value() * row_width_; - textCursor().beginEditBlock(); - clear(); + // Clear the area + painter.fillRect(viewport()->rect(), palette().base()); - length = tvb_length(tvb_); - for (int off = 0; off < length; off += per_line_) { - lineCommon(off); + // Offset background + if (show_offset_) { + QRect offset_rect = QRect(viewport()->rect()); + offset_rect.setWidth(offsetPixels()); + painter.fillRect(offset_rect, palette().midlight()); } - textCursor().endEditBlock(); - if (f_start_ > 0 && f_end_ > 0) { - start_byte = f_start_; - } else if (p_start_ > 0 && p_end_ > 0) { - start_byte = p_start_; + if (!tvb_) { + return; + } + + // Map window coordinates to byte offsets + x_pos_to_column_.clear(); + for (guint i = 0; i < row_width_; i++) { + int sep_width = (i / separator_interval_) * font_width_; + if (show_hex_) { + int hex_x = offsetPixels() + margin_ + sep_width + (i * 3 * font_width_); + for (int j = 0; j <= font_width_ * 2; j++) { + x_pos_to_column_[hex_x + j] = i; + } + } + if (show_ascii_) { + int ascii_x = offsetPixels() + hexPixels() + margin_ + sep_width + (i * font_width_); + for (int j = 0; j <= font_width_; j++) { + x_pos_to_column_[ascii_x + j] = i; + } + } } - scrollToByte(start_byte); - setUpdatesEnabled(true); + // Data rows + int widget_height = height(); + painter.save(); + while(row_y + one_em_ < widget_height && offset < tvb_captured_length(tvb_)) { + drawOffsetLine(painter, offset, row_y); + offset += row_width_; + row_y += one_em_; + } + painter.restore(); } -void ByteViewText::setMonospaceFont(const QFont &mono_font) +void ByteViewText::resizeEvent(QResizeEvent *) { - mono_normal_font_ = mono_font; - mono_bold_font_ = QFont(mono_font); - mono_bold_font_.setBold(true); - renderBytes(); + updateScrollbars(); } -// Private - -#define BYTE_VIEW_SEP 8 /* insert a space every BYTE_VIEW_SEP bytes */ - -void ByteViewText::lineCommon(const int org_off) -{ - static const guchar hexchars[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; +void ByteViewText::mousePressEvent (QMouseEvent *event) { + if (!tvb_ || event->button() != Qt::LeftButton ) { + return; + } - const guint8 *pd; - int len; + QPoint pt = event->pos(); + int byte = (verticalScrollBar()->value() + (pt.y() / one_em_)) * row_width_; + int x = (horizontalScrollBar()->value() * font_width_) + pt.x(); + int col = x_pos_to_column_.value(x, -1); - highlight_state state; + if (col < 0) { + return; + } - QString str; + byte += col; + if ((guint) byte > tvb_captured_length(tvb_)) { + return; + } - int off; - guchar c; - int byten; - int j; + field_info *fi = proto_find_field_from_offset(proto_tree_, byte, tvb_); - g_assert(org_off >= 0); + if (fi && tree_widget_) { + // XXX - This should probably be a ProtoTree method. + QTreeWidgetItemIterator iter(tree_widget_); + while (*iter) { + if (fi == (*iter)->data(0, Qt::UserRole).value<field_info *>()) { + tree_widget_->setCurrentItem((*iter)); + } - if (!tvb_) - return; - len = tvb_length(tvb_); - pd = tvb_get_ptr(tvb_, 0, -1); + iter++; + } + } +} - state = StateNormal; - setState(state); +// Private - /* Print the line number */ - str += QString("%1 ").arg(org_off, offset_width_, 16, QChar('0')); +const int ByteViewText::separator_interval_ = 8; // Insert a space after this many bytes - /* Print the hex bit */ - for (byten = 0, off = org_off; byten < per_line_; byten++) { - highlight_state state_cur = StateNormal; - bool add_space = byten > 0; +void ByteViewText::drawOffsetLine(QPainter &painter, const guint offset, const int row_y) +{ + if (!tvb_) { + return; + } + guint tvb_len = tvb_captured_length(tvb_); + guint max_pos = qMin(offset + row_width_, tvb_len); + const guint8 *pd = tvb_get_ptr(tvb_, 0, -1); - if ((off >= f_start_ && off < f_end_) || (off >= fa_start_ && off < fa_end_)) { - state_cur = StateField; - } else if (off >= p_start_ && off < p_end_) { - state_cur = StateProtocol; - } + static const guchar hexchars[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - if (state_cur != state) { - if (state != StateField && add_space) { - add_space = false; - str += ' '; - /* insert a space every BYTE_VIEW_SEP bytes */ - if ((off % BYTE_VIEW_SEP) == 0) - str += ' '; + QString text; + highlight_state state = StateNormal, offset_state = StateOffsetNormal; + int hex_x = offsetPixels() + margin_; + int 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; + + if ((tvb_pos >= f_start_ && tvb_pos < f_end_) || (tvb_pos >= fa_start_ && tvb_pos < fa_end_)) { + hex_state = StateField; + offset_state = StateOffsetField; + } else if (tvb_pos >= p_start_ && tvb_pos < p_end_) { + hex_state = StateProtocol; } - if (flushBytes(str) < 0) - return; - setState(state_cur); - state = state_cur; - } + if (hex_state != state) { + if (state != StateField && add_space) { + add_space = false; + text += ' '; + /* insert a space every separator_interval_ bytes */ + if ((tvb_pos % separator_interval_) == 0) + text += ' '; + } + hex_x += flushOffsetFragment(painter, hex_x, row_y, state, text); + state = hex_state; + } - if (add_space) { - str += ' '; - /* insert a space every BYTE_VIEW_SEP bytes */ - if ((off % BYTE_VIEW_SEP) == 0) - str += ' '; - } + if (add_space) { + text += ' '; + /* insert a space every separator_interval_ bytes */ + if ((tvb_pos % separator_interval_) == 0) + text += ' '; + } - if (off < len) { switch (format_) { case BYTES_HEX: - str += hexchars[(pd[off] & 0xf0) >> 4]; - str += hexchars[pd[off] & 0x0f]; + text += hexchars[(pd[tvb_pos] & 0xf0) >> 4]; + text += hexchars[pd[tvb_pos] & 0x0f]; break; case BYTES_BITS: /* XXX, bitmask */ - for (j = 7; j >= 0; j--) - str += (pd[off] & (1 << j)) ? '1' : '0'; - break; - } - } else { - switch (format_) { - case BYTES_HEX: - str += " "; - break; - case BYTES_BITS: - str += " "; + for (int j = 7; j >= 0; j--) + text += (pd[tvb_pos] & (1 << j)) ? '1' : '0'; break; } } - off++; } - - if (state != StateNormal) { - if (flushBytes(str) < 0) - return; - setState(StateNormal); - state = StateNormal; + if (text.length() > 0) { + flushOffsetFragment(painter, hex_x, row_y, state, text); } + state = StateNormal; - /* Print some space at the end of the line */ - str += " "; - - /* Print the ASCII bit */ - for (byten = 0, off = org_off; byten < per_line_; byten++) { - highlight_state state_cur = StateNormal; - bool add_space = byten > 0; + // ASCII + 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; + + if ((tvb_pos >= f_start_ && tvb_pos < f_end_) || (tvb_pos >= fa_start_ && tvb_pos < fa_end_)) { + ascii_state = StateField; + offset_state = StateOffsetField; + } else if (tvb_pos >= p_start_ && tvb_pos < p_end_) { + ascii_state = StateProtocol; + } - if ((off >= f_start_ && off < f_end_) || (off >= fa_start_ && off < fa_end_)) { - state_cur = StateField; - } else if (off >= p_start_ && off < p_end_) { - state_cur = StateProtocol; - } + if (ascii_state != state) { + if (state != StateField && add_space) { + add_space = false; + /* insert a space every separator_interval_ bytes */ + if ((tvb_pos % separator_interval_) == 0) + text += ' '; + } + ascii_x += flushOffsetFragment(painter, ascii_x, row_y, state, text); + state = ascii_state; + } - if (state_cur != state) { - if (state != StateField && add_space) { - add_space = false; - /* insert a space every BYTE_VIEW_SEP bytes */ - if ((off % BYTE_VIEW_SEP) == 0) - str += ' '; + if (add_space) { + /* insert a space every separator_interval_ bytes */ + if ((tvb_pos % separator_interval_) == 0) + text += ' '; } - if (flushBytes(str) < 0) - return; - setState(state_cur); - state = state_cur; - } + guchar c = (encoding_ == PACKET_CHAR_ENC_CHAR_EBCDIC) ? + EBCDIC_to_ASCII1(pd[tvb_pos]) : + pd[tvb_pos]; - if (add_space) { - /* insert a space every BYTE_VIEW_SEP bytes */ - if ((off % BYTE_VIEW_SEP) == 0) - str += ' '; + text += g_ascii_isprint(c) ? c : '.'; } - - if (off < len) { - c = (encoding_ == PACKET_CHAR_ENC_CHAR_EBCDIC) ? - EBCDIC_to_ASCII1(pd[off]) : - pd[off]; - - str += g_ascii_isprint(c) ? c : '.'; - } else - str += ' '; - - off++; } - - if (str.length() > 0) { - if (flushBytes(str) < 0) - return; + if (text.length() > 0) { + flushOffsetFragment(painter, ascii_x, row_y, state, text); } + state = StateNormal; - if (state != StateNormal) { - setState(StateNormal); - /* state = StateNormal; */ + // Offset. Must be drawn last in order for offset_state to be set. + if (show_offset_) { + text = QString("%1").arg(offset, offsetChars(), 16, QChar('0')); + flushOffsetFragment(painter, margin_, row_y, offset_state, text); } - append(""); } -void ByteViewText::setState(ByteViewText::highlight_state state) +// 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) { - QPalette pal = wsApp->palette(); - - moveCursor(QTextCursor::End); - setCurrentFont(mono_normal_font_); - setTextColor(pal.text().color()); - setTextBackgroundColor(pal.base().color()); + if (text.length() < 1) { + return 0; + } + int width = text.length() * font_width_; + // Background + if (state == StateField) { + painter.fillRect(x, y, width, one_em_, palette().highlight()); + } else if (state == StateProtocol) { + painter.fillRect(x, y, width, one_em_, palette().button()); + } + // Text + QBrush text_brush; switch (state) { - case StateProtocol: - setTextBackgroundColor(pal.alternateBase().color()); + case StateNormal: + default: + text_brush = palette().text(); break; case StateField: - if (bold_highlight_) { - setCurrentFont(mono_bold_font_); - } else { - setTextColor(pal.base().color()); - setTextBackgroundColor(pal.text().color()); - } + text_brush = palette().highlightedText(); break; - default: + case StateProtocol: + text_brush = palette().buttonText(); + break; + case StateOffsetNormal: + text_brush = palette().dark(); + break; + case StateOffsetField: + text_brush = palette().buttonText(); break; } -} - -int ByteViewText::flushBytes(QString &str) -{ - if (str.length() < 1) return 0; - insertPlainText(str); - str.clear(); - return str.length(); + painter.setPen(QPen(text_brush.color())); + painter.drawText(x, y, width, one_em_, Qt::AlignTop, text); + text.clear(); + return width; } void ByteViewText::scrollToByte(int byte) { - QTextCursor cursor(textCursor()); - cursor.setPosition(0); - - cursor.setPosition(byte * cursor.block().length() / per_line_); - setTextCursor(cursor); - ensureCursorVisible(); + verticalScrollBar()->setValue(byte / row_width_); } -int ByteViewText::byteFromRowCol(int row, int col) +// Offset character width +int ByteViewText::offsetChars() { - /* hex_pos_byte array generated with hex_view_get_byte(0, 0, 0...70) */ - static const int hex_pos_byte[70] = { - -1, -1, - 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, - 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, - -1, - 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, - 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, - -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, - -1, - 8, 9, 10, 11, 12, 13, 14, 15 - }; - - /* bits_pos_byte array generated with bit_view_get_byte(0, 0, 0...84) */ - static const int bits_pos_byte[84] = { - -1, -1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, - -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7 - }; - - int off_col = 1; - int off_row; - - off_row = row * per_line_; - - if (/* char_x < 0 || */ col < offset_width_) - return -1; - col -= offset_width_; - - switch (format_) { - case BYTES_BITS: - g_return_val_if_fail(col >= 0 && col < (int) G_N_ELEMENTS(bits_pos_byte), -1); - off_col = bits_pos_byte[col]; - break; - - case BYTES_HEX: - g_return_val_if_fail(col >= 0 && col < (int) G_N_ELEMENTS(hex_pos_byte), -1); - off_col = hex_pos_byte[col]; - break; + if (tvb_ && tvb_captured_length(tvb_) > 0xffff) { + return 8; } + return 4; +} - if (col == -1) - return -1; - - return off_row + off_col; +// Offset pixel width +int ByteViewText::offsetPixels() +{ + if (show_offset_) { + return offsetChars() * font_width_ + one_em_; + } + return 0; } -void ByteViewText::mousePressEvent (QMouseEvent * event) { - if (event->button() == Qt::LeftButton) { - int byte; - QTextCursor cursor(cursorForPosition(event->pos())); +// Hex pixel width +int ByteViewText::hexPixels() +{ + if (show_hex_) { + return (((row_width_ * 3) + ((row_width_ - 1) / separator_interval_)) * font_width_) + one_em_; + } + return 0; +} - byte = byteFromRowCol(cursor.blockNumber(), cursor.columnNumber()); - if (byte >= 0) { - field_info *fi = proto_find_field_from_offset(proto_tree_, byte, tvb_); +int ByteViewText::asciiPixels() +{ + if (show_ascii_) { + return ((row_width_ + ((row_width_ - 1) / separator_interval_)) * font_width_) + one_em_; + } + return 0; +} - if (fi && tree_widget_) { - // XXX - This should probably be a ProtoTree method. - QTreeWidgetItemIterator iter(tree_widget_); - while (*iter) { - if (fi == (*iter)->data(0, Qt::UserRole).value<field_info *>()) { - tree_widget_->setCurrentItem((*iter)); - } +int ByteViewText::totalPixels() +{ + return offsetPixels() + hexPixels() + asciiPixels(); +} - iter++; - } - } - } +void ByteViewText::updateScrollbars() +{ + const gint length = tvb_ ? tvb_captured_length(tvb_) : 0; + if (tvb_) { } - QWidget::mousePressEvent (event); + qint64 maxval = length / row_width_ + ((length % row_width_) ? 1 : 0) - viewport()->height() / one_em_; + + 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 1b1e9a23f0..24686e8ce8 100644 --- a/ui/qt/byte_view_text.h +++ b/ui/qt/byte_view_text.h @@ -29,8 +29,8 @@ #include <epan/tvbuff.h> #include "proto_tree.h" -#include <QPrinter> -#include <QTextEdit> + +#include <QAbstractScrollArea> // XXX - Is there any reason we shouldn't add ByteViewImage, etc? @@ -40,38 +40,48 @@ typedef enum { BYTES_BITS } bytes_view_type; -class ByteViewText : public QTextEdit +class ByteViewText : public QAbstractScrollArea { Q_OBJECT public: explicit ByteViewText(QWidget *parent = 0, tvbuff_t *tvb = NULL, proto_tree *tree = NULL, QTreeWidget *protoTree = NULL, packet_char_enc encoding = PACKET_CHAR_ENC_CHAR_ASCII); - bool hasDataSource(tvbuff_t *ds_tvb = NULL); + bool hasDataSource(const tvbuff_t *ds_tvb = NULL); void setEncoding(packet_char_enc encoding); void setFormat(bytes_view_type format); - void setHighlightStyle(bool bold); + void setHighlightStyle(bool bold) { bold_highlight_ = bold; } void setProtocolHighlight(int start, int end); void setFieldHighlight(int start, int end, guint32 mask = 0, int mask_le = 0); void setFieldAppendixHighlight(int start, int end); - void renderBytes(); public slots: void setMonospaceFont(const QFont &mono_font); +protected: + virtual void paintEvent(QPaintEvent *); + virtual void resizeEvent(QResizeEvent *); + void mousePressEvent (QMouseEvent * event); + + private: typedef enum { StateNormal, StateField, - StateProtocol + StateProtocol, + StateOffsetNormal, + StateOffsetField } highlight_state; - void lineCommon(const int org_off); - void setState(highlight_state state); - int flushBytes(QString &str); + void drawOffsetLine(QPainter &painter, const guint offset, const int row_y); + int flushOffsetFragment(QPainter &painter, int x, int y, highlight_state state, QString &text); void scrollToByte(int byte); - - int byteFromRowCol(int row, int col); - void mousePressEvent (QMouseEvent * event); - + int offsetChars(); + int offsetPixels(); + int hexPixels(); + int asciiPixels(); + int totalPixels(); + void updateScrollbars(); + + static const int separator_interval_; tvbuff_t *tvb_; proto_tree *proto_tree_; QTreeWidget *tree_widget_; @@ -81,17 +91,24 @@ private: gboolean bold_highlight_; /* data */ - packet_char_enc encoding_; /* ASCII or EBCDIC */ - bytes_view_type format_; /* bytes in hex or bytes as bits */ + packet_char_enc encoding_; // ASCII or EBCDIC + bytes_view_type format_; // bytes in hex or bytes as bits /* data-highlight */ - int p_start_, p_end_; /* Protocol */ - int f_start_, f_end_; /* Field */ - int fa_start_, fa_end_; /* Field appendix */ - - int per_line_; /* Number of bytes per line */ - int offset_width_; /* Byte offset field width */ - + guint p_start_, p_end_; // Protocol + guint f_start_, f_end_; // Field + guint fa_start_, fa_end_; // Field appendix + + bool show_offset_; // Should we show the byte offset? + bool show_hex_; // Should we show the hex display? + bool show_ascii_; // Should we show the ASCII display? + guint row_width_; // Number of bytes per line + int one_em_; // Font character height + qreal font_width_; // Font character width + int margin_; // Text margin + + // Data selection + QMap<int,int> x_pos_to_column_; signals: }; diff --git a/ui/qt/proto_tree.cpp b/ui/qt/proto_tree.cpp index eefa999986..80e3df65b9 100644 --- a/ui/qt/proto_tree.cpp +++ b/ui/qt/proto_tree.cpp @@ -94,7 +94,8 @@ proto_tree_draw_node(proto_node *node, gpointer data) QPalette pal = QApplication::palette(); if (fi && fi->hfinfo) { if(fi->hfinfo->type == FT_PROTOCOL) { - item->setData(0, Qt::BackgroundRole, pal.alternateBase()); + item->setData(0, Qt::BackgroundRole, pal.button()); + item->setData(0, Qt::ForegroundRole, pal.buttonText()); } if((fi->hfinfo->type == FT_FRAMENUM) || |