forked from osmocom/wireshark
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:
parent
c5165f325b
commit
56a130a152
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue