/* filter_dialog.cpp * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include #include #include #include #include "filter_dialog.h" #include #include #include #include #include #include #include #include #include "main_application.h" FilterDialog::FilterDialog(QWidget *parent, FilterType filter_type, QString new_filter_) : GeometryStateDialog(parent), ui(new Ui::FilterDialog), filter_type_(filter_type), filter_tree_delegate_(new FilterTreeDelegate(this, filter_type)) { ui->setupUi(this); if (parent) loadGeometry(parent->width() * 2 / 3, parent->height() * 2 / 3); setWindowIcon(mainApp->normalIcon()); ui->newToolButton->setStockIcon("list-add"); ui->deleteToolButton->setStockIcon("list-remove"); ui->copyToolButton->setStockIcon("list-copy"); #ifdef Q_OS_MAC ui->newToolButton->setAttribute(Qt::WA_MacSmallSize, true); ui->deleteToolButton->setAttribute(Qt::WA_MacSmallSize, true); ui->copyToolButton->setAttribute(Qt::WA_MacSmallSize, true); ui->pathLabel->setAttribute(Qt::WA_MacSmallSize, true); #endif #if 0 ui->filterTreeWidget->setDragEnabled(true); ui->filterTreeWidget->viewport()->setAcceptDrops(true); ui->filterTreeWidget->setDropIndicatorShown(true); ui->filterTreeWidget->setDragDropMode(QAbstractItemView::InternalMove); #endif ui->filterTreeView->setDragEnabled(true); ui->filterTreeView->setAcceptDrops(true); ui->filterTreeView->setDropIndicatorShown(true); const gchar * filename = NULL; QString newFilterText; if (filter_type == CaptureFilter) { setWindowTitle(mainApp->windowTitleString(tr("Capture Filters"))); filename = CFILTER_FILE_NAME; newFilterText = tr("New capture filter"); model_ = new FilterListModel(FilterListModel::Capture, this); } else { setWindowTitle(mainApp->windowTitleString(tr("Display Filters"))); filename = DFILTER_FILE_NAME; newFilterText = tr("New display filter"); model_ = new FilterListModel(FilterListModel::Display, this); } if (new_filter_.length() > 0) model_->addFilter(newFilterText, new_filter_); ui->filterTreeView->setModel(model_); ui->filterTreeView->setItemDelegate(new FilterTreeDelegate(this, filter_type)); ui->filterTreeView->resizeColumnToContents(FilterListModel::ColumnName); connect(ui->filterTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &FilterDialog::selectionChanged); QString abs_path = gchar_free_to_qstring(get_persconffile_path(filename, TRUE)); if (file_exists(abs_path.toUtf8().constData())) { ui->pathLabel->setText(abs_path); ui->pathLabel->setUrl(QUrl::fromLocalFile(abs_path).toString()); ui->pathLabel->setToolTip(tr("Open ") + filename); ui->pathLabel->setEnabled(true); } } FilterDialog::~FilterDialog() { delete ui; } void FilterDialog::addFilter(QString name, QString filter, bool start_editing) { if (model_) { QModelIndex idx = model_->addFilter(name, filter); if (start_editing) ui->filterTreeView->edit(idx); } } void FilterDialog::updateWidgets() { if (! ui->filterTreeView->selectionModel()) return; qsizetype num_selected = ui->filterTreeView->selectionModel()->selectedRows().count(); ui->copyToolButton->setEnabled(num_selected == 1); ui->deleteToolButton->setEnabled(num_selected > 0); } void FilterDialog::selectionChanged(const QItemSelection &/*selected*/, const QItemSelection &/*deselected*/) { updateWidgets(); } void FilterDialog::on_newToolButton_clicked() { QString name; QString filter; if (filter_type_ == CaptureFilter) { //: This text is automatically filled in when a new filter is created name = tr("New capture filter"); filter = "ip host host.example.com"; } else { //: This text is automatically filled in when a new filter is created name = tr("New display filter"); filter = "ip.host == host.example.com"; } addFilter(name, filter, true); } void FilterDialog::on_deleteToolButton_clicked() { QModelIndexList selected = ui->filterTreeView->selectionModel()->selectedRows(); QList rows; foreach (QModelIndex idx, selected) { if (idx.isValid() && ! rows.contains(idx.row())) { rows << idx.row(); model_->removeFilter(idx); } } } void FilterDialog::on_copyToolButton_clicked() { QModelIndexList selected = ui->filterTreeView->selectionModel()->selectedRows(); if (selected.count() <= 0) return; int rowNr = selected.at(0).row(); QModelIndex row = selected.at(0).sibling(rowNr, FilterListModel::ColumnName); addFilter(row.data().toString(), row.sibling(rowNr, FilterListModel::ColumnExpression).data().toString(), true); } void FilterDialog::on_buttonBox_accepted() { model_->saveList(); if (filter_type_ == CaptureFilter) { mainApp->emitAppSignal(MainApplication::CaptureFilterListChanged); } else { mainApp->emitAppSignal(MainApplication::DisplayFilterListChanged); } } void FilterDialog::on_buttonBox_helpRequested() { if (filter_type_ == CaptureFilter) { mainApp->helpTopicAction(HELP_CAPTURE_FILTERS_DIALOG); } else { mainApp->helpTopicAction(HELP_DISPLAY_FILTERS_DIALOG); } } // // FilterTreeDelegate // Delegate for editing capture and display filters. // FilterTreeDelegate::FilterTreeDelegate(QObject *parent, FilterDialog::FilterType filter_type) : QStyledItemDelegate(parent), filter_type_(filter_type) {} QWidget *FilterTreeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { QWidget * w = Q_NULLPTR; if (index.column() != FilterListModel::ColumnExpression) { w = QStyledItemDelegate::createEditor(parent, option, index); } else { if (filter_type_ == FilterDialog::CaptureFilter) { w = new CaptureFilterEdit(parent, true); } else { w = new DisplayFilterEdit(parent, DisplayFilterToEnter); } } if (qobject_cast(w) && index.column() == FilterListModel::ColumnName) qobject_cast(w)->setValidator(new FilterValidator()); return w; } void FilterTreeDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { if (! editor || ! index.isValid()) return; QStyledItemDelegate::setEditorData(editor, index); if (qobject_cast(editor)) qobject_cast(editor)->setText(index.data().toString()); } QValidator::State FilterValidator::validate(QString & input, int & /*pos*/) const { /* Making this a list to be able to easily add additional values in the future */ QStringList invalidKeys = QStringList() << "\""; if (input.length() <= 0) return QValidator::Intermediate; foreach (QString key, invalidKeys) if (input.indexOf(key) >= 0) return QValidator::Invalid; return QValidator::Acceptable; }