wireshark/ui/qt/widgets/filter_expression_toolbar.cpp

298 lines
9.6 KiB
C++

/* filter_expression_toolbar.cpp
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <ui/qt/widgets/filter_expression_toolbar.h>
#include <ui/qt/utils/color_utils.h>
#include <ui/qt/utils/qt_ui_utils.h>
#include <ui/qt/models/uat_model.h>
#include <ui/qt/wireshark_application.h>
#include <epan/filter_expressions.h>
#include <ui/preference_utils.h>
#include <QApplication>
#include <QFrame>
#include <QMenu>
static const char *dfe_property_ = "display filter expression"; //TODO : Fix Translate
static const char *dfe_property_label_ = "display_filter_expression_label";
static const char *dfe_property_expression_ = "display_filter_expression_expr";
struct filter_expression_data
{
FilterExpressionToolBar* toolbar;
bool actions_added;
};
FilterExpressionToolBar::FilterExpressionToolBar(QWidget * parent) :
DragDropToolBar(parent)
{
// Try to draw 1-pixel-wide separator lines from the button label
// ascent to its baseline.
int sep_margin = (fontMetrics().height() * 0.5) - 1;
QColor sep_color = ColorUtils::alphaBlend(palette().text(), palette().base(), 0.3);
setStyleSheet(QString(
"QToolBar { background: none; border: none; spacing: 1px; }"
"QFrame {"
" min-width: 1px; max-width: 1px;"
" margin: %1px 0 %2px 0; padding: 0;"
" background-color: %3;"
"}"
).arg(sep_margin).arg(sep_margin - 1).arg(sep_color.name()));
setContextMenuPolicy(Qt::CustomContextMenu);
connect ( this, &QWidget::customContextMenuRequested, this, &FilterExpressionToolBar::onCustomMenuHandler );
connect(this, &DragDropToolBar::actionMoved, this, &FilterExpressionToolBar::onActionMoved);
connect(this, &DragDropToolBar::newFilterDropped, this, &FilterExpressionToolBar::onFilterDropped);
connect(wsApp, SIGNAL(appInitialized()),
this, SLOT(filterExpressionsChanged()));
connect(wsApp, SIGNAL(filterExpressionsChanged()),
this, SLOT(filterExpressionsChanged()));
}
void FilterExpressionToolBar::onCustomMenuHandler(const QPoint& pos)
{
QAction * filterAction = actionAt(pos);
if ( ! filterAction )
return;
QMenu * filterMenu = new QMenu(this);
QAction *actFilter = filterMenu->addAction(tr("Filter Button Preferences..."));
connect(actFilter, SIGNAL(triggered()), this, SLOT(toolBarShowPreferences()));
actFilter->setProperty(dfe_property_label_, filterAction->property(dfe_property_label_));
actFilter->setProperty(dfe_property_expression_, filterAction->property(dfe_property_expression_));
actFilter->setData(filterAction->data());
filterMenu->addSeparator();
QAction * actEdit = filterMenu->addAction(tr("Edit"));
connect(actEdit, SIGNAL(triggered()), this, SLOT(editFilter()));
actEdit->setProperty(dfe_property_label_, filterAction->property(dfe_property_label_));
actEdit->setProperty(dfe_property_expression_, filterAction->property(dfe_property_expression_));
actEdit->setData(filterAction->data());
QAction * actDisable = filterMenu->addAction(tr("Disable"));
connect(actDisable, SIGNAL(triggered()), this, SLOT(disableFilter()));
actDisable->setProperty(dfe_property_label_, filterAction->property(dfe_property_label_));
actDisable->setProperty(dfe_property_expression_, filterAction->property(dfe_property_expression_));
actDisable->setData(filterAction->data());
QAction * actRemove = filterMenu->addAction(tr("Remove"));
connect(actRemove, SIGNAL(triggered()), this, SLOT(removeFilter()));
actRemove->setProperty(dfe_property_label_, filterAction->property(dfe_property_label_));
actRemove->setProperty(dfe_property_expression_, filterAction->property(dfe_property_expression_));
actRemove->setData(filterAction->data());
filterMenu->exec(mapToGlobal(pos));
}
void FilterExpressionToolBar::filterExpressionsChanged()
{
struct filter_expression_data data;
data.toolbar = this;
data.actions_added = false;
// Hiding and showing seems to be the only way to get the layout to
// work correctly in some cases. See bug 14121 for details.
clear();
setUpdatesEnabled(false);
hide();
// XXX Add a context menu for removing and changing buttons.
filter_expression_iterate_expressions(filter_expression_add_action, &data);
show();
setUpdatesEnabled(true);
}
void FilterExpressionToolBar::removeFilter()
{
UatModel * uatModel = new UatModel(this, "Display expressions");
QString label = ((QAction *)sender())->property(dfe_property_label_).toString();
QString expr = ((QAction *)sender())->property(dfe_property_expression_).toString();
int idx = uatRowIndexForFilter(label, expr);
QModelIndex rowIndex = uatModel->index(idx, 0);
if ( rowIndex.isValid() ) {
uatModel->removeRow(rowIndex.row());
save_migrated_uat("Display expressions", &prefs.filter_expressions_old);
filterExpressionsChanged();
}
}
void FilterExpressionToolBar::onActionMoved(QAction* action, int oldPos, int newPos)
{
gchar* err = NULL;
if ( oldPos == newPos )
return;
QString label = action->property(dfe_property_label_).toString();
QString expr = action->property(dfe_property_expression_).toString();
int idx = uatRowIndexForFilter(label, expr);
if ( idx > -1 && oldPos > -1 && newPos > -1 )
{
uat_t * table = uat_get_table_by_name("Display expressions");
uat_move_index(table, oldPos, newPos);
uat_save(table, &err);
g_free(err);
}
}
void FilterExpressionToolBar::disableFilter()
{
QString label = ((QAction *)sender())->property(dfe_property_label_).toString();
QString expr = ((QAction *)sender())->property(dfe_property_expression_).toString();
int idx = uatRowIndexForFilter(label, expr);
UatModel * uatModel = new UatModel(this, "Display expressions");
QModelIndex rowIndex = uatModel->index(idx, 0);
if ( rowIndex.isValid() ) {
uatModel->setData(rowIndex, QVariant::fromValue(false));
save_migrated_uat("Display expressions", &prefs.filter_expressions_old);
filterExpressionsChanged();
}
}
void FilterExpressionToolBar::editFilter()
{
if ( ! sender() )
return;
QString label = ((QAction *)sender())->property(dfe_property_label_).toString();
QString expr = ((QAction *)sender())->property(dfe_property_expression_).toString();
int idx = uatRowIndexForFilter(label, expr);
if ( idx > -1 )
emit filterEdit(idx);
}
void FilterExpressionToolBar::onFilterDropped(QString description, QString filter)
{
if ( filter.length() == 0 )
return;
filter_expression_new(qUtf8Printable(description),
qUtf8Printable(filter), qUtf8Printable(description), TRUE);
save_migrated_uat("Display expressions", &prefs.filter_expressions_old);
filterExpressionsChanged();
}
void FilterExpressionToolBar::toolBarShowPreferences()
{
emit filterPreferences();
}
int FilterExpressionToolBar::uatRowIndexForFilter(QString label, QString expression)
{
int result = -1;
if ( expression.length() == 0 )
return result;
UatModel * uatModel = new UatModel(this, "Display expressions");
QModelIndex rowIndex;
if ( label.length() > 0 )
{
for ( int cnt = 0; cnt < uatModel->rowCount() && ! rowIndex.isValid(); cnt++ )
{
if ( uatModel->data(uatModel->index(cnt, 1), Qt::DisplayRole).toString().compare(label) == 0 &&
uatModel->data(uatModel->index(cnt, 2), Qt::DisplayRole).toString().compare(expression) == 0 )
{
rowIndex = uatModel->index(cnt, 2);
}
}
}
else
{
rowIndex = uatModel->findRowForColumnContent(((QAction *)sender())->data(), 2);
}
if ( rowIndex.isValid() )
result = rowIndex.row();
delete uatModel;
return result;
}
gboolean FilterExpressionToolBar::filter_expression_add_action(const void *key _U_, void *value, void *user_data)
{
filter_expression_t* fe = (filter_expression_t*)value;
struct filter_expression_data* data = (filter_expression_data*)user_data;
if (!fe->enabled)
return FALSE;
QAction *dfb_action = new QAction(fe->label, data->toolbar);
if (strlen(fe->comment) > 0)
{
QString tooltip = QString("%1\n%2").arg(fe->comment).arg(fe->expression);
dfb_action->setToolTip(tooltip);
}
else
{
dfb_action->setToolTip(fe->expression);
}
dfb_action->setData(fe->expression);
dfb_action->setProperty(dfe_property_, true);
dfb_action->setProperty(dfe_property_label_, QString(fe->label));
dfb_action->setProperty(dfe_property_expression_, QString(fe->expression));
if (data->actions_added) {
QFrame *sep = new QFrame();
sep->setEnabled(false);
data->toolbar->addWidget(sep);
}
data->toolbar->addAction(dfb_action);
connect(dfb_action, SIGNAL(triggered()), data->toolbar, SLOT(filterClicked()));
data->actions_added = true;
return FALSE;
}
void FilterExpressionToolBar::filterClicked()
{
bool prepare = false;
QAction *dfb_action = qobject_cast<QAction*>(sender());
if (!dfb_action)
return;
QString filterText = dfb_action->data().toString();
prepare = (QApplication::keyboardModifiers() & Qt::ShiftModifier);
emit filterSelected(filterText, prepare);
}
/*
* 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:
*/