ByteViewText: Remove epan dependancy

Remove all dependancy for the byte_view_text from the epan system,
and therefore cleanly separate data and display for further separation
of dissection and view

Change-Id: Id1ee91b93da4511afa95f24da4cbbf39cbb89b1f
Reviewed-on: https://code.wireshark.org/review/24050
Petri-Dish: Roland Knall <rknall@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Roland Knall <rknall@gmail.com>
This commit is contained in:
Roland Knall 2017-10-25 15:39:35 +02:00 committed by Roland Knall
parent c5165f325b
commit 56a130a152
10 changed files with 393 additions and 344 deletions

View File

@ -20,7 +20,6 @@
*/
#include "byte_view_tab.h"
#include "byte_view_text.h"
#include <QApplication>
#include <QClipboard>
@ -28,14 +27,21 @@
#include <QTabBar>
#include <QTreeWidgetItem>
#include "cfile.h"
#include "epan/epan_dissect.h"
#include <ui/qt/utils/variant_pointer.h>
#include <ui/qt/byte_view_text.h>
#define tvb_data_property "tvb_data_property"
// To do:
// - We might want to add a callback to free_data_sources in so that we
// don't have to blindly call clear().
ByteViewTab::ByteViewTab(QWidget *parent) :
QTabWidget(parent)
QTabWidget(parent),
cap_file_(0)
{
setAccessibleName(tr("Packet bytes"));
setTabPosition(QTabWidget::South);
@ -43,39 +49,81 @@ ByteViewTab::ByteViewTab(QWidget *parent) :
addTab();
}
void ByteViewTab::addTab(const char *name, tvbuff_t *tvb, proto_tree *tree, QTreeWidget *protoTree, packet_char_enc encoding) {
void ByteViewTab::addTab(const char *name, tvbuff_t *tvb) {
if ( ! tvb || ! cap_file_ )
return;
if (count() == 1) { // Remove empty placeholder.
ByteViewText *cur_text = qobject_cast<ByteViewText *>(currentWidget());
if (cur_text && cur_text->isEmpty()) delete currentWidget();
}
ByteViewText *byte_view_text = new ByteViewText(this, tvb, tree, protoTree, encoding);
packet_char_enc encoding = (packet_char_enc)cap_file_->current_frame->flags.encoding;
QByteArray data((const char *) tvb_memdup(wmem_file_scope(), tvb, 0, -1), tvb_captured_length(tvb));
ByteViewText * byte_view_text = new ByteViewText(data, encoding, this);
byte_view_text->setAccessibleName(name);
byte_view_text->setMonospaceFont(mono_font_);
byte_view_text->setProperty(tvb_data_property, VariantPointer<tvbuff_t>::asQVariant(tvb));
connect(this, SIGNAL(monospaceFontChanged(QFont)), byte_view_text, SLOT(setMonospaceFont(QFont)));
connect(byte_view_text, SIGNAL(byteFieldHovered(const QString&)), this, SIGNAL(byteFieldHovered(const QString&)));
connect(byte_view_text, SIGNAL(byteHovered(int)), this, SLOT(byteViewTextHovered(int)));
connect(byte_view_text, SIGNAL(byteSelected(int)), this, SLOT(byteViewTextMarked(int)));
int idx = QTabWidget::addTab(byte_view_text, name);
QTabWidget::setTabToolTip(idx, name);
}
void ByteViewTab::clear()
void ByteViewTab::packetSelectionChanged()
{
bool visible = isVisible();
if (visible) {
hide();
if ( ! cap_file_ || ! cap_file_->edt )
return;
GSList *src_le;
for (src_le = cap_file_->edt->pi.data_src; src_le != NULL; src_le = src_le->next) {
struct data_source *source;
char* source_name;
source = (struct data_source *)src_le->data;
source_name = get_data_source_name(source);
addTab(source_name, get_data_source_tvb(source));
wmem_free(NULL, source_name);
}
while (currentWidget()) {
delete currentWidget();
setCurrentIndex(0);
}
void ByteViewTab::byteViewTextHovered(int idx)
{
if ( idx < 0 )
{
emit tvbOffsetHovered((tvbuff_t *)0, idx);
return;
}
addTab();
if (visible) {
show();
tvbuff_t * tvb = VariantPointer<tvbuff_t>::asPtr(sender()->property(tvb_data_property));
emit tvbOffsetHovered(tvb, idx);
}
void ByteViewTab::byteViewTextMarked(int idx)
{
if ( idx < 0 )
{
emit tvbOffsetMarked((tvbuff_t *)0, idx);
return;
}
tvbuff_t * tvb = VariantPointer<tvbuff_t>::asPtr(sender()->property(tvb_data_property));
emit tvbOffsetMarked(tvb, idx);
}
// XXX How many hex dump routines do we have?
const int byte_line_length_ = 16; // Print out data for 16 bytes on one line
void ByteViewTab::copyHexTextDump(const guint8 *data_p, int data_len, bool append_text)
void ByteViewTab::copyHexTextDump(QByteArray data, bool append_text)
{
QString clipboard_text;
/* Write hex data for a line, then ascii data, then concatenate and add to buffer */
@ -85,21 +133,19 @@ void ByteViewTab::copyHexTextDump(const guint8 *data_p, int data_len, bool appen
int byte_line_part_length;
i = 0;
while (i < data_len) {
while (i < data.count()) {
if(end_of_line) {
hex_str += QString("%1 ").arg(i, 4, 16, QChar('0')); /* Offset - note that we _append_ here */
}
hex_str += QString(" %1").arg(*data_p, 2, 16, QChar('0'));
hex_str += QString(" %1").arg(data[i], 2, 16, QChar('0'));
if(append_text) {
char_str += QString("%1").arg(g_ascii_isprint(*data_p) ? QChar(*data_p) : '.');
char_str += QString("%1").arg(g_ascii_isprint(data[i]) ? QChar(data[i]) : '.');
}
++data_p;
/* Look ahead to see if this is the end of the data */
byte_line_part_length = (++i) % byte_line_length_;
if(i >= data_len){
if(i >= data.count()){
/* End of data - need to fill in spaces in hex string and then do "end of line".
*
*/
@ -133,15 +179,14 @@ void ByteViewTab::copyHexTextDump(const guint8 *data_p, int data_len, bool appen
}
}
void ByteViewTab::copyPrintableText(const guint8 *data_p, int data_len)
void ByteViewTab::copyPrintableText(QByteArray data)
{
QString clipboard_text;
for (int i = 0; i < data_len; i++) {
const guint8 c = data_p[i];
if (g_ascii_isprint(c) || g_ascii_isspace(c)) {
clipboard_text += QChar(c);
}
for (int i = 0; i < data.count(); i++)
{
if ( QChar(data[i]).toLatin1() != 0 )
clipboard_text += QChar(data[i]);
}
if (!clipboard_text.isEmpty()) {
@ -149,23 +194,15 @@ void ByteViewTab::copyPrintableText(const guint8 *data_p, int data_len)
}
}
void ByteViewTab::copyHexStream(const guint8 *data_p, int data_len)
void ByteViewTab::copyHexStream(QByteArray data)
{
QString clipboard_text;
for (int i = 0; i < data_len; i++) {
clipboard_text += QString("%1").arg(data_p[i], 2, 16, QChar('0'));
}
if (!clipboard_text.isEmpty()) {
qApp->clipboard()->setText(clipboard_text);
if (!data.isEmpty()) {
qApp->clipboard()->setText(data.toHex().toUpper());
}
}
void ByteViewTab::copyBinary(const guint8 *data_p, int data_len)
void ByteViewTab::copyBinary(QByteArray data)
{
QByteArray clipboard_bytes = QByteArray::fromRawData((const char *) data_p, data_len);
if (!clipboard_bytes.isEmpty()) {
if (!data.isEmpty()) {
QMimeData *mime_data = new QMimeData;
// gtk/gui_utils.c:copy_binary_to_clipboard says:
/* XXX - this is not understood by most applications,
@ -174,27 +211,28 @@ void ByteViewTab::copyBinary(const guint8 *data_p, int data_len)
*/
// As of 2015-07-30, pasting into Frhed works on Windows. Pasting into
// Hex Editor Neo and HxD does not.
mime_data->setData("application/octet-stream", clipboard_bytes);
mime_data->setData("application/octet-stream", data);
qApp->clipboard()->setMimeData(mime_data);
}
}
void ByteViewTab::copyEscapedString(const guint8 *data_p, int data_len)
void ByteViewTab::copyEscapedString(QByteArray data)
{
QString clipboard_text;
// Beginning quote
clipboard_text += QString("\"");
for (int i = 0; i < data_len; i++) {
for (int i = 0; i < data.count(); i++)
{
// Terminate this line if it has reached 16 bytes,
// unless it is also the very last byte in the data,
// as the termination after this for loop will take
// care of that.
if (i % 16 == 0 && i != 0 && i != data_len - 1) {
if (i % 16 == 0 && i != 0 && i != data.count() - 1) {
clipboard_text += QString("\" \\\n\"");
}
clipboard_text += QString("\\x%1").arg(data_p[i], 2, 16, QChar('0'));
clipboard_text += QString("\\x%1").arg(data[i], 2, 16, QChar('0'));
}
// End quote
clipboard_text += QString("\"\n");
@ -204,51 +242,70 @@ void ByteViewTab::copyEscapedString(const guint8 *data_p, int data_len)
}
}
ByteViewText * ByteViewTab::findByteViewTextForTvb(tvbuff_t * search_tvb, int * idx)
{
int cnt = 0;
ByteViewText * item = 0;
if ( ! search_tvb )
return item;
item = qobject_cast<ByteViewText*>(widget(cnt));
while ( item ) {
if ( ! item->property(tvb_data_property).isNull() )
{
tvbuff_t * stored = VariantPointer<tvbuff_t>::asPtr(item->property(tvb_data_property));
if ( stored && stored == search_tvb )
{
if ( idx )
*idx = cnt;
break;
}
}
item = qobject_cast<ByteViewText*>(widget(++cnt));
}
return item;
}
void ByteViewTab::copyData(ByteViewTab::copyDataType copy_type, field_info *fi)
{
int i = 0;
ByteViewText *byte_view_text = qobject_cast<ByteViewText*>(widget(i));
ByteViewText *byte_view_text = 0;
if (fi) {
while (byte_view_text) {
if (byte_view_text->hasDataSource(fi->ds_tvb)) break;
byte_view_text = qobject_cast<ByteViewText*>(widget(++i));
}
}
if ( fi )
byte_view_text = findByteViewTextForTvb(fi->ds_tvb);
if (!byte_view_text) return;
guint data_len = 0;
const guint8 *data_p;
QByteArray data = byte_view_text->viewData();
data_p = byte_view_text->dataAndLength(&data_len);
if (!data_p) return;
if ( data.isEmpty() == 0 )
return;
if (fi && fi->start >= 0 && fi->length > 0 && fi->length <= (int) data_len) {
data_len = fi->length;
data_p += fi->start;
}
if ( fi && fi->start >= 0 && fi->length > 0 && fi->length <= data.count() )
data = data.right(fi->length);
if (!data_len) return;
if ( data.isEmpty() ) return;
switch (copy_type) {
case copyDataHexTextDump:
copyHexTextDump(data_p, data_len, true);
copyHexTextDump(data, true);
break;
case copyDataHexDump:
copyHexTextDump(data_p, data_len, false);
copyHexTextDump(data, false);
break;
case copyDataPrintableText:
copyPrintableText(data_p, data_len);
copyPrintableText(data);
break;
case copyDataHexStream:
copyHexStream(data_p, data_len);
copyHexStream(data);
break;
case copyDataBinary:
copyBinary(data_p, data_len);
copyBinary(data);
break;
case copyDataEscapedString:
copyEscapedString(data_p, data_len);
copyEscapedString(data);
break;
default:
break;
@ -278,76 +335,77 @@ void ByteViewTab::protoTreeItemChanged(QTreeWidgetItem *current) {
fi = VariantPointer<field_info>::asPtr(current->data(0, Qt::UserRole));
int i = 0;
ByteViewText *byte_view_text = qobject_cast<ByteViewText*>(widget(i));
while (byte_view_text) {
if (byte_view_text->hasDataSource(fi->ds_tvb)) {
QTreeWidgetItem *parent = current->parent();
field_info *parent_fi = NULL;
int f_start = -1, f_end = -1, f_len = -1;
int fa_start = -1, fa_end = -1, fa_len = -1;
int p_start = -1, p_end = -1, p_len = -1;
guint len = tvb_captured_length(fi->ds_tvb);
ByteViewText *byte_view_text = 0;
int idx = 0;
// Find and highlight the protocol bytes
while (parent && parent->parent()) {
parent = parent->parent();
}
if (parent) {
parent_fi = VariantPointer<field_info>::asPtr(parent->data(0, Qt::UserRole));
}
if (parent_fi && parent_fi->ds_tvb == fi->ds_tvb) {
p_start = parent_fi->start;
p_len = parent_fi->length;
}
if ( fi )
byte_view_text = findByteViewTextForTvb(fi->ds_tvb, &idx);
if (cap_file_->search_in_progress && (cap_file_->hex || (cap_file_->string && cap_file_->packet_data))) {
// In the hex view, only highlight the target bytes or string. The entire
// field can then be displayed by clicking on any of the bytes in the field.
f_start = cap_file_->search_pos - cap_file_->search_len + 1;
f_len = cap_file_->search_len;
} else {
f_start = fi->start;
f_len = fi->length;
}
if (byte_view_text) {
QTreeWidgetItem *parent = current->parent();
field_info *parent_fi = NULL;
int f_start = -1, f_end = -1, f_len = -1;
int fa_start = -1, fa_end = -1, fa_len = -1;
int p_start = -1, p_end = -1, p_len = -1;
guint len = tvb_captured_length(fi->ds_tvb);
/* bmask = finfo->hfinfo->bitmask << hfinfo_bitshift(finfo->hfinfo); */ /* (value & mask) >> shift */
fa_start = fi->appendix_start;
fa_len = fi->appendix_length;
if (p_start >= 0 && p_len > 0 && (guint)p_start < len) {
p_end = p_start + p_len;
}
if (f_start >= 0 && f_len > 0 && (guint)f_start < len) {
f_end = f_start + f_len;
}
if (fa_start >= 0 && fa_len > 0 && (guint)fa_start < len) {
fa_end = fa_start + fa_len;
}
if (f_end == -1 && fa_end != -1) {
f_start = fa_start;
f_end = fa_end;
fa_start = fa_end = -1;
}
/* don't exceed the end of available data */
if (p_end != -1 && (guint)p_end > len) p_end = len;
if (f_end != -1 && (guint)f_end > len) f_end = len;
if (fa_end != -1 && (guint)fa_end > len) fa_end = len;
// Protocol
byte_view_text->setProtocolHighlight(p_start, p_end);
// Field bytes
byte_view_text->setFieldHighlight(f_start, f_end);
// Appendix (trailer) bytes
byte_view_text->setFieldAppendixHighlight(fa_start, fa_end);
setCurrentIndex(i);
// Find and highlight the protocol bytes
while (parent && parent->parent()) {
parent = parent->parent();
}
byte_view_text = qobject_cast<ByteViewText*>(widget(++i));
if (parent) {
parent_fi = VariantPointer<field_info>::asPtr(parent->data(0, Qt::UserRole));
}
if (parent_fi && parent_fi->ds_tvb == fi->ds_tvb) {
p_start = parent_fi->start;
p_len = parent_fi->length;
}
if (cap_file_->search_in_progress && (cap_file_->hex || (cap_file_->string && cap_file_->packet_data))) {
// In the hex view, only highlight the target bytes or string. The entire
// field can then be displayed by clicking on any of the bytes in the field.
f_start = cap_file_->search_pos - cap_file_->search_len + 1;
f_len = cap_file_->search_len;
} else {
f_start = fi->start;
f_len = fi->length;
}
/* bmask = finfo->hfinfo->bitmask << hfinfo_bitshift(finfo->hfinfo); */ /* (value & mask) >> shift */
fa_start = fi->appendix_start;
fa_len = fi->appendix_length;
if (p_start >= 0 && p_len > 0 && (guint)p_start < len) {
p_end = p_start + p_len;
}
if (f_start >= 0 && f_len > 0 && (guint)f_start < len) {
f_end = f_start + f_len;
}
if (fa_start >= 0 && fa_len > 0 && (guint)fa_start < len) {
fa_end = fa_start + fa_len;
}
if (f_end == -1 && fa_end != -1) {
f_start = fa_start;
f_end = fa_end;
fa_start = fa_end = -1;
}
/* don't exceed the end of available data */
if (p_end != -1 && (guint)p_end > len) p_end = len;
if (f_end != -1 && (guint)f_end > len) f_end = len;
if (fa_end != -1 && (guint)fa_end > len) fa_end = len;
// Protocol
byte_view_text->markProtocol(p_start, p_end);
// Field bytes
byte_view_text->markField(f_start, f_end);
// Appendix (trailer) bytes
byte_view_text->markAppendix(fa_start, fa_end);
setCurrentIndex(idx);
}
}
}

View File

@ -31,9 +31,10 @@
#include "cfile.h"
#include <QTabWidget>
#include <QTreeWidget>
#include <QTreeWidgetItem>
class QTreeWidget;
class QTreeWidgetItem;
#include <ui/qt/byte_view_text.h>
class ByteViewTab : public QTabWidget
{
@ -49,33 +50,47 @@ public:
};
explicit ByteViewTab(QWidget *parent = 0);
void addTab(const char *name = "", tvbuff_t *tvb = NULL, proto_tree *tree = NULL, QTreeWidget *protoTree = NULL, packet_char_enc encoding = PACKET_CHAR_ENC_CHAR_ASCII);
void clear();
void copyData(copyDataType copy_type, field_info *fi = NULL);
public slots:
/* Set the capture file */
void setCaptureFile(capture_file *cf);
/* Creates the tabs and data, depends on an dissection which has already run */
void packetSelectionChanged();
void protoTreeItemChanged(QTreeWidgetItem *current);
void setMonospaceFont(const QFont &mono_font);
signals:
void monospaceFontChanged(const QFont &mono_font);
void byteFieldHovered(const QString &);
void tvbOffsetHovered(tvbuff_t *, int);
void tvbOffsetMarked(tvbuff_t *, int);
private:
capture_file *cap_file_;
QFont mono_font_;
void setTabsVisible();
void copyHexTextDump(const guint8 *data_p, int data_len, bool append_text);
void copyPrintableText(const guint8 *data_p, int data_len);
void copyHexStream(const guint8 *data_p, int data_len);
void copyBinary(const guint8 *data_p, int data_len);
void copyEscapedString(const guint8 *data_p, int data_len);
void copyHexTextDump(QByteArray data, bool append_text);
void copyPrintableText(QByteArray data);
void copyHexStream(QByteArray data);
void copyBinary(QByteArray data);
void copyEscapedString(QByteArray data);
ByteViewText * findByteViewTextForTvb(tvbuff_t * search, int * idx = 0);
void addTab(const char *name = "", tvbuff_t *tvb = NULL);
protected:
void tabInserted(int index);
void tabRemoved(int index);
signals:
void monospaceFontChanged(const QFont &mono_font);
void byteFieldHovered(const QString &);
public slots:
void protoTreeItemChanged(QTreeWidgetItem *current);
void setCaptureFile(capture_file *cf);
void setMonospaceFont(const QFont &mono_font);
private slots:
void byteViewTextHovered(int);
void byteViewTextMarked(int);
};
#endif // BYTE_VIEW_TAB_H

View File

@ -38,6 +38,8 @@
#include <QMouseEvent>
#include <QPainter>
#include <QScrollBar>
#include <QStyle>
#include <QStyleOption>
// To do:
// - Add recent settings and context menu items to show/hide the offset,
@ -52,14 +54,9 @@
Q_DECLARE_METATYPE(bytes_view_type)
Q_DECLARE_METATYPE(packet_char_enc)
ByteViewText::ByteViewText(QWidget *parent, tvbuff_t *tvb, proto_tree *tree, QTreeWidget *tree_widget, packet_char_enc encoding) :
ByteViewText::ByteViewText(QByteArray data, packet_char_enc encoding, QWidget *parent) :
QAbstractScrollArea(parent),
tvb_(tvb),
proto_tree_(tree),
tree_widget_(tree_widget),
bold_highlight_(false),
format_actions_(new QActionGroup(this)),
encoding_actions_(new QActionGroup(this)),
encoding_(encoding),
hovered_byte_offset_(-1),
hovered_byte_lock_(false),
@ -75,6 +72,25 @@ ByteViewText::ByteViewText(QWidget *parent, tvbuff_t *tvb, proto_tree *tree, QTr
line_spacing_(0),
margin_(0)
{
data_ = data;
createContextMenu();
setMouseTracking(true);
#ifdef Q_OS_MAC
setAttribute(Qt::WA_MacShowFocusRect, true);
#endif
}
ByteViewText::~ByteViewText()
{
ctx_menu_.clear();
}
void ByteViewText::createContextMenu()
{
QActionGroup * format_actions_ = new QActionGroup(this);
QAction *action;
action = format_actions_->addAction(tr("Show bytes as hexadecimal"));
@ -95,6 +111,7 @@ ByteViewText::ByteViewText(QWidget *parent, tvbuff_t *tvb, proto_tree *tree, QTr
ctx_menu_.addSeparator();
QActionGroup * encoding_actions_ = new QActionGroup(this);
action = encoding_actions_->addAction(tr(UTF8_HORIZONTAL_ELLIPSIS "as ASCII"));
action->setData(qVariantFromValue(PACKET_CHAR_ENC_CHAR_ASCII));
action->setCheckable(true);
@ -110,17 +127,26 @@ ByteViewText::ByteViewText(QWidget *parent, tvbuff_t *tvb, proto_tree *tree, QTr
ctx_menu_.addActions(encoding_actions_->actions());
connect(encoding_actions_, SIGNAL(triggered(QAction*)), this, SLOT(setCharacterEncoding(QAction*)));
setMouseTracking(true);
#ifdef Q_OS_MAC
setAttribute(Qt::WA_MacShowFocusRect, true);
#endif
}
ByteViewText::~ByteViewText()
void ByteViewText::reset()
{
ctx_menu_.clear();
data_.clear();
}
QByteArray ByteViewText::viewData()
{
return data_;
}
void ByteViewText::setHighlightStyle(bool bold)
{
bold_highlight_ = bold;
}
bool ByteViewText::isEmpty() const
{
return data_.isEmpty();
}
QSize ByteViewText::minimumSizeHint() const
@ -129,46 +155,34 @@ QSize ByteViewText::minimumSizeHint() const
return QSize();
}
bool ByteViewText::hasDataSource(const tvbuff_t *ds_tvb) {
if (ds_tvb != NULL && ds_tvb == tvb_)
return true;
return false;
}
void ByteViewText::setProtocolHighlight(int start, int end)
void ByteViewText::markProtocol(int start, int end)
{
p_bound_ = QPair<guint, guint>(qMax(0, start), qMax(0, end));
p_bound_save_ = p_bound_;
viewport()->update();
}
void ByteViewText::setFieldHighlight(int start, int end, guint32, int)
void ByteViewText::markField(int start, int end)
{
f_bound_ = QPair<guint, guint>(qMax(0, start), qMax(0, end));
f_bound_save_ = f_bound_;
scrollToByte(start);
viewport()->update();
}
void ByteViewText::setFieldAppendixHighlight(int start, int end)
void ByteViewText::moveToOffset(int pos)
{
scrollToByte(pos);
viewport()->update();
}
void ByteViewText::markAppendix(int start, int end)
{
fa_bound_ = QPair<guint, guint>(qMax(0, start), qMax(0, end));
fa_bound_save_ = f_bound_;
viewport()->update();
}
const guint8 *ByteViewText::dataAndLength(guint *data_len_ptr)
{
if (!tvb_) return NULL;
guint data_len = tvb_captured_length(tvb_);
if (data_len) {
*data_len_ptr = data_len;
return tvb_get_ptr(tvb_, 0, -1);
}
return NULL;
}
void ByteViewText::setMonospaceFont(const QFont &mono_font)
{
mono_font_ = mono_font;
@ -209,7 +223,7 @@ void ByteViewText::paintEvent(QPaintEvent *)
painter.fillRect(offset_rect, palette().window());
}
if (!tvb_) {
if ( data_.isEmpty() ) {
return;
}
@ -236,7 +250,7 @@ void ByteViewText::paintEvent(QPaintEvent *)
// Data rows
int widget_height = height();
painter.save();
while(row_y + line_spacing_ < widget_height && offset < tvb_captured_length(tvb_)) {
while( (int) (row_y + line_spacing_) < widget_height && (int) offset < (int) data_.count()) {
drawOffsetLine(painter, offset, row_y);
offset += row_width_;
row_y += line_spacing_;
@ -254,26 +268,12 @@ void ByteViewText::resizeEvent(QResizeEvent *)
}
void ByteViewText::mousePressEvent (QMouseEvent *event) {
if (!tvb_ || !event || event->button() != Qt::LeftButton) {
if (isEmpty() || !event || event->button() != Qt::LeftButton) {
return;
}
hovered_byte_lock_ = !hovered_byte_lock_;
QPoint pos = event->pos();
field_info *fi = fieldAtPixel(pos);
if (fi && tree_widget_) {
// XXX - This should probably be a ProtoTree method.
QTreeWidgetItemIterator iter(tree_widget_);
while (*iter) {
if (fi == VariantPointer<field_info>::asPtr((*iter)->data(0, Qt::UserRole))) {
tree_widget_->setCurrentItem((*iter));
tree_widget_->scrollToItem((*iter));
}
++iter;
}
}
emit byteSelected(byteOffsetAtPixel(event->pos()));
}
void ByteViewText::mouseMoveEvent(QMouseEvent *event)
@ -282,53 +282,16 @@ void ByteViewText::mouseMoveEvent(QMouseEvent *event)
return;
}
QString field_str;
// XXX can the event really be NULL?
if (!event) {
emit byteFieldHovered(field_str);
p_bound_ = p_bound_save_;
f_bound_ = f_bound_save_;
fa_bound_ = fa_bound_save_;
viewport()->update();
return;
}
QPoint pos = event->pos();
hovered_byte_offset_ = byteOffsetAtPixel(pos);
field_info *fi = fieldAtPixel(pos);
if (fi) {
if (fi->length < 2) {
field_str = QString(tr("Byte %1"))
.arg(fi->start);
} else {
field_str = QString(tr("Bytes %1-%2"))
.arg(fi->start)
.arg(fi->start + fi->length - 1);
}
field_str += QString(": %1 (%2)")
.arg(fi->hfinfo->name)
.arg(fi->hfinfo->abbrev);
f_bound_ = QPair<guint, guint>(fi->start, fi->start + fi->length);
p_bound_ = QPair<guint, guint>(0, 0);
fa_bound_ = QPair<guint, guint>(0, 0);
} else {
p_bound_ = p_bound_save_;
f_bound_ = f_bound_save_;
fa_bound_ = fa_bound_save_;
}
emit byteFieldHovered(field_str);
emit byteHovered(byteOffsetAtPixel(event->pos()));
viewport()->update();
}
void ByteViewText::leaveEvent(QEvent *event)
{
QString empty;
emit byteFieldHovered(empty);
if (!hovered_byte_lock_) {
hovered_byte_offset_ = -1;
}
p_bound_ = p_bound_save_;
f_bound_ = f_bound_save_;
fa_bound_ = fa_bound_save_;
emit byteHovered(-1);
viewport()->update();
QAbstractScrollArea::leaveEvent(event);
}
@ -348,12 +311,11 @@ const int ByteViewText::separator_interval_ = 8; // Insert a space after this ma
// 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_) {
if (isEmpty()) {
return;
}
guint tvb_len = tvb_captured_length(tvb_);
guint tvb_len = data_.count();
guint max_pos = qMin(offset + row_width_, tvb_len);
const guint8 *pd = tvb_get_ptr(tvb_, 0, -1);
static const guchar hexchars[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
@ -399,13 +361,13 @@ void ByteViewText::drawOffsetLine(QPainter &painter, const guint offset, const i
switch (recent.gui_bytes_view) {
case BYTES_HEX:
text += hexchars[(pd[tvb_pos] & 0xf0) >> 4];
text += hexchars[pd[tvb_pos] & 0x0f];
text += hexchars[(data_[tvb_pos] & 0xf0) >> 4];
text += hexchars[data_[tvb_pos] & 0x0f];
break;
case BYTES_BITS:
/* XXX, bitmask */
for (int j = 7; j >= 0; j--)
text += (pd[tvb_pos] & (1 << j)) ? '1' : '0';
text += (data_[tvb_pos] & (1 << j)) ? '1' : '0';
break;
}
if (draw_hover) {
@ -450,8 +412,8 @@ void ByteViewText::drawOffsetLine(QPainter &painter, const guint offset, const i
}
guchar c = (encoding_ == PACKET_CHAR_ENC_CHAR_EBCDIC) ?
EBCDIC_to_ASCII1(pd[tvb_pos]) :
pd[tvb_pos];
EBCDIC_to_ASCII1(data_[tvb_pos]) :
data_[tvb_pos];
text += g_ascii_isprint(c) ? c : '.';
if (highlight_text) {
@ -532,7 +494,7 @@ void ByteViewText::scrollToByte(int byte)
// Offset character width
int ByteViewText::offsetChars()
{
if (tvb_ && tvb_captured_length(tvb_) > 0xffff) {
if (! isEmpty() && data_.count() > 0xffff) {
return 8;
}
return 4;
@ -572,17 +534,16 @@ int ByteViewText::totalPixels()
void ByteViewText::updateScrollbars()
{
const gint length = tvb_ ? tvb_captured_length(tvb_) : 0;
if (tvb_) {
const int length = data_.count();
if (length > 0) {
qint64 maxval = length / row_width_ + ((length % row_width_) ? 1 : 0) - viewport()->height() / line_spacing_;
verticalScrollBar()->setRange(0, int(qMax((qint64)0, maxval)));
horizontalScrollBar()->setRange(0, qMax(0, static_cast<int>((totalPixels() - viewport()->width()) / font_width_)));
}
qint64 maxval = length / row_width_ + ((length % row_width_) ? 1 : 0) - viewport()->height() / line_spacing_;
verticalScrollBar()->setRange(0, int(qMax((qint64)0, maxval)));
horizontalScrollBar()->setRange(0, qMax(0, static_cast<int>((totalPixels() - viewport()->width()) / font_width_)));
}
int ByteViewText::byteOffsetAtPixel(QPoint &pos)
int ByteViewText::byteOffsetAtPixel(QPoint pos)
{
int byte = (verticalScrollBar()->value() + (pos.y() / line_spacing_)) * row_width_;
int x = (horizontalScrollBar()->value() * font_width_) + pos.x();
@ -593,21 +554,12 @@ int ByteViewText::byteOffsetAtPixel(QPoint &pos)
}
byte += col;
if ((guint) byte > tvb_captured_length(tvb_)) {
if (byte > data_.count()) {
return -1;
}
return byte;
}
field_info *ByteViewText::fieldAtPixel(QPoint &pos)
{
int byte = byteOffsetAtPixel(pos);
if (byte < 0) {
return NULL;
}
return proto_find_field_from_offset(proto_tree_, byte, tvb_);
}
void ByteViewText::setHexDisplayFormat(QAction *action)
{
if (!action) {

View File

@ -24,17 +24,14 @@
#include <config.h>
#include <epan/packet.h>
#include <epan/proto.h>
#include <epan/tvbuff.h>
#include "proto_tree.h"
#include "ui/recent.h"
#include <QAbstractScrollArea>
#include <QString>
#include <QFont>
#include <QSize>
#include <QMenu>
class QActionGroup;
#include <QMap>
// XXX - Is there any reason we shouldn't add ByteViewImage, etc?
@ -42,25 +39,34 @@ 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);
explicit ByteViewText(QByteArray data, packet_char_enc encoding = PACKET_CHAR_ENC_CHAR_ASCII, QWidget *parent = 0);
~ByteViewText();
virtual QSize minimumSizeHint() const;
bool hasDataSource(const tvbuff_t *ds_tvb = NULL);
void setFormat(bytes_view_type format);
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);
bool isEmpty() { return tvb_ == NULL || proto_tree_ == NULL; }
const guint8 *dataAndLength(guint *data_len_ptr);
void setHighlightStyle(bool bold);
bool isEmpty() const;
QByteArray viewData();
signals:
void byteFieldHovered(const QString &);
void byteHovered(int pos);
void byteSelected(int pos);
public slots:
void reset();
void setMonospaceFont(const QFont &mono_font);
void markProtocol(int start, int end);
void markField(int start, int end);
void markAppendix(int start, int end);
void moveToOffset(int pos);
protected:
virtual void paintEvent(QPaintEvent *);
virtual void resizeEvent(QResizeEvent *);
@ -80,22 +86,23 @@ private:
ModeHover
} HighlightMode;
QByteArray data_;
void drawOffsetLine(QPainter &painter, const guint offset, const int row_y);
qreal flushOffsetFragment(QPainter &painter, qreal x, int y, HighlightMode mode, QString &text);
void scrollToByte(int byte);
void updateScrollbars();
int byteOffsetAtPixel(QPoint pos);
void createContextMenu();
int offsetChars();
int offsetPixels();
int hexPixels();
int asciiPixels();
int totalPixels();
void updateScrollbars();
int byteOffsetAtPixel(QPoint &pos);
field_info *fieldAtPixel(QPoint &pos);
static const int separator_interval_;
tvbuff_t *tvb_;
proto_tree *proto_tree_;
QTreeWidget *tree_widget_;
// Fonts and colors
QFont mono_font_;
@ -103,11 +110,9 @@ private:
QBrush offset_normal_fg_;
QBrush offset_field_fg_;
gboolean bold_highlight_;
bool bold_highlight_;
// Data
QActionGroup *format_actions_;
QActionGroup *encoding_actions_;
packet_char_enc encoding_; // ASCII or EBCDIC
QMenu ctx_menu_;

View File

@ -476,6 +476,9 @@ MainWindow::MainWindow(QWidget *parent) :
packet_list_->setByteViewTab(byte_view_tab_);
packet_list_->installEventFilter(this);
connect(packet_list_, SIGNAL(packetSelectionChanged()),
byte_view_tab_, SLOT(packetSelectionChanged()));
main_welcome_ = main_ui_->welcomePage;
// Packet list and proto tree must exist before these are called.
@ -685,10 +688,8 @@ MainWindow::MainWindow(QWidget *parent) :
connect(proto_tree_, SIGNAL(editProtocolPreference(preference*,pref_module*)),
main_ui_->preferenceEditorFrame, SLOT(editPreference(preference*,pref_module*)));
connect(byte_view_tab_, SIGNAL(byteFieldHovered(const QString&)),
main_ui_->statusBar, SLOT(pushByteStatus(const QString&)));
connect(byte_view_tab_, SIGNAL(currentChanged(int)),
this, SLOT(byteViewTabChanged(int)));
connect(byte_view_tab_, SIGNAL(tvbOffsetHovered(tvbuff_t *, int)),
this, SLOT(setTvbOffsetHovered(tvbuff_t *, int)));
connect(main_ui_->statusBar, SIGNAL(showExpertInfo()),
this, SLOT(on_actionAnalyzeExpertInfo_triggered()));

View File

@ -388,7 +388,7 @@ private slots:
void openTapParameterDialog(const QString cfg_str, const QString arg, void *userdata);
void openTapParameterDialog();
void byteViewTabChanged(int tab_index);
void setTvbOffsetHovered(tvbuff_t * tvb, int idx);
#ifdef HAVE_SOFTWARE_UPDATE
void softwareUpdateRequested();

View File

@ -1779,13 +1779,33 @@ void MainWindow::openTapParameterDialog()
openTapParameterDialog(cfg_str, NULL, NULL);
}
void MainWindow::byteViewTabChanged(int tab_index)
void MainWindow::setTvbOffsetHovered(tvbuff_t * tvb, int idx)
{
QWidget *new_tab = byte_view_tab_->widget(tab_index);
if (new_tab) {
setTabOrder(proto_tree_, new_tab);
setTabOrder(new_tab, df_combo_box_->lineEdit()); // XXX Toolbar instead?
QString field_str("");
if ( tvb && capture_file_.capFile() && capture_file_.capFile()->edt )
{
proto_tree * tree = capture_file_.capFile()->edt->tree;
if ( tree )
{
field_info * fi = proto_find_field_from_offset(tree, idx, tvb);
if (fi) {
if (fi->length < 2) {
field_str = QString(tr("Byte %1"))
.arg(fi->start);
} else {
field_str = QString(tr("Bytes %1-%2"))
.arg(fi->start)
.arg(fi->start + fi->length - 1);
}
field_str += QString(": %1 (%2)")
.arg(fi->hfinfo->name)
.arg(fi->hfinfo->abbrev);
}
}
}
main_ui_->statusBar->pushByteStatus(field_str);
}
#ifdef HAVE_SOFTWARE_UPDATE

View File

@ -71,19 +71,7 @@ PacketDialog::PacketDialog(QWidget &parent, CaptureFile &cf, frame_data *fdata)
byte_view_tab_ = new ByteViewTab(ui->packetSplitter);
byte_view_tab_->setCaptureFile(cap_file_.capFile());
byte_view_tab_->clear();
GSList *src_le;
for (src_le = edt_.pi.data_src; src_le != NULL; src_le = src_le->next) {
struct data_source *source;
char* source_name;
source = (struct data_source *)src_le->data;
source_name = get_data_source_name(source);
byte_view_tab_->addTab(source_name, get_data_source_tvb(source), edt_.tree, proto_tree_,
(packet_char_enc)cap_file_.capFile()->current_frame->flags.encoding);
wmem_free(NULL, source_name);
}
byte_view_tab_->setCurrentIndex(0);
byte_view_tab_->packetSelectionChanged();
ui->packetSplitter->setStretchFactor(1, 0);
@ -95,7 +83,8 @@ PacketDialog::PacketDialog(QWidget &parent, CaptureFile &cf, frame_data *fdata)
.arg(cap_file_.capFile()->cinfo.columns[i].col_data);
}
col_info_ = col_parts.join(" " UTF8_MIDDLE_DOT " ");
setHintText();
ui->hintLabel->setText(col_info_);
connect(this, SIGNAL(monospaceFontChanged(QFont)),
proto_tree_, SLOT(setMonospaceFont(QFont)));
@ -106,6 +95,8 @@ PacketDialog::PacketDialog(QWidget &parent, CaptureFile &cf, frame_data *fdata)
byte_view_tab_, SLOT(protoTreeItemChanged(QTreeWidgetItem*)));
connect(byte_view_tab_, SIGNAL(byteFieldHovered(const QString&)),
this, SLOT(setHintText(const QString&)));
connect(byte_view_tab_, SIGNAL(tvbOffsetHovered(tvbuff_t *, int)),
this, SLOT(setTvbOffsetHovered(tvbuff_t *, int)));
}
PacketDialog::~PacketDialog()
@ -120,13 +111,38 @@ void PacketDialog::captureFileClosing()
QString closed_title = tr("[%1 closed] " UTF8_MIDDLE_DOT " %2")
.arg(cap_file_.fileName())
.arg(col_info_);
setHintText(closed_title);
ui->hintLabel->setText(closed_title);
WiresharkDialog::captureFileClosing();
}
void PacketDialog::setHintText(const QString &hint)
void PacketDialog::setTvbOffsetHovered(tvbuff_t * tvb, int idx)
{
ui->hintLabel->setText(hint.isEmpty() ? col_info_ : hint);
QString field_str("");
if ( tvb && cap_file_.capFile() && cap_file_.capFile()->edt )
{
proto_tree * tree = cap_file_.capFile()->edt->tree;
if ( tree )
{
field_info * fi = proto_find_field_from_offset(tree, idx, tvb);
if (fi) {
if (fi->length < 2) {
field_str = QString(tr("Byte %1"))
.arg(fi->start);
} else {
field_str = QString(tr("Bytes %1-%2"))
.arg(fi->start)
.arg(fi->start + fi->length - 1);
}
field_str += QString(": %1 (%2)")
.arg(fi->hfinfo->name)
.arg(fi->hfinfo->abbrev);
}
}
}
ui->hintLabel->setText(field_str);
}
void PacketDialog::on_buttonBox_helpRequested()

View File

@ -47,8 +47,7 @@ signals:
private slots:
void captureFileClosing();
void setHintText() { QString empty; setHintText(empty); }
void setHintText(const QString &hint);
void setTvbOffsetHovered(tvbuff_t * tvb, int idx);
void on_buttonBox_helpRequested();
private:

View File

@ -505,7 +505,6 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS
related_packet_delegate_.clear();
if (proto_tree_) proto_tree_->clear();
if (byte_view_tab_) byte_view_tab_->clear();
emit packetSelectionChanged();
@ -525,20 +524,6 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS
viewport()->update();
}
if (byte_view_tab_) {
GSList *src_le;
struct data_source *source;
char* source_name;
for (src_le = cap_file_->edt->pi.data_src; src_le != NULL; src_le = src_le->next) {
source = (struct data_source *)src_le->data;
source_name = get_data_source_name(source);
byte_view_tab_->addTab(source_name, get_data_source_tvb(source), cap_file_->edt->tree, proto_tree_, (packet_char_enc)cap_file_->current_frame->flags.encoding);
wmem_free(NULL, source_name);
}
byte_view_tab_->setCurrentIndex(0);
}
if (cap_file_->search_in_progress &&
(cap_file_->search_pos != 0 || (cap_file_->string && cap_file_->decode_data)))
{
@ -944,7 +929,6 @@ void PacketList::freeze()
// call selectionChanged.
related_packet_delegate_.clear();
proto_tree_->clear();
byte_view_tab_->clear();
}
void PacketList::thaw(bool restore_selection)
@ -970,7 +954,6 @@ void PacketList::clear() {
selectionModel()->clear();
packet_list_model_->clear();
proto_tree_->clear();
byte_view_tab_->clear();
selection_history_.clear();
cur_history_ = -1;
in_history_ = false;