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>
This commit is contained in:
Michael Mann 2017-07-23 10:53:43 -04:00 committed by Anders Broman
parent f63b0241c9
commit 5b3e3ee587
13 changed files with 649 additions and 720 deletions

View File

@ -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;

View File

@ -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
@ -615,6 +630,23 @@ static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr,
{#field_name, title, PT_TXTMOD_ENUM,{uat_fld_chk_enum,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{&(enum),&(enum),&(enum)},&(enum),desc,FLDFILL}
/*
* 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
*/

View File

@ -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) {

View File

@ -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

View File

@ -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 \

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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"/>

View File

@ -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:

View File

@ -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;

View File

@ -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())) {

View File

@ -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:
*/

View File

@ -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:
*/