diff options
author | Gerald Combs <gerald@wireshark.org> | 2013-01-23 19:04:36 +0000 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2013-01-23 19:04:36 +0000 |
commit | 21e66f0c6f38d20dc4ac3968324fff0959113b14 (patch) | |
tree | e801135c51e407d67516e1969c1ef788af48292e /ui/qt/column_preferences_frame.cpp | |
parent | d59e9cf574976b1e9849f5c35be1fd2abdf8ed6d (diff) | |
download | wireshark-21e66f0c6f38d20dc4ac3968324fff0959113b14.tar.gz |
Add column preferences.
svn path=/trunk/; revision=47231
Diffstat (limited to 'ui/qt/column_preferences_frame.cpp')
-rw-r--r-- | ui/qt/column_preferences_frame.cpp | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/ui/qt/column_preferences_frame.cpp b/ui/qt/column_preferences_frame.cpp new file mode 100644 index 0000000000..ebfdbdce30 --- /dev/null +++ b/ui/qt/column_preferences_frame.cpp @@ -0,0 +1,440 @@ +/* column_preferences_frame.cpp + * + * $Id$ + * + * 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 "config.h" + +#include <glib.h> + +#include "color.h" +#include "packet-range.h" + +#include <epan/column_info.h> +#include <epan/column.h> +#include <epan/prefs.h> +#include <epan/proto.h> + +#include <ui/preference_utils.h> + +#include "column_preferences_frame.h" +#include "ui_column_preferences_frame.h" +#include "syntax_line_edit.h" +#include "wireshark_application.h" + +#include <QTreeWidgetItemIterator> +#include <QLineEdit> +#include <QKeyEvent> + +#include <QDebug> + +const int visible_col_ = 0; +const int title_col_ = 1; +const int type_col_ = 2; +const int custom_field_col_ = 3; +const int custom_occurrence_col_ = 4; + +ColumnPreferencesFrame::ColumnPreferencesFrame(QWidget *parent) : + QFrame(parent), + ui(new Ui::ColumnPreferencesFrame), + cur_line_edit_(NULL), + cur_combo_box_(NULL) +{ + ui->setupUi(this); + + int one_em = ui->columnTreeWidget->fontMetrics().height(); + ui->columnTreeWidget->setColumnWidth(3, one_em * 10); + ui->columnTreeWidget->setColumnWidth(4, one_em * 5); + + ui->columnTreeWidget->setMinimumWidth(one_em * 20); + ui->columnTreeWidget->setMinimumHeight(one_em * 12); + + ui->columnTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection); + ui->columnTreeWidget->setDragEnabled(true); + ui->columnTreeWidget->viewport()->setAcceptDrops(true); + ui->columnTreeWidget->setDropIndicatorShown(true); + ui->columnTreeWidget->setDragDropMode(QAbstractItemView::InternalMove); + + updateWidgets(); +} + +ColumnPreferencesFrame::~ColumnPreferencesFrame() +{ + delete ui; +} + +void ColumnPreferencesFrame::unstash() +{ + GList *new_col_list = NULL; + bool changed = false; + + QTreeWidgetItemIterator it(ui->columnTreeWidget); + while (*it) { + fmt_data *cfmt = g_new0(fmt_data, 1); + cfmt->visible = (*it)->checkState(visible_col_) == Qt::Checked ? TRUE : FALSE; + cfmt->title = g_strdup((*it)->text(title_col_).toUtf8().constData()); + cfmt->fmt = (*it)->data(type_col_, Qt::UserRole).value<int>(); + if (cfmt->fmt == COL_CUSTOM) { + bool ok; + int occurrence = (*it)->text(custom_occurrence_col_).toInt(&ok); + cfmt->custom_field = g_strdup((*it)->text(custom_field_col_).toUtf8().constData()); + cfmt->custom_occurrence = ok ? occurrence : 0; + } + + if (prefs.col_list == NULL) { + changed = true; + } else { + fmt_data *old_cfmt = (fmt_data *) prefs.col_list->data; + if (!old_cfmt || + g_strcmp0(old_cfmt->title, cfmt->title) != 0 || + old_cfmt->fmt != cfmt->fmt || + old_cfmt->visible != cfmt->visible || + (old_cfmt->fmt == COL_CUSTOM && ( + g_strcmp0(old_cfmt->custom_field, cfmt->custom_field) != 0 || + old_cfmt->custom_occurrence != cfmt->custom_occurrence))) { + changed = true; + } + column_prefs_remove_link(prefs.col_list); + } + + new_col_list = g_list_append(new_col_list, cfmt); + ++it; + } + + while (prefs.col_list) { + changed = true; + column_prefs_remove_link(prefs.col_list); + } + prefs.col_list = new_col_list; + + if (changed) { + wsApp->emitAppSignal(WiresharkApplication::ColumnsChanged); + } +} + +void ColumnPreferencesFrame::showEvent(QShowEvent *evt) +{ + Q_UNUSED(evt); +} + +void ColumnPreferencesFrame::keyPressEvent(QKeyEvent *evt) +{ + if (cur_line_edit_ && cur_line_edit_->hasFocus()) { + int new_idx = COL_CUSTOM; + switch (evt->key()) { + case Qt::Key_Escape: + cur_line_edit_->setText(saved_col_string_); + new_idx = saved_combo_idx_; + case Qt::Key_Enter: + case Qt::Key_Return: + switch (cur_column_) { + case title_col_: + columnTitleEditingFinished(); + break; + case custom_field_col_: + customFieldEditingFinished(); + columnTypeCurrentIndexChanged(new_idx); + break; + case custom_occurrence_col_: + customOccurrenceEditingFinished(); + columnTypeCurrentIndexChanged(new_idx); + break; + default: + break; + } + + delete cur_line_edit_; + return; + default: + break; + } + } else if (cur_combo_box_ && cur_combo_box_->hasFocus()) { + switch (evt->key()) { + case Qt::Key_Escape: + cur_combo_box_->setCurrentIndex(saved_combo_idx_); + case Qt::Key_Enter: + case Qt::Key_Return: + // XXX The combo box eats enter and return + columnTypeCurrentIndexChanged(cur_combo_box_->currentIndex()); + delete cur_combo_box_; + return; + default: + break; + } + } + QFrame::keyPressEvent(evt); +} + +void ColumnPreferencesFrame::addColumn(bool visible, const char *title, int fmt, const char *custom_field, int custom_occurrence) +{ + QTreeWidgetItem *item = new QTreeWidgetItem(ui->columnTreeWidget); + + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + item->setFlags(item->flags() & ~(Qt::ItemIsDropEnabled)); + item->setCheckState(visible_col_, visible ? Qt::Checked : Qt::Unchecked); + item->setText(title_col_, title); + item->setText(type_col_, col_format_desc(fmt)); + item->setData(type_col_, Qt::UserRole, QVariant(fmt)); + if (fmt == COL_CUSTOM) { + item->setText(custom_field_col_, custom_field); + item->setText(custom_occurrence_col_, QString::number(custom_occurrence)); + } +} + +void ColumnPreferencesFrame::updateWidgets() +{ + ui->columnTreeWidget->clear(); + + for (GList *cur = g_list_first(prefs.col_list); cur != NULL && cur->data != NULL; cur = cur->next) { + fmt_data *cfmt = (fmt_data *) cur->data; + addColumn(cfmt->visible, cfmt->title, cfmt->fmt, cfmt->custom_field, cfmt->custom_occurrence); + } + + ui->columnTreeWidget->resizeColumnToContents(visible_col_); + ui->columnTreeWidget->resizeColumnToContents(title_col_); + ui->columnTreeWidget->resizeColumnToContents(type_col_); +} + + +void ColumnPreferencesFrame::on_columnTreeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) +{ + ui->deleteToolButton->setEnabled(current ? true : false); + + if (previous && ui->columnTreeWidget->itemWidget(previous, title_col_)) { + ui->columnTreeWidget->removeItemWidget(previous, title_col_); + } + if (previous && ui->columnTreeWidget->itemWidget(previous, type_col_)) { + ui->columnTreeWidget->removeItemWidget(previous, type_col_); + previous->setText(type_col_, col_format_desc(previous->data(type_col_, Qt::UserRole).toInt())); + } + if (previous && ui->columnTreeWidget->itemWidget(previous, custom_field_col_)) { + ui->columnTreeWidget->removeItemWidget(previous, custom_field_col_); + } + if (previous && ui->columnTreeWidget->itemWidget(previous, custom_occurrence_col_)) { + ui->columnTreeWidget->removeItemWidget(previous, custom_occurrence_col_); + } +} + +void ColumnPreferencesFrame::on_columnTreeWidget_itemActivated(QTreeWidgetItem *item, int column) +{ + if (!item || cur_line_edit_ || cur_combo_box_) return; + + QWidget *editor = NULL; + cur_column_ = column; + saved_combo_idx_ = item->data(type_col_, Qt::UserRole).toInt(); + + switch (column) { + case title_col_: + { + cur_line_edit_ = new QLineEdit(); + cur_column_ = column; + saved_col_string_ = item->text(title_col_); + connect(cur_line_edit_, SIGNAL(editingFinished()), this, SLOT(columnTitleEditingFinished())); + editor = cur_line_edit_; + break; + } + case type_col_: + { + cur_combo_box_ = new QComboBox(); + for (int i = 0; i < NUM_COL_FMTS; i++) { + cur_combo_box_->addItem(col_format_desc(i), QVariant(i)); + if (i == saved_combo_idx_) { + cur_combo_box_->setCurrentIndex(i); + } + } + connect(cur_combo_box_, SIGNAL(currentIndexChanged(int)), this, SLOT(columnTypeCurrentIndexChanged(int))); + editor = cur_combo_box_; + break; + } + case custom_field_col_: + { + SyntaxLineEdit *syntax_edit = new SyntaxLineEdit(); + saved_col_string_ = item->text(custom_field_col_); + connect(syntax_edit, SIGNAL(textChanged(QString)), + this, SLOT(customFieldTextChanged(QString))); + connect(syntax_edit, SIGNAL(editingFinished()), this, SLOT(customFieldEditingFinished())); + editor = cur_line_edit_ = syntax_edit; + + saved_combo_idx_ = item->data(type_col_, Qt::UserRole).toInt(); + item->setText(type_col_, col_format_desc(COL_CUSTOM)); + item->setData(type_col_, Qt::UserRole, QVariant(COL_CUSTOM)); + break; + } + case custom_occurrence_col_: + { + SyntaxLineEdit *syntax_edit = new SyntaxLineEdit(); + saved_col_string_ = item->text(custom_occurrence_col_); + connect(syntax_edit, SIGNAL(textChanged(QString)), + this, SLOT(customOccurrenceTextChanged(QString))); + connect(syntax_edit, SIGNAL(editingFinished()), this, SLOT(customOccurrenceEditingFinished())); + editor = cur_line_edit_ = syntax_edit; + + saved_combo_idx_ = item->data(type_col_, Qt::UserRole).toInt(); + item->setText(type_col_, col_format_desc(COL_CUSTOM)); + item->setData(type_col_, Qt::UserRole, QVariant(COL_CUSTOM)); + break; + } + default: + return; + } + + if (cur_line_edit_) { + cur_line_edit_->setText(saved_col_string_); + cur_line_edit_->selectAll(); + connect(cur_line_edit_, SIGNAL(destroyed()), this, SLOT(lineEditDestroyed())); + } + if (cur_combo_box_) { + connect(cur_combo_box_, SIGNAL(destroyed()), this, SLOT(comboDestroyed())); + } + if (editor) { + QFrame *edit_frame = new QFrame(); + QHBoxLayout *hb = new QHBoxLayout(); + QSpacerItem *spacer = new QSpacerItem(5, 10); + + hb->addWidget(editor, 0); + hb->addSpacerItem(spacer); + hb->setStretch(1, 1); + hb->setContentsMargins(0, 0, 0, 0); + + edit_frame->setLineWidth(0); + edit_frame->setFrameStyle(QFrame::NoFrame); + // The documentation suggests setting autoFillbackground. That looks silly + // so we clear the item text instead. + item->setText(cur_column_, ""); + edit_frame->setLayout(hb); + ui->columnTreeWidget->setItemWidget(item, cur_column_, edit_frame); + editor->setFocus(); + } +} + +void ColumnPreferencesFrame::lineEditDestroyed() +{ + cur_line_edit_ = NULL; +} + +void ColumnPreferencesFrame::comboDestroyed() +{ + cur_combo_box_ = NULL; +} + +void ColumnPreferencesFrame::columnTitleEditingFinished() +{ + QTreeWidgetItem *item = ui->columnTreeWidget->currentItem(); + if (!cur_line_edit_ || !item) return; + + item->setText(title_col_, cur_line_edit_->text()); + ui->columnTreeWidget->removeItemWidget(item, title_col_); +} + +void ColumnPreferencesFrame::columnTypeCurrentIndexChanged(int index) +{ + QTreeWidgetItem *item = ui->columnTreeWidget->currentItem(); + if (!item || index < 0) return; + + item->setData(type_col_, Qt::UserRole, QVariant(index)); + item->setText(type_col_, col_format_desc(index)); + + if (index != COL_CUSTOM) { + item->setText(custom_field_col_, ""); + item->setText(custom_occurrence_col_, ""); + } +} + +void ColumnPreferencesFrame::customFieldTextChanged(QString) +{ + SyntaxLineEdit *syntax_edit = qobject_cast<SyntaxLineEdit *>(cur_line_edit_); + QTreeWidgetItem *item = ui->columnTreeWidget->currentItem(); + if (!syntax_edit || !item) return; + + dfilter_t *dfp = NULL; + const char *field_text = syntax_edit->text().toUtf8().constData(); + if (strlen(field_text) < 1) { + syntax_edit->setSyntaxState(SyntaxLineEdit::Empty); + } else if (proto_check_field_name(field_text) != 0 || !dfilter_compile(field_text, &dfp)) { + syntax_edit->setSyntaxState(SyntaxLineEdit::Invalid); + } else { + syntax_edit->setSyntaxState(SyntaxLineEdit::Valid); + } + dfilter_free(dfp); +} + +void ColumnPreferencesFrame::customFieldEditingFinished() +{ + QTreeWidgetItem *item = ui->columnTreeWidget->currentItem(); + if (!cur_line_edit_ || !item) return; + + item->setText(custom_field_col_, cur_line_edit_->text()); + ui->columnTreeWidget->removeItemWidget(item, custom_field_col_); +} + +void ColumnPreferencesFrame::customOccurrenceTextChanged(QString) +{ + SyntaxLineEdit *syntax_edit = qobject_cast<SyntaxLineEdit *>(cur_line_edit_); + QTreeWidgetItem *item = ui->columnTreeWidget->currentItem(); + if (!syntax_edit || !item) return; + + if (syntax_edit->text().isEmpty()) { + syntax_edit->setSyntaxState(SyntaxLineEdit::Empty); + } else { + bool ok; + syntax_edit->text().toInt(&ok); + if (ok) { + syntax_edit->setSyntaxState(SyntaxLineEdit::Valid); + } else { + syntax_edit->setSyntaxState(SyntaxLineEdit::Invalid); + } + } +} + +void ColumnPreferencesFrame::customOccurrenceEditingFinished() +{ + QTreeWidgetItem *item = ui->columnTreeWidget->currentItem(); + if (!cur_line_edit_ || !item) return; + + item->setText(custom_occurrence_col_, cur_line_edit_->text()); + ui->columnTreeWidget->removeItemWidget(item, custom_occurrence_col_); +} + +void ColumnPreferencesFrame::on_newToolButton_clicked() +{ + addColumn(true, "New Column", COL_NUMBER, NULL, 0); +} + +void ColumnPreferencesFrame::on_deleteToolButton_clicked() +{ + QTreeWidgetItem *item = ui->columnTreeWidget->currentItem(); + if (item) { + ui->columnTreeWidget->invisibleRootItem()->removeChild(item); + } +} + +/* + * 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: + */ |