aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2017-07-23 10:53:43 -0400
committerAnders Broman <a.broman58@gmail.com>2017-08-07 17:25:02 +0000
commit5b3e3ee58748ac1fd9201d2d3facbed1b9b1e800 (patch)
tree9b19a5d0f8abb396dd6063fa887892581e286b8a
parentf63b0241c9eeb1ef3dc1e915820c440119c30526 (diff)
Use UAT model for I/O graph
Convert from using TreeWidgetItems to UAT model/delegate. More of the GUI is "just handled" within the table. Required to add support for "colors" and "protocol fields" to UAT types. Also needed to add some hacks for "custom" UAT field handlers for backwards compatibility with the existing UAT structure used. Because UAT functionality was switched completely to the model, some information in the table was "lost in translation" because the UATs themselves aren't translated to other languages. TODO: 2. Better "order of operations"? A bunch of NULL/size checks needed to be added to prevent crashing. Now with model/"view" should events/functions be reordered? Bug: 13585 Change-Id: I2bbba78182317c4fada07b927c05d0c6f4cdc0fe Reviewed-on: https://code.wireshark.org/review/22766 Petri-Dish: Anders Broman <a.broman58@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
-rw-r--r--epan/uat.c15
-rw-r--r--epan/uat.h32
-rw-r--r--ui/gtk/uat_gui.c2
-rw-r--r--ui/qt/CMakeLists.txt2
-rw-r--r--ui/qt/Makefile.am2
-rw-r--r--ui/qt/io_graph_dialog.cpp1043
-rw-r--r--ui/qt/io_graph_dialog.h46
-rw-r--r--ui/qt/io_graph_dialog.ui42
-rw-r--r--ui/qt/models/uat_delegate.cpp40
-rw-r--r--ui/qt/models/uat_delegate.h1
-rw-r--r--ui/qt/models/uat_model.cpp26
-rw-r--r--ui/qt/widgets/editor_color_dialog.cpp57
-rw-r--r--ui/qt/widgets/editor_color_dialog.h59
13 files changed, 648 insertions, 719 deletions
diff --git a/epan/uat.c b/epan/uat.c
index 03f73d2a34..4c83a5e899 100644
--- a/epan/uat.c
+++ b/epan/uat.c
@@ -291,6 +291,8 @@ char *uat_fld_tostr(void *rec, uat_field_t *f) {
case PT_TXTMOD_FILENAME:
case PT_TXTMOD_DIRECTORYNAME:
case PT_TXTMOD_DISPLAY_FILTER:
+ case PT_TXTMOD_COLOR:
+ case PT_TXTMOD_PROTO_FIELD:
out = g_strndup(ptr, len);
break;
case PT_TXTMOD_HEXBYTES: {
@@ -326,6 +328,8 @@ static void putfld(FILE* fp, void* rec, uat_field_t* f) {
case PT_TXTMOD_FILENAME:
case PT_TXTMOD_DIRECTORYNAME:
case PT_TXTMOD_DISPLAY_FILTER:
+ case PT_TXTMOD_PROTO_FIELD:
+ case PT_TXTMOD_COLOR:
case PT_TXTMOD_STRING: {
guint i;
@@ -719,6 +723,17 @@ gboolean uat_fld_chk_range(void* u1 _U_, const char* strptr, guint len, const vo
return ret_value;
}
+gboolean uat_fld_chk_color(void* u1 _U_, const char* strptr, guint len, const void* v _U_, const void* u3 _U_, char** err) {
+
+ if ((len != 7) || (*strptr != '#')) {
+ *err = g_strdup("Color must be of the format #RRGGBB");
+ return FALSE;
+ }
+
+ /* Color is just # followed by hex string, so use hex verification */
+ return uat_fld_chk_num(16, strptr + 1, len - 1, err);
+}
+
char* uat_unbinstring(const char* si, guint in_len, guint* len_p) {
guint8* buf;
guint len = in_len/2;
diff --git a/epan/uat.h b/epan/uat.h
index a23f6760b7..f3305b4b5d 100644
--- a/epan/uat.h
+++ b/epan/uat.h
@@ -215,12 +215,17 @@ typedef enum _uat_text_mode_t {
PT_TXTMOD_ENUM,
/* Read/Writes/displays the string value (not number!) */
+ PT_TXTMOD_COLOR,
+ /* Reads/Writes/display color in #RRGGBB format */
+
PT_TXTMOD_FILENAME,
/* processed like a PT_TXTMOD_STRING, but shows a filename dialog */
PT_TXTMOD_DIRECTORYNAME,
/* processed like a PT_TXTMOD_STRING, but shows a directory dialog */
PT_TXTMOD_DISPLAY_FILTER,
/* processed like a PT_TXTMOD_STRING, but verifies display filter */
+ PT_TXTMOD_PROTO_FIELD,
+ /* processed like a PT_TXTMOD_STRING, but verifies protocol field name (e.g tcp.flags.syn) */
PT_TXTMOD_BOOL
/* Displays a checkbox for value */
} uat_text_mode_t;
@@ -354,6 +359,8 @@ WS_DLL_PUBLIC
gboolean uat_fld_chk_enum(void*, const char*, unsigned, const void*, const void*, char**);
WS_DLL_PUBLIC
gboolean uat_fld_chk_range(void*, const char*, unsigned, const void*, const void*, char**);
+WS_DLL_PUBLIC
+gboolean uat_fld_chk_color(void*, const char*, unsigned, const void*, const void*, char**);
typedef void (*uat_cb_t)(void* uat,void* user_data);
WS_DLL_PUBLIC
@@ -453,6 +460,14 @@ static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr,
#define UAT_FLD_DISPLAY_FILTER(basename,field_name,title,desc) \
{#field_name, title, PT_TXTMOD_DISPLAY_FILTER, {uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
+/*
+ * PROTO_FIELD,
+ * a simple c-string contained in (((rec_t*)rec)->(field_name))
+ */
+#define UAT_PROTO_FIELD_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t)
+
+#define UAT_FLD_PROTO_FIELD(basename,field_name,title,desc) \
+ {#field_name, title, PT_TXTMOD_PROTO_FIELD, {uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
/*
* OID - just a CSTRING with a specific check routine
@@ -616,6 +631,23 @@ static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr,
/*
+ * Color Macros,
+ * an boolean value contained in
+ */
+#define UAT_COLOR_CB_DEF(basename,field_name,rec_t) \
+static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
+ char* tmp_str = g_strndup(buf+1,len-1); \
+ ((rec_t*)rec)->field_name = (guint)strtol(tmp_str,NULL,16); \
+ g_free(tmp_str); } \
+static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
+ *out_ptr = g_strdup_printf("#%06X",((rec_t*)rec)->field_name); \
+ *out_len = (unsigned)strlen(*out_ptr); }
+
+#define UAT_FLD_COLOR(basename,field_name,title,desc) \
+{#field_name, title, PT_TXTMOD_COLOR,{uat_fld_chk_color,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
+
+
+/*
* PROTO macros
*/
diff --git a/ui/gtk/uat_gui.c b/ui/gtk/uat_gui.c
index d63a153ea8..d18e840d62 100644
--- a/ui/gtk/uat_gui.c
+++ b/ui/gtk/uat_gui.c
@@ -294,6 +294,7 @@ static gboolean uat_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
case PT_TXTMOD_STRING:
case PT_TXTMOD_BOOL:
case PT_TXTMOD_DISPLAY_FILTER:
+ case PT_TXTMOD_PROTO_FIELD:
text = gtk_entry_get_text(GTK_ENTRY(e));
len = (unsigned) strlen(text);
break;
@@ -518,6 +519,7 @@ static void uat_edit_dialog(uat_t *uat, gint row, gboolean copy) {
case PT_TXTMOD_STRING:
case PT_TXTMOD_HEXBYTES:
case PT_TXTMOD_DISPLAY_FILTER:
+ case PT_TXTMOD_PROTO_FIELD:
case PT_TXTMOD_BOOL:
entry = gtk_entry_new();
if (! dd->is_new || copy) {
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index 1c63d693f1..3fb1090629 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -30,6 +30,7 @@ set(WIRESHARK_WIDGET_HEADERS
widgets/display_filter_combo.h
widgets/display_filter_edit.h
widgets/drag_drop_toolbar.h
+ widgets/editor_color_dialog.h
widgets/editor_file_dialog.h
widgets/elided_label.h
widgets/field_filter_edit.h
@@ -228,6 +229,7 @@ set(WIRESHARK_WIDGET_SRCS
widgets/display_filter_combo.cpp
widgets/display_filter_edit.cpp
widgets/drag_drop_toolbar.cpp
+ widgets/editor_color_dialog.cpp
widgets/editor_file_dialog.cpp
widgets/elided_label.cpp
widgets/field_filter_edit.cpp
diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am
index 29b56aec0f..37723c9360 100644
--- a/ui/qt/Makefile.am
+++ b/ui/qt/Makefile.am
@@ -159,6 +159,7 @@ MOC_WIDGET_HDRS = \
widgets/clickable_label.h \
widgets/display_filter_combo.h \
widgets/display_filter_edit.h \
+ widgets/editor_color_dialog.h \
widgets/editor_file_dialog.h \
widgets/elided_label.h \
widgets/field_filter_edit.h \
@@ -472,6 +473,7 @@ WIRESHARK_QT_WIDGET_SRC = \
widgets/clickable_label.cpp \
widgets/display_filter_combo.cpp \
widgets/display_filter_edit.cpp \
+ widgets/editor_color_dialog.cpp \
widgets/editor_file_dialog.cpp \
widgets/elided_label.cpp \
widgets/field_filter_edit.cpp \
diff --git a/ui/qt/io_graph_dialog.cpp b/ui/qt/io_graph_dialog.cpp
index b940e93bf4..9400aa2eae 100644
--- a/ui/qt/io_graph_dialog.cpp
+++ b/ui/qt/io_graph_dialog.cpp
@@ -37,14 +37,12 @@
#include <ui/qt/utils/color_utils.h>
#include <ui/qt/widgets/qcustomplot.h>
#include "progress_frame.h"
-#include <ui/qt/utils/stock_icon.h>
-#include <ui/qt/widgets/syntax_line_edit.h>
-#include <ui/qt/widgets/display_filter_edit.h>
-#include <ui/qt/widgets/field_filter_edit.h>
#include "wireshark_application.h"
+#include <wsutil/report_message.h>
+
+#include <ui/qt/utils/tango_colors.h> //provides some default colors
#include <QClipboard>
-#include <QComboBox>
#include <QFileDialog>
#include <QFontMetrics>
#include <QFrame>
@@ -55,15 +53,12 @@
#include <QRubberBand>
#include <QSpacerItem>
#include <QTimer>
-#include <QTreeWidget>
#include <QVariant>
// Bugs and uncertainties:
// - Regular (non-stacked) bar graphs are drawn on top of each other on the Z axis.
// The QCP forum suggests drawing them side by side:
// http://www.qcustomplot.com/index.php/support/forum/62
-// - You can't manually set a graph color other than manually editing the io_graphs
-// UAT. We should add a "graph color" preference.
// - We retap and redraw more than we should.
// - Smoothing doesn't seem to match GTK+
@@ -72,24 +67,10 @@
// - Scroll during live captures
// - Set ticks per pixel (e.g. pressing "2" sets 2 tpp).
-const int name_col_ = 0;
-const int dfilter_col_ = 1;
-const int color_col_ = 2;
-const int style_col_ = 3;
-const int yaxis_col_ = 4;
-const int yfield_col_ = 5;
-const int sma_period_col_ = 6;
-const int num_cols_ = 7;
const qreal graph_line_width_ = 1.0;
-// When we drop support for Qt <5 we can initialize these with
-// datastreams.
-const QMap<io_graph_item_unit_t, QString> value_unit_to_name_ = IOGraph::valueUnitsToNames();
-const QMap<IOGraph::PlotStyles, QString> plot_style_to_name_ = IOGraph::plotStylesToNames();
-const QMap<int, QString> moving_average_to_name_ = IOGraph::movingAveragesToNames();
-
-const int default_moving_average_ = 0;
+const int DEFAULT_MOVING_AVERAGE = 0;
// Don't accidentally zoom into a 1x1 rect if you happen to click on the graph
// in zoom mode.
@@ -106,40 +87,194 @@ static const value_string graph_enabled_vs[] = {
};
typedef struct _io_graph_settings_t {
- guint32 enabled;
+ gboolean enabled;
char* name;
char* dfilter;
- char* color;
- char* style;
- char* yaxis;
+ guint color;
+ guint32 style;
+ guint32 yaxis;
char* yfield;
- int sma_period;
+ guint32 sma_period;
} io_graph_settings_t;
+static const value_string graph_style_vs[] = {
+ { IOGraph::psLine, "Line" },
+ { IOGraph::psImpulse, "Impulse" },
+ { IOGraph::psBar, "Bar" },
+ { IOGraph::psStackedBar, "Stacked Bar" },
+ { IOGraph::psDot, "Dot" },
+ { IOGraph::psSquare, "Square" },
+ { IOGraph::psDiamond, "Diamond" },
+ { 0, NULL }
+};
+
+static const value_string y_axis_vs[] = {
+ { IOG_ITEM_UNIT_PACKETS, "Packets" },
+ { IOG_ITEM_UNIT_BYTES, "Bytes" },
+ { IOG_ITEM_UNIT_BITS, "Bits" },
+ { IOG_ITEM_UNIT_CALC_SUM, "SUM(Y Field)" },
+ { IOG_ITEM_UNIT_CALC_FRAMES, "COUNT FRAMES(Y Field)" },
+ { IOG_ITEM_UNIT_CALC_FIELDS, "COUNT FIELDS(Y Field)" },
+ { IOG_ITEM_UNIT_CALC_MAX, "MAX(Y Field)" },
+ { IOG_ITEM_UNIT_CALC_MIN, "MIN(Y Field)" },
+ { IOG_ITEM_UNIT_CALC_AVERAGE, "AVG(Y Field)" },
+ { IOG_ITEM_UNIT_CALC_LOAD, "LOAD(Y Field)" },
+ { 0, NULL }
+};
+
+static const value_string moving_avg_vs[] = {
+ { 0, "None" },
+ { 10, "10 interval SMA" },
+ { 20, "20 interval SMA" },
+ { 50, "50 interval SMA" },
+ { 100, "100 interval SMA" },
+ { 200, "200 interval SMA" },
+ { 500, "500 interval SMA" },
+ { 1000, "1000 interval SMA" },
+ { 0, NULL }
+};
+
static io_graph_settings_t *iog_settings_ = NULL;
static guint num_io_graphs_ = 0;
static uat_t *iog_uat_ = NULL;
extern "C" {
-UAT_VS_DEF(io_graph, enabled, io_graph_settings_t, guint32, 0, "Disabled")
+//Allow the enable/disable field to be a checkbox, but for backwards compatibility,
+//the strings have to be "Enabled"/"Disabled", not "TRUE"/"FALSE"
+#define UAT_BOOL_ENABLE_CB_DEF(basename,field_name,rec_t) \
+static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
+ char* tmp_str = g_strndup(buf,len); \
+ if ((g_strcmp0(tmp_str, "Enabled") == 0) || \
+ (g_strcmp0(tmp_str, "TRUE") == 0)) \
+ ((rec_t*)rec)->field_name = 1; \
+ else \
+ ((rec_t*)rec)->field_name = 0; \
+ g_free(tmp_str); } \
+static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
+ *out_ptr = g_strdup_printf("%s",((rec_t*)rec)->field_name ? "Enabled" : "Disabled"); \
+ *out_len = (unsigned)strlen(*out_ptr); }
+
+static gboolean uat_fld_chk_enable(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err)
+{
+ char* str = g_strndup(strptr,len);
+
+ if ((g_strcmp0(str, "Enabled") == 0) ||
+ (g_strcmp0(str, "Disabled") == 0) ||
+ (g_strcmp0(str, "TRUE") == 0) || //just for UAT functionality
+ (g_strcmp0(str, "FALSE") == 0)) {
+ *err = NULL;
+ g_free(str);
+ return TRUE;
+ }
+
+ //User should never see this unless they are manually modifying UAT
+ *err = g_strdup_printf("invalid value: %s (must be Enabled or Disabled)", str);
+ g_free(str);
+ return FALSE;
+}
+
+#define UAT_FLD_BOOL_ENABLE(basename,field_name,title,desc) \
+{#field_name, title, PT_TXTMOD_BOOL,{uat_fld_chk_enable,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
+
+//"Custom" handler for sma_period enumeration for backwards compatibility
+static void io_graph_sma_period_set_cb(void* rec, const char* buf, guint len, const void* vs, const void* u2 _U_)
+{
+ guint i;
+ char* str = g_strndup(buf,len);
+ const char* cstr;
+ ((io_graph_settings_t*)rec)->sma_period = 0;
+
+ //Original UAT had just raw numbers and not enumerated values with "interval SMA"
+ if (strstr(str, "interval SMA") == NULL) {
+ if (strcmp(str, "None") == 0) { //Valid enumerated value
+ } else if (strcmp(str, "0") == 0) {
+ g_free(str);
+ str = g_strdup("None");
+ } else {
+ char *str2 = g_strdup_printf("%s interval SMA", str);
+ g_free(str);
+ str = str2;
+ }
+ }
+
+ for(i=0; ( cstr = ((const value_string*)vs)[i].strptr ) ;i++) {
+ if (g_str_equal(cstr,str)) {
+ ((io_graph_settings_t*)rec)->sma_period = (guint32)((const value_string*)vs)[i].value;
+ g_free(str);
+ return;
+ }
+ }
+ g_free(str);
+}
+//Duplicated because macro covers both functions
+static void io_graph_sma_period_tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* vs, const void* u2 _U_)
+{
+ guint i;
+ for(i=0;((const value_string*)vs)[i].strptr;i++) {
+ if ( ((const value_string*)vs)[i].value == ((io_graph_settings_t*)rec)->sma_period ) {
+ *out_ptr = g_strdup(((const value_string*)vs)[i].strptr);
+ *out_len = (unsigned)strlen(*out_ptr);
+ return;
+ }
+ }
+ *out_ptr = g_strdup("None");
+ *out_len = (unsigned)strlen("None");
+}
+
+static gboolean sma_period_chk_enum(void* u1 _U_, const char* strptr, guint len, const void* v, const void* u3 _U_, char** err) {
+ char *str = g_strndup(strptr,len);
+ guint i;
+ const value_string* vs = (const value_string *)v;
+
+ //Original UAT had just raw numbers and not enumerated values with "interval SMA"
+ if (strstr(str, "interval SMA") == NULL) {
+ if (strcmp(str, "None") == 0) { //Valid enumerated value
+ } else if (strcmp(str, "0") == 0) {
+ g_free(str);
+ str = g_strdup("None");
+ } else {
+ char *str2 = g_strdup_printf("%s interval SMA", str);
+ g_free(str);
+ str = str2;
+ }
+ }
+
+ for(i=0;vs[i].strptr;i++) {
+ if (g_strcmp0(vs[i].strptr,str) == 0) {
+ *err = NULL;
+ g_free(str);
+ return TRUE;
+ }
+ }
+
+ *err = g_strdup_printf("invalid value: %s",str);
+ g_free(str);
+ return FALSE;
+}
+
+#define UAT_FLD_SMA_PERIOD(basename,field_name,title,enum,desc) \
+ {#field_name, title, PT_TXTMOD_ENUM,{sma_period_chk_enum,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{&(enum),&(enum),&(enum)},&(enum),desc,FLDFILL}
+
+
+UAT_BOOL_ENABLE_CB_DEF(io_graph, enabled, io_graph_settings_t)
UAT_CSTRING_CB_DEF(io_graph, name, io_graph_settings_t)
-UAT_CSTRING_CB_DEF(io_graph, dfilter, io_graph_settings_t)
-UAT_CSTRING_CB_DEF(io_graph, color, io_graph_settings_t)
-UAT_CSTRING_CB_DEF(io_graph, style, io_graph_settings_t)
-UAT_CSTRING_CB_DEF(io_graph, yaxis, io_graph_settings_t)
-UAT_CSTRING_CB_DEF(io_graph, yfield, io_graph_settings_t)
-UAT_DEC_CB_DEF(io_graph, sma_period, io_graph_settings_t)
+UAT_DISPLAY_FILTER_CB_DEF(io_graph, dfilter, io_graph_settings_t)
+UAT_COLOR_CB_DEF(io_graph, color, io_graph_settings_t)
+UAT_VS_DEF(io_graph, style, io_graph_settings_t, guint32, 0, "Line")
+UAT_VS_DEF(io_graph, yaxis, io_graph_settings_t, guint32, 0, "Packets")
+UAT_PROTO_FIELD_CB_DEF(io_graph, yfield, io_graph_settings_t)
static uat_field_t io_graph_fields[] = {
- UAT_FLD_VS(io_graph, enabled, "Enabled", graph_enabled_vs, "Graph visibility"),
+ UAT_FLD_BOOL_ENABLE(io_graph, enabled, "Enabled", "Graph visibility"),
UAT_FLD_CSTRING(io_graph, name, "Graph Name", "The name of the graph"),
- UAT_FLD_CSTRING(io_graph, dfilter, "Display Filter", "Graph packets matching this display filter"),
- UAT_FLD_CSTRING(io_graph, color, "Color", "Graph color (#RRGGBB)"),
- UAT_FLD_CSTRING(io_graph, style, "Style", "Graph style (Line, Bars, etc.)"),
- UAT_FLD_CSTRING(io_graph, yaxis, "Y Axis", "Y Axis units"),
- UAT_FLD_CSTRING(io_graph, yfield, "Y Field", "Apply calculations to this field"),
- UAT_FLD_DEC(io_graph, sma_period, "SMA Period", "Simple moving average period"),
+ UAT_FLD_DISPLAY_FILTER(io_graph, dfilter, "Display Filter", "Graph packets matching this display filter"),
+ UAT_FLD_COLOR(io_graph, color, "Color", "Graph color (#RRGGBB)"),
+ UAT_FLD_VS(io_graph, style, "Style", graph_style_vs, "Graph style (Line, Bars, etc.)"),
+ UAT_FLD_VS(io_graph, yaxis, "Y Axis", y_axis_vs, "Y Axis units"),
+ UAT_FLD_PROTO_FIELD(io_graph, yfield, "Y Field", "Apply calculations to this field"),
+ UAT_FLD_SMA_PERIOD(io_graph, sma_period, "SMA Period", moving_avg_vs, "Simple moving average period"),
+
UAT_END_FIELDS
};
@@ -150,9 +285,9 @@ static void* io_graph_copy_cb(void* dst_ptr, const void* src_ptr, size_t) {
dst->enabled = src->enabled;
dst->name = g_strdup(src->name);
dst->dfilter = g_strdup(src->dfilter);
- dst->color = g_strdup(src->color);
- dst->style = g_strdup(src->style);
- dst->yaxis = g_strdup(src->yaxis);
+ dst->color = src->color;
+ dst->style = src->style;
+ dst->yaxis = src->yaxis;
dst->yfield = g_strdup(src->yfield);
dst->sma_period = src->sma_period;
@@ -163,7 +298,6 @@ static void io_graph_free_cb(void* p) {
io_graph_settings_t *iogs = (io_graph_settings_t *)p;
g_free(iogs->name);
g_free(iogs->dfilter);
- g_free(iogs->color);
g_free(iogs->yfield);
}
@@ -172,13 +306,8 @@ static void io_graph_free_cb(void* p) {
IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf) :
WiresharkDialog(parent, cf),
ui(new Ui::IOGraphDialog),
- name_line_edit_(NULL),
- dfilter_line_edit_(NULL),
- yfield_line_edit_(NULL),
- color_combo_box_(NULL),
- style_combo_box_(NULL),
- yaxis_combo_box_(NULL),
- sma_combo_box_(NULL),
+ uat_model_(NULL),
+ uat_delegate_(NULL),
base_graph_(NULL),
tracer_(NULL),
start_time_(0.0),
@@ -187,8 +316,7 @@ IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf) :
stat_timer_(NULL),
need_replot_(false),
need_retap_(false),
- auto_axes_(true),
- colors_(ColorUtils::graphColors())
+ auto_axes_(true)
{
ui->setupUi(this);
loadGeometry();
@@ -265,56 +393,22 @@ IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf) :
loadProfileGraphs();
if (num_io_graphs_ > 0) {
for (guint i = 0; i < num_io_graphs_; i++) {
- io_graph_settings_t *iogs = &iog_settings_[i];
- QRgb pcolor = QColor(iogs->color).rgb();
- int color_idx;
- IOGraph::PlotStyles style = plot_style_to_name_.key(iogs->style, IOGraph::psLine);
-
- io_graph_item_unit_t value_units;
- if (g_strcmp0(iogs->yaxis, "Bytes/s") == 0) { // Silently upgrade obsolete yaxis unit name
- value_units = value_unit_to_name_.key(iogs->yaxis, IOG_ITEM_UNIT_BYTES);
- } else if (g_strcmp0(iogs->yaxis, "Bits/s") == 0) { // Silently upgrade obsolete yaxis unit name
- value_units = value_unit_to_name_.key(iogs->yaxis, IOG_ITEM_UNIT_BITS);
- } else {
- value_units = value_unit_to_name_.key(iogs->yaxis, IOG_ITEM_UNIT_PACKETS);
- }
-
- for (color_idx = 0; color_idx < colors_.size(); color_idx++) {
- if (pcolor == colors_[color_idx]) break;
- }
- if (color_idx >= colors_.size()) {
- colors_ << pcolor;
- }
-
- addGraph(iogs->enabled == 1, iogs->name, iogs->dfilter, color_idx, style, value_units, iogs->yfield, iogs->sma_period);
+ createIOGraph(i);
}
} else {
addDefaultGraph(true, 0);
addDefaultGraph(true, 1);
}
- on_graphTreeWidget_itemSelectionChanged();
-
toggleTracerStyle(true);
iop->setFocus();
iop->rescaleAxes();
- // Shrink columns down, then expand as needed
- QTreeWidget *gtw = ui->graphTreeWidget;
- int one_em = fontMetrics().height();
- gtw->setRootIsDecorated(false);
- gtw->setColumnWidth(name_col_, one_em * 10);
- gtw->setColumnWidth(dfilter_col_, one_em * 10);
- gtw->setColumnWidth(color_col_, one_em * 2.5);
- gtw->setColumnWidth(style_col_, one_em * 5.5);
- gtw->setColumnWidth(yaxis_col_, one_em * 6.5);
- gtw->setColumnWidth(yfield_col_, one_em * 6);
- gtw->setColumnWidth(sma_period_col_, one_em * 6);
+ //XXX - resize columns?
ProgressFrame::addToButtonBox(ui->buttonBox, &parent);
- connect(wsApp, SIGNAL(focusChanged(QWidget*,QWidget*)), this, SLOT(focusChanged(QWidget*,QWidget*)));
connect(iop, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(graphClicked(QMouseEvent*)));
connect(iop, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMoved(QMouseEvent*)));
connect(iop, SIGNAL(mouseRelease(QMouseEvent*)), this, SLOT(mouseReleased(QMouseEvent*)));
@@ -324,8 +418,7 @@ IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf) :
IOGraphDialog::~IOGraphDialog()
{
cap_file_.stopLoading();
- for (int i = 0; i < ui->graphTreeWidget->topLevelItemCount(); i++) {
- IOGraph *iog = VariantPointer<IOGraph>::asPtr(ui->graphTreeWidget->topLevelItem(i)->data(name_col_, Qt::UserRole));
+ foreach(IOGraph* iog, ioGraphs_) {
delete iog;
}
delete ui;
@@ -334,57 +427,71 @@ IOGraphDialog::~IOGraphDialog()
void IOGraphDialog::addGraph(bool checked, QString name, QString dfilter, int color_idx, IOGraph::PlotStyles style, io_graph_item_unit_t value_units, QString yfield, int moving_average)
{
- QTreeWidgetItem *ti = new QTreeWidgetItem();
- ui->graphTreeWidget->addTopLevelItem(ti);
-
- IOGraph *iog = new IOGraph(ui->ioPlot);
- ti->setData(name_col_, Qt::UserRole, VariantPointer<IOGraph>::asQVariant(iog));
- ti->setCheckState(name_col_, checked ? Qt::Checked : Qt::Unchecked);
- ti->setText(name_col_, name);
- ti->setText(dfilter_col_, dfilter);
- color_idx = color_idx % colors_.size();
- ti->setData(color_col_, Qt::UserRole, color_idx);
- ti->setIcon(color_col_, graphColorIcon(color_idx));
- ti->setText(style_col_, plot_style_to_name_[style]);
- ti->setData(style_col_, Qt::UserRole, style);
- ti->setText(yaxis_col_, value_unit_to_name_[value_units]);
- ti->setData(yaxis_col_, Qt::UserRole, value_units);
- ti->setText(yfield_col_, yfield);
- ti->setText(sma_period_col_, moving_average_to_name_[moving_average]);
- ti->setData(sma_period_col_, Qt::UserRole, moving_average);
+ // should not fail, but you never know.
+ if (!uat_model_->insertRows(uat_model_->rowCount(), 1)) {
+ qDebug() << "Failed to add a new record";
+ return;
+ }
+ int currentRow = uat_model_->rowCount() - 1;
+ const QModelIndex &new_index = uat_model_->index(currentRow, 0);
- connect(this, SIGNAL(recalcGraphData(capture_file *, bool)), iog, SLOT(recalcGraphData(capture_file *, bool)));
- connect(this, SIGNAL(reloadValueUnitFields()), iog, SLOT(reloadValueUnitField()));
- connect(&cap_file_, SIGNAL(captureFileClosing()), iog, SLOT(captureFileClosing()));
- connect(iog, SIGNAL(requestRetap()), this, SLOT(scheduleRetap()));
- connect(iog, SIGNAL(requestRecalc()), this, SLOT(scheduleRecalc()));
- connect(iog, SIGNAL(requestReplot()), this, SLOT(scheduleReplot()));
+ //populate model with data
+ uat_model_->setData(uat_model_->index(currentRow, colEnabled), checked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
+ uat_model_->setData(uat_model_->index(currentRow, colName), name);
+ uat_model_->setData(uat_model_->index(currentRow, colDFilter), dfilter);
+ uat_model_->setData(uat_model_->index(currentRow, colColor), QColor(color_idx));
+ uat_model_->setData(uat_model_->index(currentRow, colStyle), val_to_str_const(style, graph_style_vs, "None"));
+ uat_model_->setData(uat_model_->index(currentRow, colYAxis), value_units);
+ uat_model_->setData(uat_model_->index(currentRow, colYField), yfield);
+ uat_model_->setData(uat_model_->index(currentRow, colSMAPeriod), moving_average);
- syncGraphSettings(ti);
- if (iog->visible()) {
- scheduleRetap();
- }
+ // due to an EditTrigger, this will also start editing.
+ ui->graphUat->setCurrentIndex(new_index);
+
+ createIOGraph(currentRow);
}
void IOGraphDialog::addGraph(bool copy_from_current)
{
- QTreeWidgetItem *cur_ti = NULL;
+ const QModelIndex &current = ui->graphUat->currentIndex();
+ if (copy_from_current && !current.isValid())
+ return;
if (copy_from_current) {
- cur_ti = ui->graphTreeWidget->currentItem();
- }
-
- if (copy_from_current && cur_ti) {
- addGraph(cur_ti->checkState(name_col_) == Qt::Checked,
- cur_ti->text(name_col_),
- cur_ti->text(dfilter_col_),
- cur_ti->data(color_col_, Qt::UserRole).toInt(),
- (IOGraph::PlotStyles)cur_ti->data(style_col_, Qt::UserRole).toInt(),
- (io_graph_item_unit_t)cur_ti->data(yaxis_col_, Qt::UserRole).toInt(),
- cur_ti->text(yfield_col_),
- cur_ti->data(sma_period_col_, Qt::UserRole).toInt());
+ // should not fail, but you never know.
+ if (!uat_model_->insertRows(uat_model_->rowCount(), 1)) {
+ qDebug() << "Failed to add a new record";
+ return;
+ }
+ const QModelIndex &new_index = uat_model_->index(uat_model_->rowCount() - 1, 0);
+ if (copy_from_current) {
+ uat_model_->copyRow(new_index.row(), current.row());
+ }
+
+ ui->graphUat->setCurrentIndex(new_index);
} else {
addDefaultGraph(false);
+ const QModelIndex &new_index = uat_model_->index(uat_model_->rowCount() - 1, 0);
+ ui->graphUat->setCurrentIndex(new_index);
+ }
+}
+
+void IOGraphDialog::createIOGraph(int currentRow)
+{
+ // XXX - Should IOGraph have it's own list that has to sync with UAT?
+ ioGraphs_.append(new IOGraph(ui->ioPlot));
+ IOGraph* iog = ioGraphs_[currentRow];
+
+ connect(this, SIGNAL(recalcGraphData(capture_file *, bool)), iog, SLOT(recalcGraphData(capture_file *, bool)));
+ connect(this, SIGNAL(reloadValueUnitFields()), iog, SLOT(reloadValueUnitField()));
+ connect(&cap_file_, SIGNAL(captureFileClosing()), iog, SLOT(captureFileClosing()));
+ connect(iog, SIGNAL(requestRetap()), this, SLOT(scheduleRetap()));
+ connect(iog, SIGNAL(requestRecalc()), this, SLOT(scheduleRecalc()));
+ connect(iog, SIGNAL(requestReplot()), this, SLOT(scheduleReplot()));
+
+ syncGraphSettings(currentRow);
+ if (iog->visible()) {
+ scheduleRetap();
}
}
@@ -392,17 +499,17 @@ void IOGraphDialog::addDefaultGraph(bool enabled, int idx)
{
switch (idx % 2) {
case 0:
- addGraph(enabled, tr("All packets"), QString(), ui->graphTreeWidget->topLevelItemCount(),
- IOGraph::psLine, IOG_ITEM_UNIT_PACKETS, QString(), default_moving_average_);
+ addGraph(enabled, tr("All packets"), QString(), ColorUtils::graphColor(idx),
+ IOGraph::psLine, IOG_ITEM_UNIT_PACKETS, QString(), DEFAULT_MOVING_AVERAGE);
break;
default:
- addGraph(enabled, tr("TCP errors"), "tcp.analysis.flags", ui->graphTreeWidget->topLevelItemCount(),
- IOGraph::psBar, IOG_ITEM_UNIT_PACKETS, QString(), default_moving_average_);
+ addGraph(enabled, tr("TCP errors"), "tcp.analysis.flags", ColorUtils::graphColor(idx),
+ IOGraph::psBar, IOG_ITEM_UNIT_PACKETS, QString(), DEFAULT_MOVING_AVERAGE);
break;
}
}
-// Sync the settings from a graphTreeWidget item to its IOGraph.
+// Sync the settings from UAT model to its IOGraph.
// Disables the graph if any errors are found.
//
// NOTE: Setting dfilter, yaxis and yfield here will all end up in setFilter() and this
@@ -413,42 +520,35 @@ void IOGraphDialog::addDefaultGraph(bool enabled, int idx)
// TODO: The issues in the above note should be fixed and setFilter() should not be
// called so frequently.
-void IOGraphDialog::syncGraphSettings(QTreeWidgetItem *item)
+void IOGraphDialog::syncGraphSettings(int row)
{
- if (!item) return;
- IOGraph *iog = VariantPointer<IOGraph>::asPtr(item->data(name_col_, Qt::UserRole));
- if (!iog) return;
+ if (!uat_model_->index(row, colEnabled).isValid() || (ioGraphs_.size() <= row))
+ return;
+
+ IOGraph *iog = ioGraphs_[row];
- bool visible = item->checkState(name_col_) == Qt::Checked;
+ bool visible = uat_model_->data(uat_model_->index(row, colEnabled), Qt::DisplayRole).toBool();
bool retap = !iog->visible() && visible;
- iog->setName(item->text(name_col_));
- iog->setFilter(item->text(dfilter_col_));
+ iog->setName(uat_model_->data(uat_model_->index(row, colName), Qt::DisplayRole).toString());
+ iog->setFilter(uat_model_->data(uat_model_->index(row, colDFilter), Qt::DisplayRole).toString());
/* plot style depend on the value unit, so set it first. */
- iog->setValueUnits(item->data(yaxis_col_, Qt::UserRole).toInt());
- iog->setValueUnitField(item->text(yfield_col_));
+ iog->setValueUnits(uat_model_->data(uat_model_->index(row, colYAxis), Qt::DisplayRole).toUInt());
+ iog->setValueUnitField(uat_model_->data(uat_model_->index(row, colYField), Qt::DisplayRole).toString());
- iog->setColor(colors_[item->data(color_col_, Qt::UserRole).toInt() % colors_.size()]);
- iog->setPlotStyle(item->data(style_col_, Qt::UserRole).toInt());
+ iog->setColor(QRgb(uat_model_->data(uat_model_->index(row, colColor), Qt::DisplayRole).toUInt()));
+ iog->setPlotStyle(uat_model_->data(uat_model_->index(row, colStyle), Qt::DisplayRole).toUInt());
- iog->moving_avg_period_ = item->data(sma_period_col_, Qt::UserRole).toUInt();
+ iog->moving_avg_period_ = uat_model_->data(uat_model_->index(row, colSMAPeriod), Qt::DisplayRole).toUInt();
iog->setInterval(ui->intervalComboBox->itemData(ui->intervalComboBox->currentIndex()).toInt());
- ui->graphTreeWidget->blockSignals(true); // setFlags emits itemChanged
if (!iog->configError().isEmpty()) {
hint_err_ = iog->configError();
visible = false;
retap = false;
- // On macOS the "not user checkable" checkbox isn't obviously disabled.
- // For now show it as partially checked.
- item->setCheckState(name_col_, Qt::PartiallyChecked);
- item->setFlags(item->flags() & ~Qt::ItemIsUserCheckable);
- } else {
- item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
}
- ui->graphTreeWidget->blockSignals(false);
iog->setVisible(visible);
@@ -569,52 +669,21 @@ void IOGraphDialog::keyPressEvent(QKeyEvent *event)
void IOGraphDialog::reject()
{
- // Catch escape keys.
- QList<QWidget *>editors = QList<QWidget *>() << name_line_edit_ << dfilter_line_edit_ << yfield_line_edit_;
-
- foreach (QWidget *w, editors) {
- if (w && w->hasFocus()) {
- ui->graphTreeWidget->setFocus(); // Trigger itemEditingFinished
- return;
- }
- }
+ if (!iog_uat_)
+ return;
- QList<QComboBox *>combos = QList<QComboBox *>() << color_combo_box_ << style_combo_box_ <<
- yaxis_combo_box_ << sma_combo_box_;
- foreach (QComboBox *cb, combos) {
- if (cb && (cb->hasFocus() || cb->view()->hasFocus())) {
- ui->graphTreeWidget->setFocus(); // Trigger itemEditingFinished
- return;
- }
- }
+ //There is no "rejection" of the UAT created. Just save what we have
+ if (iog_uat_->changed) {
+ gchar *err = NULL;
- if (iog_uat_) {
- uat_clear(iog_uat_);
-
- for (int i = 0; i < ui->graphTreeWidget->topLevelItemCount(); i++) {
- QTreeWidgetItem *item = ui->graphTreeWidget->topLevelItem(i);
- IOGraph *iog = NULL;
- if (item) {
- iog = VariantPointer<IOGraph>::asPtr(item->data(name_col_, Qt::UserRole));
- io_graph_settings_t iogs;
- QColor color(iog->color());
- iogs.enabled = iog->visible() ? 1 : 0;
- iogs.name = qstring_strdup(iog->name());
- iogs.dfilter = qstring_strdup(iog->filter());
- iogs.color = qstring_strdup(color.name());
- iogs.style = qstring_strdup(plot_style_to_name_[(IOGraph::PlotStyles)item->data(style_col_, Qt::UserRole).toInt()]);
- iogs.yaxis = qstring_strdup(iog->valueUnitLabel());
- iogs.yfield = qstring_strdup(iog->valueUnitField());
- iogs.sma_period = iog->movingAveragePeriod();
- uat_add_record(iog_uat_, &iogs, TRUE);
- io_graph_free_cb(&iogs);
- }
- }
- char* err = NULL;
if (!uat_save(iog_uat_, &err)) {
- /* XXX - report this error */
+ report_failure("Error while saving %s: %s", iog_uat_->name, err);
g_free(err);
}
+
+ if (iog_uat_->post_update_cb) {
+ iog_uat_->post_update_cb();
+ }
}
QDialog::reject();
@@ -689,10 +758,6 @@ void IOGraphDialog::panAxes(int x_pixels, int y_pixels)
}
}
-QIcon IOGraphDialog::graphColorIcon(int color_idx)
-{
- return StockIcon::colorIcon(colors_[color_idx % colors_.size()], QColor(QPalette::Mid).rgb());
-}
void IOGraphDialog::toggleTracerStyle(bool force_default)
{
@@ -723,26 +788,19 @@ void IOGraphDialog::toggleTracerStyle(bool force_default)
// currently selected, visible graph or the first visible graph otherwise.
IOGraph *IOGraphDialog::currentActiveGraph() const
{
- QTreeWidgetItem *selectedItem = ui->graphTreeWidget->currentItem();
- if (selectedItem && selectedItem->checkState(name_col_) != Qt::Checked) {
- selectedItem = NULL;
+ QModelIndex index = ui->graphUat->currentIndex();
+ if (index.isValid()) {
+ return ioGraphs_[index.row()];
}
- if (!selectedItem) {
- for (int i = 0; i < ui->graphTreeWidget->topLevelItemCount(); i++) {
- QTreeWidgetItem *item = ui->graphTreeWidget->topLevelItem(i);
- if (item && item->checkState(name_col_) == Qt::Checked) {
- selectedItem = item;
- break;
- }
- }
+ //if no currently selected item, go with first item enabled
+ for (int row = 0; row < uat_model_->rowCount(); row++)
+ {
+ if (uat_model_->data(uat_model_->index(row, colEnabled), Qt::DisplayRole).toBool())
+ return ioGraphs_[row];
}
- if (selectedItem) {
- return VariantPointer<IOGraph>::asPtr(selectedItem->data(name_col_, Qt::UserRole));
- } else {
- return NULL;
- }
+ return NULL;
}
// Scan through our graphs and gather information.
@@ -756,25 +814,30 @@ void IOGraphDialog::getGraphInfo()
tracer_->setGraph(NULL);
IOGraph *selectedGraph = currentActiveGraph();
- for (int i = 0; i < ui->graphTreeWidget->topLevelItemCount(); i++) {
- QTreeWidgetItem *item = ui->graphTreeWidget->topLevelItem(i);
- if (item && item->checkState(name_col_) == Qt::Checked) {
- IOGraph *iog = VariantPointer<IOGraph>::asPtr(item->data(name_col_, Qt::UserRole));
- QCPGraph *graph = iog->graph();
- QCPBars *bars = iog->bars();
- int style = item->data(style_col_, Qt::UserRole).toInt();
- if (graph && (!base_graph_ || iog == selectedGraph)) {
- base_graph_ = graph;
- } else if (bars && style == IOGraph::psStackedBar && iog->visible()) {
- bars->moveBelow(NULL); // Remove from existing stack
- bars->moveBelow(prev_bars);
- prev_bars = bars;
- }
- if (iog->visible()) {
- double iog_start = iog->startOffset();
- if (start_time_ == 0.0 || iog_start < start_time_) {
- start_time_ = iog_start;
+
+ if (uat_model_ != NULL) {
+ //all graphs may not be created yet, so bounds check the graph array
+ for (int row = 0; ((row < uat_model_->rowCount()) && (row < ioGraphs_.size())); row++) {
+ if (uat_model_->data(uat_model_->index(row, colEnabled), Qt::DisplayRole).toBool()) {
+ IOGraph* iog = ioGraphs_[row];
+ QCPGraph *graph = iog->graph();
+ QCPBars *bars = iog->bars();
+ if (graph && (!base_graph_ || iog == selectedGraph)) {
+ base_graph_ = graph;
+ } else if (bars &&
+ (uat_model_->data(uat_model_->index(row, colStyle), Qt::DisplayRole).toString().compare(val_to_str_const(IOGraph::psStackedBar, graph_style_vs, "None")) == 0) &&
+ iog->visible()) {
+ bars->moveBelow(NULL); // Remove from existing stack
+ bars->moveBelow(prev_bars);
+ prev_bars = bars;
}
+ if (iog->visible()) {
+ double iog_start = iog->startOffset();
+ if (start_time_ == 0.0 || iog_start < start_time_) {
+ start_time_ = iog_start;
+ }
+ }
+
}
}
}
@@ -794,16 +857,17 @@ void IOGraphDialog::updateLegend()
iop->yAxis->setLabel(QString());
// Find unique labels
- for (int i = 0; i < ui->graphTreeWidget->topLevelItemCount(); i++) {
- QTreeWidgetItem *ti = ui->graphTreeWidget->topLevelItem(i);
- IOGraph *iog = NULL;
- if (ti && ti->checkState(name_col_) == Qt::Checked) {
- iog = VariantPointer<IOGraph>::asPtr(ti->data(name_col_, Qt::UserRole));
- QString label(iog->valueUnitLabel());
- if (!iog->scaledValueUnit().isEmpty()) {
- label += " (" + iog->scaledValueUnit() + ")";
+ if (uat_model_ != NULL) {
+ for (int row = 0; row < uat_model_->rowCount(); row++) {
+ if (uat_model_->data(uat_model_->index(row, colEnabled), Qt::DisplayRole).toBool() &&
+ ioGraphs_[row]) {
+ IOGraph *iog = ioGraphs_[row];
+ QString label(iog->valueUnitLabel());
+ if (!iog->scaledValueUnit().isEmpty()) {
+ label += " (" + iog->scaledValueUnit() + ")";
+ }
+ vu_label_set.insert(label);
}
- vu_label_set.insert(label);
}
}
@@ -828,15 +892,15 @@ void IOGraphDialog::updateLegend()
}
legendTitle->setText(QString(intervalText + " Intervals "));
- for (int i = 0; i < ui->graphTreeWidget->topLevelItemCount(); i++) {
- QTreeWidgetItem *ti = ui->graphTreeWidget->topLevelItem(i);
- IOGraph *iog = NULL;
- if (ti) {
- iog = VariantPointer<IOGraph>::asPtr(ti->data(name_col_, Qt::UserRole));
- if (ti->checkState(name_col_) == Qt::Checked) {
- iog->addToLegend();
- } else {
- iog->removeFromLegend();
+ if (uat_model_ != NULL) {
+ for (int row = 0; row < uat_model_->rowCount(); row++) {
+ IOGraph *iog = ioGraphs_[row];
+ if (iog) {
+ if (uat_model_->data(uat_model_->index(row, colEnabled), Qt::DisplayRole).toBool()) {
+ iog->addToLegend();
+ } else {
+ iog->removeFromLegend();
+ }
}
}
}
@@ -993,49 +1057,6 @@ void IOGraphDialog::mouseReleased(QMouseEvent *event)
}
}
-void IOGraphDialog::focusChanged(QWidget *, QWidget *current)
-{
- QTreeWidgetItem *item = ui->graphTreeWidget->currentItem();
- if (!item) {
- return;
- }
-
- // If we navigated away from an editing session, clear it.
- QList<QWidget *>editors = QList<QWidget *>() << name_line_edit_ << dfilter_line_edit_ <<
- color_combo_box_ << style_combo_box_ <<
- yaxis_combo_box_ << yfield_line_edit_ <<
- sma_combo_box_;
- bool edit_active = false;
- foreach (QWidget *w, editors) {
- if (w) {
- edit_active = true;
- }
- }
- if (!edit_active) {
- return;
- }
- editors.append(color_combo_box_->view());
- editors.append(style_combo_box_->view());
- editors.append(yaxis_combo_box_->view());
- editors.append(sma_combo_box_->view());
-
- if (! editors.contains(current)) {
- itemEditingFinished(item);
- }
-}
-
-void IOGraphDialog::activateLastItem()
-{
- int last_idx = ui->graphTreeWidget->topLevelItemCount() - 1;
- if (last_idx < 0) return;
-
- QTreeWidgetItem *last_item = ui->graphTreeWidget->invisibleRootItem()->child(last_idx);
- if (!last_item) return;
-
- ui->graphTreeWidget->setCurrentItem(last_item);
- on_graphTreeWidget_itemActivated(last_item, name_col_);
-}
-
void IOGraphDialog::resetAxes()
{
QCustomPlot *iop = ui->ioPlot;
@@ -1070,10 +1091,12 @@ void IOGraphDialog::updateStatistics()
need_recalc_ = false;
need_replot_ = true;
int enabled_graphs = 0;
- for (int i = 0; i < ui->graphTreeWidget->topLevelItemCount(); i++) {
- QTreeWidgetItem *item = ui->graphTreeWidget->topLevelItem(i);
- if (item && item->checkState(name_col_) == Qt::Checked) {
- ++enabled_graphs;
+
+ if (uat_model_ != NULL) {
+ for (int row = 0; row < uat_model_->rowCount(); row++) {
+ if (uat_model_->data(uat_model_->index(row, colEnabled), Qt::DisplayRole).toBool()) {
+ ++enabled_graphs;
+ }
}
}
// With multiple visible graphs, disable Y scaling to avoid
@@ -1098,123 +1121,42 @@ void IOGraphDialog::updateStatistics()
}
}
-// We're done editing a treewidgetitem. Set its values based on its
-// widgets, remove each widget, then sync with our associated graph.
-void IOGraphDialog::itemEditingFinished(QTreeWidgetItem *item)
+void IOGraphDialog::loadProfileGraphs()
{
- if (item) {
- bool recalc = false;
- // Don't force a retap here. Disable the graph instead.
- Qt::CheckState check_state = item->checkState(name_col_);
- hint_err_.clear();
- io_graph_item_unit_t item_unit = IOG_ITEM_UNIT_PACKETS;
- QString field_name;
-
- if (name_line_edit_) {
- item->setText(name_col_, name_line_edit_->text());
- name_line_edit_ = NULL;
- }
- if (dfilter_line_edit_) {
- QString df = dfilter_line_edit_->text();
- if (item->text(dfilter_col_).compare(df)) {
- check_state = Qt::Unchecked;
- }
- item->setText(dfilter_col_, df);
- dfilter_line_edit_ = NULL;
- }
- if (color_combo_box_) {
- int index = color_combo_box_->currentIndex();
- item->setData(color_col_, Qt::UserRole, index);
- item->setIcon(color_col_, graphColorIcon(index));
- color_combo_box_ = NULL;
- }
- if (style_combo_box_) {
- IOGraph::PlotStyles ps = IOGraph::psLine;
- int index = style_combo_box_->currentIndex();
- if (index < plot_style_to_name_.size()) {
- ps = plot_style_to_name_.keys()[index];
- }
- item->setText(style_col_, plot_style_to_name_[ps]);
- item->setData(style_col_, Qt::UserRole, ps);
- style_combo_box_ = NULL;
- }
- if (yaxis_combo_box_) {
- int index = yaxis_combo_box_->currentIndex();
- if (index != item->data(yaxis_col_, Qt::UserRole).toInt()) {
- if (index <= IOG_ITEM_UNIT_CALC_SUM) {
- recalc = true;
- } else {
- check_state = Qt::Unchecked;
- }
- }
- if (index < value_unit_to_name_.size()) {
- item_unit = value_unit_to_name_.keys()[index];
- }
- item->setText(yaxis_col_, value_unit_to_name_[item_unit]);
- item->setData(yaxis_col_, Qt::UserRole, item_unit);
- yaxis_combo_box_ = NULL;
- }
- if (yfield_line_edit_) {
- if (item->text(yfield_col_).compare(yfield_line_edit_->text())) {
- check_state = Qt::Unchecked;
- }
- item->setText(yfield_col_, yfield_line_edit_->text());
- field_name = yfield_line_edit_->text();
- yfield_line_edit_ = NULL;
- }
- if (sma_combo_box_) {
- int index = sma_combo_box_->currentIndex();
- if (index != item->data(sma_period_col_, Qt::UserRole).toInt()) {
- recalc = true;
- }
- QString text = sma_combo_box_->itemText(index);
- int sma = sma_combo_box_->itemData(index, Qt::UserRole).toInt();
- item->setText(sma_period_col_, text);
- item->setData(sma_period_col_, Qt::UserRole, sma);
- sma_combo_box_ = NULL;
- }
+ if (iog_uat_ == NULL) {
+
+ iog_uat_ = uat_new("I/O Graphs",
+ sizeof(io_graph_settings_t),
+ "io_graphs",
+ TRUE,
+ &iog_settings_,
+ &num_io_graphs_,
+ 0, /* doesn't affect anything that requires a GUI update */
+ "ChStatIOGraphs",
+ io_graph_copy_cb,
+ NULL,
+ io_graph_free_cb,
+ NULL,
+ NULL,
+ io_graph_fields);
- for (int col = 0; col < num_cols_; col++) {
- QWidget *w = ui->graphTreeWidget->itemWidget(item, col);
- if (w) {
- ui->graphTreeWidget->removeItemWidget(item, col);
- }
+ char* err = NULL;
+ if (!uat_load(iog_uat_, &err)) {
+ /* XXX - report the error */
+ g_free(err);
}
+ }
- item->setCheckState(name_col_, check_state);
- syncGraphSettings(item);
+ uat_model_ = new UatModel(NULL, iog_uat_);
+ uat_delegate_ = new UatDelegate;
+ ui->graphUat->setModel(uat_model_);
+ ui->graphUat->setItemDelegate(uat_delegate_);
- if (recalc) {
- scheduleRecalc(true);
- } else {
- scheduleReplot(true);
- }
- }
-}
+ connect(uat_model_, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ this, SLOT(modelDataChanged(QModelIndex)));
+ connect(uat_model_, SIGNAL(rowsRemoved(QModelIndex, int, int)),
+ this, SLOT(modelRowsRemoved()));
-void IOGraphDialog::loadProfileGraphs()
-{
- if (iog_uat_) return;
-
- iog_uat_ = uat_new("I/O Graphs",
- sizeof(io_graph_settings_t),
- "io_graphs",
- TRUE,
- &iog_settings_,
- &num_io_graphs_,
- 0, /* doesn't affect anything that requires a GUI update */
- "ChStatIOGraphs",
- io_graph_copy_cb,
- NULL,
- io_graph_free_cb,
- NULL,
- NULL,
- io_graph_fields);
- char* err = NULL;
- if (!uat_load(iog_uat_, &err)) {
- /* XXX - report the error */
- g_free(err);
- }
}
// Slots
@@ -1224,11 +1166,9 @@ void IOGraphDialog::on_intervalComboBox_currentIndexChanged(int)
int interval = ui->intervalComboBox->itemData(ui->intervalComboBox->currentIndex()).toInt();
bool need_retap = false;
- for (int i = 0; i < ui->graphTreeWidget->topLevelItemCount(); i++) {
- QTreeWidgetItem *item = ui->graphTreeWidget->topLevelItem(i);
- IOGraph *iog = NULL;
- if (item) {
- iog = VariantPointer<IOGraph>::asPtr(item->data(name_col_, Qt::UserRole));
+ if (uat_model_ != NULL) {
+ for (int row = 0; row < uat_model_->rowCount(); row++) {
+ IOGraph *iog = ioGraphs_[row];
if (iog) {
iog->setInterval(interval);
if (iog->visible()) {
@@ -1259,162 +1199,9 @@ void IOGraphDialog::on_todCheckBox_toggled(bool checked)
mouseMoved(NULL); // Update hint
}
-void IOGraphDialog::on_graphTreeWidget_currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *previous)
-{
- if (previous && ui->graphTreeWidget->itemWidget(previous, name_col_)) {
- itemEditingFinished(previous);
- }
-}
-
-// XXX It might be more correct to create a custom item delegate for editing
-// an item, but that appears to only allow one editor widget at a time. Adding
-// editors for every column is *much* more convenient since it lets the user
-// move from item to item with a single mouse click or by tabbing.
-void IOGraphDialog::on_graphTreeWidget_itemActivated(QTreeWidgetItem *item, int column)
+void IOGraphDialog::on_graphUat_currentItemChanged(const QModelIndex &current, const QModelIndex&)
{
- if (!item || name_line_edit_) return;
-
- QTreeWidget *gtw = ui->graphTreeWidget;
- QWidget *editor = NULL;
- int cur_idx;
-
- name_line_edit_ = new QLineEdit();
- name_line_edit_->setFixedWidth(gtw->columnWidth(name_col_));
- name_line_edit_->setText(item->text(name_col_));
-
- dfilter_line_edit_ = new DisplayFilterEdit();
- connect(dfilter_line_edit_, SIGNAL(textChanged(QString)),
- dfilter_line_edit_, SLOT(checkDisplayFilter(QString)));
- dfilter_line_edit_->setFixedWidth(gtw->columnWidth(dfilter_col_));
- dfilter_line_edit_->setText(item->text(dfilter_col_));
-
- color_combo_box_ = new QComboBox();
- cur_idx = item->data(color_col_, Qt::UserRole).toInt();
- for (int i = 0; i < colors_.size(); i++) {
- color_combo_box_->addItem(QString());
- color_combo_box_->setItemIcon(i, graphColorIcon(i));
- if (i == cur_idx) {
- color_combo_box_->setCurrentIndex(i);
- }
- }
- item->setIcon(color_col_, QIcon());
- color_combo_box_->setFocusPolicy(Qt::StrongFocus);
-
-#ifdef Q_OS_WIN
- // QTBUG-3097
- color_combo_box_->view()->setMinimumWidth(
- style()->pixelMetric(QStyle::PM_ListViewIconSize) + // Not entirely correct but close enough.
- style()->pixelMetric(QStyle::PM_ScrollBarExtent));
-#endif
-
- style_combo_box_ = new QComboBox();
- cur_idx = item->data(style_col_, Qt::UserRole).toInt();
- for (int i = 0; i < plot_style_to_name_.size(); i++) {
- IOGraph::PlotStyles ps = plot_style_to_name_.keys()[i];
- style_combo_box_->addItem(plot_style_to_name_[ps], ps);
- if (ps == cur_idx) {
- style_combo_box_->setCurrentIndex(i);
- }
- }
- style_combo_box_->setFocusPolicy(Qt::StrongFocus);
-
- yaxis_combo_box_ = new QComboBox();
- cur_idx = item->data(yaxis_col_, Qt::UserRole).toInt();
- for (int i = 0; i < value_unit_to_name_.size(); i++) {
- io_graph_item_unit_t vu = value_unit_to_name_.keys()[i];
- yaxis_combo_box_->addItem(value_unit_to_name_[vu], vu);
- if (vu == cur_idx) {
- yaxis_combo_box_->setCurrentIndex(i);
- }
- }
- yaxis_combo_box_->setFocusPolicy(Qt::StrongFocus);
-
- yfield_line_edit_ = new FieldFilterEdit();
- connect(yfield_line_edit_, SIGNAL(textChanged(QString)),
- yfield_line_edit_, SLOT(checkFieldName(QString)));
- yfield_line_edit_->setFixedWidth(gtw->columnWidth(yfield_col_));
- yfield_line_edit_->setText(item->text(yfield_col_));
-
- sma_combo_box_ = new QComboBox();
- cur_idx = item->data(sma_period_col_, Qt::UserRole).toInt();
- for (int i = 0; i < moving_average_to_name_.size(); i++) {
- int sma = moving_average_to_name_.keys()[i];
- sma_combo_box_->addItem(moving_average_to_name_[sma], sma);
- if (sma == cur_idx) {
- sma_combo_box_->setCurrentIndex(i);
- }
- }
- sma_combo_box_->setFocusPolicy(Qt::StrongFocus);
-
- switch (column) {
- case name_col_:
- editor = name_line_edit_;
- name_line_edit_->selectAll();
- break;
- case dfilter_col_:
- editor = dfilter_line_edit_;
- dfilter_line_edit_->selectAll();
- break;
- case color_col_:
- {
- editor = color_combo_box_;
- break;
- }
- case style_col_:
- {
- editor = style_combo_box_;
- break;
- }
- case yaxis_col_:
- {
- editor = yaxis_combo_box_;
- break;
- }
- case yfield_col_:
- editor = yfield_line_edit_;
- yfield_line_edit_->selectAll();
- break;
- case sma_period_col_:
- {
- editor = sma_combo_box_;
- break;
- }
- default:
- return;
- }
-
- QList<QWidget *>editors = QList<QWidget *>() << name_line_edit_ << dfilter_line_edit_ <<
- color_combo_box_ << style_combo_box_ <<
- yaxis_combo_box_ << yfield_line_edit_ <<
- sma_combo_box_;
- int cur_col = name_col_;
- QWidget *prev_widget = ui->graphTreeWidget;
- foreach (QWidget *editorItem, editors) {
- QFrame *edit_frame = new QFrame();
- QHBoxLayout *hb = new QHBoxLayout();
- QSpacerItem *spacer = new QSpacerItem(5, 10);
-
- hb->addWidget(editorItem, 0);
- hb->addSpacerItem(spacer);
- hb->setStretch(1, 1);
- hb->setContentsMargins(0, 0, 0, 0);
-
- edit_frame->setLineWidth(0);
- edit_frame->setFrameStyle(QFrame::NoFrame);
- edit_frame->setLayout(hb);
- ui->graphTreeWidget->setItemWidget(item, cur_col, edit_frame);
- setTabOrder(prev_widget, editorItem);
- prev_widget = editorItem;
- cur_col++;
- }
-
-// setTabOrder(prev_widget, ui->graphTreeWidget);
- editor->setFocus();
-}
-
-void IOGraphDialog::on_graphTreeWidget_itemSelectionChanged()
-{
- if (ui->graphTreeWidget->selectedItems().length() > 0) {
+ if (current.isValid()) {
ui->deleteToolButton->setEnabled(true);
ui->copyToolButton->setEnabled(true);
} else {
@@ -1423,16 +1210,24 @@ void IOGraphDialog::on_graphTreeWidget_itemSelectionChanged()
}
}
-void IOGraphDialog::on_graphTreeWidget_itemChanged(QTreeWidgetItem *item, int column)
+void IOGraphDialog::modelDataChanged(const QModelIndex &index)
{
- if (!item) {
- return;
- }
+ bool recalc = false;
- if (column == name_col_ && !name_line_edit_) {
- syncGraphSettings(item);
+ switch (index.column())
+ {
+ case colYAxis:
+ case colSMAPeriod:
+ recalc = true;
}
+ syncGraphSettings(index.row());
+
+ if (recalc) {
+ scheduleRecalc(true);
+ } else {
+ scheduleReplot(true);
+ }
}
void IOGraphDialog::on_resetButton_clicked()
@@ -1447,13 +1242,15 @@ void IOGraphDialog::on_newToolButton_clicked()
void IOGraphDialog::on_deleteToolButton_clicked()
{
- QTreeWidgetItem *item = ui->graphTreeWidget->currentItem();
- if (!item) return;
-
- IOGraph *iog = VariantPointer<IOGraph>::asPtr(item->data(name_col_, Qt::UserRole));
+ const QModelIndex &current = ui->graphUat->currentIndex();
+ if (uat_model_ && current.isValid()) {
+ delete ioGraphs_[current.row()];
+ ioGraphs_.remove(current.row());
- delete item;
- delete iog;
+ if (!uat_model_->removeRows(current.row(), 1)) {
+ qDebug() << "Failed to remove row";
+ }
+ }
// We should probably be smarter about this.
hint_err_.clear();
@@ -1648,19 +1445,21 @@ void IOGraphDialog::makeCsv(QTextStream &stream) const
int max_interval = 0;
stream << "\"Interval start\"";
- for (int i = 0; i < ui->graphTreeWidget->topLevelItemCount(); i++) {
- QTreeWidgetItem *ti = ui->graphTreeWidget->topLevelItem(i);
- if (ti && ti->checkState(name_col_) == Qt::Checked) {
- IOGraph *iog = VariantPointer<IOGraph>::asPtr(ti->data(name_col_, Qt::UserRole));
- activeGraphs.append(iog);
- if (max_interval < iog->maxInterval()) {
- max_interval = iog->maxInterval();
+ if (uat_model_ != NULL) {
+ for (int row = 0; row < uat_model_->rowCount(); row++) {
+ if (uat_model_->data(uat_model_->index(row, colEnabled), Qt::DisplayRole).toBool() &&
+ (ioGraphs_[row] != NULL)) {
+ activeGraphs.append(ioGraphs_[row]);
+ if (max_interval < ioGraphs_[row]->maxInterval()) {
+ max_interval = ioGraphs_[row]->maxInterval();
+ }
+ QString name = ioGraphs_[row]->name().toUtf8();
+ name = QString("\"%1\"").arg(name.replace("\"", "\"\"")); // RFC 4180
+ stream << "," << name;
}
- QString name = iog->name().toUtf8();
- name = QString("\"%1\"").arg(name.replace("\"", "\"\"")); // RFC 4180
- stream << "," << name;
}
}
+
stream << endl;
for (int interval = 0; interval <= max_interval; interval++) {
@@ -1904,10 +1703,7 @@ void IOGraph::setPlotStyle(int style)
const QString IOGraph::valueUnitLabel()
{
- if (val_units_ >= IOG_ITEM_UNIT_FIRST && val_units_ <= IOG_ITEM_UNIT_LAST) {
- return value_unit_to_name_[val_units_];
- }
- return tr("Unknown");
+ return val_to_str_const(val_units_, y_axis_vs, "Unknown");
}
void IOGraph::setValueUnits(int val_units)
@@ -2003,53 +1799,6 @@ void IOGraph::clearAllData()
start_time_ = 0.0;
}
-QMap<io_graph_item_unit_t, QString> IOGraph::valueUnitsToNames()
-{
- QMap<io_graph_item_unit_t, QString> vuton;
-
- vuton[IOG_ITEM_UNIT_PACKETS] = QObject::tr("Packets");
- vuton[IOG_ITEM_UNIT_BYTES] = QObject::tr("Bytes");
- vuton[IOG_ITEM_UNIT_BITS] = QObject::tr("Bits");
- vuton[IOG_ITEM_UNIT_CALC_SUM] = QObject::tr("SUM(Y Field)");
- vuton[IOG_ITEM_UNIT_CALC_FRAMES] = QObject::tr("COUNT FRAMES(Y Field)");
- vuton[IOG_ITEM_UNIT_CALC_FIELDS] = QObject::tr("COUNT FIELDS(Y Field)");
- vuton[IOG_ITEM_UNIT_CALC_MAX] = QObject::tr("MAX(Y Field)");
- vuton[IOG_ITEM_UNIT_CALC_MIN] = QObject::tr("MIN(Y Field)");
- vuton[IOG_ITEM_UNIT_CALC_AVERAGE] = QObject::tr("AVG(Y Field)");
- vuton[IOG_ITEM_UNIT_CALC_LOAD] = QObject::tr("LOAD(Y Field)");
-
- return vuton;
-}
-
-QMap<IOGraph::PlotStyles, QString> IOGraph::plotStylesToNames()
-{
- QMap<IOGraph::PlotStyles, QString> pston;
-
- pston[psLine] = QObject::tr("Line");
- pston[psImpulse] = QObject::tr("Impulse");
- pston[psBar] = QObject::tr("Bar");
- pston[psStackedBar] = QObject::tr("Stacked Bar");
- pston[psDot] = QObject::tr("Dot");
- pston[psSquare] = QObject::tr("Square");
- pston[psDiamond] = QObject::tr("Diamond");
-
- return pston;
-}
-
-QMap<int, QString> IOGraph::movingAveragesToNames()
-{
- QMap<int, QString> maton;
- QList<int> averages = QList<int>()
- /* << 8 */ << 10 /* << 16 */ << 20 << 50 << 100 << 200 << 500 << 1000; // Arbitrarily chosen
-
- maton[0] = QObject::tr("None");
- foreach (int avg, averages) {
- maton[avg] = QString(QObject::tr("%1 interval SMA")).arg(avg);
- }
-
- return maton;
-}
-
void IOGraph::recalcGraphData(capture_file *cap_file, bool enable_scaling)
{
/* Moving average variables */
diff --git a/ui/qt/io_graph_dialog.h b/ui/qt/io_graph_dialog.h
index 13f3d7578e..899d99a0e4 100644
--- a/ui/qt/io_graph_dialog.h
+++ b/ui/qt/io_graph_dialog.h
@@ -32,17 +32,15 @@
#include "wireshark_dialog.h"
+#include <ui/qt/models/uat_model.h>
+#include <ui/qt/models/uat_delegate.h>
+
#include <QIcon>
#include <QMenu>
#include <QTextStream>
-class QComboBox;
-class QLineEdit;
class QRubberBand;
class QTimer;
-class QTreeWidgetItem;
-
-class SyntaxLineEdit;
class QCPBars;
class QCPGraph;
@@ -90,10 +88,6 @@ public:
void clearAllData();
- static QMap<io_graph_item_unit_t, QString> valueUnitsToNames();
- static QMap<PlotStyles, QString> plotStylesToNames();
- static QMap<int, QString> movingAveragesToNames();
-
unsigned int moving_avg_period_;
public slots:
@@ -149,11 +143,13 @@ public:
explicit IOGraphDialog(QWidget &parent, CaptureFile &cf);
~IOGraphDialog();
+ enum UatColumns { colEnabled = 0, colName, colDFilter, colColor, colStyle, colYAxis, colYField, colSMAPeriod, colMaxNum};
+
void addGraph(bool checked, QString name, QString dfilter, int color_idx, IOGraph::PlotStyles style,
io_graph_item_unit_t value_units, QString yfield, int moving_average);
void addGraph(bool copy_from_current = false);
void addDefaultGraph(bool enabled, int idx = 0);
- void syncGraphSettings(QTreeWidgetItem *item);
+ void syncGraphSettings(int row);
public slots:
void scheduleReplot(bool now = false);
@@ -174,13 +170,14 @@ signals:
private:
Ui::IOGraphDialog *ui;
- QLineEdit *name_line_edit_;
- SyntaxLineEdit *dfilter_line_edit_;
- SyntaxLineEdit *yfield_line_edit_;
- QComboBox *color_combo_box_;
- QComboBox *style_combo_box_;
- QComboBox *yaxis_combo_box_;
- QComboBox *sma_combo_box_;
+ //Model and delegate were chosen over UatFrame because add/remove/copy
+ //buttons would need realignment (UatFrame has its own)
+ UatModel *uat_model_;
+ UatDelegate *uat_delegate_;
+
+ // XXX - This needs to stay synced with UAT index
+ QVector<IOGraph*> ioGraphs_;
+
QString hint_err_;
QCPGraph *base_graph_;
QCPItemTracer *tracer_;
@@ -195,9 +192,6 @@ private:
bool need_recalc_; // Medium weight: recalculate values, then replot
bool need_retap_; // Heavy weight: re-read packet data
bool auto_axes_;
- // Available colors
- // XXX - Add custom
- QList<QRgb> colors_;
// void fillGraph();
@@ -205,12 +199,11 @@ private:
void zoomXAxis(bool in);
void zoomYAxis(bool in);
void panAxes(int x_pixels, int y_pixels);
- QIcon graphColorIcon(int color_idx);
void toggleTracerStyle(bool force_default = false);
void getGraphInfo();
void updateLegend();
QRectF getZoomRanges(QRect zoom_rect);
- void itemEditingFinished(QTreeWidgetItem *item);
+ void createIOGraph(int currentRow);
void loadProfileGraphs();
void makeCsv(QTextStream &stream) const;
bool saveCsv(const QString &file_name) const;
@@ -221,18 +214,15 @@ private slots:
void graphClicked(QMouseEvent *event);
void mouseMoved(QMouseEvent *event);
void mouseReleased(QMouseEvent *event);
- void focusChanged(QWidget *previous, QWidget *current);
- void activateLastItem();
+
void resetAxes();
void updateStatistics(void);
void copyAsCsvClicked();
void on_intervalComboBox_currentIndexChanged(int index);
void on_todCheckBox_toggled(bool checked);
- void on_graphTreeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
- void on_graphTreeWidget_itemActivated(QTreeWidgetItem *item, int column);
- void on_graphTreeWidget_itemSelectionChanged();
- void on_graphTreeWidget_itemChanged(QTreeWidgetItem *item, int column);
+ void modelDataChanged(const QModelIndex &index);
+ void on_graphUat_currentItemChanged(const QModelIndex &current, const QModelIndex &previous);
void on_resetButton_clicked();
void on_logCheckBox_toggled(bool checked);
diff --git a/ui/qt/io_graph_dialog.ui b/ui/qt/io_graph_dialog.ui
index b2a69235b1..5c4caf16b5 100644
--- a/ui/qt/io_graph_dialog.ui
+++ b/ui/qt/io_graph_dialog.ui
@@ -64,48 +64,13 @@
</widget>
</item>
<item>
- <widget class="QTreeWidget" name="graphTreeWidget">
+ <widget class="TabnavTreeView" name="graphUat">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
- <column>
- <property name="text">
- <string>Name</string>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Display filter</string>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Color</string>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Style</string>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Y Axis</string>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Y Field</string>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Smoothing</string>
- </property>
- </column>
</widget>
</item>
<item>
@@ -513,6 +478,11 @@
<extends>QLabel</extends>
<header>widgets/elided_label.h</header>
</customwidget>
+ <customwidget>
+ <class>TabnavTreeView</class>
+ <extends>QTreeView</extends>
+ <header>widgets/tabnav_tree_view.h</header>
+ </customwidget>
</customwidgets>
<resources>
<include location="../../image/toolbar.qrc"/>
diff --git a/ui/qt/models/uat_delegate.cpp b/ui/qt/models/uat_delegate.cpp
index 9d77337aef..f28ae3e355 100644
--- a/ui/qt/models/uat_delegate.cpp
+++ b/ui/qt/models/uat_delegate.cpp
@@ -29,9 +29,12 @@
#include <QFileDialog>
#include <QLineEdit>
#include <QCheckBox>
+#include <QColorDialog>
#include <ui/qt/widgets/display_filter_edit.h>
+#include <ui/qt/widgets/field_filter_edit.h>
#include <ui/qt/widgets/editor_file_dialog.h>
+#include <ui/qt/widgets/editor_color_dialog.h>
UatDelegate::UatDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
@@ -50,7 +53,6 @@ QWidget *UatDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &
switch (field->mode) {
case PT_TXTMOD_DIRECTORYNAME:
- {
if (index.isValid()) {
QString filename_old = index.model()->data(index, Qt::EditRole).toString();
EditorFileDialog* fileDialog = new EditorFileDialog(index, parent, QString(field->title), filename_old);
@@ -64,10 +66,8 @@ QWidget *UatDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &
//shouldn't happen
return 0;
- }
case PT_TXTMOD_FILENAME:
- {
if (index.isValid()) {
QString filename_old = index.model()->data(index, Qt::EditRole).toString();
EditorFileDialog* fileDialog = new EditorFileDialog(index, parent, QString(field->title), filename_old);
@@ -82,7 +82,22 @@ QWidget *UatDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &
//shouldn't happen
return 0;
- }
+
+ case PT_TXTMOD_COLOR:
+ if (index.isValid()) {
+ QColor color(index.model()->data(index, Qt::DecorationRole).toString());
+ EditorColorDialog *colorDialog = new EditorColorDialog(index, color, new QWidget(parent));
+
+ colorDialog->setWindowFlags(Qt::Window);
+
+ //Use signals to accept data from cell
+ connect(colorDialog, SIGNAL(acceptEdit(const QModelIndex &)), this, SLOT(applyColor(const QModelIndex &)));
+ return colorDialog;
+ }
+
+ //shouldn't happen
+ return 0;
+
case PT_TXTMOD_ENUM:
{
// Note: the string repr. is written, not the integer value.
@@ -103,6 +118,11 @@ QWidget *UatDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &
DisplayFilterEdit *editor = new DisplayFilterEdit(parent);
return editor;
}
+ case PT_TXTMOD_PROTO_FIELD:
+ {
+ FieldFilterEdit *editor = new FieldFilterEdit(parent);
+ return editor;
+ }
case PT_TXTMOD_HEXBYTES:
{
// Requires input of the form "ab cd ef" (with possibly no or a colon
@@ -174,8 +194,10 @@ void UatDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
}
case PT_TXTMOD_DIRECTORYNAME:
case PT_TXTMOD_FILENAME:
+ case PT_TXTMOD_COLOR:
//do nothing, dialog signals will update table
break;
+
default:
QStyledItemDelegate::setModelData(editor, model, index);
}
@@ -229,6 +251,16 @@ void UatDelegate::applyDirectory(const QModelIndex& index)
}
}
+void UatDelegate::applyColor(const QModelIndex& index)
+{
+ if (index.isValid()) {
+ QColorDialog *colorDialog = static_cast<QColorDialog*>(sender());
+ QColor newColor = colorDialog->currentColor();
+ ((QAbstractItemModel *)index.model())->setData(index, newColor.name(), Qt::EditRole);
+ }
+}
+
+
/* * Editor modelines
*
* Local Variables:
diff --git a/ui/qt/models/uat_delegate.h b/ui/qt/models/uat_delegate.h
index 81ad108864..86f971adff 100644
--- a/ui/qt/models/uat_delegate.h
+++ b/ui/qt/models/uat_delegate.h
@@ -51,6 +51,7 @@ public:
private slots:
void applyDirectory(const QModelIndex& index);
void applyFilename(const QModelIndex& index);
+ void applyColor(const QModelIndex& index);
private:
uat_field_t *indexToField(const QModelIndex &index) const;
diff --git a/ui/qt/models/uat_model.cpp b/ui/qt/models/uat_model.cpp
index 5b0813f0a6..b782247b13 100644
--- a/ui/qt/models/uat_model.cpp
+++ b/ui/qt/models/uat_model.cpp
@@ -85,18 +85,25 @@ QVariant UatModel::data(const QModelIndex &index, int role) const
guint length = 0;
field->cb.tostr(rec, &str, &length, field->cbdata.tostr, field->fld_data);
- if (field->mode == PT_TXTMOD_HEXBYTES) {
+ switch (field->mode) {
+ case PT_TXTMOD_HEXBYTES:
+ {
char* temp_str = bytes_to_str(NULL, (const guint8 *) str, length);
g_free(str);
QString qstr(temp_str);
wmem_free(NULL, temp_str);
return qstr;
- } else if (field->mode == PT_TXTMOD_BOOL) {
+ }
+ case PT_TXTMOD_BOOL:
return "";
- } else {
+ case PT_TXTMOD_COLOR:
+ return QVariant();
+ default:
+ {
QString qstr(str);
g_free(str);
return qstr;
+ }
}
}
@@ -106,7 +113,8 @@ QVariant UatModel::data(const QModelIndex &index, int role) const
guint length = 0;
enum Qt::CheckState state = Qt::Unchecked;
field->cb.tostr(rec, &str, &length, field->cbdata.tostr, field->fld_data);
- if (g_strcmp0(str, "TRUE") == 0)
+ if ((g_strcmp0(str, "TRUE") == 0) ||
+ (g_strcmp0(str, "Enabled") == 0))
state = Qt::Checked;
g_free(str);
@@ -127,6 +135,16 @@ QVariant UatModel::data(const QModelIndex &index, int role) const
return QVariant();
}
+ if (role == Qt::DecorationRole) {
+ if (field->mode == PT_TXTMOD_COLOR) {
+ char *str = NULL;
+ guint length = 0;
+ field->cb.tostr(rec, &str, &length, field->cbdata.tostr, field->fld_data);
+
+ return QColor(QString(str));
+ }
+ }
+
// expose error message if any.
if (role == Qt::UserRole + 1) {
if (errors.contains(index.column())) {
diff --git a/ui/qt/widgets/editor_color_dialog.cpp b/ui/qt/widgets/editor_color_dialog.cpp
new file mode 100644
index 0000000000..5870f28efd
--- /dev/null
+++ b/ui/qt/widgets/editor_color_dialog.cpp
@@ -0,0 +1,57 @@
+/* editor_color_dialog.cpp
+ *
+ * Color dialog that can be used as an "inline editor" in a table
+ *
+ * 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 <ui/qt/widgets/editor_color_dialog.h>
+
+EditorColorDialog::EditorColorDialog(const QModelIndex& index, QWidget* parent)
+ : QColorDialog(parent)
+ , index_(index)
+{
+
+}
+
+EditorColorDialog::EditorColorDialog(const QModelIndex& index, const QColor& initial, QWidget* parent)
+ : QColorDialog(initial, parent)
+ , index_(index)
+{
+
+}
+
+void EditorColorDialog::accept()
+{
+ emit acceptEdit(index_);
+ QColorDialog::accept();
+}
+
+/*
+ * 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/widgets/editor_color_dialog.h b/ui/qt/widgets/editor_color_dialog.h
new file mode 100644
index 0000000000..a9ab749b84
--- /dev/null
+++ b/ui/qt/widgets/editor_color_dialog.h
@@ -0,0 +1,59 @@
+/* editor_color_dialog.h
+ *
+ * Color dialog that can be used as an "inline editor" in a table
+ *
+ * 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 EDITOR_COLOR_DIALOG_H_
+#define EDITOR_COLOR_DIALOG_H_
+
+#include <QColorDialog>
+#include <QModelIndex>
+
+class EditorColorDialog : public QColorDialog
+{
+ Q_OBJECT
+public:
+ EditorColorDialog(const QModelIndex& index, QWidget* parent = 0);
+ EditorColorDialog(const QModelIndex& index, const QColor& initial, QWidget* parent = 0);
+
+ void accept();
+
+signals:
+ void acceptEdit(const QModelIndex& index);
+
+protected:
+ const QModelIndex index_; //saved index of table cell
+};
+
+#endif /* EDITOR_COLOR_DIALOG_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:
+ */