HACK: 1. try to match RowsetProperties
[wireshark-wip.git] / ui / qt / column_preferences_frame.cpp
blobb1f803adc80149c8d7cd5cf9cba280f6a859fc58
1 /* column_preferences_frame.cpp
3 * $Id$
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.
24 #include "config.h"
26 #include <glib.h>
28 #include "color.h"
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>
43 #include <QLineEdit>
44 #include <QKeyEvent>
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) :
53 QFrame(parent),
54 ui(new Ui::ColumnPreferencesFrame),
55 cur_line_edit_(NULL),
56 cur_combo_box_(NULL)
58 ui->setupUi(this);
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);
73 updateWidgets();
76 ColumnPreferencesFrame::~ColumnPreferencesFrame()
78 delete ui;
81 void ColumnPreferencesFrame::unstash()
83 GList *new_col_list = NULL;
84 bool changed = false;
86 QTreeWidgetItemIterator it(ui->columnTreeWidget);
87 while (*it) {
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) {
93 bool ok;
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) {
100 changed = true;
101 } else {
102 fmt_data *old_cfmt = (fmt_data *) prefs.col_list->data;
103 if (!old_cfmt ||
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))) {
110 changed = true;
112 column_prefs_remove_link(prefs.col_list);
115 new_col_list = g_list_append(new_col_list, cfmt);
116 ++it;
119 while (prefs.col_list) {
120 changed = true;
121 column_prefs_remove_link(prefs.col_list);
123 prefs.col_list = new_col_list;
125 if (changed) {
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()) {
135 case Qt::Key_Escape:
136 cur_line_edit_->setText(saved_col_string_);
137 new_idx = saved_combo_idx_;
138 case Qt::Key_Enter:
139 case Qt::Key_Return:
140 switch (cur_column_) {
141 case title_col_:
142 columnTitleEditingFinished();
143 break;
144 case custom_field_col_:
145 customFieldEditingFinished();
146 columnTypeCurrentIndexChanged(new_idx);
147 break;
148 case custom_occurrence_col_:
149 customOccurrenceEditingFinished();
150 columnTypeCurrentIndexChanged(new_idx);
151 break;
152 default:
153 break;
156 delete cur_line_edit_;
157 return;
158 default:
159 break;
161 } else if (cur_combo_box_ && cur_combo_box_->hasFocus()) {
162 switch (evt->key()) {
163 case Qt::Key_Escape:
164 cur_combo_box_->setCurrentIndex(saved_combo_idx_);
165 case Qt::Key_Enter:
166 case Qt::Key_Return:
167 // XXX The combo box eats enter and return
168 columnTypeCurrentIndexChanged(cur_combo_box_->currentIndex());
169 delete cur_combo_box_;
170 return;
171 default:
172 break;
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();
236 switch (column) {
237 case title_col_:
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_;
244 break;
246 case type_col_:
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_;
257 break;
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));
271 break;
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));
285 break;
287 default:
288 return;
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()));
299 if (editor) {
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);
316 editor->setFocus();
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);
365 } else {
366 syntax_edit->setSyntaxState(SyntaxLineEdit::Valid);
368 dfilter_free(dfp);
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);
388 } else {
389 bool ok;
390 syntax_edit->text().toInt(&ok);
391 if (ok) {
392 syntax_edit->setSyntaxState(SyntaxLineEdit::Valid);
393 } else {
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();
416 if (item) {
417 ui->columnTreeWidget->invisibleRootItem()->removeChild(item);
422 * Editor modelines
424 * Local Variables:
425 * c-basic-offset: 4
426 * tab-width: 8
427 * indent-tabs-mode: nil
428 * End:
430 * ex: set shiftwidth=4 tabstop=8 expandtab:
431 * :indentSize=4:tabSize=8:noTabs=true: