1 /* column_editor_frame.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include <epan/column.h>
13 #include <epan/prefs.h>
14 #include <ui/recent.h>
16 #include <ui/preference_utils.h>
18 #include "main_application.h"
20 #include "column_editor_frame.h"
21 #include <ui_column_editor_frame.h>
23 #include <QPushButton>
26 #include <QAbstractItemView>
28 ColumnEditorFrame::ColumnEditorFrame(QWidget
*parent
) :
29 AccordionFrame(parent
),
30 ui(new Ui::ColumnEditorFrame
),
34 ui
->fieldsNameLineEdit
->setType(CustomColumnToEnter
);
37 foreach (QWidget
*w
, findChildren
<QWidget
*>()) {
38 w
->setAttribute(Qt::WA_MacSmallSize
, true);
42 for (int i
= 0; i
< NUM_COL_FMTS
; i
++) {
43 ui
->typeComboBox
->addItem(col_format_desc(i
), QVariant(i
));
46 // We want a behavior where the occurrenceLineEdit and type line edit
47 // will shrink, but where they won't expand past their needed space.
48 // Setting a stretch factor will make them expand (ignoring their
49 // SizePolicy) unless we also set the maximum width to their size hints.
51 ui
->horizontalLayout
->setStretchFactor(ui
->titleLineEdit
, 2);
52 ui
->horizontalLayout
->setStretchFactor(ui
->occurrenceLineEdit
, 1);
53 ui
->occurrenceLineEdit
->setMaximumWidth(ui
->occurrenceLineEdit
->sizeHint().width());
54 // On Windows, this is necessary to make the popup be the width of the
55 // longest item, instead of the width matching the combobox and using
56 // ellipses. (Linux has the popup wider by default.)
57 ui
->typeComboBox
->view()->setMinimumWidth(ui
->typeComboBox
->sizeHint().width());
58 // This lets the typeComboBox shrink a bit if the width is very small.
59 ui
->typeComboBox
->setMinimumContentsLength(20);
61 ui
->displayComboBox
->addItem(tr("Values"), QVariant(COLUMN_DISPLAY_VALUES
));
62 ui
->displayComboBox
->addItem(tr("Strings"), QVariant(COLUMN_DISPLAY_STRINGS
));
63 ui
->displayComboBox
->addItem(tr("Details"), QVariant(COLUMN_DISPLAY_DETAILS
));
65 connect(ui
->fieldsNameLineEdit
, &DisplayFilterEdit::textChanged
,
66 ui
->fieldsNameLineEdit
, &DisplayFilterEdit::checkCustomColumn
);
67 connect(ui
->fieldsNameLineEdit
, &DisplayFilterEdit::textChanged
,
68 this, &ColumnEditorFrame::checkCanResolve
);
69 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
70 connect(ui
->typeComboBox
, QOverload
<int>::of(&QComboBox::currentIndexChanged
), this,
71 &ColumnEditorFrame::typeChanged
);
73 connect(ui
->typeComboBox
, &QComboBox::currentIndexChanged
, this,
74 &ColumnEditorFrame::typeChanged
);
79 ColumnEditorFrame::~ColumnEditorFrame()
84 bool ColumnEditorFrame::syntaxIsValid(void)
86 // Fields must be a valid filter.
87 // Occurrence must be empty or valid.
88 return ((ui
->fieldsNameLineEdit
->syntaxState() == SyntaxLineEdit::Valid
) &&
89 (ui
->occurrenceLineEdit
->syntaxState() != SyntaxLineEdit::Invalid
));
92 void ColumnEditorFrame::setFields(int index
)
96 if (index
== COL_CUSTOM
) {
97 ui
->fieldsNameLineEdit
->setText(saved_fields_
);
98 ui
->fieldsNameLineEdit
->checkCustomColumn(saved_fields_
);
99 ui
->occurrenceLineEdit
->setText(saved_occurrence_
);
100 ui
->occurrenceLineEdit
->checkInteger(saved_occurrence_
);
101 ok
= syntaxIsValid();
103 ui
->fieldsNameLineEdit
->clear();
104 ui
->fieldsNameLineEdit
->setSyntaxState(SyntaxLineEdit::Empty
);
105 ui
->occurrenceLineEdit
->clear();
106 ui
->occurrenceLineEdit
->setSyntaxState(SyntaxLineEdit::Empty
);
108 ui
->buttonBox
->button(QDialogButtonBox::Ok
)->setEnabled(ok
);
111 void ColumnEditorFrame::typeChanged(int index
)
113 // The fieldsNameLineEdit and occurrenceLineEdit are only relevant if the
114 // typeComboBox is COL_CUSTOM. The text for "Custom" is small. So when
115 // COL_CUSTOM is selected, shrink the size of the typeComboBox to what is
116 // necessary for "Custom" and give extra space to the fieldsNameLineEdit.
117 // For any other column type, do the reverse.
118 if (index
== COL_CUSTOM
) {
119 int width
= fontMetrics().boundingRect(ui
->typeComboBox
->currentText()).width();
120 if (!ui
->typeComboBox
->itemIcon(index
).isNull()) {
121 width
+= ui
->typeComboBox
->iconSize().width() + 4;
123 QStyleOptionComboBox opt
;
124 opt
.initFrom(ui
->typeComboBox
);
125 QSize
sh(width
, ui
->typeComboBox
->height());
126 width
= ui
->typeComboBox
->style()->sizeFromContents(QStyle::CT_ComboBox
, &opt
, sh
, ui
->typeComboBox
).width();
127 ui
->typeComboBox
->setMaximumWidth(width
);
128 ui
->fieldsNameLineEdit
->setMaximumWidth(16777215); // Default (no) maximum
129 ui
->horizontalLayout
->setStretchFactor(ui
->typeComboBox
, 1);
130 ui
->horizontalLayout
->setStretchFactor(ui
->fieldsNameLineEdit
, 4);
132 ui
->typeComboBox
->setMaximumWidth(ui
->typeComboBox
->sizeHint().width());
133 ui
->fieldsNameLineEdit
->setMaximumWidth(ui
->fieldsNameLineEdit
->sizeHint().width());
134 ui
->horizontalLayout
->setStretchFactor(ui
->typeComboBox
, 2);
135 ui
->horizontalLayout
->setStretchFactor(ui
->fieldsNameLineEdit
, 1);
139 void ColumnEditorFrame::editColumn(int column
)
141 cur_column_
= column
;
142 ui
->titleLineEdit
->setText(get_column_title(column
));
143 saved_fields_
= get_column_custom_fields(column
);
144 saved_occurrence_
= QString::number(get_column_custom_occurrence(column
));
145 ui
->typeComboBox
->setCurrentIndex(get_column_format(column
));
146 ui
->displayComboBox
->setCurrentIndex(ui
->displayComboBox
->findData(get_column_display_format(column
)));
147 setFields(ui
->typeComboBox
->currentIndex());
150 void ColumnEditorFrame::showEvent(QShowEvent
*event
)
152 ui
->titleLineEdit
->setFocus();
153 ui
->titleLineEdit
->selectAll();
155 AccordionFrame::showEvent(event
);
158 void ColumnEditorFrame::on_typeComboBox_activated(int index
)
163 void ColumnEditorFrame::on_fieldsNameLineEdit_textEdited(const QString
&fields
)
165 ui
->fieldsNameLineEdit
->checkCustomColumn(fields
);
166 if (ui
->typeComboBox
->currentIndex() != COL_CUSTOM
) {
167 ui
->typeComboBox
->setCurrentIndex(COL_CUSTOM
);
168 ui
->occurrenceLineEdit
->setText(saved_occurrence_
);
171 ui
->buttonBox
->button(QDialogButtonBox::Ok
)->setEnabled(syntaxIsValid());
173 saved_fields_
= fields
;
176 void ColumnEditorFrame::on_occurrenceLineEdit_textEdited(const QString
&occurrence
)
178 ui
->occurrenceLineEdit
->checkInteger(occurrence
);
179 if (ui
->typeComboBox
->currentIndex() != COL_CUSTOM
) {
180 ui
->typeComboBox
->setCurrentIndex(COL_CUSTOM
);
181 ui
->fieldsNameLineEdit
->setText(saved_fields_
);
184 ui
->buttonBox
->button(QDialogButtonBox::Ok
)->setEnabled(syntaxIsValid());
186 saved_occurrence_
= occurrence
;
189 void ColumnEditorFrame::on_buttonBox_rejected()
195 void ColumnEditorFrame::on_buttonBox_accepted()
198 if (cur_column_
>= 0) {
199 col_str
= ui
->titleLineEdit
->text().toUtf8();
200 set_column_title(cur_column_
, col_str
.constData());
201 set_column_format(cur_column_
, ui
->typeComboBox
->currentIndex());
202 if (ui
->typeComboBox
->currentIndex() == COL_CUSTOM
) {
203 col_str
= ui
->fieldsNameLineEdit
->text().toUtf8();
204 set_column_custom_fields(cur_column_
, col_str
.constData());
205 if (!ui
->occurrenceLineEdit
->text().isEmpty()) {
206 set_column_custom_occurrence(cur_column_
, ui
->occurrenceLineEdit
->text().toInt());
208 if (ui
->displayComboBox
->isEnabled()) {
209 set_column_display_format(cur_column_
, ui
->displayComboBox
->itemData(ui
->displayComboBox
->currentIndex()).toInt());
216 on_buttonBox_rejected();
219 void ColumnEditorFrame::keyPressEvent(QKeyEvent
*event
)
221 if (event
->modifiers() == Qt::NoModifier
) {
222 if (event
->key() == Qt::Key_Escape
) {
223 on_buttonBox_rejected();
224 } else if (event
->key() == Qt::Key_Enter
|| event
->key() == Qt::Key_Return
) {
225 if (ui
->buttonBox
->button(QDialogButtonBox::Ok
)->isEnabled()) {
226 on_buttonBox_accepted();
227 } else if (ui
->fieldsNameLineEdit
->syntaxState() == SyntaxLineEdit::Empty
) {
228 mainApp
->pushStatus(MainApplication::FilterSyntax
, tr("Missing fields."));
229 } else if (ui
->fieldsNameLineEdit
->syntaxState() != SyntaxLineEdit::Valid
) {
230 mainApp
->pushStatus(MainApplication::FilterSyntax
, tr("Invalid fields."));
231 } else if (ui
->occurrenceLineEdit
->syntaxState() == SyntaxLineEdit::Invalid
) {
232 mainApp
->pushStatus(MainApplication::FilterSyntax
, tr("Invalid occurrence value."));
237 AccordionFrame::keyPressEvent(event
);
240 void ColumnEditorFrame::checkCanResolve()
242 bool canResolve
= false;
244 if (ui
->fieldsNameLineEdit
->syntaxState() == SyntaxLineEdit::Valid
) {
245 bool displayStrings
= column_prefs_custom_display_strings(ui
->fieldsNameLineEdit
->text().toUtf8().constData());
246 int strings_idx
= ui
->displayComboBox
->findData(COLUMN_DISPLAY_STRINGS
);
248 if (displayStrings
&& strings_idx
== -1) {
249 ui
->displayComboBox
->insertItem(1, "Strings", QVariant(COLUMN_DISPLAY_STRINGS
));
250 } else if (!displayStrings
&& strings_idx
!= -1) {
251 ui
->displayComboBox
->removeItem(strings_idx
);
254 bool displayDetails
= column_prefs_custom_display_details(ui
->fieldsNameLineEdit
->text().toUtf8().constData());
255 int details_idx
= ui
->displayComboBox
->findData(COLUMN_DISPLAY_DETAILS
);
257 if (displayDetails
&& details_idx
== -1) {
258 ui
->displayComboBox
->addItem("Details", QVariant(COLUMN_DISPLAY_DETAILS
));
259 } else if (!displayDetails
&& details_idx
!= -1) {
260 ui
->displayComboBox
->removeItem(details_idx
);
263 canResolve
= displayStrings
|| displayDetails
;
266 ui
->displayLabel
->setEnabled(canResolve
);
267 ui
->displayComboBox
->setEnabled(canResolve
);
269 int idx
= ui
->displayComboBox
->findData(get_column_display_format(cur_column_
));
273 ui
->displayComboBox
->setCurrentIndex(idx
);
275 ui
->displayComboBox
->setCurrentIndex(-1);