aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ui/qt/byte_view_tab.cpp332
-rw-r--r--ui/qt/byte_view_tab.h49
-rw-r--r--ui/qt/byte_view_text.cpp190
-rw-r--r--ui/qt/byte_view_text.h55
-rw-r--r--ui/qt/main_window.cpp9
-rw-r--r--ui/qt/main_window.h2
-rw-r--r--ui/qt/main_window_slots.cpp30
-rw-r--r--ui/qt/packet_dialog.cpp50
-rw-r--r--ui/qt/packet_dialog.h3
-rw-r--r--ui/qt/packet_list.cpp17
10 files changed, 393 insertions, 344 deletions
diff --git a/ui/qt/byte_view_tab.cpp b/ui/qt/byte_view_tab.cpp
index afc7aa834e..b8d12bbe33 100644
--- a/ui/qt/byte_view_tab.cpp
+++ b/ui/qt/byte_view_tab.cpp
@@ -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)
}
}
-void ByteViewTab::copyData(ByteViewTab::copyDataType copy_type, field_info *fi)
+ByteViewText * ByteViewTab::findByteViewTextForTvb(tvbuff_t * search_tvb, int * idx)
{
- int i = 0;
- ByteViewText *byte_view_text = qobject_cast<ByteViewText*>(widget(i));
-
- if (fi) {
- while (byte_view_text) {
- if (byte_view_text->hasDataSource(fi->ds_tvb)) break;
- byte_view_text = qobject_cast<ByteViewText*>(widget(++i));
+ 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)
+{
+ ByteViewText *byte_view_text = 0;
+
+ 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);
-
- // 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 (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->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);
+ ByteViewText *byte_view_text = 0;
+ int idx = 0;
+
+ if ( fi )
+ byte_view_text = findByteViewTextForTvb(fi->ds_tvb, &idx);
+
+ 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);
+
+ // 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;
}
- byte_view_text = qobject_cast<ByteViewText*>(widget(++i));
+
+ 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);
}
}
}
diff --git a/ui/qt/byte_view_tab.h b/ui/qt/byte_view_tab.h
index 041832809c..202409ef2a 100644
--- a/ui/qt/byte_view_tab.h
+++ b/ui/qt/byte_view_tab.h
@@ -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
diff --git a/ui/qt/byte_view_text.cpp b/ui/qt/byte_view_text.cpp
index 47595c763e..95575140ed 100644
--- a/ui/qt/byte_view_text.cpp
+++ b/ui/qt/byte_view_text.cpp
@@ -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);
+void ByteViewText::reset()
+{
+ data_.clear();
+}
-#ifdef Q_OS_MAC
- setAttribute(Qt::WA_MacShowFocusRect, true);
-#endif
+QByteArray ByteViewText::viewData()
+{
+ return data_;
}
-ByteViewText::~ByteViewText()
+void ByteViewText::setHighlightStyle(bool bold)
{
- ctx_menu_.clear();
+ bold_highlight_ = bold;
+}
+
+bool ByteViewText::isEmpty() const
+{
+ return data_.isEmpty();
}
QSize ByteViewText::minimumSizeHint() const
@@ -129,44 +155,32 @@ 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)
{
- fa_bound_ = QPair<guint, guint>(qMax(0, start), qMax(0, end));
- fa_bound_save_ = f_bound_;
+ scrollToByte(pos);
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::markAppendix(int start, int end)
+{
+ fa_bound_ = QPair<guint, guint>(qMax(0, start), qMax(0, end));
+ fa_bound_save_ = f_bound_;
+ viewport()->update();
}
void ByteViewText::setMonospaceFont(const QFont &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_) {
- }
-
- qint64 maxval = length / row_width_ + ((length % row_width_) ? 1 : 0) - viewport()->height() / line_spacing_;
+ 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_)));
+ 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) {
diff --git a/ui/qt/byte_view_text.h b/ui/qt/byte_view_text.h
index f2af3c01d1..f5a7430f94 100644
--- a/ui/qt/byte_view_text.h
+++ b/ui/qt/byte_view_text.h
@@ -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_;
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index 0336b27d52..c2f0718515 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -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()));
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index 0ab3614e4d..77c8c35b03 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -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();
diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp
index c61b03abd6..c4068eab80 100644
--- a/ui/qt/main_window_slots.cpp
+++ b/ui/qt/main_window_slots.cpp
@@ -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
diff --git a/ui/qt/packet_dialog.cpp b/ui/qt/packet_dialog.cpp
index 5daec09601..7849a3d5f9 100644
--- a/ui/qt/packet_dialog.cpp
+++ b/ui/qt/packet_dialog.cpp
@@ -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()
diff --git a/ui/qt/packet_dialog.h b/ui/qt/packet_dialog.h
index 4f4cde7885..429519c85b 100644
--- a/ui/qt/packet_dialog.h
+++ b/ui/qt/packet_dialog.h
@@ -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:
diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp
index 46985c0bb8..2e904a0fdb 100644
--- a/ui/qt/packet_list.cpp
+++ b/ui/qt/packet_list.cpp
@@ -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;