summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docbook/release-notes.asciidoc1
-rw-r--r--epan/conversation.c8
-rw-r--r--epan/conversation.h2
-rw-r--r--ui/CMakeLists.txt1
-rw-r--r--ui/Makefile.common2
-rw-r--r--ui/gtk/packet_list.c80
-rw-r--r--ui/packet_list_utils.c122
-rw-r--r--ui/packet_list_utils.h71
-rw-r--r--ui/qt/CMakeLists.txt2
-rw-r--r--ui/qt/Makefile.common2
-rw-r--r--ui/qt/QtShark.pro2
-rw-r--r--ui/qt/packet_list.cpp31
-rw-r--r--ui/qt/packet_list.h7
-rw-r--r--ui/qt/packet_list_model.cpp38
-rw-r--r--ui/qt/packet_list_record.cpp9
-rw-r--r--ui/qt/proto_tree.cpp11
-rw-r--r--ui/qt/proto_tree.h2
-rw-r--r--ui/qt/related_packet_delegate.cpp135
-rw-r--r--ui/qt/related_packet_delegate.h71
19 files changed, 499 insertions, 98 deletions
diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc
index 300343b20f..c5db50713b 100644
--- a/docbook/release-notes.asciidoc
+++ b/docbook/release-notes.asciidoc
@@ -25,6 +25,7 @@ since version 1.10:
* Expert info is now filterable (if the dissector has been updated to support the new API).
* The Windows installer now uninstalls the previous version of Wireshark silently.
You can still run the uninstaller manually beforehand if you wish to run it interactively.
+* The "Number" column shows related packets and protocol conversation spans (Qt only).
=== New Protocol Support
diff --git a/epan/conversation.c b/epan/conversation.c
index 1164769c79..d2beee7810 100644
--- a/epan/conversation.c
+++ b/epan/conversation.c
@@ -650,7 +650,7 @@ conversation_new(const guint32 setup_frame, const address *addr1, const address
memset(conversation, 0, sizeof(conversation_t));
conversation->index = new_index;
- conversation->setup_frame = setup_frame;
+ conversation->setup_frame = conversation->last_frame = setup_frame;
conversation->data_list = NULL;
/* clear dissector handle */
@@ -1242,7 +1242,11 @@ find_or_create_conversation(packet_info *pinfo)
/* Have we seen this conversation before? */
if((conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
pinfo->ptype, pinfo->srcport,
- pinfo->destport, 0)) == NULL) {
+ pinfo->destport, 0)) != NULL) {
+ if (pinfo->fd->num > conv->last_frame) {
+ conv->last_frame = pinfo->fd->num;
+ }
+ } else {
/* No, this is a new conversation. */
conv = conversation_new(pinfo->fd->num, &pinfo->src,
&pinfo->dst, pinfo->ptype,
diff --git a/epan/conversation.h b/epan/conversation.h
index 3a019c6be8..fef0b9d7fa 100644
--- a/epan/conversation.h
+++ b/epan/conversation.h
@@ -78,6 +78,8 @@ typedef struct conversation {
/** pointer to the last conversation on hash chain */
guint32 index; /** unique ID for conversation */
guint32 setup_frame; /** frame number that setup this conversation */
+ /* Assume that setup_frame is also the lowest frame number for now. */
+ guint32 last_frame; /** highest frame number in this conversation */
GSList *data_list; /** list of data associated with conversation */
dissector_handle_t dissector_handle;
/** handle for protocol dissector client associated with conversation */
diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt
index bb60ba8505..edffb42447 100644
--- a/ui/CMakeLists.txt
+++ b/ui/CMakeLists.txt
@@ -29,6 +29,7 @@ set(COMMON_UI_SRC
export_object_http.c
export_object_smb.c
help_url.c
+ packet_list_utils.c
iface_lists.c
preference_utils.c
profile.c
diff --git a/ui/Makefile.common b/ui/Makefile.common
index 0c513092cf..a0c156c90a 100644
--- a/ui/Makefile.common
+++ b/ui/Makefile.common
@@ -51,6 +51,7 @@ WIRESHARK_UI_SRC = \
export_object_smb.c \
iface_lists.c \
help_url.c \
+ packet_list_utils.c \
preference_utils.c \
profile.c \
recent.c \
@@ -69,6 +70,7 @@ noinst_HEADERS = \
last_open_dir.h \
file_dialog.h \
help_url.h \
+ packet_list_utils.h \
iface_lists.h \
main_statusbar.h \
preference_utils.h \
diff --git a/ui/gtk/packet_list.c b/ui/gtk/packet_list.c
index b263485cb3..7e9ea7f575 100644
--- a/ui/gtk/packet_list.c
+++ b/ui/gtk/packet_list.c
@@ -42,6 +42,7 @@
#include <epan/emem.h>
#include "ui/main_statusbar.h"
+#include "ui/packet_list_utils.h"
#include "ui/preference_utils.h"
#include "ui/progress_dlg.h"
#include "ui/recent.h"
@@ -158,77 +159,6 @@ packet_list_append(column_info *cinfo _U_, frame_data *fdata, packet_info *pinfo
return visible_pos;
}
-static gboolean
-right_justify_column (gint col)
-{
- header_field_info *hfi;
- gboolean right_justify = FALSE;
-
- switch (cfile.cinfo.col_fmt[col]) {
-
- case COL_NUMBER:
- case COL_PACKET_LENGTH:
- case COL_CUMULATIVE_BYTES:
- case COL_DCE_CALL:
- case COL_DSCP_VALUE:
- case COL_UNRES_DST_PORT:
- case COL_UNRES_SRC_PORT:
- case COL_DEF_DST_PORT:
- case COL_DEF_SRC_PORT:
- case COL_DELTA_TIME:
- case COL_DELTA_TIME_DIS:
- right_justify = TRUE;
- break;
-
- case COL_CUSTOM:
- hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[col]);
- /* Check if this is a valid field and we have no strings lookup table */
- if ((hfi != NULL) && ((hfi->strings == NULL) || !get_column_resolved(col))) {
- /* Check for bool, framenum and decimal/octal integer types */
- if ((hfi->type == FT_BOOLEAN) || (hfi->type == FT_FRAMENUM) ||
- (((hfi->display == BASE_DEC) || (hfi->display == BASE_OCT)) &&
- (IS_FT_INT(hfi->type) || IS_FT_UINT(hfi->type)))) {
- right_justify = TRUE;
- }
- }
- break;
-
- default:
- break;
- }
-
- return right_justify;
-}
-
-static gboolean
-resolve_column (gint col)
-{
- header_field_info *hfi;
- gboolean resolve = FALSE;
-
- switch (cfile.cinfo.col_fmt[col]) {
-
- case COL_CUSTOM:
- hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[col]);
- /* Check if this is a valid field */
- if (hfi != NULL) {
- /* Check if we have an OID or a strings table with integer values */
- if ((hfi->type == FT_OID) ||
- ((hfi->strings != NULL) &&
- ((hfi->type == FT_BOOLEAN) || (hfi->type == FT_FRAMENUM) ||
- IS_FT_INT(hfi->type) || IS_FT_UINT(hfi->type)))) {
- resolve = TRUE;
- }
- }
- break;
-
- default:
- break;
- }
-
- return resolve;
-}
-
static void
col_title_change_ok (GtkWidget *w, gpointer parent_w)
{
@@ -527,7 +457,7 @@ static void
packet_list_xalign_column (gint col_id, GtkTreeViewColumn *col, gchar xalign)
{
GList *renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT(col));
- gboolean right_justify = right_justify_column(col_id);
+ gboolean right_justify = right_justify_column(col_id, &cfile);
gdouble value = get_xalign_value (xalign, right_justify);
GList *entry;
GtkCellRenderer *renderer;
@@ -676,10 +606,10 @@ packet_list_column_button_pressed_cb (GtkWidget *widget, GdkEvent *event, gpoint
GtkWidget *col = (GtkWidget *) data;
GtkWidget *menu = (GtkWidget *)g_object_get_data(G_OBJECT(popup_menu_object), PM_PACKET_LIST_COL_KEY);
gint col_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(col), E_MPACKET_LIST_COL_KEY));
- gboolean right_justify = right_justify_column (col_id);
+ gboolean right_justify = right_justify_column (col_id, &cfile);
menus_set_column_align_default (right_justify);
- menus_set_column_resolved (get_column_resolved (col_id), resolve_column (col_id));
+ menus_set_column_resolved (get_column_resolved (col_id), resolve_column (col_id, &cfile));
g_object_set_data(G_OBJECT(packetlist->view), E_MPACKET_LIST_COLUMN_KEY, col);
return popup_menu_handler (widget, event, menu);
}
@@ -765,7 +695,7 @@ create_view_and_model(void)
renderer = gtk_cell_renderer_text_new();
col = gtk_tree_view_column_new();
gtk_tree_view_column_pack_start(col, renderer, TRUE);
- value = get_xalign_value(recent_get_column_xalign(i), right_justify_column(i));
+ value = get_xalign_value(recent_get_column_xalign(i), right_justify_column(i, &cfile));
g_object_set(G_OBJECT(renderer),
"xalign", value,
NULL);
diff --git a/ui/packet_list_utils.c b/ui/packet_list_utils.c
new file mode 100644
index 0000000000..24f0dd47b5
--- /dev/null
+++ b/ui/packet_list_utils.c
@@ -0,0 +1,122 @@
+/* packet_list_utils.c
+ * Packet list display utilities
+ * Copied from gtk/packet_list.c
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include "packet_list_utils.h"
+
+#include <epan/column.h>
+#include <epan/proto.h>
+
+gboolean
+right_justify_column (gint col, capture_file *cf)
+{
+ header_field_info *hfi;
+ gboolean right_justify = FALSE;
+
+ if (!cf) return FALSE;
+
+ switch (cf->cinfo.col_fmt[col]) {
+
+ case COL_NUMBER:
+ case COL_PACKET_LENGTH:
+ case COL_CUMULATIVE_BYTES:
+ case COL_DCE_CALL:
+ case COL_DSCP_VALUE:
+ case COL_UNRES_DST_PORT:
+ case COL_UNRES_SRC_PORT:
+ case COL_DEF_DST_PORT:
+ case COL_DEF_SRC_PORT:
+ case COL_DELTA_TIME:
+ case COL_DELTA_TIME_DIS:
+ right_justify = TRUE;
+ break;
+
+ case COL_CUSTOM:
+ hfi = proto_registrar_get_byname(cf->cinfo.col_custom_field[col]);
+ /* Check if this is a valid field and we have no strings lookup table */
+ if ((hfi != NULL) && ((hfi->strings == NULL) || !get_column_resolved(col))) {
+ /* Check for bool, framenum and decimal/octal integer types */
+ if ((hfi->type == FT_BOOLEAN) || (hfi->type == FT_FRAMENUM) ||
+ (((hfi->display == BASE_DEC) || (hfi->display == BASE_OCT)) &&
+ (IS_FT_INT(hfi->type) || IS_FT_UINT(hfi->type)))) {
+ right_justify = TRUE;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return right_justify;
+}
+
+gboolean
+resolve_column (gint col, capture_file *cf)
+{
+ header_field_info *hfi;
+ gboolean resolve = FALSE;
+
+ if (!cf) return FALSE;
+
+ switch (cf->cinfo.col_fmt[col]) {
+
+ case COL_CUSTOM:
+ hfi = proto_registrar_get_byname(cf->cinfo.col_custom_field[col]);
+ /* Check if this is a valid field */
+ if (hfi != NULL) {
+ /* Check if we have an OID or a strings table with integer values */
+ if ((hfi->type == FT_OID) ||
+ ((hfi->strings != NULL) &&
+ ((hfi->type == FT_BOOLEAN) || (hfi->type == FT_FRAMENUM) ||
+ IS_FT_INT(hfi->type) || IS_FT_UINT(hfi->type)))) {
+ resolve = TRUE;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return resolve;
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/packet_list_utils.h b/ui/packet_list_utils.h
new file mode 100644
index 0000000000..be36ec0884
--- /dev/null
+++ b/ui/packet_list_utils.h
@@ -0,0 +1,71 @@
+/* packet_list_utils.h
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifndef __PACKET_LIST_UTILS_H__
+#define __PACKET_LIST_UTILS_H__
+
+#include "cfile.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Check to see if a column should be right justified.
+ *
+ * @param col[IN] The column number.
+ * @param cf[IN] The capture file containing the packet data.
+ *
+ * @return TRUE if the column should be right justified, FALSE otherwise.
+ */
+gboolean right_justify_column (gint col, capture_file *cf);
+
+/**
+ * Check to see if a column's data should be resolved.
+ *
+ * @param col[IN] The column number.
+ * @param cf[IN] The capture file containing the packet data.
+ *
+ * @return TRUE if resolution is required, FALSE otherwise.
+ */
+gboolean resolve_column (gint col, capture_file *cf);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __PACKET_LIST_UTILS_H__ */
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index 51614c9211..96d9dfad8b 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -71,6 +71,7 @@ set(QTSHARK_H_SRC
# No Q_OBJECT:
# packet_list_record.h
# qt_ui_utils.h
+ # related_packet_delegate.h
# sparkline_delegate.h
)
@@ -116,6 +117,7 @@ set(QTSHARK_CPP_SRC
proto_tree.cpp
qt_ui_utils.cpp
recent_file_status.cpp
+ related_packet_delegate.cpp
simple_dialog_qt.cpp
sparkline_delegate.cpp
search_frame.cpp
diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common
index 283229bc04..b87005a537 100644
--- a/ui/qt/Makefile.common
+++ b/ui/qt/Makefile.common
@@ -123,6 +123,7 @@ MOC_HDRS = \
progress_bar.h \
proto_tree.h \
recent_file_status.h \
+ related_packet_delegate.h \
search_frame.h \
simple_dialog_qt.h \
sparkline_delegate.h \
@@ -243,6 +244,7 @@ WIRESHARK_QT_SRC = \
proto_tree.cpp \
qt_ui_utils.cpp \
recent_file_status.cpp \
+ related_packet_delegate.cpp \
search_frame.cpp \
simple_dialog_qt.cpp \
sparkline_delegate.cpp \
diff --git a/ui/qt/QtShark.pro b/ui/qt/QtShark.pro
index be4ef33f4d..d61217ebfe 100644
--- a/ui/qt/QtShark.pro
+++ b/ui/qt/QtShark.pro
@@ -467,6 +467,7 @@ HEADERS += \
qt_ui_utils.h \
qt_ui_utils.h \
recent_file_status.h \
+ related_packet_delegate.h \
simple_dialog_qt.h \
sparkline_delegate.h \
syntax_line_edit.h \
@@ -516,6 +517,7 @@ SOURCES += \
proto_tree.cpp \
qt_ui_utils.cpp \
recent_file_status.cpp \
+ related_packet_delegate.cpp \
search_frame.cpp \
simple_dialog_qt.cpp \
sparkline_delegate.cpp \
diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp
index a82ba0b478..0eeb4a1588 100644
--- a/ui/qt/packet_list.cpp
+++ b/ui/qt/packet_list.cpp
@@ -232,7 +232,7 @@ PacketList::PacketList(QWidget *parent) :
setSortingEnabled(TRUE);
setUniformRowHeights(TRUE);
setAccessibleName("Packet list");
-
+ setItemDelegateForColumn(0, &related_packet_delegate_);
packet_list_model_ = new PacketListModel(this, cap_file_);
setModel(packet_list_model_);
@@ -370,6 +370,7 @@ void PacketList::setProtoTree (ProtoTree *proto_tree) {
proto_tree_ = proto_tree;
connect(proto_tree_, SIGNAL(goToFrame(int)), this, SLOT(goToPacket(int)));
+ connect(proto_tree_, SIGNAL(relatedFrame(int)), this, SLOT(addRelatedFrame(int)));
}
void PacketList::setByteViewTab (ByteViewTab *byte_view_tab) {
@@ -408,18 +409,24 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS
if (!cap_file_) return;
- if (proto_tree_) {
- int row = selected.first().top();
- cf_select_packet(cap_file_, row);
+ int row = selected.first().top();
+ cf_select_packet(cap_file_, row);
+ related_packet_delegate_.clear();
- if (!cap_file_->edt && !cap_file_->edt->tree) {
- return;
- }
+ if (!cap_file_->edt) return;
+ if (proto_tree_ && cap_file_->edt->tree) {
proto_tree_->fillProtocolTree(cap_file_->edt->tree);
+ packet_info *pi = &cap_file_->edt->pi;
+ conversation_t *conv = find_conversation(pi->fd->num, &pi->src, &pi->dst, pi->ptype,
+ pi->srcport, pi->destport, 0);
+ if (conv) {
+ related_packet_delegate_.setConversationSpan(conv->setup_frame, conv->last_frame);
+ }
+ viewport()->update();
}
- if (byte_view_tab_ && cap_file_->edt) {
+ if (byte_view_tab_) {
GSList *src_le;
struct data_source *source;
@@ -506,6 +513,7 @@ void PacketList::updateAll() {
void PacketList::clear() {
// packet_history_clear();
+ related_packet_delegate_.clear();
packet_list_model_->clear();
proto_tree_->clear();
byte_view_tab_->clear();
@@ -513,7 +521,7 @@ void PacketList::clear() {
/* XXX is this correct in all cases?
* Reset the sort column, use packetlist as model in case the list is frozen.
*/
- gbl_cur_packet_list->sortByColumn(0, Qt::AscendingOrder);
+ sortByColumn(0, Qt::AscendingOrder);
}
void PacketList::writeRecent(FILE *rf) {
@@ -806,6 +814,11 @@ void PacketList::unsetAllTimeReferences()
updateAll();
}
+void PacketList::addRelatedFrame(int related_frame)
+{
+ related_packet_delegate_.addRelatedFrame(related_frame);
+}
+
/*
* Editor modelines
*
diff --git a/ui/qt/packet_list.h b/ui/qt/packet_list.h
index e8e1595c5c..d7c3978901 100644
--- a/ui/qt/packet_list.h
+++ b/ui/qt/packet_list.h
@@ -24,9 +24,10 @@
#ifndef PACKET_LIST_H
#define PACKET_LIST_H
+#include "byte_view_tab.h"
#include "packet_list_model.h"
#include "proto_tree.h"
-#include "byte_view_tab.h"
+#include "related_packet_delegate.h"
#include <QTreeView>
#include <QTreeWidget>
@@ -64,6 +65,7 @@ private:
QList<QMenu *> submenus_;
QList<QAction *> filter_actions_;
int ctx_column_;
+ RelatedPacketDelegate related_packet_delegate_;
void markFramesReady();
void setFrameMark(gboolean set, frame_data *fdata);
@@ -86,6 +88,9 @@ public slots:
void ignoreAllDisplayedFrames(bool set);
void setTimeReference();
void unsetAllTimeReferences();
+
+private slots:
+ void addRelatedFrame(int related_frame);
};
#endif // PACKET_LIST_H
diff --git a/ui/qt/packet_list_model.cpp b/ui/qt/packet_list_model.cpp
index d34a35bb37..28d65c385e 100644
--- a/ui/qt/packet_list_model.cpp
+++ b/ui/qt/packet_list_model.cpp
@@ -29,13 +29,15 @@
#include <wsutil/nstime.h>
#include <epan/prefs.h>
+#include "ui/packet_list_utils.h"
+#include "ui/recent.h"
+
#include "color.h"
#include "color_filters.h"
-#include "globals.h"
-
#include "wireshark_application.h"
#include <QColor>
+#include <QModelIndex>
PacketListModel::PacketListModel(QObject *parent, capture_file *cf) :
QAbstractItemModel(parent)
@@ -132,7 +134,26 @@ QVariant PacketListModel::data(const QModelIndex &index, int role) const
switch (role) {
case Qt::FontRole:
return wsApp->monospaceFont();
-// case Qt::TextAlignmentRole:
+ case Qt::TextAlignmentRole:
+ switch(recent_get_column_xalign(index.column())) {
+ case COLUMN_XALIGN_RIGHT:
+ return Qt::AlignRight;
+ break;
+ case COLUMN_XALIGN_CENTER:
+ return Qt::AlignCenter;
+ break;
+ case COLUMN_XALIGN_LEFT:
+ return Qt::AlignLeft;
+ break;
+ case COLUMN_XALIGN_DEFAULT:
+ default:
+ if (right_justify_column(index.column(), cap_file_)) {
+ return Qt::AlignRight;
+ }
+ break;
+ }
+ return Qt::AlignLeft;
+
case Qt::BackgroundRole:
const color_t *color;
if (fdata->flags.ignored) {
@@ -160,7 +181,7 @@ QVariant PacketListModel::data(const QModelIndex &index, int role) const
}
return QColor(color->red >> 8, color->green >> 8, color->blue >> 8);
case Qt::DisplayRole:
- // Fall through
+ // Need packet data -- fall through
break;
default:
return QVariant();
@@ -251,7 +272,14 @@ QVariant PacketListModel::data(const QModelIndex &index, int role) const
epan_dissect_cleanup(&edt);
buffer_free(&buf);
- return record->data(col_num, cinfo);
+ switch (role) {
+ case Qt::DisplayRole:
+ return record->data(col_num, cinfo);
+ break;
+ default:
+ break;
+ }
+ return QVariant();
}
QVariant PacketListModel::headerData(int section, Qt::Orientation orientation,
diff --git a/ui/qt/packet_list_record.cpp b/ui/qt/packet_list_record.cpp
index da8741f100..8220e731d2 100644
--- a/ui/qt/packet_list_record.cpp
+++ b/ui/qt/packet_list_record.cpp
@@ -35,13 +35,10 @@ QVariant PacketListRecord::data(int col_num, column_info *cinfo) const
if (!cinfo)
return QVariant();
- if (col_based_on_frame_data(cinfo, col_num)) //{
+ if (col_based_on_frame_data(cinfo, col_num))
col_fill_in_frame_data(fdata_, cinfo, col_num, FALSE);
- return cinfo->col_data[col_num];
-// } else {
-// QString unknown;
-// return unknown.sprintf("Unknown: frame %d col %d", fdata->num, col_num);
-// }
+
+ return cinfo->col_data[col_num];
}
frame_data *PacketListRecord::getFdata() {
diff --git a/ui/qt/proto_tree.cpp b/ui/qt/proto_tree.cpp
index 1dcec3b5b1..1db31165df 100644
--- a/ui/qt/proto_tree.cpp
+++ b/ui/qt/proto_tree.cpp
@@ -89,6 +89,8 @@ proto_tree_draw_node(proto_node *node, gpointer data)
QTreeWidgetItem *parentItem = (QTreeWidgetItem *)data;
QTreeWidgetItem *item;
+ ProtoTree *proto_tree = qobject_cast<ProtoTree *>(parentItem->treeWidget());
+
item = new QTreeWidgetItem(parentItem, 0);
// Set our colors.
@@ -105,6 +107,10 @@ proto_tree_draw_node(proto_node *node, gpointer data)
item->setData(0, Qt::ForegroundRole, pal.link());
font.setUnderline(true);
item->setData(0, Qt::FontRole, font);
+
+ if (fi->hfinfo->type == FT_FRAMENUM) {
+ proto_tree->emitRelatedFrame(fi->value.value.uinteger);
+ }
}
}
@@ -254,6 +260,11 @@ void ProtoTree::fillProtocolTree(proto_tree *protocol_tree) {
proto_tree_children_foreach(protocol_tree, proto_tree_draw_node, invisibleRootItem());
}
+void ProtoTree::emitRelatedFrame(int related_frame)
+{
+ emit relatedFrame(related_frame);
+}
+
void ProtoTree::updateSelectionStatus(QTreeWidgetItem* item) {
if (item) {
diff --git a/ui/qt/proto_tree.h b/ui/qt/proto_tree.h
index bd18ae4f58..fa788a611a 100644
--- a/ui/qt/proto_tree.h
+++ b/ui/qt/proto_tree.h
@@ -39,6 +39,7 @@ class ProtoTree : public QTreeWidget
public:
explicit ProtoTree(QWidget *parent = 0);
void fillProtocolTree(proto_tree *protocol_tree);
+ void emitRelatedFrame(int related_frame);
void clear();
protected:
@@ -51,6 +52,7 @@ signals:
void protoItemSelected(QString &);
void protoItemSelected(field_info *);
void goToFrame(int);
+ void relatedFrame(int);
public slots:
void updateSelectionStatus(QTreeWidgetItem*);
diff --git a/ui/qt/related_packet_delegate.cpp b/ui/qt/related_packet_delegate.cpp
new file mode 100644
index 0000000000..780c52958a
--- /dev/null
+++ b/ui/qt/related_packet_delegate.cpp
@@ -0,0 +1,135 @@
+/* related_packet_delegate.cpp
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "related_packet_delegate.h"
+#include "packet_list_record.h"
+
+#include <QPainter>
+#include <QApplication>
+
+void RelatedPacketDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ int en_w = option.fontMetrics.height() / 2;
+
+ QStyleOptionViewItemV4 optv4 = option;
+ QStyledItemDelegate::initStyleOption(&optv4, index);
+
+ optv4.features |= QStyleOptionViewItemV4::HasDecoration;
+ optv4.decorationSize.setHeight(1);
+ optv4.decorationSize.setWidth(en_w);
+ QStyledItemDelegate::paint(painter, optv4, index);
+
+ frame_data *fd;
+ PacketListRecord *record = static_cast<PacketListRecord*>(index.internalPointer());
+ if (!record || (fd = record->getFdata()) == NULL) {
+ return;
+ }
+
+ painter->save();
+
+ if (QApplication::style()->objectName().contains("vista")) {
+ // QWindowsVistaStyle::drawControl does this internally. Unfortunately there
+ // doesn't appear to be a more general way to do this.
+ optv4.palette.setColor(QPalette::All, QPalette::HighlightedText, optv4.palette.color(QPalette::Active, QPalette::Text));
+ }
+
+ QPalette::ColorGroup cg = optv4.state & QStyle::State_Enabled
+ ? QPalette::Normal : QPalette::Disabled;
+ QColor fg;
+ if (cg == QPalette::Normal && !(optv4.state & QStyle::State_Active))
+ cg = QPalette::Inactive;
+ if (optv4.state & QStyle::State_Selected) {
+ fg = optv4.palette.color(cg, QPalette::HighlightedText);
+ } else {
+ fg = optv4.palette.color(cg, QPalette::Text);
+ }
+ qreal alpha = 0.20; // Arbitrary. Should arguably be a preference.
+
+ // We draw in the same place more than once so we first draw on a
+ // QImage at 100% opacity then draw that on our packet list item.
+ QImage overlay = QImage(en_w * 2, optv4.rect.height(), QImage::Format_ARGB32_Premultiplied);
+ QPainter op(&overlay);
+
+ overlay.fill(Qt::transparent);
+ op.setPen(fg);
+ op.translate(en_w + 0.5, 0.5);
+ op.setRenderHint(QPainter::Antialiasing, true);
+
+ if (first_frame_ > 0 && last_frame_ > 0 && first_frame_ != last_frame_) {
+ int height = optv4.rect.height();
+ if ((int) fd->num == first_frame_) {
+ op.drawLine(0, height / 2, 0, height);
+ op.drawLine(1, height / 2, en_w, height / 2);
+ } else if ((int) fd->num > first_frame_ && (int) fd->num < last_frame_) {
+ op.drawLine(0, 0, 0, height);
+ } else if ((int) fd->num == last_frame_) {
+ op.drawLine(0, 0, 0, height / 2);
+ op.drawLine(1, height / 2, en_w, height / 2);
+ }
+ }
+ if (related_frames_.contains(fd->num)) {
+ op.setBrush(fg);
+ op.drawEllipse(QPointF(0.0, optv4.rect.height() / 2), 2, 2);
+ }
+
+ painter->setOpacity(alpha);
+ painter->drawImage(optv4.rect.x(), optv4.rect.y(), overlay);
+ painter->restore();
+}
+
+QSize RelatedPacketDelegate::sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const {
+ return QSize(option.fontMetrics.height() + QStyledItemDelegate::sizeHint(option, index).width(),
+ QStyledItemDelegate::sizeHint(option, index).height());
+}
+
+void RelatedPacketDelegate::clear()
+{
+ related_frames_.clear();
+ first_frame_ = last_frame_ = -1;
+}
+
+void RelatedPacketDelegate::addRelatedFrame(int frame_num)
+{
+ related_frames_ << frame_num;
+}
+
+void RelatedPacketDelegate::setConversationSpan(int first_frame, int last_frame)
+{
+ first_frame_ = first_frame;
+ last_frame_ = last_frame;
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/qt/related_packet_delegate.h b/ui/qt/related_packet_delegate.h
new file mode 100644
index 0000000000..4f0671780a
--- /dev/null
+++ b/ui/qt/related_packet_delegate.h
@@ -0,0 +1,71 @@
+/* related_packet_delegate.h
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef RELATED_PACKET_DELEGATE_H
+#define RELATED_PACKET_DELEGATE_H
+
+#include "config.h"
+
+#include "epan/conversation.h"
+
+#include <QList>
+#include <QStyledItemDelegate>
+
+class RelatedPacketDelegate : public QStyledItemDelegate
+{
+public:
+ RelatedPacketDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) { clear(); }
+ void clear();
+ void addRelatedFrame(int frame_num);
+ void setConversationSpan(int first_frame, int last_frame);
+
+protected:
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+ QSize sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+private:
+ QList<int> related_frames_;
+ int first_frame_;
+ int last_frame_;
+
+signals:
+
+
+};
+
+#endif // RELATED_PACKET_DELEGATE_H
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */