1 /* column_preferences_frame.cpp
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/column-info.h>
31 #include <epan/column.h>
32 #include <epan/prefs.h>
33 #include <epan/proto.h>
35 #include <ui/preference_utils.h>
37 #include "column_preferences_frame.h"
38 #include "ui_column_preferences_frame.h"
39 #include "syntax_line_edit.h"
40 #include "wireshark_application.h"
42 #include <QTreeWidgetItemIterator>
46 const int visible_col_
= 0;
47 const int title_col_
= 1;
48 const int type_col_
= 2;
49 const int custom_field_col_
= 3;
50 const int custom_occurrence_col_
= 4;
52 ColumnPreferencesFrame::ColumnPreferencesFrame(QWidget
*parent
) :
54 ui(new Ui::ColumnPreferencesFrame
),
60 int one_em
= ui
->columnTreeWidget
->fontMetrics().height();
61 ui
->columnTreeWidget
->setColumnWidth(custom_field_col_
, one_em
* 10);
62 ui
->columnTreeWidget
->setColumnWidth(custom_occurrence_col_
, one_em
* 5);
64 ui
->columnTreeWidget
->setMinimumWidth(one_em
* 20);
65 ui
->columnTreeWidget
->setMinimumHeight(one_em
* 12);
67 ui
->columnTreeWidget
->setSelectionMode(QAbstractItemView::SingleSelection
);
68 ui
->columnTreeWidget
->setDragEnabled(true);
69 ui
->columnTreeWidget
->viewport()->setAcceptDrops(true);
70 ui
->columnTreeWidget
->setDropIndicatorShown(true);
71 ui
->columnTreeWidget
->setDragDropMode(QAbstractItemView::InternalMove
);
76 ColumnPreferencesFrame::~ColumnPreferencesFrame()
81 void ColumnPreferencesFrame::unstash()
83 GList
*new_col_list
= NULL
;
86 QTreeWidgetItemIterator
it(ui
->columnTreeWidget
);
88 fmt_data
*cfmt
= g_new0(fmt_data
, 1);
89 cfmt
->visible
= (*it
)->checkState(visible_col_
) == Qt::Checked
? TRUE
: FALSE
;
90 cfmt
->title
= g_strdup((*it
)->text(title_col_
).toUtf8().constData());
91 cfmt
->fmt
= (*it
)->data(type_col_
, Qt::UserRole
).value
<int>();
92 if (cfmt
->fmt
== COL_CUSTOM
) {
94 int occurrence
= (*it
)->text(custom_occurrence_col_
).toInt(&ok
);
95 cfmt
->custom_field
= g_strdup((*it
)->text(custom_field_col_
).toUtf8().constData());
96 cfmt
->custom_occurrence
= ok
? occurrence
: 0;
99 if (prefs
.col_list
== NULL
) {
102 fmt_data
*old_cfmt
= (fmt_data
*) prefs
.col_list
->data
;
104 g_strcmp0(old_cfmt
->title
, cfmt
->title
) != 0 ||
105 old_cfmt
->fmt
!= cfmt
->fmt
||
106 old_cfmt
->visible
!= cfmt
->visible
||
107 (old_cfmt
->fmt
== COL_CUSTOM
&& (
108 g_strcmp0(old_cfmt
->custom_field
, cfmt
->custom_field
) != 0 ||
109 old_cfmt
->custom_occurrence
!= cfmt
->custom_occurrence
))) {
112 column_prefs_remove_link(prefs
.col_list
);
115 new_col_list
= g_list_append(new_col_list
, cfmt
);
119 while (prefs
.col_list
) {
121 column_prefs_remove_link(prefs
.col_list
);
123 prefs
.col_list
= new_col_list
;
126 wsApp
->emitAppSignal(WiresharkApplication::ColumnsChanged
);
130 void ColumnPreferencesFrame::keyPressEvent(QKeyEvent
*evt
)
132 if (cur_line_edit_
&& cur_line_edit_
->hasFocus()) {
133 int new_idx
= COL_CUSTOM
;
134 switch (evt
->key()) {
136 cur_line_edit_
->setText(saved_col_string_
);
137 new_idx
= saved_combo_idx_
;
140 switch (cur_column_
) {
142 columnTitleEditingFinished();
144 case custom_field_col_
:
145 customFieldEditingFinished();
146 columnTypeCurrentIndexChanged(new_idx
);
148 case custom_occurrence_col_
:
149 customOccurrenceEditingFinished();
150 columnTypeCurrentIndexChanged(new_idx
);
156 delete cur_line_edit_
;
161 } else if (cur_combo_box_
&& cur_combo_box_
->hasFocus()) {
162 switch (evt
->key()) {
164 cur_combo_box_
->setCurrentIndex(saved_combo_idx_
);
167 // XXX The combo box eats enter and return
168 columnTypeCurrentIndexChanged(cur_combo_box_
->currentIndex());
169 delete cur_combo_box_
;
175 QFrame::keyPressEvent(evt
);
178 void ColumnPreferencesFrame::addColumn(bool visible
, const char *title
, int fmt
, const char *custom_field
, int custom_occurrence
)
180 QTreeWidgetItem
*item
= new QTreeWidgetItem(ui
->columnTreeWidget
);
182 item
->setFlags(item
->flags() | Qt::ItemIsUserCheckable
);
183 item
->setFlags(item
->flags() & ~(Qt::ItemIsDropEnabled
));
184 item
->setCheckState(visible_col_
, visible
? Qt::Checked
: Qt::Unchecked
);
185 item
->setText(title_col_
, title
);
186 item
->setText(type_col_
, col_format_desc(fmt
));
187 item
->setData(type_col_
, Qt::UserRole
, QVariant(fmt
));
188 if (fmt
== COL_CUSTOM
) {
189 item
->setText(custom_field_col_
, custom_field
);
190 item
->setText(custom_occurrence_col_
, QString::number(custom_occurrence
));
194 void ColumnPreferencesFrame::updateWidgets()
196 ui
->columnTreeWidget
->clear();
198 for (GList
*cur
= g_list_first(prefs
.col_list
); cur
!= NULL
&& cur
->data
!= NULL
; cur
= cur
->next
) {
199 fmt_data
*cfmt
= (fmt_data
*) cur
->data
;
200 addColumn(cfmt
->visible
, cfmt
->title
, cfmt
->fmt
, cfmt
->custom_field
, cfmt
->custom_occurrence
);
203 ui
->columnTreeWidget
->resizeColumnToContents(visible_col_
);
204 ui
->columnTreeWidget
->resizeColumnToContents(title_col_
);
205 ui
->columnTreeWidget
->resizeColumnToContents(type_col_
);
209 void ColumnPreferencesFrame::on_columnTreeWidget_currentItemChanged(QTreeWidgetItem
*current
, QTreeWidgetItem
*previous
)
211 ui
->deleteToolButton
->setEnabled(current
? true : false);
213 if (previous
&& ui
->columnTreeWidget
->itemWidget(previous
, title_col_
)) {
214 ui
->columnTreeWidget
->removeItemWidget(previous
, title_col_
);
216 if (previous
&& ui
->columnTreeWidget
->itemWidget(previous
, type_col_
)) {
217 ui
->columnTreeWidget
->removeItemWidget(previous
, type_col_
);
218 previous
->setText(type_col_
, col_format_desc(previous
->data(type_col_
, Qt::UserRole
).toInt()));
220 if (previous
&& ui
->columnTreeWidget
->itemWidget(previous
, custom_field_col_
)) {
221 ui
->columnTreeWidget
->removeItemWidget(previous
, custom_field_col_
);
223 if (previous
&& ui
->columnTreeWidget
->itemWidget(previous
, custom_occurrence_col_
)) {
224 ui
->columnTreeWidget
->removeItemWidget(previous
, custom_occurrence_col_
);
228 void ColumnPreferencesFrame::on_columnTreeWidget_itemActivated(QTreeWidgetItem
*item
, int column
)
230 if (!item
|| cur_line_edit_
|| cur_combo_box_
) return;
232 QWidget
*editor
= NULL
;
233 cur_column_
= column
;
234 saved_combo_idx_
= item
->data(type_col_
, Qt::UserRole
).toInt();
239 cur_line_edit_
= new QLineEdit();
240 cur_column_
= column
;
241 saved_col_string_
= item
->text(title_col_
);
242 connect(cur_line_edit_
, SIGNAL(editingFinished()), this, SLOT(columnTitleEditingFinished()));
243 editor
= cur_line_edit_
;
248 cur_combo_box_
= new QComboBox();
249 for (int i
= 0; i
< NUM_COL_FMTS
; i
++) {
250 cur_combo_box_
->addItem(col_format_desc(i
), QVariant(i
));
251 if (i
== saved_combo_idx_
) {
252 cur_combo_box_
->setCurrentIndex(i
);
255 connect(cur_combo_box_
, SIGNAL(currentIndexChanged(int)), this, SLOT(columnTypeCurrentIndexChanged(int)));
256 editor
= cur_combo_box_
;
259 case custom_field_col_
:
261 SyntaxLineEdit
*syntax_edit
= new SyntaxLineEdit();
262 saved_col_string_
= item
->text(custom_field_col_
);
263 connect(syntax_edit
, SIGNAL(textChanged(QString
)),
264 this, SLOT(customFieldTextChanged(QString
)));
265 connect(syntax_edit
, SIGNAL(editingFinished()), this, SLOT(customFieldEditingFinished()));
266 editor
= cur_line_edit_
= syntax_edit
;
268 saved_combo_idx_
= item
->data(type_col_
, Qt::UserRole
).toInt();
269 item
->setText(type_col_
, col_format_desc(COL_CUSTOM
));
270 item
->setData(type_col_
, Qt::UserRole
, QVariant(COL_CUSTOM
));
273 case custom_occurrence_col_
:
275 SyntaxLineEdit
*syntax_edit
= new SyntaxLineEdit();
276 saved_col_string_
= item
->text(custom_occurrence_col_
);
277 connect(syntax_edit
, SIGNAL(textChanged(QString
)),
278 this, SLOT(customOccurrenceTextChanged(QString
)));
279 connect(syntax_edit
, SIGNAL(editingFinished()), this, SLOT(customOccurrenceEditingFinished()));
280 editor
= cur_line_edit_
= syntax_edit
;
282 saved_combo_idx_
= item
->data(type_col_
, Qt::UserRole
).toInt();
283 item
->setText(type_col_
, col_format_desc(COL_CUSTOM
));
284 item
->setData(type_col_
, Qt::UserRole
, QVariant(COL_CUSTOM
));
291 if (cur_line_edit_
) {
292 cur_line_edit_
->setText(saved_col_string_
);
293 cur_line_edit_
->selectAll();
294 connect(cur_line_edit_
, SIGNAL(destroyed()), this, SLOT(lineEditDestroyed()));
296 if (cur_combo_box_
) {
297 connect(cur_combo_box_
, SIGNAL(destroyed()), this, SLOT(comboDestroyed()));
300 QFrame
*edit_frame
= new QFrame();
301 QHBoxLayout
*hb
= new QHBoxLayout();
302 QSpacerItem
*spacer
= new QSpacerItem(5, 10);
304 hb
->addWidget(editor
, 0);
305 hb
->addSpacerItem(spacer
);
306 hb
->setStretch(1, 1);
307 hb
->setContentsMargins(0, 0, 0, 0);
309 edit_frame
->setLineWidth(0);
310 edit_frame
->setFrameStyle(QFrame::NoFrame
);
311 // The documentation suggests setting autoFillbackground. That looks silly
312 // so we clear the item text instead.
313 item
->setText(cur_column_
, "");
314 edit_frame
->setLayout(hb
);
315 ui
->columnTreeWidget
->setItemWidget(item
, cur_column_
, edit_frame
);
320 void ColumnPreferencesFrame::lineEditDestroyed()
322 cur_line_edit_
= NULL
;
325 void ColumnPreferencesFrame::comboDestroyed()
327 cur_combo_box_
= NULL
;
330 void ColumnPreferencesFrame::columnTitleEditingFinished()
332 QTreeWidgetItem
*item
= ui
->columnTreeWidget
->currentItem();
333 if (!cur_line_edit_
|| !item
) return;
335 item
->setText(title_col_
, cur_line_edit_
->text());
336 ui
->columnTreeWidget
->removeItemWidget(item
, title_col_
);
339 void ColumnPreferencesFrame::columnTypeCurrentIndexChanged(int index
)
341 QTreeWidgetItem
*item
= ui
->columnTreeWidget
->currentItem();
342 if (!item
|| index
< 0) return;
344 item
->setData(type_col_
, Qt::UserRole
, QVariant(index
));
345 item
->setText(type_col_
, col_format_desc(index
));
347 if (index
!= COL_CUSTOM
) {
348 item
->setText(custom_field_col_
, "");
349 item
->setText(custom_occurrence_col_
, "");
353 void ColumnPreferencesFrame::customFieldTextChanged(QString
)
355 SyntaxLineEdit
*syntax_edit
= qobject_cast
<SyntaxLineEdit
*>(cur_line_edit_
);
356 QTreeWidgetItem
*item
= ui
->columnTreeWidget
->currentItem();
357 if (!syntax_edit
|| !item
) return;
359 dfilter_t
*dfp
= NULL
;
360 const char *field_text
= syntax_edit
->text().toUtf8().constData();
361 if (strlen(field_text
) < 1) {
362 syntax_edit
->setSyntaxState(SyntaxLineEdit::Empty
);
363 } else if (!dfilter_compile(field_text
, &dfp
)) {
364 syntax_edit
->setSyntaxState(SyntaxLineEdit::Invalid
);
366 syntax_edit
->setSyntaxState(SyntaxLineEdit::Valid
);
371 void ColumnPreferencesFrame::customFieldEditingFinished()
373 QTreeWidgetItem
*item
= ui
->columnTreeWidget
->currentItem();
374 if (!cur_line_edit_
|| !item
) return;
376 item
->setText(custom_field_col_
, cur_line_edit_
->text());
377 ui
->columnTreeWidget
->removeItemWidget(item
, custom_field_col_
);
380 void ColumnPreferencesFrame::customOccurrenceTextChanged(QString
)
382 SyntaxLineEdit
*syntax_edit
= qobject_cast
<SyntaxLineEdit
*>(cur_line_edit_
);
383 QTreeWidgetItem
*item
= ui
->columnTreeWidget
->currentItem();
384 if (!syntax_edit
|| !item
) return;
386 if (syntax_edit
->text().isEmpty()) {
387 syntax_edit
->setSyntaxState(SyntaxLineEdit::Empty
);
390 syntax_edit
->text().toInt(&ok
);
392 syntax_edit
->setSyntaxState(SyntaxLineEdit::Valid
);
394 syntax_edit
->setSyntaxState(SyntaxLineEdit::Invalid
);
399 void ColumnPreferencesFrame::customOccurrenceEditingFinished()
401 QTreeWidgetItem
*item
= ui
->columnTreeWidget
->currentItem();
402 if (!cur_line_edit_
|| !item
) return;
404 item
->setText(custom_occurrence_col_
, cur_line_edit_
->text());
405 ui
->columnTreeWidget
->removeItemWidget(item
, custom_occurrence_col_
);
408 void ColumnPreferencesFrame::on_newToolButton_clicked()
410 addColumn(true, "New Column", COL_NUMBER
, NULL
, 0); //TODO : Fix Translate
413 void ColumnPreferencesFrame::on_deleteToolButton_clicked()
415 QTreeWidgetItem
*item
= ui
->columnTreeWidget
->currentItem();
417 ui
->columnTreeWidget
->invisibleRootItem()->removeChild(item
);
427 * indent-tabs-mode: nil
430 * ex: set shiftwidth=4 tabstop=8 expandtab:
431 * :indentSize=4:tabSize=8:noTabs=true: