From 0a28fb8f6a354aa9a446b6bf70733c305534e074 Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Tue, 30 Oct 2012 19:21:24 +0000 Subject: [PATCH] Update the Qt byte view widget to reflect the recent changes in the GTK+ byte view. Move the packet_char_enc enum from packet.h to frame_data.h. Make the encoding flag a packet_char_enc and make it one bit. Get rid of the "cfile" global in a few places. C++-ize some of the font code. Clean up some variable names. svn path=/trunk/; revision=45838 --- epan/frame_data.h | 11 +- epan/packet.h | 6 - ui/qt/byte_view_tab.cpp | 115 ++++- ui/qt/byte_view_tab.h | 6 +- ui/qt/byte_view_text.cpp | 856 ++++++++++++---------------------- ui/qt/byte_view_text.h | 58 ++- ui/qt/main_window.cpp | 5 + ui/qt/main_window.h | 1 + ui/qt/main_window_slots.cpp | 2 + ui/qt/monospace_font.cpp | 36 +- ui/qt/monospace_font.h | 4 +- ui/qt/packet_list.cpp | 47 +- ui/qt/packet_list.h | 2 + ui/qt/packet_list_model.cpp | 39 +- ui/qt/packet_list_model.h | 5 +- ui/qt/proto_tree.cpp | 5 +- ui/qt/wireshark_application.h | 1 + 17 files changed, 558 insertions(+), 641 deletions(-) diff --git a/epan/frame_data.h b/epan/frame_data.h index dc4f177a34..5ab3205417 100644 --- a/epan/frame_data.h +++ b/epan/frame_data.h @@ -36,6 +36,12 @@ should we keep that stuff in the "packet_info" structure, instead, to save memory? */ +/* Types of character encodings */ +typedef enum { + PACKET_CHAR_ENC_CHAR_ASCII = 0, /* ASCII */ + PACKET_CHAR_ENC_CHAR_EBCDIC = 1 /* EBCDIC */ +} packet_char_enc; + /** The frame number is the ordinal number of the frame in the capture, so it's 1-origin. In various contexts, 0 as a frame number means "frame number unknown". */ @@ -52,7 +58,7 @@ typedef struct _frame_data { struct { unsigned int passed_dfilter : 1; /**< 1 = display, 0 = no display */ unsigned int dependent_of_displayed : 1; /**< 1 if a displayed frame depends on this frame */ - unsigned int encoding : 2; /**< Character encoding (ASCII, EBCDIC...) */ + packet_char_enc encoding : 1; /**< Character encoding (ASCII, EBCDIC...) */ unsigned int visited : 1; /**< Has this packet been visited yet? 1=Yes,0=No*/ unsigned int marked : 1; /**< 1 = marked by user, 0 = normal */ unsigned int ref_time : 1; /**< 1 = marked as a reference time frame, 0 = normal */ @@ -94,7 +100,7 @@ extern void frame_data_init(frame_data *fdata, guint32 num, const struct wtap_pkthdr *phdr, gint64 offset, guint32 cum_bytes); -extern void frame_delta_abs_time(const frame_data *fdata, +extern void frame_delta_abs_time(const frame_data *fdata, const frame_data *prev, nstime_t *delta); /** * Sets the frame data struct values before dissection. @@ -109,4 +115,3 @@ extern void frame_data_set_after_dissect(frame_data *fdata, guint32 *cum_bytes); #endif /* __FRAME_DATA__ */ - diff --git a/epan/packet.h b/epan/packet.h index 0d933994cd..88ec915c14 100644 --- a/epan/packet.h +++ b/epan/packet.h @@ -77,12 +77,6 @@ typedef struct _packet_counts { /** Number of packet counts. */ #define PACKET_COUNTS_SIZE sizeof(packet_counts) / sizeof (gint) -/* Types of character encodings */ -typedef enum { - PACKET_CHAR_ENC_CHAR_ASCII = 0, /* ASCII */ - PACKET_CHAR_ENC_CHAR_EBCDIC = 1 /* EBCDIC */ -} packet_char_enc; - extern void packet_init(void); extern void packet_cleanup(void); diff --git a/ui/qt/byte_view_tab.cpp b/ui/qt/byte_view_tab.cpp index 7828e572a2..6c84fb5ccb 100644 --- a/ui/qt/byte_view_tab.cpp +++ b/ui/qt/byte_view_tab.cpp @@ -33,11 +33,11 @@ ByteViewTab::ByteViewTab(QWidget *parent) : addTab(); } -void ByteViewTab::addTab(const char *name, tvbuff_t *tvb, proto_tree *tree, QTreeWidget *protoTree, unsigned int encoding) { - ByteViewText *byteViewText = new ByteViewText(this, tvb, tree, protoTree, encoding); +void ByteViewTab::addTab(const char *name, tvbuff_t *tvb, proto_tree *tree, QTreeWidget *protoTree, packet_char_enc encoding) { + ByteViewText *byte_view_text = new ByteViewText(this, tvb, tree, protoTree, encoding); - byteViewText->setAccessibleName(name); - QTabWidget::addTab(byteViewText, name); + byte_view_text->setAccessibleName(name); + QTabWidget::addTab(byte_view_text, name); } void ByteViewTab::tabInserted(int index) { @@ -58,18 +58,27 @@ void ByteViewTab::setTabsVisible() { } void ByteViewTab::protoTreeItemChanged(QTreeWidgetItem *current) { - if (current) { + if (current && cap_file_) { field_info *fi; fi = current->data(0, Qt::UserRole).value(); // g_log(NULL, G_LOG_LEVEL_DEBUG, "fi selected %p", fi); int i = 0; - ByteViewText *byteViewText = dynamic_cast(widget(i)); - while (byteViewText) { - if (byteViewText->hasDataSource(fi->ds_tvb)) { + ByteViewText *byte_view_text = dynamic_cast(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; + guint32 bmask = 0x00; + int bmask_le = 0; + int fa_start = -1, fa_end = -1, fa_len = -1; + int p_start = -1, p_end = -1, p_len = -1; + guint len = tvb_length(fi->ds_tvb); + +// byte_view_text->setEncoding(cap_file_->current_frame->flags.encoding); + // Find and highlight the protocol bytes while (parent && parent->parent()) { parent = parent->parent(); } @@ -77,18 +86,98 @@ void ByteViewTab::protoTreeItemChanged(QTreeWidgetItem *current) { parent_fi = parent->data(0, Qt::UserRole).value(); } if (parent_fi && parent_fi->ds_tvb == fi->ds_tvb) { - byteViewText->highlight(parent_fi->start, parent_fi->length, true); - } else { - byteViewText->highlight(0, 0, true); + p_start = parent_fi->start; + p_len = parent_fi->length; } - byteViewText->highlight(fi->start, 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. */ + if (cap_file_->hex) { + f_len = (int)strlen(cap_file_->sfilter)/2; + } else { + f_len = (int)strlen(cap_file_->sfilter); + } + f_start = cap_file_->search_pos - (f_len-1); + } else { + f_start = fi->start; + f_len = fi->length; + } + + /* bmask = finfo->hfinfo->bitmask << finfo->hfinfo->bitshift; */ /* (value & mask) >> shift */ + if (fi->hfinfo) bmask = fi->hfinfo->bitmask; + fa_start = fi->appendix_start; + fa_len = fi->appendix_length; + + if (FI_GET_FLAG(fi, FI_LITTLE_ENDIAN)) + bmask_le = 1; + else if (FI_GET_FLAG(fi, FI_BIG_ENDIAN)) + bmask_le = 0; + else { /* unknown endianess - disable mask + bmask_le = (G_BYTE_ORDER == G_LITTLE_ENDIAN); + */ + bmask = 0x00; + } + + if (bmask == 0x00) { + int bito = FI_GET_BITS_OFFSET(fi); + int bitc = FI_GET_BITS_SIZE(fi); + int bitt = bito + bitc; + + /* construct mask using bito & bitc */ + /* XXX, mask has only 32 bit, later we can store bito&bitc, and use them (which should be faster) */ + if (bitt > 0 && bitt < 32) { + + bmask = ((1 << bitc) - 1) << ((8-bitt) & 7); + bmask_le = 0; /* ? */ + } + } + + 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; + bmask = 0x00; + 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); + + byte_view_text->render(); } - byteViewText = dynamic_cast(widget(++i)); + byte_view_text = dynamic_cast(widget(++i)); } } } +void ByteViewTab::setCaptureFile(capture_file *cf) +{ + cap_file_ = cf; +} + /* * Editor modelines * diff --git a/ui/qt/byte_view_tab.h b/ui/qt/byte_view_tab.h index 425ea79fa8..c06102e5fe 100644 --- a/ui/qt/byte_view_tab.h +++ b/ui/qt/byte_view_tab.h @@ -30,6 +30,8 @@ #include #include +#include "cfile.h" + #include #include @@ -38,10 +40,11 @@ class ByteViewTab : public QTabWidget Q_OBJECT public: explicit ByteViewTab(QWidget *parent = 0); - void addTab(const char *name = "", tvbuff_t *tvb = NULL, proto_tree *tree = NULL, QTreeWidget *protoTree = NULL, unsigned int encoding = PACKET_CHAR_ENC_CHAR_ASCII); + 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); private: void setTabsVisible(); + capture_file *cap_file_; protected: void tabInserted(int index); @@ -51,6 +54,7 @@ signals: public slots: void protoTreeItemChanged(QTreeWidgetItem *current); + void setCaptureFile(capture_file *cf); }; #endif // BYTE_VIEW_TAB_H diff --git a/ui/qt/byte_view_text.cpp b/ui/qt/byte_view_text.cpp index ba814e0966..fca655ed47 100644 --- a/ui/qt/byte_view_text.cpp +++ b/ui/qt/byte_view_text.cpp @@ -21,11 +21,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "monospace_font.h" #include "byte_view_text.h" #include +#include "wireshark_application.h" #include #include #include @@ -33,579 +33,334 @@ // XXX - Use KHexEdit instead? // http://api.kde.org/4.x-api/kdelibs-apidocs/interfaces/khexedit/html/index.html -ByteViewText::ByteViewText(QWidget *parent, tvbuff_t *tvb, proto_tree *tree, QTreeWidget *protoTree, unsigned int encoding) : - QTextEdit(parent) +ByteViewText::ByteViewText(QWidget *parent, tvbuff_t *tvb, proto_tree *tree, QTreeWidget *tree_widget, packet_char_enc encoding) : + QTextEdit(parent), + tvb_(tvb), + proto_tree_(tree), + tree_widget_(tree_widget), + max_width_(0), + bold_highlight_(false), + encoding_(encoding), + format_(BYTES_HEX), + per_line_(16), + offset_width_(4) { setReadOnly(true); setLineWrapMode(QTextEdit::NoWrap); - setCurrentFont(get_monospace_font()); - - m_tvb = tvb; - m_tree = tree; - m_protoTree = protoTree; - m_encoding = encoding; - m_start = m_len = 0; - -// m_background = textBackgroundColor(); -// m_foreground = textColor(); - -// g_log(NULL, G_LOG_LEVEL_DEBUG, "fg %d %d %d bg %d %d %d", -// m_foreground.red(), m_foreground.green(), m_foreground.blue(), -// m_background.red(), m_background.green(), m_background.blue() -// ); - - hexPrintCommon(); + setState(StateNormal); } -#define MAX_OFFSET_LEN 8 /* max length of hex offset of bytes */ -#define BYTES_PER_LINE 16 /* max byte values in a line */ -#define BITS_PER_LINE 8 /* max bit values in a line */ -#define BYTE_VIEW_SEP 8 /* insert a space every BYTE_VIEW_SEP bytes */ -#define HEX_DUMP_LEN (BYTES_PER_LINE*3 + 1) -/* max number of characters hex dump takes - - 2 digits plus trailing blank - plus separator between first and - second 8 digits */ -#define DATA_DUMP_LEN (HEX_DUMP_LEN + 2 + BYTES_PER_LINE) -/* number of characters those bytes take; - 3 characters per byte of hex dump, - 2 blanks separating hex from ASCII, - 1 character per byte of ASCII dump */ -#define MAX_LINE_LEN (MAX_OFFSET_LEN + 2 + DATA_DUMP_LEN) -/* number of characters per line; - offset, 2 blanks separating offset - from data dump, data dump */ -#define MAX_LINES 100 -#define MAX_LINES_LEN (MAX_LINES*MAX_LINE_LEN) - -// Copied from packet_hex_print_common -void -ByteViewText::hexPrintCommon() +void ByteViewText::setEncoding(packet_char_enc encoding) { - int i = 0, j, k = 0, len; - const guint8 *pd; - QString line; - static guchar hexchars[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; -// static const guint8 bitmask[8] = { -// 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; - guchar c = '\0'; - -// progdlg_t *progbar = NULL; -// float progbar_val; -// gboolean progbar_stop_flag; -// GTimeVal progbar_start_time; -// gchar progbar_status_str[100]; -// int progbar_nextstep; -// int progbar_quantum; - - setPlainText(""); - // Replaces get_byte_view_data_and_length(). - if (!m_tvb) - return; - len = tvb_length(m_tvb); - pd = tvb_get_ptr(m_tvb, 0, -1); - - /* - * How many of the leading digits of the offset will we supply? - * We always supply at least 4 digits, but if the maximum offset - * won't fit in 4 digits, we use as many digits as will be needed. - */ - if (((len - 1) & 0xF0000000) != 0) - m_useDigits = 8; /* need all 8 digits */ - else if (((len - 1) & 0x0F000000) != 0) - m_useDigits = 7; /* need 7 digits */ - else if (((len - 1) & 0x00F00000) != 0) - m_useDigits = 6; /* need 6 digits */ - else if (((len - 1) & 0x000F0000) != 0) - m_useDigits = 5; /* need 5 digits */ - else - m_useDigits = 4; /* we'll supply 4 digits */ - - /* Update the progress bar when it gets to this value. */ -// if (len > MIN_PACKET_LENGTH){ -// progbar_nextstep = 0; -// }else{ -// /* If length =< MIN_PACKET_LENGTH -// * there is no need to calculate the progress -// */ -// progbar_nextstep = len+1; -// } - -// /* When we reach the value that triggers a progress bar update, -// bump that value by this amount. */ -// progbar_quantum = len/N_PROGBAR_UPDATES; -// /* Progress so far. */ -// progbar_val = 0.0f; - -// progbar_stop_flag = FALSE; -// g_get_current_time(&progbar_start_time); - - while (i < len) { - /* Create the progress bar if necessary. - We check on every iteration of the loop, so that it takes no - longer than the standard time to create it (otherwise, for a - large packet, we might take considerably longer than that standard - time in order to get to the next progress bar step). */ -// if ((progbar == NULL) && (len > MIN_PACKET_LENGTH)) -// progbar = delayed_create_progress_dlg("Processing", "Packet Details", -// TRUE, -// &progbar_stop_flag, -// &progbar_start_time, -// progbar_val); - - /* Update the progress bar, but do it only N_PROGBAR_UPDATES times; - when we update it, we have to run the GTK+ main loop to get it - to repaint what's pending, and doing so may involve an "ioctl()" - to see if there's any pending input from an X server, and doing - that for every packet can be costly, especially on a big file. */ -// if (i >= progbar_nextstep) { - -// if (progbar != NULL) { -// /* let's not divide by zero. I should never be started -// * with count == 0, so let's assert that -// */ -// g_assert(len > 0); -// progbar_val = (gfloat) i / len; -// g_snprintf(progbar_status_str, sizeof(progbar_status_str), -// "%4u of %u bytes", i, len); -// update_progress_dlg(progbar, progbar_val, progbar_status_str); -// } - -// progbar_nextstep += progbar_quantum; -// } - -// if (progbar_stop_flag) { -// /* Well, the user decided to abort the operation. Just stop, -// and arrange to return TRUE to our caller, so they know it -// was stopped explicitly. */ -// break; -// } - - /* Print the line number */ - j = m_useDigits; - do { - j--; - c = (i >> (j*4)) & 0xF; - line += hexchars[c]; - } while (j != 0); - line += " "; - - j = i; -// switch (recent.gui_bytes_view) { -// case BYTES_HEX: - k = i + BYTES_PER_LINE; -// break; -// case BYTES_BITS: -// k = i + BITS_PER_LINE; -// break; -// default: -// g_assert_not_reached(); -// } - /* Print the hex bit */ - while (i < k) { - if (i < len) { -// switch (recent.gui_bytes_view) { -// case BYTES_HEX: - line += hexchars[(pd[i] & 0xf0) >> 4]; - line += hexchars[pd[i] & 0x0f]; -// break; -// case BYTES_BITS: -// for (b = 0; b < 8; b++) { -// line += (pd[i] & bitmask[b]) ? '1' : '0'; -// } -// break; -// default: -// g_assert_not_reached(); -// } - } else { -// switch (recent.gui_bytes_view) { -// case BYTES_HEX: - line += " "; -// break; -// case BYTES_BITS: -// for (b = 0; b < 8; b++) { -// line += ' '; -// } -// break; -// default: -// g_assert_not_reached(); -// } - } - i++; - /* Inter byte space if not at end of line */ - if (i < k) { - line += ' '; - /* insert a space every BYTE_VIEW_SEP bytes */ - if( ( i % BYTE_VIEW_SEP ) == 0 ) { - line += ' '; - } - } - } - - /* Print some space at the end of the line */ - line += " "; - - /* Print the ASCII bit */ - i = j; - - while (i < k) { - if (i < len) { - if (m_encoding == PACKET_CHAR_ENC_CHAR_ASCII) { - c = pd[i]; - } - else if (m_encoding == PACKET_CHAR_ENC_CHAR_EBCDIC) { - c = EBCDIC_to_ASCII1(pd[i]); - } - else { - g_assert_not_reached(); - } - line += isascii(c) && isprint(c) ? c : '.'; - } else { - line += ' '; - } - i++; - if (i < k) { - /* insert a space every BYTE_VIEW_SEP bytes */ - if( ( i % BYTE_VIEW_SEP ) == 0 ) { - line += ' '; - } - } - } - line += '\n'; - if (line.length() >= (MAX_LINES_LEN - MAX_LINE_LEN)) { - append(line); - line.clear(); - } - } - -// /* We're done printing the packets; destroy the progress bar if -// it was created. */ -// if (progbar != NULL) -// destroy_progress_dlg(progbar); - - if (line.length()) { - append(line); - } + encoding_ = encoding; } bool ByteViewText::hasDataSource(tvbuff_t *ds_tvb) { - if (ds_tvb != NULL && ds_tvb == m_tvb) + if (ds_tvb != NULL && ds_tvb == tvb_) return true; return false; } -// Copied from packet_hex_apply_reverse_tag -void ByteViewText::highlight(int bstart, int blen, bool is_root) { - m_start = bstart; -// m_len = blen; +void ByteViewText::setProtocolHighlight(int start, int end) +{ + p_start_ = start; + p_end_ = end; +} -// g_log(NULL, G_LOG_LEVEL_DEBUG, "hl %d %d %d %d", start, len, m_foreground.color().red(), m_background.color().red()); - QTextCursor cursor(textCursor()); - QTextCharFormat format = cursor.charFormat(); +void ByteViewText::setFieldHighlight(int start, int end, guint32 mask, int mask_le) +{ + Q_UNUSED(mask); + Q_UNUSED(mask_le); + f_start_ = start; + f_end_ = end; +} - QPalette pal = QApplication::palette(); +void ByteViewText::setFieldAppendixHighlight(int start, int end) +{ + fa_start_ = start; + fa_end_ = end; +} - if (is_root) { - cursor.movePosition(QTextCursor::Start); - cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); - format.setForeground(pal.text()); - format.setBackground(pal.base()); - cursor.setCharFormat(format); - } +void ByteViewText::render() +{ + int length; - // XXX - We should probably use the same colors as the packet list and proto tree selections. - // It isn't obvious how to fetch these. - format.setForeground(is_root ? pal.text() : pal.base()); - format.setBackground(is_root ? pal.alternateBase() : pal.text()); - - int bend = bstart + blen; - int per_line = 0; - int per_one = 0; -// int bits_per_one = 0; - int hex_offset, ascii_offset; - - int start_line, start_line_pos; - int stop_line, stop_line_pos; - - if (bstart == -1 || blen == -1) + if (!tvb_) { + clear(); return; + } -// /* Display with inverse video ? */ -// if (prefs.gui_hex_dump_highlight_style) -// revstyle = "reverse"; -// else -// revstyle = "bold"; + setUpdatesEnabled(false); + clear(); -// switch (recent.gui_bytes_view) { -// case BYTES_HEX: - per_line = BYTES_PER_LINE; - per_one = 2+1; /* "ff " */ -// bits_per_one = 4; -// break; -// case BYTES_BITS: -// per_line = BITS_PER_LINE; -// per_one = 8+1; /* "10101010 " */ -// bits_per_one = 1; -// break; -// default: -// g_assert_not_reached(); -// } + length = tvb_length(tvb_); + for (int off = 0; off < length; off += per_line_) { + lineCommon(off); + } - start_line = bstart / per_line; - start_line_pos = bstart % per_line; + if (f_start_ != -1 && f_end_ != -1) { + scrollToByte(f_start_); + } else if (p_start_ != -1 && p_end_ != -1) { + scrollToByte(p_start_); + } - stop_line = bend / per_line; - stop_line_pos = bend % per_line; - -#define hex_fix(pos) hex_offset + (pos * per_one) + (pos / BYTE_VIEW_SEP) - (pos == per_line) -#define ascii_fix(pos) pos + (pos / BYTE_VIEW_SEP) - (pos == per_line) - - hex_offset = m_useDigits + 2; - ascii_offset = hex_fix(per_line) + 2; - - cursor.setPosition(0); - cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, start_line); - -// if (mask == 0x00) { - while (start_line <= stop_line) { - int line_pos_end = (start_line == stop_line) ? stop_line_pos : per_line; -// int first_block_adjust = (recent.gui_bytes_view == BYTES_HEX) ? (line_pos_end == per_line/2) : 0; - int first_block_adjust = line_pos_end == per_line/2; - - if (start_line_pos == line_pos_end) break; - - // Should we just jump to absolute offsets instead? - /* bits/hex */ - int cursor_start = hex_fix(start_line_pos); - int cursor_len = hex_fix(line_pos_end) - cursor_start - 1 - first_block_adjust; - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, cursor_start); - cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, cursor_len); - cursor.setCharFormat(format); - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, ascii_offset - cursor_start - cursor_len); - - /* ascii */ - cursor_start = ascii_fix(start_line_pos); - cursor_len = ascii_fix(line_pos_end) - cursor_start - first_block_adjust; - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, cursor_start); - cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, cursor_len); - cursor.setCharFormat(format); - - start_line_pos = 0; - start_line++; - // You are encouraged to make carriage return and line feed sound - // effects as you read the next two lines. - cursor.movePosition(QTextCursor::StartOfLine); - cursor.movePosition(QTextCursor::Down); - } - -// } else if (mask_le) { /* LSB of mask first (little-endian) */ -// while (start_line <= stop_line) { -// int line_pos_end = (start_line == stop_line) ? stop_line_pos : per_line; -// int line_pos = start_line_pos; - -// while (line_pos < line_pos_end) { -// int lop = 8 / bits_per_one; -// int mask_per_one = (1 << bits_per_one) - 1; -// int ascii_on = 0; - -// while (lop--) { -// if ((mask & mask_per_one)) { -// /* bits/hex */ -// gtk_text_buffer_get_iter_at_line_index(buf, &i_start, start_line, hex_fix(line_pos)+lop); -// gtk_text_buffer_get_iter_at_line_index(buf, &i_stop, start_line, hex_fix(line_pos)+lop+1); -// gtk_text_buffer_apply_tag(buf, revstyle_tag, &i_start, &i_stop); - -// ascii_on = 1; -// } -// mask >>= bits_per_one; -// } - -// /* at least one bit of ascii was one -> turn ascii on */ -// if (ascii_on) { -// /* ascii */ -// gtk_text_buffer_get_iter_at_line_index(buf, &i_start, start_line, ascii_fix(line_pos)); -// gtk_text_buffer_get_iter_at_line_index(buf, &i_stop, start_line, ascii_fix(line_pos)+1); -// gtk_text_buffer_apply_tag(buf, revstyle_tag, &i_start, &i_stop); -// } - -// if (!mask) -// goto xend; - -// line_pos++; -// } - -// start_line_pos = 0; -// start_line++; -// } -// } else { /* mask starting from end (big-endian) */ -// while (start_line <= stop_line) { -// int line_pos_start = (start_line == stop_line) ? start_line_pos : 0; -// int line_pos = stop_line_pos-1; - -// while (line_pos >= line_pos_start) { -// int lop = 8 / bits_per_one; -// int mask_per_one = (1 << bits_per_one) - 1; -// int ascii_on = 0; - -// while (lop--) { -// if ((mask & mask_per_one)) { -// /* bits/hex */ -// gtk_text_buffer_get_iter_at_line_index(buf, &i_start, stop_line, hex_fix(line_pos)+lop); -// gtk_text_buffer_get_iter_at_line_index(buf, &i_stop, stop_line, hex_fix(line_pos)+lop+1); -// gtk_text_buffer_apply_tag(buf, revstyle_tag, &i_start, &i_stop); - -// ascii_on = 1; -// } -// mask >>= bits_per_one; -// } - -// /* at least one bit of ascii was one -> turn ascii on */ -// if (ascii_on) { -// /* ascii */ -// gtk_text_buffer_get_iter_at_line_index(buf, &i_start, stop_line, ascii_fix(line_pos)); -// gtk_text_buffer_get_iter_at_line_index(buf, &i_stop, stop_line, ascii_fix(line_pos)+1); -// gtk_text_buffer_apply_tag(buf, revstyle_tag, &i_start, &i_stop); -// } - -// if (!mask) -// goto xend; - -// line_pos--; -// } - -// stop_line_pos = per_line; -// stop_line--; -// } -// } -//xend: - -#undef hex_fix -#undef ascii_fix + setUpdatesEnabled(true); } -// XXX - Copied from main_proto_draw.c -/* Which byte the offset is referring to. Associates - * whitespace with the preceding digits. */ -static int -byte_num(int offset, int start_point) +// Private + +#define BYTE_VIEW_SEP 8 /* insert a space every BYTE_VIEW_SEP bytes */ + +void ByteViewText::lineCommon(const int org_off) { - return (offset - start_point) / 3; + static const guchar hexchars[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + const guint8 *pd; + int len; + + highlight_state state; + + QString str; + + int off; + guchar c; + int byten; + int j; + + g_assert(org_off >= 0); + + if (!tvb_) + return; + len = tvb_length(tvb_); + pd = tvb_get_ptr(tvb_, 0, -1); + + state = StateNormal; + setState(state); + + /* Print the line number */ + str += QString("%1 ").arg(org_off, offset_width_, 16, QChar('0')); + + /* Print the hex bit */ + for (byten = 0, off = org_off; byten < per_line_; byten++) { + highlight_state state_cur = StateNormal; + bool add_space = byten > 0; + + if ((off >= f_start_ && off < f_end_) || (off >= fa_start_ && off < fa_end_)) { + state_cur = StateField; + } else if (off >= p_start_ && off < p_end_) { + state_cur = StateProtocol; + } + + if (state_cur != state) { + if (state != StateField && add_space) { + add_space = false; + str += ' '; + /* insert a space every BYTE_VIEW_SEP bytes */ + if ((off % BYTE_VIEW_SEP) == 0) + str += ' '; + } + + if (flushBytes(str) < 0) + return; + setState(state_cur); + state = state_cur; + } + + if (add_space) { + str += ' '; + /* insert a space every BYTE_VIEW_SEP bytes */ + if ((off % BYTE_VIEW_SEP) == 0) + str += ' '; + } + + if (off < len) { + switch (format_) { + case BYTES_HEX: + str += hexchars[(pd[off] & 0xf0) >> 4]; + str += hexchars[pd[off] & 0x0f]; + break; + case BYTES_BITS: + /* XXX, bitmask */ + for (j = 7; j >= 0; j--) + str += (pd[off] & (1 << j)) ? '1' : '0'; + break; + } + } else { + switch (format_) { + case BYTES_HEX: + str += " "; + break; + case BYTES_BITS: + str += " "; + break; + } + } + off++; + } + + if (state != StateNormal) { + if (flushBytes(str) < 0) + return; + setState(StateNormal); + state = StateNormal; + } + + /* Print some space at the end of the line */ + str += " "; + + /* Print the ASCII bit */ + for (byten = 0, off = org_off; byten < per_line_; byten++) { + highlight_state state_cur = StateNormal; + bool add_space = byten > 0; + + if ((off >= f_start_ && off < f_end_) || (off >= fa_start_ && off < fa_end_)) { + state_cur = StateField; + } else if (off >= p_start_ && off < p_end_) { + state_cur = StateProtocol; + } + + if (state_cur != state) { + if (state != StateField && add_space) { + add_space = false; + /* insert a space every BYTE_VIEW_SEP bytes */ + if ((off % BYTE_VIEW_SEP) == 0) + str += ' '; + } + + if (flushBytes(str) < 0) + return; + setState(state_cur); + state = state_cur; + } + + if (add_space) { + /* insert a space every BYTE_VIEW_SEP bytes */ + if ((off % BYTE_VIEW_SEP) == 0) + str += ' '; + } + + if (off < len) { + c = (encoding_ == PACKET_CHAR_ENC_CHAR_EBCDIC) ? + EBCDIC_to_ASCII1(pd[off]) : + pd[off]; + + str += isprint(c) ? c : '.'; + } else + str += ' '; + + off++; + } + + if (str.length() > 0) { + if (flushBytes(str) < 0) + return; + } + + if (state != StateNormal) { + setState(StateNormal); + /* state = StateNormal; */ + } + append(""); } -// XXX - Copied from main_proto_draw.c -//static int -//bit_num(int offset, int start_point) -//{ -// return (offset - start_point) / 9; -//} - -// XXX - Copied from main_proto_draw.c -static int -hex_view_get_byte(guint ndigits, int row, int column) +void ByteViewText::setState(ByteViewText::highlight_state state) { - int byte; - int digits_start_1; - int digits_end_1; - int digits_start_2; - int digits_end_2; - int text_start_1; - int text_end_1; - int text_start_2; - int text_end_2; + QPalette pal = wsApp->palette(); - /* - * The column of the first hex digit in the first half. - * That starts after "ndigits" digits of offset and two - * separating blanks. - */ - digits_start_1 = ndigits + 2; + moveCursor(QTextCursor::End); + setCurrentFont(wsApp->monospaceFont()); + setTextColor(pal.text().color()); + setTextBackgroundColor(pal.base().color()); - /* - * The column of the last hex digit in the first half. - * There are BYTES_PER_LINE/2 bytes displayed in the first - * half; there are 2 characters per byte, plus a separating - * blank after all but the last byte's characters. - */ - digits_end_1 = digits_start_1 + (BYTES_PER_LINE/2)*2 + - (BYTES_PER_LINE/2 - 1); - - /* - * The column of the first hex digit in the second half. - * Add 2 for the 2 separating blanks between the halves. - */ - digits_start_2 = digits_end_1 + 2; - - /* - * The column of the last hex digit in the second half. - * Add the same value we used to get "digits_end_1" from - * "digits_start_1". - */ - digits_end_2 = digits_start_2 + (BYTES_PER_LINE/2)*2 + - (BYTES_PER_LINE/2 - 1); - - /* - * The column of the first "text dump" character in the first half. - * Add 3 for the 3 separating blanks between the hex and text dump. - */ - text_start_1 = digits_end_2 + 3; - - /* - * The column of the last "text dump" character in the first half. - * There are BYTES_PER_LINE/2 bytes displayed in the first - * half; there is 1 character per byte. - * - * Then subtract 1 to get the last column of the first half - * rather than the first column after the first half. - */ - text_end_1 = text_start_1 + BYTES_PER_LINE/2 - 1; - - /* - * The column of the first "text dump" character in the second half. - * Add back the 1 to get the first column after the first half, - * and then add 1 for the separating blank between the halves. - */ - text_start_2 = text_end_1 + 2; - - /* - * The column of the last "text dump" character in second half. - * Add the same value we used to get "text_end_1" from - * "text_start_1". - */ - text_end_2 = text_start_2 + BYTES_PER_LINE/2 - 1; - - /* Given the column and row, determine which byte offset - * the user clicked on. */ - if (column >= digits_start_1 && column <= digits_end_1) { - byte = byte_num(column, digits_start_1); - if (byte == -1) { - return byte; + switch (state) { + case StateProtocol: + setTextBackgroundColor(pal.alternateBase().color()); + break; + case StateField: + if (bold_highlight_) { + setCurrentFont(wsApp->monospaceFont(true)); + } else { + setTextColor(pal.base().color()); + setTextBackgroundColor(pal.text().color()); } + break; + default: + break; } - else if (column >= digits_start_2 && column <= digits_end_2) { - byte = byte_num(column, digits_start_2); - if (byte == -1) { - return byte; - } - byte += 8; - } - else if (column >= text_start_1 && column <= text_end_1) { - byte = column - text_start_1; - } - else if (column >= text_start_2 && column <= text_end_2) { - byte = 8 + column - text_start_2; - } - else { - /* The user didn't select a hex digit or - * text-dump character. */ +} + +int ByteViewText::flushBytes(QString &str) +{ + if (str.length() < 1) return 0; + + insertPlainText(str); + str.clear(); + return str.length(); +} + +void ByteViewText::scrollToByte(int byte) +{ + QTextCursor cursor(textCursor()); + + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, byte / per_line_); + setTextCursor(cursor); +} + +int ByteViewText::byteFromRowCol(int row, int col) +{ + /* hex_pos_byte array generated with hex_view_get_byte(0, 0, 0...70) */ + static const int hex_pos_byte[70] = { + -1, -1, + 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, + 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, + -1, + 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, + 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, + -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + -1, + 8, 9, 10, 11, 12, 13, 14, 15 + }; + + /* bits_pos_byte array generated with bit_view_get_byte(0, 0, 0...84) */ + static const int bits_pos_byte[84] = { + -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, + -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7 + }; + + int off_col = 1; + int off_row; + + off_row = row * per_line_; + + if (/* char_x < 0 || */ col < offset_width_) return -1; + col -= offset_width_; + + switch (format_) { + case BYTES_BITS: + g_return_val_if_fail(col >= 0 && col < (int) G_N_ELEMENTS(bits_pos_byte), -1); + off_col = bits_pos_byte[col]; + break; + + case BYTES_HEX: + g_return_val_if_fail(col >= 0 && col < (int) G_N_ELEMENTS(hex_pos_byte), -1); + off_col = hex_pos_byte[col]; + break; } - /* Add the number of bytes from the previous rows. */ - byte += row * BYTES_PER_LINE; + if (col == -1) + return -1; - return byte; + return off_row + off_col; } void ByteViewText::mousePressEvent (QMouseEvent * event) { @@ -614,26 +369,27 @@ void ByteViewText::mousePressEvent (QMouseEvent * event) { QTextCursor cursor(cursorForPosition(event->pos())); field_info *fi; - byte = hex_view_get_byte(m_useDigits, cursor.blockNumber(), cursor.columnNumber()); - fi = proto_find_field_from_offset(m_tree, byte, m_tvb); - g_log(NULL, G_LOG_LEVEL_DEBUG, "byte %d fi %p", byte, fi); + byte = byteFromRowCol(cursor.blockNumber(), cursor.columnNumber()); + if (byte >= 0) { + fi = proto_find_field_from_offset(proto_tree_, byte, tvb_); - if (fi && m_protoTree) { - // XXX - This should probably be a ProtoTree method. - QTreeWidgetItemIterator iter(m_protoTree); - while (*iter) { - if (fi == (*iter)->data(0, Qt::UserRole).value()) { - g_log(NULL, G_LOG_LEVEL_DEBUG, "found %p", fi); - m_protoTree->setCurrentItem((*iter)); + if (fi && tree_widget_) { + // XXX - This should probably be a ProtoTree method. + QTreeWidgetItemIterator iter(tree_widget_); + while (*iter) { + if (fi == (*iter)->data(0, Qt::UserRole).value()) { + tree_widget_->setCurrentItem((*iter)); + } + + iter++; } - - iter++; } } } QWidget::mousePressEvent (event); } + /* * Editor modelines * diff --git a/ui/qt/byte_view_text.h b/ui/qt/byte_view_text.h index a2dca40bbe..c20af58625 100644 --- a/ui/qt/byte_view_text.h +++ b/ui/qt/byte_view_text.h @@ -35,27 +35,63 @@ // XXX - Is there any reason we shouldn't add ByteViewImage, etc? +// XXX Copied from gtk/packet_panes.h +typedef enum { + BYTES_HEX, + BYTES_BITS +} bytes_view_type; + class ByteViewText : public QTextEdit { Q_OBJECT public: - explicit ByteViewText(QWidget *parent = 0, tvbuff_t *tvb = NULL, proto_tree *tree = NULL, QTreeWidget *protoTree = NULL, unsigned int encoding = PACKET_CHAR_ENC_CHAR_ASCII); - void hexPrintCommon(); + explicit ByteViewText(QWidget *parent = 0, tvbuff_t *tvb = NULL, proto_tree *tree = NULL, QTreeWidget *protoTree = NULL, packet_char_enc encoding = PACKET_CHAR_ENC_CHAR_ASCII); bool hasDataSource(tvbuff_t *ds_tvb = NULL); - void highlight(int start, int len, bool is_root = false); + void setEncoding(packet_char_enc encoding); + void setFormat(bytes_view_type format); + void setHighlightStyle(bool bold); + void setProtocolHighlight(int start, int end); + void setFieldHighlight(int start, int end, guint32 mask = 0, int mask_le = 0); + void setFieldAppendixHighlight(int start, int end); + void render(); private: - tvbuff_t *m_tvb; - proto_tree *m_tree; - QTreeWidget *m_protoTree; - int m_encoding; - unsigned int m_useDigits; - int m_start, m_len; + typedef enum { + StateNormal, + StateField, + StateProtocol + } highlight_state; + + void lineCommon(const int org_off); + void setState(highlight_state state); + int flushBytes(QString &str); + void scrollToByte(int byte); + + int byteFromRowCol(int row, int col); void mousePressEvent (QMouseEvent * event); -signals: + tvbuff_t *tvb_; + proto_tree *proto_tree_; + QTreeWidget *tree_widget_; -public slots: + gint adj_tag_; + int max_width_; + + gboolean bold_highlight_; + +/* data */ + packet_char_enc encoding_; /* ASCII or EBCDIC */ + bytes_view_type format_; /* bytes in hex or bytes as bits */ + +/* data-highlight */ + int p_start_, p_end_; /* Protocol */ + int f_start_, f_end_; /* Field */ + int fa_start_, fa_end_; /* Field appendix */ + + int per_line_; /* Number of bytes per line */ + int offset_width_; /* Byte offset field width */ + +signals: }; diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index cde782d8a0..b975cba046 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -183,6 +183,11 @@ MainWindow::MainWindow(QWidget *parent) : connect(main_welcome_, SIGNAL(recentFileActivated(QString&)), this, SLOT(openCaptureFile(QString&))); + connect(this, SIGNAL(setCaptureFile(capture_file*)), + packet_list_, SLOT(setCaptureFile(capture_file*))); + connect(this, SIGNAL(setCaptureFile(capture_file*)), + byte_view_tab, SLOT(setCaptureFile(capture_file*))); + connect(main_ui_->actionGoNextPacket, SIGNAL(triggered()), packet_list_, SLOT(goNextPacket())); connect(main_ui_->actionGoPreviousPacket, SIGNAL(triggered()), diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 71e6d6af0d..6f821f0898 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -119,6 +119,7 @@ private: signals: void showProgress(progdlg_t **dlg_p, bool animate, const QString message, bool terminate_is_stop, bool *stop_flag, float pct); + void setCaptureFile(capture_file *cf); public slots: // in main_window_slots.cpp diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 916c8315f8..7ed09ff70f 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -244,6 +244,7 @@ void MainWindow::captureFileOpened(const capture_file *cf) { file_set_dialog_.fileOpened(cf); setMenusForFileSet(true); + emit setCaptureFile(cap_file_); } void MainWindow::captureFileReadStarted(const capture_file *cf) { @@ -296,6 +297,7 @@ void MainWindow::captureFileClosing(const capture_file *cf) { // Reset expert info indicator main_ui_->statusBar->hideExpert(); // gtk_widget_show(expert_info_none); + emit setCaptureFile(NULL); } void MainWindow::captureFileClosed(const capture_file *cf) { diff --git a/ui/qt/monospace_font.cpp b/ui/qt/monospace_font.cpp index 81afd557ed..28014c280e 100644 --- a/ui/qt/monospace_font.cpp +++ b/ui/qt/monospace_font.cpp @@ -23,8 +23,6 @@ #include "monospace_font.h" -#include "wireshark_application.h" - #include #include #include @@ -39,7 +37,7 @@ //{ //} -QFont m_r_font, m_b_font; +QFont mono_regular_font_, mono_bold_font_; //void MonospaceFont::propagate() { // emit(monospaceFontChanged(self)); @@ -73,24 +71,24 @@ font_init(void) { substitutes = QStringList() << X11_ALT_FONTS << WIN_DEF_FONT << WIN_ALT_FONTS << OSX_DEF_FONT << OSX_ALT_FONTS << FALLBACK_FONTS; #endif - m_r_font.setFamily(DEF_FONT); - m_r_font.insertSubstitutions(DEF_FONT, substitutes); - m_r_font.setPointSize(wsApp->font().pointSize() + FONT_SIZE_ADJUST); + mono_regular_font_.setFamily(DEF_FONT); + mono_regular_font_.insertSubstitutions(DEF_FONT, substitutes); + mono_regular_font_.setPointSize(wsApp->font().pointSize() + FONT_SIZE_ADJUST); #if QT_VERSION >= 0x040700 - m_b_font.setStyleHint(QFont::Monospace); + mono_bold_font_.setStyleHint(QFont::Monospace); #else - m_b_font.setStyleHint(QFont::TypeWriter); + mono_bold_font_.setStyleHint(QFont::TypeWriter); #endif - m_b_font.setFamily(DEF_FONT); - m_b_font.insertSubstitutions(DEF_FONT, substitutes); - m_b_font.setPointSize(wsApp->font().pointSize() + FONT_SIZE_ADJUST); + mono_bold_font_.setFamily(DEF_FONT); + mono_bold_font_.insertSubstitutions(DEF_FONT, substitutes); + mono_bold_font_.setPointSize(wsApp->font().pointSize() + FONT_SIZE_ADJUST); #if QT_VERSION >= 0x040700 - m_b_font.setStyleHint(QFont::Monospace); + mono_bold_font_.setStyleHint(QFont::Monospace); #else - m_b_font.setStyleHint(QFont::TypeWriter); + mono_bold_font_.setStyleHint(QFont::TypeWriter); #endif - m_b_font.setWeight(QFont::Bold); + mono_bold_font_.setWeight(QFont::Bold); } fa_ret_t @@ -154,18 +152,18 @@ user_font_apply(void) { return FA_SUCCESS; } -// XXX - We might want to use a signal/slot for this (or just us a global variable). -QFont get_monospace_font(void) { - return m_r_font; +QFont WiresharkApplication::monospaceFont(bool bold) +{ + return bold ? mono_bold_font_ : mono_regular_font_; } int get_monospace_text_size(const char *str, bool regular) { QFontMetrics *fm; if (regular) - fm = new QFontMetrics(m_r_font); + fm = new QFontMetrics(mono_regular_font_); else - fm = new QFontMetrics(m_b_font); + fm = new QFontMetrics(mono_bold_font_); return fm->width(str); } diff --git a/ui/qt/monospace_font.h b/ui/qt/monospace_font.h index 39279297c4..53e8cace72 100644 --- a/ui/qt/monospace_font.h +++ b/ui/qt/monospace_font.h @@ -24,6 +24,8 @@ #ifndef MONOSPACE_FONT_H #define MONOSPACE_FONT_H +#include "wireshark_application.h" + #include //class MonospaceFont : public QFont @@ -57,8 +59,6 @@ typedef enum { */ extern fa_ret_t user_font_apply(void); -extern QFont get_monospace_font(void); - extern int get_monospace_text_size(const char *str, bool regular); #endif // MONOSPACE_FONT_H diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp index 510029907f..932033da42 100644 --- a/ui/qt/packet_list.cpp +++ b/ui/qt/packet_list.cpp @@ -36,7 +36,6 @@ #include "monospace_font.h" #include "proto_tree.h" -#include "globals.h" #include "qt_ui_utils.h" #include "ui/main_statusbar.h" @@ -214,7 +213,10 @@ packet_list_recent_write_all(FILE *rf) { #define MIN_COL_WIDTH_STR "...." PacketList::PacketList(QWidget *parent) : - QTreeView(parent) + QTreeView(parent), + proto_tree_(NULL), + byte_view_tab_(NULL), + cap_file_(NULL) { setItemsExpandable(FALSE); setRootIsDecorated(FALSE); @@ -222,16 +224,13 @@ PacketList::PacketList(QWidget *parent) : setUniformRowHeights(TRUE); setAccessibleName("Packet list"); - packet_list_model_ = new PacketListModel(this, &cfile); + packet_list_model_ = new PacketListModel(this, cap_file_); setModel(packet_list_model_); packet_list_model_->setColorEnabled(true); // We don't yet fetch color settings. // packet_list_model_->setColorEnabled(recent.packet_list_colorize); g_assert(gbl_cur_packet_list == NULL); gbl_cur_packet_list = this; - - proto_tree_ = NULL; - byte_view_tab_ = NULL; } void PacketList::setProtoTree (ProtoTree *proto_tree) { @@ -250,8 +249,10 @@ PacketListModel *PacketList::packetListModel() const { void PacketList::showEvent (QShowEvent *event) { Q_UNUSED(event); -// g_log(NULL, G_LOG_LEVEL_DEBUG, "cols: %d", cfile.cinfo.num_cols); - for (int i = 0; i < cfile.cinfo.num_cols; i++) { + + if (!cap_file_) return; + + for (int i = 0; i < cap_file_->cinfo.num_cols; i++) { int fmt, col_width; const char *long_str; @@ -269,18 +270,20 @@ void PacketList::showEvent (QShowEvent *event) { void PacketList::selectionChanged (const QItemSelection & selected, const QItemSelection & deselected) { QTreeView::selectionChanged(selected, deselected); + if (!cap_file_) return; + if (proto_tree_) { int row = selected.first().top(); - cf_select_packet(&cfile, row); + cf_select_packet(cap_file_, row); - if (!cfile.edt && !cfile.edt->tree) { + if (!cap_file_->edt && !cap_file_->edt->tree) { return; } - proto_tree_->fillProtocolTree(cfile.edt->tree); + proto_tree_->fillProtocolTree(cap_file_->edt->tree); } - if (byte_view_tab_ && cfile.edt) { + if (byte_view_tab_ && cap_file_->edt) { GSList *src_le; struct data_source *source; @@ -289,9 +292,9 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS delete byte_view_tab_->currentWidget(); } - for (src_le = cfile.edt->pi.data_src; src_le != NULL; src_le = src_le->next) { + for (src_le = cap_file_->edt->pi.data_src; src_le != NULL; src_le = src_le->next) { source = (struct data_source *)src_le->data; - byte_view_tab_->addTab(get_data_source_name(source), get_data_source_tvb(source), cfile.edt->tree, proto_tree_, cfile.current_frame->flags.encoding); + byte_view_tab_->addTab(get_data_source_name(source), get_data_source_tvb(source), cap_file_->edt->tree, proto_tree_, cap_file_->current_frame->flags.encoding); } } @@ -306,14 +309,14 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS void PacketList::updateAll() { update(); - if (selectedIndexes().length() > 0) { - cf_select_packet(&cfile, selectedIndexes()[0].row()); + if (cap_file_ && selectedIndexes().length() > 0) { + cf_select_packet(cap_file_, selectedIndexes()[0].row()); } } void PacketList::clear() { // packet_history_clear(); - packetListModel()->clear(); + packet_list_model_->clear(); proto_tree_->clear(); // Clear out existing tabs @@ -332,7 +335,7 @@ void PacketList::writeRecent(FILE *rf) { gchar xalign; fprintf (rf, "%s:", RECENT_KEY_COL_WIDTH); - for (col = 0; col < packetListModel()->columnCount(); col++) { + for (col = 0; col < packet_list_model_->columnCount(); col++) { if (col > 0) { fprintf (rf, ","); } @@ -357,6 +360,14 @@ void PacketList::writeRecent(FILE *rf) { } +// Slots + +void PacketList::setCaptureFile(capture_file *cf) +{ + cap_file_ = cf; + packet_list_model_->setCaptureFile(cf); +} + void PacketList::goNextPacket(void) { setCurrentIndex(moveCursor(MoveDown, Qt::NoModifier)); } diff --git a/ui/qt/packet_list.h b/ui/qt/packet_list.h index d5ec392edb..2b620c3258 100644 --- a/ui/qt/packet_list.h +++ b/ui/qt/packet_list.h @@ -52,10 +52,12 @@ private: PacketListModel *packet_list_model_; ProtoTree *proto_tree_; ByteViewTab *byte_view_tab_; + capture_file *cap_file_; signals: public slots: + void setCaptureFile(capture_file *cf); void goNextPacket(); void goPreviousPacket(); void goFirstPacket(); diff --git a/ui/qt/packet_list_model.cpp b/ui/qt/packet_list_model.cpp index c63ed9a5ff..a5f24d17ea 100644 --- a/ui/qt/packet_list_model.cpp +++ b/ui/qt/packet_list_model.cpp @@ -22,7 +22,6 @@ */ #include "packet_list_model.h" -#include "monospace_font.h" #include #include @@ -35,13 +34,19 @@ #include "globals.h" +#include "wireshark_application.h" #include -PacketListModel::PacketListModel(QObject *parent, capture_file *cfPtr) : +PacketListModel::PacketListModel(QObject *parent, capture_file *cf) : QAbstractItemModel(parent) { - cf = cfPtr; + cap_file_ = cf; +} + +void PacketListModel::setCaptureFile(capture_file *cf) +{ + cap_file_ = cf; } // Packet list records have no children (for now, at least). @@ -49,7 +54,8 @@ QModelIndex PacketListModel::index(int row, int column, const QModelIndex &paren const { Q_UNUSED(parent); - if (row >= visible_rows_.count() || row < 0 || column >= cf->cinfo.num_cols) + + if (row >= visible_rows_.count() || row < 0 || !cap_file_ || column >= cap_file_->cinfo.num_cols) return QModelIndex(); PacketListRecord *record = visible_rows_[row]; @@ -95,7 +101,9 @@ void PacketListModel::clear() { int PacketListModel::rowCount(const QModelIndex &parent) const { - if (parent.column() >= cf->cinfo.num_cols) + if (!cap_file_) return 0; + + if (parent.column() >= cap_file_->cinfo.num_cols) return 0; return visible_rows_.count(); @@ -104,7 +112,10 @@ int PacketListModel::rowCount(const QModelIndex &parent) const int PacketListModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); - return cf->cinfo.num_cols; + + if (!cap_file_) return 0; + + return cap_file_->cinfo.num_cols; } QVariant PacketListModel::data(const QModelIndex &index, int role) const @@ -121,7 +132,7 @@ QVariant PacketListModel::data(const QModelIndex &index, int role) const switch (role) { case Qt::FontRole: - return get_monospace_font(); + return wsApp->monospaceFont(); // case Qt::TextAlignmentRole: case Qt::BackgroundRole: const color_t *color; @@ -159,7 +170,7 @@ QVariant PacketListModel::data(const QModelIndex &index, int role) const int col_num = index.column(); // g_log(NULL, G_LOG_LEVEL_DEBUG, "showing col %d", col_num); - if (col_num > cf->cinfo.num_cols) + if (!cap_file_ || col_num > cap_file_->cinfo.num_cols) return QVariant(); epan_dissect_t edt; @@ -169,12 +180,12 @@ QVariant PacketListModel::data(const QModelIndex &index, int role) const guint8 pd[WTAP_MAX_PACKET_SIZE]; /* Packet data */ gboolean dissect_columns = TRUE; // XXX - Currently only a placeholder - if (dissect_columns) - cinfo = &cf->cinfo; + if (dissect_columns && cap_file_) + cinfo = &cap_file_->cinfo; else cinfo = NULL; - if (!cf_read_frame_r(cf, fdata, &phdr, pd)) { + if (!cap_file_ || !cf_read_frame_r(cap_file_, fdata, &phdr, pd)) { /* * Error reading the frame. * @@ -244,10 +255,12 @@ QVariant PacketListModel::data(const QModelIndex &index, int role) const QVariant PacketListModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (orientation == Qt::Horizontal && section < cf->cinfo.num_cols) { + if (!cap_file_) return QVariant(); + + if (orientation == Qt::Horizontal && section < cap_file_->cinfo.num_cols) { switch (role) { case Qt::DisplayRole: - return cf->cinfo.col_title[section]; + return cap_file_->cinfo.col_title[section]; default: break; } diff --git a/ui/qt/packet_list_model.h b/ui/qt/packet_list_model.h index 84a2832a5a..6f56054be0 100644 --- a/ui/qt/packet_list_model.h +++ b/ui/qt/packet_list_model.h @@ -44,7 +44,8 @@ class PacketListModel : public QAbstractItemModel { Q_OBJECT public: - explicit PacketListModel(QObject *parent = 0, capture_file *cfPtr = NULL); + explicit PacketListModel(QObject *parent = 0, capture_file *cf = NULL); + void setCaptureFile(capture_file *cf); QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; QModelIndex parent(const QModelIndex &index) const; @@ -68,7 +69,7 @@ signals: public slots: private: - capture_file *cf; + capture_file *cap_file_; QList col_names_; QVector visible_rows_; QVector physical_rows_; diff --git a/ui/qt/proto_tree.cpp b/ui/qt/proto_tree.cpp index 2d45334343..ac3b734da1 100644 --- a/ui/qt/proto_tree.cpp +++ b/ui/qt/proto_tree.cpp @@ -24,12 +24,11 @@ #include #include "proto_tree.h" -#include "monospace_font.h" #include #include -#include +#include "wireshark_application.h" #include #include #include @@ -153,7 +152,7 @@ ProtoTree::ProtoTree(QWidget *parent) : QTreeWidget(parent) { setAccessibleName(tr("Packet details")); - setFont(get_monospace_font()); + setFont(wsApp->monospaceFont()); setUniformRowHeights(true); connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), diff --git a/ui/qt/wireshark_application.h b/ui/qt/wireshark_application.h index 9b613fa242..49b103f4d9 100644 --- a/ui/qt/wireshark_application.h +++ b/ui/qt/wireshark_application.h @@ -66,6 +66,7 @@ public: void setLastOpenDir(const char *dir_name); void setLastOpenDir(QString *dir_str); void helpTopicAction(topic_action_e action); + QFont monospaceFont(bool bold = false); private: QTimer *recent_timer_;