New Qt feature: Show related packet list items in the frame number
authorGerald Combs <gerald@wireshark.org>
Mon, 8 Jul 2013 16:54:18 +0000 (16:54 -0000)
committerGerald Combs <gerald@wireshark.org>
Mon, 8 Jul 2013 16:54:18 +0000 (16:54 -0000)
column. Conversation spans (setup frame to last frame) are shown with a
square bracket. Linked frames are shown with a circle.

Use correct column justifications in Qt. Move common
justification-related packet list code to ui/packet_list_utils.[ch].

Add a last_frame element to conversation_t.

svn path=/trunk/; revision=50447

19 files changed:
docbook/release-notes.asciidoc
epan/conversation.c
epan/conversation.h
ui/CMakeLists.txt
ui/Makefile.common
ui/gtk/packet_list.c
ui/packet_list_utils.c [new file with mode: 0644]
ui/packet_list_utils.h [new file with mode: 0644]
ui/qt/CMakeLists.txt
ui/qt/Makefile.common
ui/qt/QtShark.pro
ui/qt/packet_list.cpp
ui/qt/packet_list.h
ui/qt/packet_list_model.cpp
ui/qt/packet_list_record.cpp
ui/qt/proto_tree.cpp
ui/qt/proto_tree.h
ui/qt/related_packet_delegate.cpp [new file with mode: 0644]
ui/qt/related_packet_delegate.h [new file with mode: 0644]

index 300343b20fad28862361b60c55b21d37f0e6be40..c5db50713ba6bd8b3ae6b662ffdba6e18cfc1107 100644 (file)
@@ -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
 
index 1164769c7914a17700272c077faaafcbd9788c08..d2beee7810943479cd673568f11bdddb22994f68 100644 (file)
@@ -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,
index 3a019c6be86eaef1d0ae267dcab1300f68aec8af..fef0b9d7fa89ce53f7e8e27c482cb08af0c6b612 100644 (file)
@@ -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 */
index bb60ba85055777c69b653392290ae894cb861c7a..edffb424475f14ded06ba8bf9e2eff966fac0163 100644 (file)
@@ -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
index 0c513092cfb42752ed81523e359aa17e1c8870ed..a0c156c90ab8e5b77e63a2963297732414fd5442 100644 (file)
@@ -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      \
index b263485cb31aee91fd1f5362e195f301cf23324f..7e9ea7f57588f5c6dbaa961b89709930184a9882 100644 (file)
@@ -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 (file)
index 0000000..24f0dd4
--- /dev/null
@@ -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 (file)
index 0000000..be36ec0
--- /dev/null
@@ -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:
+ */
index 51614c9211345d1e419992c2d929aa6a2ad91166..96d9dfad8b137d2a9555f1a17bfffbf076975247 100644 (file)
@@ -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
index 283229bc04f88eac320100341ba796156b043198..b87005a53726c72d6332b52686041addf9a7d93c 100644 (file)
@@ -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 \
index be4ef33f4d540e27a18897d23ba936de01f7cfe5..d61217ebfe0190dcfd147a7852807ce9d592fd03 100644 (file)
@@ -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 \
index a82ba0b478f0a6c1aa49f8fce9cf76b86feabfb7..0eeb4a158813a23d8e7f6e498009aee5d3f1aa10 100644 (file)
@@ -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
  *
index e8e1595c5ce9be65bd876edc546515275ea4f2a5..d7c397890105a6e92822dfe152deb627cc455570 100644 (file)
 #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
index d34a35bb37beea61a4cb9feef00f9129d1e25395..28d65c385ea460cf5f658def38d9420bf7b4e636 100644 (file)
 #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,
index da8741f100e9315d04ce5a7a00061df092ef2190..8220e731d2e3b9c07381d4f090a3fa1f260139b5 100644 (file)
@@ -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() {
index 1dcec3b5b19341e309f76ad00962bce546c77063..1db31165df6bd07fb8ac0ff94b54be8efc237131 100644 (file)
@@ -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) {
index bd18ae4f58d65e2078faca6086ab7260361fbdfe..fa788a611aec0ee5afda3a88c257f472f29ff421 100644 (file)
@@ -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 (file)
index 0000000..780c529
--- /dev/null
@@ -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 (file)
index 0000000..4f06717
--- /dev/null
@@ -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:
+ */