wireshark/ui/qt/filter_expressions_preferen...

314 lines
9.9 KiB
C++

/* filter_expressions_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 <epan/filter_expressions.h>
#include "filter_expressions_preferences_frame.h"
#include "ui_filter_expressions_preferences_frame.h"
#include "syntax_line_edit.h"
#include "wireshark_application.h"
#include <qt_ui_utils.h>
#include <QKeyEvent>
#include <QTreeWidgetItemIterator>
const int enabled_col_ = 0;
const int label_col_ = 1;
const int expression_col_ = 2;
// This shouldn't exist in its current form. Instead it should be the "display filters"
// dialog, and the "dfilters" file should support a "show in toolbar" flag.
FilterExpressionsPreferencesFrame::FilterExpressionsPreferencesFrame(QWidget *parent) :
QFrame(parent),
ui(new Ui::FilterExpressionsPreferencesFrame),
cur_line_edit_(NULL)
{
ui->setupUi(this);
int one_em = ui->expressionTreeWidget->fontMetrics().height();
ui->expressionTreeWidget->resizeColumnToContents(enabled_col_);
ui->expressionTreeWidget->setColumnWidth(label_col_, one_em * 10);
ui->expressionTreeWidget->setColumnWidth(expression_col_, one_em * 5);
ui->expressionTreeWidget->setMinimumWidth(one_em * 15);
ui->expressionTreeWidget->setMinimumHeight(one_em * 10);
ui->expressionTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
ui->expressionTreeWidget->setDragEnabled(true);
ui->expressionTreeWidget->viewport()->setAcceptDrops(true);
ui->expressionTreeWidget->setDropIndicatorShown(true);
ui->expressionTreeWidget->setDragDropMode(QAbstractItemView::InternalMove);
updateWidgets();
connect(wsApp, SIGNAL(filterExpressionsChanged()), this, SLOT(updateWidgets()));
}
FilterExpressionsPreferencesFrame::~FilterExpressionsPreferencesFrame()
{
delete ui;
}
void FilterExpressionsPreferencesFrame::unstash()
{
struct filter_expression *cur_fe = *pfilter_expression_head, *new_fe_head = NULL, *new_fe = NULL;
bool changed = false;
QTreeWidgetItemIterator it(ui->expressionTreeWidget);
while (*it) {
struct filter_expression *fe = g_new0(struct filter_expression, 1);
if (!new_fe_head) {
new_fe_head = fe;
} else {
new_fe->next = fe;
}
new_fe = fe;
new_fe->enabled = (*it)->checkState(enabled_col_) == Qt::Checked ? TRUE : FALSE;
new_fe->label = qstring_strdup((*it)->text(label_col_));
new_fe->expression = qstring_strdup((*it)->text(expression_col_));
if (cur_fe == NULL) {
changed = true;
} else {
if (cur_fe->enabled != new_fe->enabled ||
g_strcmp0(cur_fe->label, new_fe->label) != 0 ||
g_strcmp0(cur_fe->expression, new_fe->expression) != 0) {
changed = true;
}
cur_fe = cur_fe->next;
}
++it;
}
if (cur_fe) changed = true;
cur_fe = new_fe_head;
if (changed) {
cur_fe = *pfilter_expression_head;
*pfilter_expression_head = new_fe_head;
wsApp->emitAppSignal(WiresharkApplication::FilterExpressionsChanged);
}
while (cur_fe) {
struct filter_expression *fe = cur_fe;
cur_fe = fe->next;
g_free(fe->label);
g_free(fe->expression);
g_free(fe);
}
}
void FilterExpressionsPreferencesFrame::keyPressEvent(QKeyEvent *evt)
{
if (cur_line_edit_ && cur_line_edit_->hasFocus()) {
switch (evt->key()) {
case Qt::Key_Escape:
cur_line_edit_->setText(saved_col_string_);
case Qt::Key_Enter:
case Qt::Key_Return:
switch (cur_column_) {
case label_col_:
labelEditingFinished();
break;
case expression_col_:
expressionEditingFinished();
break;
default:
break;
}
delete cur_line_edit_;
return;
default:
break;
}
}
QFrame::keyPressEvent(evt);
}
void FilterExpressionsPreferencesFrame::addExpression(bool enabled, const char *label, char *expression)
{
QTreeWidgetItem *item = new QTreeWidgetItem(ui->expressionTreeWidget);
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setFlags(item->flags() & ~(Qt::ItemIsDropEnabled));
item->setCheckState(enabled_col_, enabled ? Qt::Checked : Qt::Unchecked);
item->setText(label_col_, label);
item->setText(expression_col_, expression);
}
void FilterExpressionsPreferencesFrame::updateWidgets()
{
ui->expressionTreeWidget->clear();
for (struct filter_expression *fe = *pfilter_expression_head; fe != NULL; fe = fe->next) {
if (fe->deleted) continue;
addExpression(fe->enabled, fe->label, fe->expression);
}
}
void FilterExpressionsPreferencesFrame::on_expressionTreeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
ui->deleteToolButton->setEnabled(current ? true : false);
if (previous && ui->expressionTreeWidget->itemWidget(previous, label_col_)) {
ui->expressionTreeWidget->removeItemWidget(previous, label_col_);
}
if (previous && ui->expressionTreeWidget->itemWidget(previous, expression_col_)) {
ui->expressionTreeWidget->removeItemWidget(previous, expression_col_);
}
}
void FilterExpressionsPreferencesFrame::on_expressionTreeWidget_itemActivated(QTreeWidgetItem *item, int column)
{
if (!item || cur_line_edit_) return;
QWidget *editor = NULL;
cur_column_ = column;
switch (column) {
case label_col_:
{
cur_line_edit_ = new QLineEdit();
cur_column_ = column;
saved_col_string_ = item->text(label_col_);
connect(cur_line_edit_, SIGNAL(editingFinished()), this, SLOT(labelEditingFinished()));
editor = cur_line_edit_;
break;
}
case expression_col_:
{
SyntaxLineEdit *syntax_edit = new SyntaxLineEdit();
saved_col_string_ = item->text(expression_col_);
connect(syntax_edit, SIGNAL(textChanged(QString)),
this, SLOT(expressionTextChanged(QString)));
connect(syntax_edit, SIGNAL(editingFinished()), this, SLOT(expressionEditingFinished()));
editor = cur_line_edit_ = syntax_edit;
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 (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->expressionTreeWidget->setItemWidget(item, cur_column_, edit_frame);
editor->setFocus();
}
}
void FilterExpressionsPreferencesFrame::lineEditDestroyed()
{
cur_line_edit_ = NULL;
}
void FilterExpressionsPreferencesFrame::labelEditingFinished()
{
QTreeWidgetItem *item = ui->expressionTreeWidget->currentItem();
if (!cur_line_edit_ || !item) return;
item->setText(label_col_, cur_line_edit_->text());
ui->expressionTreeWidget->removeItemWidget(item, label_col_);
}
void FilterExpressionsPreferencesFrame::expressionTextChanged(QString)
{
SyntaxLineEdit *syntax_edit = qobject_cast<SyntaxLineEdit *>(cur_line_edit_);
QTreeWidgetItem *item = ui->expressionTreeWidget->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 FilterExpressionsPreferencesFrame::expressionEditingFinished()
{
QTreeWidgetItem *item = ui->expressionTreeWidget->currentItem();
if (!cur_line_edit_ || !item) return;
item->setText(expression_col_, cur_line_edit_->text());
ui->expressionTreeWidget->removeItemWidget(item, expression_col_);
}
void FilterExpressionsPreferencesFrame::on_newToolButton_clicked()
{
addExpression(true, "My Filter", NULL);
}
void FilterExpressionsPreferencesFrame::on_deleteToolButton_clicked()
{
QTreeWidgetItem *item = ui->expressionTreeWidget->currentItem();
if (item) {
ui->expressionTreeWidget->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:
*/