2 * Delegates for editing various field types in a UAT record.
4 * Copyright 2016 Peter Wu <peter@lekensteyn.nl>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include <ui/qt/models/uat_delegate.h>
14 #include <epan/packet.h> // for get_dissector_names()
15 #include "epan/value_string.h"
16 #include <wsutil/ws_assert.h>
17 #include <QRegularExpression>
20 #include <QFileDialog>
23 #include <QColorDialog>
25 #include <ui/qt/widgets/display_filter_edit.h>
26 #include <ui/qt/widgets/dissector_syntax_line_edit.h>
27 #include <ui/qt/widgets/field_filter_edit.h>
28 #include <ui/qt/widgets/editor_file_dialog.h>
29 #include <ui/qt/widgets/path_selection_edit.h>
31 // The Qt docs suggest overriding updateEditorGeometry, but the
32 // defaults seem sane.
34 UatDelegate::UatDelegate(QObject
*parent
) : QStyledItemDelegate(parent
)
38 uat_field_t
*UatDelegate::indexToField(const QModelIndex
&index
) const
40 const QVariant v
= index
.model()->data(index
, Qt::UserRole
);
41 return static_cast<uat_field_t
*>(v
.value
<void *>());
44 QWidget
*UatDelegate::createEditor(QWidget
*parent
, const QStyleOptionViewItem
&option
,
45 const QModelIndex
&index
) const
47 uat_field_t
*field
= indexToField(index
);
48 QWidget
*editor
= nullptr;
50 switch (field
->mode
) {
51 case PT_TXTMOD_DIRECTORYNAME
:
52 case PT_TXTMOD_FILENAME
:
53 if (index
.isValid()) {
54 QString filename_old
= index
.model()->data(index
, Qt::EditRole
).toString();
55 PathSelectionEdit
* pathEdit
= new PathSelectionEdit(field
->title
, QString(), field
->mode
!= PT_TXTMOD_DIRECTORYNAME
, parent
);
56 connect(pathEdit
, &PathSelectionEdit::pathChanged
, this, &UatDelegate::pathHasChanged
);
61 if (index
.isValid()) {
62 QColor
color(index
.model()->data(index
, Qt::DecorationRole
).toString());
63 QColorDialog
* colorDialog
= new QColorDialog(color
, parent
);
64 // Don't fall through and set setAutoFillBackground(true)
71 // Note: the string repr. is written, not the integer value.
72 QComboBox
*cb_editor
= new QComboBox(parent
);
73 const value_string
*enum_vals
= (const value_string
*)field
->fld_data
;
74 for (int i
= 0; enum_vals
[i
].strptr
!= nullptr; i
++) {
75 cb_editor
->addItem(enum_vals
[i
].strptr
);
78 cb_editor
->setMinimumWidth(cb_editor
->minimumSizeHint().width());
82 case PT_TXTMOD_DISSECTOR
:
84 editor
= new DissectorSyntaxLineEdit(parent
);
88 case PT_TXTMOD_STRING
:
89 // TODO add a live validator? Should SyntaxLineEdit be used?
90 editor
= QStyledItemDelegate::createEditor(parent
, option
, index
);
93 case PT_TXTMOD_DISPLAY_FILTER
:
94 editor
= new DisplayFilterEdit(parent
);
97 case PT_TXTMOD_PROTO_FIELD
:
98 editor
= new FieldFilterEdit(parent
);
101 case PT_TXTMOD_HEXBYTES
:
103 // Requires input of the form "ab cd ef" (with possibly no or a colon
104 // separator instead of a single whitespace) for the editor to accept.
105 QRegularExpression
hexbytes_regex("([0-9a-f]{2}[ :]?)*");
106 hexbytes_regex
.setPatternOptions(QRegularExpression::CaseInsensitiveOption
);
107 // QString types from QStyledItemDelegate are documented to return a
108 // QLineEdit. Note that Qt returns a subclass from QLineEdit which
109 // automatically adapts the width to the typed contents.
110 QLineEdit
*le_editor
= static_cast<QLineEdit
*>(
111 QStyledItemDelegate::createEditor(parent
, option
, index
));
112 le_editor
->setValidator(new QRegularExpressionValidator(hexbytes_regex
, le_editor
));
118 // model will handle creating checkbox
125 ws_assert_not_reached();
130 editor
->setAutoFillBackground(true);
135 void UatDelegate::setEditorData(QWidget
*editor
, const QModelIndex
&index
) const
137 uat_field_t
*field
= indexToField(index
);
139 switch (field
->mode
) {
140 case PT_TXTMOD_DIRECTORYNAME
:
141 case PT_TXTMOD_FILENAME
:
142 if (index
.isValid() && qobject_cast
<PathSelectionEdit
*>(editor
))
143 qobject_cast
<PathSelectionEdit
*>(editor
)->setPath(index
.model()->data(index
, Qt::EditRole
).toString());
147 QComboBox
*combobox
= static_cast<QComboBox
*>(editor
);
148 const QString
&data
= index
.model()->data(index
, Qt::EditRole
).toString();
149 combobox
->setCurrentText(data
);
153 case PT_TXTMOD_COLOR
:
155 if (qobject_cast
<QColorDialog
*>(editor
))
157 QColor
color(index
.model()->data(index
, Qt::DecorationRole
).toString());
158 qobject_cast
<QColorDialog
*>(editor
)->setCurrentColor(color
);
164 QStyledItemDelegate::setEditorData(editor
, index
);
168 void UatDelegate::setModelData(QWidget
*editor
, QAbstractItemModel
*model
,
169 const QModelIndex
&index
) const
171 uat_field_t
*field
= indexToField(index
);
173 switch (field
->mode
) {
174 case PT_TXTMOD_DIRECTORYNAME
:
175 case PT_TXTMOD_FILENAME
:
176 if (index
.isValid() && qobject_cast
<PathSelectionEdit
*>(editor
))
177 const_cast<QAbstractItemModel
*>(index
.model())->setData(index
, qobject_cast
<PathSelectionEdit
*>(editor
)->path(), Qt::EditRole
);
181 QComboBox
*combobox
= static_cast<QComboBox
*>(editor
);
182 const QString
&data
= combobox
->currentText();
183 model
->setData(index
, data
, Qt::EditRole
);
186 case PT_TXTMOD_COLOR
:
187 //do nothing, dialog signals will update table
188 if (qobject_cast
<QColorDialog
*>(editor
))
190 QColor newColor
= qobject_cast
<QColorDialog
*>(editor
)->currentColor();
191 const_cast<QAbstractItemModel
*>(index
.model())->setData(index
, newColor
.name(), Qt::EditRole
);
196 QStyledItemDelegate::setModelData(editor
, model
, index
);
200 void UatDelegate::updateEditorGeometry(QWidget
*editor
,
201 const QStyleOptionViewItem
&option
,
202 const QModelIndex
&index
) const
204 uat_field_t
*field
= indexToField(index
);
206 switch (field
->mode
) {
207 case PT_TXTMOD_DIRECTORYNAME
:
208 case PT_TXTMOD_FILENAME
:
209 editor
->setGeometry(option
.rect
);
212 QStyledItemDelegate::updateEditorGeometry(editor
, option
, index
);
216 void UatDelegate::pathHasChanged(QString
)
218 PathSelectionEdit
* editor
= qobject_cast
<PathSelectionEdit
*>(sender());
220 emit
commitData(editor
);