Convert coloring rules dialog to use model.
Change-Id: I12a465b5451bdbaea871828329d48fda3627fca3 Reviewed-on: https://code.wireshark.org/review/25372 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
parent
a3e14cb514
commit
f0db412f57
|
@ -74,6 +74,8 @@ set(WIRESHARK_UTILS_HEADERS
|
|||
set(WIRESHARK_MODEL_HEADERS
|
||||
models/astringlist_list_model.h
|
||||
models/cache_proxy_model.h
|
||||
models/coloring_rules_delegate.h
|
||||
models/coloring_rules_model.h
|
||||
models/decode_as_delegate.h
|
||||
models/decode_as_model.h
|
||||
models/dissector_tables_model.h
|
||||
|
@ -297,6 +299,8 @@ set(WIRESHARK_UTILS_SRCS
|
|||
set(WIRESHARK_MODEL_SRCS
|
||||
models/astringlist_list_model.cpp
|
||||
models/cache_proxy_model.cpp
|
||||
models/coloring_rules_delegate.cpp
|
||||
models/coloring_rules_model.cpp
|
||||
models/decode_as_delegate.cpp
|
||||
models/decode_as_model.cpp
|
||||
models/dissector_tables_model.cpp
|
||||
|
|
|
@ -211,6 +211,8 @@ MOC_UTILS_HDRS = \
|
|||
MOC_MODELS_HDRS = \
|
||||
models/astringlist_list_model.h \
|
||||
models/cache_proxy_model.h \
|
||||
models/coloring_rules_delegate.h \
|
||||
models/coloring_rules_model.h \
|
||||
models/decode_as_delegate.h \
|
||||
models/decode_as_model.h \
|
||||
models/dissector_tables_model.h \
|
||||
|
@ -559,6 +561,8 @@ WIRESHARK_QT_UTILS_SRC = \
|
|||
WIRESHARK_QT_MODELS_SRCS = \
|
||||
models/astringlist_list_model.cpp \
|
||||
models/cache_proxy_model.cpp \
|
||||
models/coloring_rules_delegate.cpp \
|
||||
models/coloring_rules_model.cpp \
|
||||
models/decode_as_delegate.cpp \
|
||||
models/decode_as_model.cpp \
|
||||
models/dissector_tables_model.cpp \
|
||||
|
|
|
@ -4,41 +4,27 @@
|
|||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later*/
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "coloring_rules_dialog.h"
|
||||
#include <ui_coloring_rules_dialog.h>
|
||||
|
||||
#include "epan/color_filters.h"
|
||||
|
||||
#include "ui/simple_dialog.h"
|
||||
#include "ui/simple_dialog.h"
|
||||
#include "epan/dfilter/dfilter.h"
|
||||
#include "epan/prefs.h"
|
||||
|
||||
#include <wsutil/utf8_entities.h>
|
||||
|
||||
#include "wsutil/filesystem.h"
|
||||
|
||||
#include <ui/qt/utils/color_utils.h>
|
||||
#include "ui/ws_ui_util.h"
|
||||
#include <ui/qt/widgets/display_filter_combo.h>
|
||||
#include <ui/qt/widgets/syntax_line_edit.h>
|
||||
#include <ui/qt/widgets/display_filter_edit.h>
|
||||
#include "wireshark_application.h"
|
||||
|
||||
#include <QColorDialog>
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QTreeWidgetItemIterator>
|
||||
|
||||
/*
|
||||
* @file Coloring Rules dialog
|
||||
|
@ -50,73 +36,58 @@
|
|||
// - Make the filter column narrower? It's easy to run into Qt's annoying
|
||||
// habit of horizontally scrolling QTreeWidgets here.
|
||||
|
||||
|
||||
enum {
|
||||
name_col_ = 0,
|
||||
filter_col_
|
||||
};
|
||||
|
||||
static const QString new_rule_name_ = QObject::tr("New coloring rule");
|
||||
|
||||
ColoringRulesDialog::ColoringRulesDialog(QWidget *parent, QString add_filter) :
|
||||
GeometryStateDialog(parent),
|
||||
ui(new Ui::ColoringRulesDialog),
|
||||
conversation_colors_(NULL)
|
||||
colorRuleModel_(palette().color(QPalette::Text), palette().color(QPalette::Base), this),
|
||||
colorRuleDelegate_(this)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
if (parent) loadGeometry(parent->width() * 2 / 3, parent->height() * 4 / 5);
|
||||
|
||||
setWindowTitle(wsApp->windowTitleString(QStringList() << tr("Coloring Rules") << get_profile_name()));
|
||||
setWindowTitle(wsApp->windowTitleString(tr("Coloring Rules %1").arg(get_profile_name())));
|
||||
|
||||
ui->coloringRulesTreeWidget->setDragEnabled(true);
|
||||
ui->coloringRulesTreeWidget->viewport()->setAcceptDrops(true);
|
||||
ui->coloringRulesTreeWidget->setDropIndicatorShown(true);
|
||||
ui->coloringRulesTreeWidget->setDragDropMode(QAbstractItemView::InternalMove);
|
||||
ui->coloringRulesTreeView->setModel(&colorRuleModel_);
|
||||
ui->coloringRulesTreeView->setItemDelegate(&colorRuleDelegate_);
|
||||
|
||||
color_filters_clone(this, color_filter_add_cb);
|
||||
ui->coloringRulesTreeView->viewport()->setAcceptDrops(true);
|
||||
|
||||
for (int i = 0; i < ui->coloringRulesTreeWidget->columnCount(); i++) {
|
||||
ui->coloringRulesTreeWidget->setItemDelegateForColumn(i, &coloring_rules_tree_delegate_);
|
||||
ui->coloringRulesTreeWidget->resizeColumnToContents(i);
|
||||
}
|
||||
coloring_rules_tree_delegate_.setTree(ui->coloringRulesTreeWidget);
|
||||
|
||||
if (!add_filter.isEmpty()) {
|
||||
addColoringRule(false, new_rule_name_, add_filter,
|
||||
palette().color(QPalette::Text),
|
||||
palette().color(QPalette::Base),
|
||||
true);
|
||||
for (int i = 0; i < colorRuleModel_.columnCount(); i++) {
|
||||
ui->coloringRulesTreeView->resizeColumnToContents(i);
|
||||
}
|
||||
|
||||
connect(ui->coloringRulesTreeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
|
||||
this, SLOT(updateWidgets()));
|
||||
connect(ui->coloringRulesTreeView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
|
||||
this, SLOT(colorRuleSelectionChanged(const QItemSelection &, const QItemSelection &)));
|
||||
connect(&colorRuleModel_, SIGNAL(dragDropComplete()),
|
||||
this, SLOT(dragDropComplete()));
|
||||
connect(&colorRuleDelegate_, SIGNAL(invalidField(const QModelIndex&, const QString&)),
|
||||
this, SLOT(invalidField(const QModelIndex&, const QString&)));
|
||||
connect(&colorRuleDelegate_, SIGNAL(validField(const QModelIndex&)),
|
||||
this, SLOT(validField(const QModelIndex&)));
|
||||
|
||||
import_button_ = ui->buttonBox->addButton(tr("Import" UTF8_HORIZONTAL_ELLIPSIS), QDialogButtonBox::ApplyRole);
|
||||
import_button_->setToolTip(tr("Select a file and add its filters to the end of the list."));
|
||||
export_button_ = ui->buttonBox->addButton(tr("Export" UTF8_HORIZONTAL_ELLIPSIS), QDialogButtonBox::ApplyRole);
|
||||
export_button_->setToolTip(tr("Save filters in a file."));
|
||||
|
||||
updateWidgets();
|
||||
if (!add_filter.isEmpty()) {
|
||||
colorRuleModel_.addColor(false, add_filter, palette().color(QPalette::Text), palette().color(QPalette::Base));
|
||||
|
||||
//setup the buttons appropriately
|
||||
ui->coloringRulesTreeView->setCurrentIndex(colorRuleModel_.index(0, 0));
|
||||
|
||||
//set edit on display filter
|
||||
ui->coloringRulesTreeView->edit(colorRuleModel_.index(0, 1));
|
||||
}else {
|
||||
ui->coloringRulesTreeView->setCurrentIndex(QModelIndex());
|
||||
}
|
||||
|
||||
updateHint();
|
||||
}
|
||||
|
||||
ColoringRulesDialog::~ColoringRulesDialog()
|
||||
{
|
||||
delete ui;
|
||||
color_filter_list_delete(&conversation_colors_);
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::addColor(_color_filter *colorf)
|
||||
{
|
||||
if (!colorf) return;
|
||||
|
||||
if(strstr(colorf->filter_name, CONVERSATION_COLOR_PREFIX) != NULL) {
|
||||
conversation_colors_ = g_slist_append(conversation_colors_, colorf);
|
||||
} else {
|
||||
addColoringRule(colorf->disabled, colorf->filter_name, colorf->filter_text,
|
||||
ColorUtils::fromColorT(colorf->fg_color),
|
||||
ColorUtils::fromColorT(colorf->bg_color),
|
||||
false, false);
|
||||
}
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::showEvent(QShowEvent *)
|
||||
|
@ -126,124 +97,113 @@ void ColoringRulesDialog::showEvent(QShowEvent *)
|
|||
ui->displayFilterPushButton->setFixedHeight(ui->copyToolButton->geometry().height());
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::updateWidgets()
|
||||
void ColoringRulesDialog::invalidField(const QModelIndex &index, const QString& errMessage)
|
||||
{
|
||||
errors_.insert(index, errMessage);
|
||||
updateHint();
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::validField(const QModelIndex &index)
|
||||
{
|
||||
if (errors_.remove(index) > 0) {
|
||||
updateHint();
|
||||
}
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::updateHint()
|
||||
{
|
||||
QString hint = "<small><i>";
|
||||
int num_selected = ui->coloringRulesTreeWidget->selectedItems().count();
|
||||
QString error_text;
|
||||
bool enable_save = true;
|
||||
|
||||
if (errors_.count() > 0) {
|
||||
//take the list of QModelIndexes and sort them so first color rule error is displayed
|
||||
//This isn't the most efficent algorithm, but the list shouldn't be large to matter
|
||||
QList<QModelIndex> keys = errors_.keys();
|
||||
|
||||
//list is not guaranteed to be sorted, so force it
|
||||
qSort(keys.begin(), keys.end());
|
||||
const QModelIndex& error_key = keys[0];
|
||||
error_text = QString("%1: %2")
|
||||
.arg(colorRuleModel_.data(colorRuleModel_.index(error_key.row(), ColoringRulesModel::colName), Qt::DisplayRole).toString())
|
||||
.arg(errors_[error_key]);
|
||||
}
|
||||
|
||||
if (error_text.isEmpty()) {
|
||||
hint += tr("Double click to edit. Drag to move. Rules are processed in order until a match is found.");
|
||||
} else {
|
||||
hint += error_text;
|
||||
enable_save = false;
|
||||
}
|
||||
|
||||
hint += "</i></small>";
|
||||
ui->hintLabel->setText(hint);
|
||||
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enable_save);
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::setColorButtons(QModelIndex &index)
|
||||
{
|
||||
QString color_button_ss =
|
||||
"QPushButton {"
|
||||
" border: 1px solid palette(Dark);"
|
||||
" padding-left: %1px;"
|
||||
" padding-right: %1px;"
|
||||
" color: %2;"
|
||||
" background-color: %3;"
|
||||
"}";
|
||||
|
||||
int one_em = fontMetrics().height();
|
||||
QVariant fg = colorRuleModel_.data(index, Qt::ForegroundRole);
|
||||
QVariant bg = colorRuleModel_.data(index, Qt::BackgroundRole);
|
||||
if (fg.isNull() || bg.isNull()) {
|
||||
//should never happen
|
||||
ui->fGPushButton->setVisible(false);
|
||||
ui->bGPushButton->setVisible(false);
|
||||
} else {
|
||||
QString fg_color = fg.toString();
|
||||
QString bg_color = bg.toString();
|
||||
|
||||
if (num_selected == 1) {
|
||||
QTreeWidgetItem *ti = ui->coloringRulesTreeWidget->currentItem();
|
||||
QString color_button_ss =
|
||||
"QPushButton {"
|
||||
" border: 1px solid palette(Dark);"
|
||||
" padding-left: %1px;"
|
||||
" padding-right: %1px;"
|
||||
" color: %2;"
|
||||
" background-color: %3;"
|
||||
"}";
|
||||
int one_em = fontMetrics().height();
|
||||
QString fg_color = ti->foreground(0).color().name();
|
||||
QString bg_color = ti->background(0).color().name();
|
||||
ui->fGPushButton->setStyleSheet(color_button_ss.arg(one_em).arg(bg_color).arg(fg_color));
|
||||
ui->bGPushButton->setStyleSheet(color_button_ss.arg(one_em).arg(fg_color).arg(bg_color));
|
||||
}
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::colorRuleSelectionChanged(const QItemSelection&, const QItemSelection&)
|
||||
{
|
||||
QModelIndexList selectedList = ui->coloringRulesTreeView->selectionModel()->selectedIndexes();
|
||||
|
||||
//determine the number of unique rows
|
||||
QHash<int, QModelIndex> selectedRows;
|
||||
foreach (const QModelIndex &index, selectedList) {
|
||||
selectedRows.insert(index.row(), index);
|
||||
}
|
||||
|
||||
int num_selected = selectedRows.count();
|
||||
if (num_selected == 1) {
|
||||
setColorButtons(selectedList[0]);
|
||||
}
|
||||
|
||||
ui->copyToolButton->setEnabled(num_selected == 1);
|
||||
ui->deleteToolButton->setEnabled(num_selected > 0);
|
||||
ui->fGPushButton->setVisible(num_selected == 1);
|
||||
ui->bGPushButton->setVisible(num_selected == 1);
|
||||
ui->displayFilterPushButton->setVisible(num_selected == 1);
|
||||
|
||||
QString error_text;
|
||||
QTreeWidgetItemIterator iter(ui->coloringRulesTreeWidget);
|
||||
bool enable_save = true;
|
||||
|
||||
while (*iter) {
|
||||
QTreeWidgetItem *item = (*iter);
|
||||
if (item->text(name_col_).contains("@")) {
|
||||
error_text = tr("the \"@\" symbol will be ignored.");
|
||||
}
|
||||
|
||||
// Check the rule's display filter syntax only if it's checked.
|
||||
QString display_filter = item->text(filter_col_);
|
||||
if (!display_filter.isEmpty() && item->checkState(name_col_) == Qt::Checked) {
|
||||
dfilter_t *dfilter;
|
||||
bool status;
|
||||
gchar *err_msg;
|
||||
status = dfilter_compile(display_filter.toUtf8().constData(), &dfilter, &err_msg);
|
||||
dfilter_free(dfilter);
|
||||
if (!status) {
|
||||
if (!error_text.isEmpty()) error_text += " ";
|
||||
error_text += err_msg;
|
||||
g_free(err_msg);
|
||||
enable_save = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!error_text.isEmpty()) {
|
||||
error_text.prepend(QString("%1: ").arg(item->text(name_col_)));
|
||||
break;
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (error_text.isEmpty()) {
|
||||
hint += tr("Double click to edit. Drag to move. Rules are processed in order until a match is found.");
|
||||
} else {
|
||||
hint += error_text;
|
||||
}
|
||||
hint += "</i></small>";
|
||||
ui->hintLabel->setText(hint);
|
||||
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enable_save);
|
||||
}
|
||||
|
||||
GSList *ColoringRulesDialog::createColorFilterList()
|
||||
{
|
||||
GSList *cfl = NULL;
|
||||
QTreeWidgetItemIterator iter(ui->coloringRulesTreeWidget);
|
||||
|
||||
while (*iter) {
|
||||
QTreeWidgetItem *item = (*iter);
|
||||
color_t fg = ColorUtils::toColorT(item->foreground(0).color());
|
||||
color_t bg = ColorUtils::toColorT(item->background(0).color());
|
||||
color_filter_t *colorf = color_filter_new(item->text(name_col_).toUtf8().constData(),
|
||||
item->text(filter_col_).toUtf8().constData(),
|
||||
&bg, &fg, item->checkState(0) == Qt::Unchecked);
|
||||
cfl = g_slist_append(cfl, colorf);
|
||||
++iter;
|
||||
}
|
||||
return cfl;
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::on_coloringRulesTreeWidget_itemSelectionChanged()
|
||||
{
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::changeColor(bool foreground)
|
||||
{
|
||||
if (!ui->coloringRulesTreeWidget->currentItem()) return;
|
||||
QModelIndex current = ui->coloringRulesTreeView->currentIndex();
|
||||
if (!current.isValid())
|
||||
return;
|
||||
|
||||
QTreeWidgetItem *ti = ui->coloringRulesTreeWidget->currentItem();
|
||||
QColorDialog color_dlg;
|
||||
|
||||
color_dlg.setCurrentColor(foreground ?
|
||||
ti->foreground(0).color() : ti->background(0).color());
|
||||
color_dlg.setCurrentColor(colorRuleModel_.data(current, foreground ? Qt::ForegroundRole : Qt::BackgroundRole).toString());
|
||||
if (color_dlg.exec() == QDialog::Accepted) {
|
||||
QColor cc = color_dlg.currentColor();
|
||||
if (foreground) {
|
||||
for (int i = 0; i < ui->coloringRulesTreeWidget->columnCount(); i++) {
|
||||
ti->setForeground(i, cc);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < ui->coloringRulesTreeWidget->columnCount(); i++) {
|
||||
ti->setBackground(i, cc);
|
||||
}
|
||||
}
|
||||
updateWidgets();
|
||||
colorRuleModel_.setData(current, color_dlg.currentColor(), foreground ? Qt::ForegroundRole : Qt::BackgroundRole);
|
||||
setColorButtons(current);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::on_fGPushButton_clicked()
|
||||
|
@ -258,107 +218,99 @@ void ColoringRulesDialog::on_bGPushButton_clicked()
|
|||
|
||||
void ColoringRulesDialog::on_displayFilterPushButton_clicked()
|
||||
{
|
||||
if (!ui->coloringRulesTreeWidget->currentItem()) return;
|
||||
|
||||
QTreeWidgetItem *ti = ui->coloringRulesTreeWidget->currentItem();
|
||||
QString filter = ti->text(filter_col_);
|
||||
QModelIndex current = ui->coloringRulesTreeView->currentIndex();
|
||||
if (!current.isValid())
|
||||
return;
|
||||
|
||||
QString filter = colorRuleModel_.data(colorRuleModel_.index(current.row(), ColoringRulesModel::colFilter), Qt::DisplayRole).toString();
|
||||
emit filterAction(filter, FilterAction::ActionApply, FilterAction::ActionTypePlain);
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::addColoringRule(bool disabled, QString name, QString filter, QColor foreground, QColor background, bool start_editing, bool at_top)
|
||||
void ColoringRulesDialog::addRule(bool copy_from_current)
|
||||
{
|
||||
QTreeWidgetItem *ti = new QTreeWidgetItem();
|
||||
const QModelIndex ¤t = ui->coloringRulesTreeView->currentIndex();
|
||||
if (copy_from_current && !current.isValid())
|
||||
return;
|
||||
|
||||
ti->setFlags(ti->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsEditable);
|
||||
ti->setFlags(ti->flags() & ~(Qt::ItemIsDropEnabled));
|
||||
ti->setCheckState(name_col_, disabled ? Qt::Unchecked : Qt::Checked);
|
||||
ti->setText(name_col_, name);
|
||||
ti->setText(filter_col_, filter);
|
||||
|
||||
for (int i = 0; i < ui->coloringRulesTreeWidget->columnCount(); i++) {
|
||||
ti->setForeground(i, foreground);
|
||||
ti->setBackground(i, background);
|
||||
}
|
||||
|
||||
if (at_top) {
|
||||
ui->coloringRulesTreeWidget->insertTopLevelItem(0, ti);
|
||||
//always add rules at the top of the list
|
||||
if (copy_from_current) {
|
||||
colorRuleModel_.copyRow(colorRuleModel_.index(0, 0).row(), current.row());
|
||||
} else {
|
||||
ui->coloringRulesTreeWidget->addTopLevelItem(ti);
|
||||
if (!colorRuleModel_.insertRows(0, 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (start_editing) {
|
||||
ui->coloringRulesTreeWidget->setCurrentItem(ti);
|
||||
updateWidgets();
|
||||
ui->coloringRulesTreeWidget->editItem(ti, filter_col_);
|
||||
}
|
||||
//set edit on display filter
|
||||
ui->coloringRulesTreeView->edit(colorRuleModel_.index(0, 1));
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::on_newToolButton_clicked()
|
||||
{
|
||||
addColoringRule(false, new_rule_name_, QString(), palette().color(QPalette::Text),
|
||||
palette().color(QPalette::Base), true);
|
||||
addRule();
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::on_deleteToolButton_clicked()
|
||||
{
|
||||
QList<QTreeWidgetItem*> selected = ui->coloringRulesTreeWidget->selectedItems();
|
||||
foreach (QTreeWidgetItem *ti, selected) {
|
||||
delete ti;
|
||||
QModelIndexList selectedList = ui->coloringRulesTreeView->selectionModel()->selectedIndexes();
|
||||
int num_selected = selectedList.count()/colorRuleModel_.columnCount();
|
||||
if (num_selected > 0) {
|
||||
//list is not guaranteed to be sorted, so force it
|
||||
qSort(selectedList.begin(), selectedList.end());
|
||||
|
||||
//walk the list from the back because deleting a value in
|
||||
//the middle will leave the selectedList out of sync and
|
||||
//delete the wrong elements
|
||||
for (int i = selectedList.count()-1; i >= 0; i--) {
|
||||
QModelIndex deleteIndex = selectedList[i];
|
||||
//selectedList includes all cells, use first column as key to remove row
|
||||
if (deleteIndex.isValid() && (deleteIndex.column() == 0)) {
|
||||
colorRuleModel_.removeRows(deleteIndex.row(), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::on_copyToolButton_clicked()
|
||||
{
|
||||
if (!ui->coloringRulesTreeWidget->currentItem()) return;
|
||||
QTreeWidgetItem *ti = ui->coloringRulesTreeWidget->currentItem();
|
||||
|
||||
addColoringRule(ti->checkState(0) == Qt::Unchecked, ti->text(name_col_),
|
||||
ti->text(filter_col_), ti->foreground(0).color(),
|
||||
ti->background(0).color(), true);
|
||||
addRule(true);
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
{
|
||||
QString err;
|
||||
|
||||
if (button == import_button_) {
|
||||
QString file_name = QFileDialog::getOpenFileName(this, wsApp->windowTitleString(tr("Import Coloring Rules")),
|
||||
wsApp->lastOpenDir().path());
|
||||
if (!file_name.isEmpty()) {
|
||||
gchar* err_msg = NULL;
|
||||
if (!color_filters_import(file_name.toUtf8().constData(), this, &err_msg, color_filter_add_cb)) {
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
|
||||
g_free(err_msg);
|
||||
if (!colorRuleModel_.importColors(file_name, err)) {
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err.toUtf8().constData());
|
||||
}
|
||||
}
|
||||
} else if (button == export_button_) {
|
||||
int num_items = ui->coloringRulesTreeWidget->selectedItems().count();
|
||||
int num_items = ui->coloringRulesTreeView->selectionModel()->selectedIndexes().count()/colorRuleModel_.columnCount();
|
||||
|
||||
if (num_items < 1) {
|
||||
num_items = ui->coloringRulesTreeWidget->topLevelItemCount();
|
||||
num_items = colorRuleModel_.rowCount();
|
||||
}
|
||||
|
||||
if (num_items < 1) return;
|
||||
if (num_items < 1)
|
||||
return;
|
||||
|
||||
QString caption = wsApp->windowTitleString(tr("Export %1 Coloring Rules").arg(num_items));
|
||||
QString file_name = QFileDialog::getSaveFileName(this, caption,
|
||||
wsApp->lastOpenDir().path());
|
||||
if (!file_name.isEmpty()) {
|
||||
GSList *cfl = createColorFilterList();
|
||||
gchar* err_msg = NULL;
|
||||
if (!color_filters_export(file_name.toUtf8().constData(), cfl, FALSE, &err_msg)) {
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
|
||||
g_free(err_msg);
|
||||
if (!colorRuleModel_.exportColors(file_name, err)) {
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err.toUtf8().constData());
|
||||
}
|
||||
color_filter_list_delete(&cfl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::on_buttonBox_accepted()
|
||||
{
|
||||
GSList *cfl = createColorFilterList();
|
||||
gchar* err_msg = NULL;
|
||||
if (prefs.unknown_colorfilters) {
|
||||
QMessageBox mb;
|
||||
mb.setText(tr("Your coloring rules file contains unknown rules"));
|
||||
|
@ -369,15 +321,11 @@ void ColoringRulesDialog::on_buttonBox_accepted()
|
|||
int result = mb.exec();
|
||||
if (result != QMessageBox::Save) return;
|
||||
}
|
||||
if (!color_filters_apply(conversation_colors_, cfl, &err_msg)) {
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
|
||||
g_free(err_msg);
|
||||
|
||||
QString err;
|
||||
if (!colorRuleModel_.writeColors(err)) {
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err.toUtf8().constData());
|
||||
}
|
||||
if (!color_filters_write(cfl, &err_msg)) {
|
||||
QMessageBox::warning(this, tr("Unable to save coloring rules: %s"), g_strerror(errno));
|
||||
g_free(err_msg);
|
||||
}
|
||||
color_filter_list_delete(&cfl);
|
||||
}
|
||||
|
||||
void ColoringRulesDialog::on_buttonBox_helpRequested()
|
||||
|
@ -385,70 +333,6 @@ void ColoringRulesDialog::on_buttonBox_helpRequested()
|
|||
wsApp->helpTopicAction(HELP_COLORING_RULES_DIALOG);
|
||||
}
|
||||
|
||||
//
|
||||
// ColoringRulesTreeDelegate
|
||||
// Delegate for editing coloring rule names and filters.
|
||||
//
|
||||
|
||||
QWidget *ColoringRulesTreeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const
|
||||
{
|
||||
QWidget *w = NULL;
|
||||
|
||||
QTreeWidgetItem *ti = tree_->topLevelItem(index.row());
|
||||
if (!ti) return NULL;
|
||||
|
||||
switch (index.column()) {
|
||||
case name_col_:
|
||||
{
|
||||
SyntaxLineEdit *sle = new SyntaxLineEdit(parent);
|
||||
connect(sle, SIGNAL(textChanged(QString)), this, SLOT(ruleNameChanged(QString)));
|
||||
sle->setText(ti->text(name_col_));
|
||||
w = (QWidget*) sle;
|
||||
}
|
||||
break;
|
||||
|
||||
case filter_col_:
|
||||
{
|
||||
DisplayFilterEdit *dfe = new DisplayFilterEdit(parent);
|
||||
// It's possible to have an invalid filter and an enabled OK button at this point.
|
||||
// We might want to add a local slot for checking the filter status.
|
||||
connect(dfe, SIGNAL(textChanged(QString)), dfe, SLOT(checkDisplayFilter(QString)));
|
||||
dfe->setText(ti->text(filter_col_));
|
||||
w = (QWidget*) dfe;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
void ColoringRulesTreeDelegate::ruleNameChanged(const QString name)
|
||||
{
|
||||
SyntaxLineEdit *name_edit = qobject_cast<SyntaxLineEdit*>(QObject::sender());
|
||||
if (!name_edit) return;
|
||||
|
||||
if (name.isEmpty()) {
|
||||
name_edit->setSyntaxState(SyntaxLineEdit::Empty);
|
||||
} else if (name.contains("@")) {
|
||||
name_edit->setSyntaxState(SyntaxLineEdit::Invalid);
|
||||
} else {
|
||||
name_edit->setSyntaxState(SyntaxLineEdit::Valid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Callback for color_filters_clone.
|
||||
void
|
||||
color_filter_add_cb(color_filter_t *colorf, gpointer user_data)
|
||||
{
|
||||
ColoringRulesDialog *coloring_rules_dialog = static_cast<ColoringRulesDialog*>(user_data);
|
||||
|
||||
if (!coloring_rules_dialog) return;
|
||||
coloring_rules_dialog->addColor(colorf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines
|
||||
*
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later*/
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef COLORING_RULES_DIALOG_H
|
||||
#define COLORING_RULES_DIALOG_H
|
||||
|
@ -12,36 +13,17 @@
|
|||
#include "geometry_state_dialog.h"
|
||||
#include "filter_action.h"
|
||||
|
||||
class QAbstractButton;
|
||||
class QTreeWidget;
|
||||
#include <ui/qt/models/coloring_rules_model.h>
|
||||
#include <ui/qt/models/coloring_rules_delegate.h>
|
||||
|
||||
struct _color_filter;
|
||||
struct _GSList; // This is a completely and totally safe forward declaration, right?
|
||||
#include <QMap>
|
||||
|
||||
class QAbstractButton;
|
||||
|
||||
namespace Ui {
|
||||
class ColoringRulesDialog;
|
||||
}
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class ColoringRulesTreeDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ColoringRulesTreeDelegate(QObject *parent = 0) : QStyledItemDelegate(parent), tree_(NULL) {}
|
||||
~ColoringRulesTreeDelegate() {}
|
||||
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
void setTree(QTreeWidget* tree) { tree_ = tree; }
|
||||
|
||||
private:
|
||||
QTreeWidget* tree_;
|
||||
|
||||
private slots:
|
||||
void ruleNameChanged(const QString name);
|
||||
};
|
||||
|
||||
class ColoringRulesDialog : public GeometryStateDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -50,8 +32,6 @@ public:
|
|||
explicit ColoringRulesDialog(QWidget *parent = 0, QString add_filter = QString());
|
||||
~ColoringRulesDialog();
|
||||
|
||||
void addColor(struct _color_filter *colorf);
|
||||
|
||||
signals:
|
||||
void filterAction(QString filter, FilterAction::Action action, FilterAction::ActionType type);
|
||||
|
||||
|
@ -59,9 +39,7 @@ protected:
|
|||
void showEvent(QShowEvent *);
|
||||
|
||||
private slots:
|
||||
void updateWidgets();
|
||||
struct _GSList *createColorFilterList();
|
||||
void on_coloringRulesTreeWidget_itemSelectionChanged();
|
||||
void colorRuleSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
||||
void on_fGPushButton_clicked();
|
||||
void on_bGPushButton_clicked();
|
||||
void on_displayFilterPushButton_clicked();
|
||||
|
@ -71,15 +49,22 @@ private slots:
|
|||
void on_buttonBox_clicked(QAbstractButton *button);
|
||||
void on_buttonBox_accepted();
|
||||
void on_buttonBox_helpRequested();
|
||||
void invalidField(const QModelIndex &index, const QString& errMessage);
|
||||
void validField(const QModelIndex &index);
|
||||
|
||||
private:
|
||||
Ui::ColoringRulesDialog *ui;
|
||||
QPushButton *import_button_;
|
||||
QPushButton *export_button_;
|
||||
ColoringRulesTreeDelegate coloring_rules_tree_delegate_;
|
||||
struct _GSList *conversation_colors_;
|
||||
ColoringRulesModel colorRuleModel_;
|
||||
ColoringRulesDelegate colorRuleDelegate_;
|
||||
|
||||
void addColoringRule(bool disabled, QString name, QString filter, QColor foreground, QColor background, bool start_editing = false, bool at_top = true);
|
||||
QMap<QModelIndex, QString> errors_;
|
||||
|
||||
void setColorButtons(QModelIndex &index);
|
||||
void updateHint();
|
||||
|
||||
void addRule(bool copy_from_current = false);
|
||||
void changeColor(bool foreground = true);
|
||||
};
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="TabnavTreeWidget" name="coloringRulesTreeWidget">
|
||||
<widget class="TabnavTreeView" name="coloringRulesTreeView">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
|
@ -34,16 +34,15 @@
|
|||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Filter</string>
|
||||
</property>
|
||||
</column>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="DropIndicatorShown">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::InternalMove</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -114,6 +113,9 @@
|
|||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -133,6 +135,9 @@
|
|||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -146,6 +151,9 @@
|
|||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -177,9 +185,9 @@
|
|||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TabnavTreeWidget</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>tabnav_tree_widget.h</header>
|
||||
<class>TabnavTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>widgets/tabnav_tree_view.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
/* coloring_rules_delegate.cpp
|
||||
* Delegates for editing various coloring rule fields.
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <ui/qt/models/coloring_rules_delegate.h>
|
||||
#include <ui/qt/models/coloring_rules_model.h>
|
||||
#include <ui/qt/widgets/display_filter_edit.h>
|
||||
|
||||
ColoringRulesDelegate::ColoringRulesDelegate(QObject *parent) : QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QWidget* ColoringRulesDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem&,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case ColoringRulesModel::colName:
|
||||
{
|
||||
SyntaxLineEdit *editor = new SyntaxLineEdit(parent);
|
||||
connect(editor, SIGNAL(textChanged(QString)), this, SLOT(ruleNameChanged(QString)));
|
||||
return editor;
|
||||
}
|
||||
|
||||
case ColoringRulesModel::colFilter:
|
||||
return new DisplayFilterEdit(parent);
|
||||
|
||||
default:
|
||||
Q_ASSERT(FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ColoringRulesDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case ColoringRulesModel::colName:
|
||||
{
|
||||
SyntaxLineEdit *syntaxEdit = static_cast<SyntaxLineEdit*>(editor);
|
||||
syntaxEdit->setText(index.model()->data(index, Qt::EditRole).toString());
|
||||
break;
|
||||
}
|
||||
case ColoringRulesModel::colFilter:
|
||||
{
|
||||
DisplayFilterEdit *displayEdit = static_cast<DisplayFilterEdit*>(editor);
|
||||
displayEdit->setText(index.model()->data(index, Qt::EditRole).toString());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
QStyledItemDelegate::setEditorData(editor, index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ColoringRulesDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case ColoringRulesModel::colName:
|
||||
{
|
||||
SyntaxLineEdit *syntaxEdit = static_cast<SyntaxLineEdit*>(editor);
|
||||
model->setData(index, syntaxEdit->text(), Qt::EditRole);
|
||||
if (syntaxEdit->syntaxState() == SyntaxLineEdit::Invalid) {
|
||||
QString error_text = tr("the \"@\" symbol will be ignored.");
|
||||
emit invalidField(index, error_text);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit validField(index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ColoringRulesModel::colFilter:
|
||||
{
|
||||
DisplayFilterEdit *displayEdit = static_cast<DisplayFilterEdit*>(editor);
|
||||
model->setData(index, displayEdit->text(), Qt::EditRole);
|
||||
if ((displayEdit->syntaxState() == SyntaxLineEdit::Invalid) &&
|
||||
(model->data(model->index(index.row(), ColoringRulesModel::colName), Qt::CheckStateRole) == Qt::Checked))
|
||||
{
|
||||
emit invalidField(index, displayEdit->syntaxErrorMessage());
|
||||
}
|
||||
else
|
||||
{
|
||||
emit validField(index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
QStyledItemDelegate::setModelData(editor, model, index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ColoringRulesDelegate::updateEditorGeometry(QWidget *editor,
|
||||
const QStyleOptionViewItem &option, const QModelIndex&) const
|
||||
{
|
||||
editor->setGeometry(option.rect);
|
||||
}
|
||||
|
||||
void ColoringRulesDelegate::ruleNameChanged(const QString name)
|
||||
{
|
||||
SyntaxLineEdit *name_edit = qobject_cast<SyntaxLineEdit*>(QObject::sender());
|
||||
if (!name_edit) return;
|
||||
|
||||
if (name.isEmpty()) {
|
||||
name_edit->setSyntaxState(SyntaxLineEdit::Empty);
|
||||
} else if (name.contains("@")) {
|
||||
name_edit->setSyntaxState(SyntaxLineEdit::Invalid);
|
||||
} else {
|
||||
name_edit->setSyntaxState(SyntaxLineEdit::Valid);
|
||||
}
|
||||
}
|
||||
|
||||
/* * 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:
|
||||
*/
|
|
@ -0,0 +1,42 @@
|
|||
/* coloring_rules_delegate.h
|
||||
* Delegates for editing various coloring rule fields.
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef COLORING_RULE_DELEGATE_H
|
||||
#define COLORING_RULE_DELEGATE_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QModelIndex>
|
||||
|
||||
class ColoringRulesDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ColoringRulesDelegate(QObject *parent = 0);
|
||||
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const;
|
||||
|
||||
void updateEditorGeometry(QWidget *editor,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
|
||||
signals:
|
||||
void invalidField(const QModelIndex &index, const QString& errMessage) const;
|
||||
void validField(const QModelIndex &index) const;
|
||||
|
||||
private slots:
|
||||
void ruleNameChanged(const QString name);
|
||||
};
|
||||
#endif // COLORING_RULE_DELEGATE_H
|
|
@ -0,0 +1,557 @@
|
|||
/* coloring_rules_model.cpp
|
||||
* Data model for coloring rules.
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "coloring_rules_model.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "ui/ws_ui_util.h" //for color_filter_add_cb
|
||||
|
||||
#include <ui/qt/utils/color_utils.h>
|
||||
#include <ui/qt/utils/qt_ui_utils.h>
|
||||
#include <ui/qt/utils/variant_pointer.h>
|
||||
|
||||
#include <QMimeData>
|
||||
|
||||
|
||||
static const QString new_rule_name_ = QObject::tr("New coloring rule");
|
||||
static const QString color_rule_mime_type_ = "application/x-wireshark-coloring-rules";
|
||||
|
||||
ColoringRuleItem::ColoringRuleItem(bool disabled, QString name, QString filter, QColor foreground, QColor background, ColoringRuleItem* parent)
|
||||
: ModelHelperTreeItem<ColoringRuleItem>(parent),
|
||||
disabled_(disabled),
|
||||
name_(name),
|
||||
filter_(filter),
|
||||
foreground_(foreground),
|
||||
background_(background)
|
||||
{
|
||||
}
|
||||
|
||||
ColoringRuleItem::~ColoringRuleItem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ColoringRuleItem::ColoringRuleItem(color_filter_t *colorf, ColoringRuleItem* parent)
|
||||
: ModelHelperTreeItem<ColoringRuleItem>(parent),
|
||||
disabled_(colorf->disabled),
|
||||
name_(colorf->filter_name),
|
||||
filter_(colorf->filter_text),
|
||||
foreground_(ColorUtils::fromColorT(colorf->fg_color)),
|
||||
background_(ColorUtils::fromColorT(colorf->bg_color))
|
||||
{
|
||||
}
|
||||
|
||||
ColoringRuleItem::ColoringRuleItem(const ColoringRuleItem& item)
|
||||
: ModelHelperTreeItem<ColoringRuleItem>(item.parent_),
|
||||
disabled_(item.disabled_),
|
||||
name_(item.name_),
|
||||
filter_(item.filter_),
|
||||
foreground_(item.foreground_),
|
||||
background_(item.background_)
|
||||
{
|
||||
}
|
||||
|
||||
// Callback for color_filters_clone.
|
||||
void
|
||||
color_filter_add_cb(color_filter_t *colorf, gpointer user_data)
|
||||
{
|
||||
ColoringRulesModel *model = (ColoringRulesModel*)user_data;
|
||||
|
||||
if (model == NULL)
|
||||
return;
|
||||
|
||||
model->addColor(colorf);
|
||||
}
|
||||
|
||||
ColoringRulesModel::ColoringRulesModel(QColor defaultForeground, QColor defaultBackground, QObject *parent) :
|
||||
QAbstractItemModel(parent),
|
||||
root_(new ColoringRuleItem(false, "", "", QColor(), QColor(), NULL)),
|
||||
conversation_colors_(NULL),
|
||||
defaultForeground_(defaultForeground),
|
||||
defaultBackground_(defaultBackground)
|
||||
|
||||
{
|
||||
color_filters_clone(this, color_filter_add_cb);
|
||||
}
|
||||
|
||||
ColoringRulesModel::~ColoringRulesModel()
|
||||
{
|
||||
delete root_;
|
||||
color_filter_list_delete(&conversation_colors_);
|
||||
}
|
||||
|
||||
GSList *ColoringRulesModel::createColorFilterList()
|
||||
{
|
||||
GSList *cfl = NULL;
|
||||
for (int row = 0; row < root_->childCount(); row++)
|
||||
{
|
||||
ColoringRuleItem* rule = root_->child(row);
|
||||
if (rule == NULL)
|
||||
continue;
|
||||
|
||||
color_t fg = ColorUtils::toColorT(rule->foreground_);
|
||||
color_t bg = ColorUtils::toColorT(rule->background_);
|
||||
color_filter_t *colorf = color_filter_new(rule->name_.toUtf8().constData(),
|
||||
rule->filter_.toUtf8().constData(),
|
||||
&bg, &fg, rule->disabled_);
|
||||
cfl = g_slist_append(cfl, colorf);
|
||||
}
|
||||
|
||||
return cfl;
|
||||
}
|
||||
|
||||
void ColoringRulesModel::addColor(color_filter_t* colorf)
|
||||
{
|
||||
if (!colorf) return;
|
||||
|
||||
if(strstr(colorf->filter_name, CONVERSATION_COLOR_PREFIX) != NULL) {
|
||||
conversation_colors_ = g_slist_append(conversation_colors_, colorf);
|
||||
} else {
|
||||
int count = root_->childCount();
|
||||
|
||||
beginInsertRows(QModelIndex(), count, count);
|
||||
ColoringRuleItem* item = new ColoringRuleItem(colorf, root_);
|
||||
root_->appendChild(item);
|
||||
endInsertRows();
|
||||
}
|
||||
}
|
||||
|
||||
void ColoringRulesModel::addColor(bool disabled, QString filter, QColor foreground, QColor background)
|
||||
{
|
||||
//add rule to top of the list
|
||||
beginInsertRows(QModelIndex(), 0, 0);
|
||||
ColoringRuleItem* item = new ColoringRuleItem(disabled, new_rule_name_, filter, foreground, background, root_);
|
||||
root_->prependChild(item);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
|
||||
bool ColoringRulesModel::importColors(QString filename, QString& err)
|
||||
{
|
||||
bool success = true;
|
||||
gchar* err_msg = NULL;
|
||||
if (!color_filters_import(filename.toUtf8().constData(), this, &err_msg, color_filter_add_cb)) {
|
||||
err = gchar_free_to_qstring(err_msg);
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ColoringRulesModel::exportColors(QString filename, QString& err)
|
||||
{
|
||||
GSList *cfl = createColorFilterList();
|
||||
bool success = true;
|
||||
gchar* err_msg = NULL;
|
||||
if (!color_filters_export(filename.toUtf8().constData(), cfl, FALSE, &err_msg)) {
|
||||
err = gchar_free_to_qstring(err_msg);
|
||||
success = false;
|
||||
}
|
||||
color_filter_list_delete(&cfl);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ColoringRulesModel::writeColors(QString& err)
|
||||
{
|
||||
GSList *cfl = createColorFilterList();
|
||||
bool success = true;
|
||||
gchar* err_msg = NULL;
|
||||
if (!color_filters_apply(conversation_colors_, cfl, &err_msg)) {
|
||||
err = gchar_free_to_qstring(err_msg);
|
||||
success = false;
|
||||
}
|
||||
if (!color_filters_write(cfl, &err_msg)) {
|
||||
err = QString(tr("Unable to save coloring rules: %1").arg(g_strerror(errno)));
|
||||
success = false;
|
||||
g_free(err_msg);
|
||||
}
|
||||
color_filter_list_delete(&cfl);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ColoringRulesModel::insertRows(int row, int count, const QModelIndex& parent)
|
||||
{
|
||||
// sanity check insertion
|
||||
if (row < 0 )
|
||||
return false;
|
||||
|
||||
beginInsertRows(parent, row, row+(count-1));
|
||||
|
||||
for (int i = row; i < row + count; i++)
|
||||
{
|
||||
ColoringRuleItem* item = new ColoringRuleItem(true, new_rule_name_, "", defaultForeground_, defaultBackground_, root_);
|
||||
root_->insertChild(i, item);
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ColoringRulesModel::removeRows(int row, int count, const QModelIndex& parent)
|
||||
{
|
||||
if (row < 0 )
|
||||
return false;
|
||||
|
||||
beginRemoveRows(parent, row, row+(count-1));
|
||||
for (int i = row; i < row + count; i++)
|
||||
{
|
||||
root_->removeChild(row);
|
||||
}
|
||||
endRemoveRows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ColoringRulesModel::copyRow(int dst_row, int src_row)
|
||||
{
|
||||
if (src_row < 0 || src_row >= rowCount() || dst_row < 0 || dst_row >= rowCount()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ColoringRuleItem* src_item = root_->child(src_row);
|
||||
if (src_item == NULL)
|
||||
return false;
|
||||
|
||||
ColoringRuleItem* dst_item = new ColoringRuleItem(*src_item);
|
||||
if (dst_item == NULL)
|
||||
return false;
|
||||
|
||||
beginInsertRows(QModelIndex(), dst_row, dst_row);
|
||||
root_->insertChild(dst_row, dst_item);
|
||||
endInsertRows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Qt::ItemFlags ColoringRulesModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags flags = QAbstractItemModel::flags(index);
|
||||
switch (index.column())
|
||||
{
|
||||
case colName:
|
||||
flags |= (Qt::ItemIsUserCheckable|Qt::ItemIsEditable);
|
||||
break;
|
||||
case colFilter:
|
||||
flags |= Qt::ItemIsEditable;
|
||||
break;
|
||||
}
|
||||
|
||||
if (index.isValid())
|
||||
flags |= (Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
else
|
||||
flags |= Qt::ItemIsDropEnabled;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
QVariant ColoringRulesModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
ColoringRuleItem* rule = root_->child(index.row());
|
||||
if (rule == NULL)
|
||||
return QVariant();
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
switch(index.column())
|
||||
{
|
||||
case colName:
|
||||
return rule->name_;
|
||||
case colFilter:
|
||||
return rule->filter_;
|
||||
}
|
||||
break;
|
||||
case Qt::CheckStateRole:
|
||||
switch(index.column())
|
||||
{
|
||||
case colName:
|
||||
return rule->disabled_ ? Qt::Unchecked : Qt::Checked;
|
||||
}
|
||||
break;
|
||||
case Qt::BackgroundRole:
|
||||
return rule->background_;
|
||||
case Qt::ForegroundRole:
|
||||
return rule->foreground_;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool ColoringRulesModel::setData(const QModelIndex &dataIndex, const QVariant &value, int role)
|
||||
{
|
||||
if (!dataIndex.isValid())
|
||||
return false;
|
||||
|
||||
if (data(dataIndex, role) == value) {
|
||||
// Data appears unchanged, do not do additional checks.
|
||||
return true;
|
||||
}
|
||||
|
||||
ColoringRuleItem* rule = root_->child(dataIndex.row());
|
||||
if (rule == NULL)
|
||||
return false;
|
||||
|
||||
QModelIndex topLeft = dataIndex,
|
||||
bottomRight = dataIndex;
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::EditRole:
|
||||
switch (dataIndex.column())
|
||||
{
|
||||
case colName:
|
||||
rule->name_ = value.toString();
|
||||
break;
|
||||
case colFilter:
|
||||
rule->filter_ = value.toString();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Qt::CheckStateRole:
|
||||
switch (dataIndex.column())
|
||||
{
|
||||
case colName:
|
||||
rule->disabled_ = (value == Qt::Checked) ? false : true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Qt::BackgroundRole:
|
||||
if (!value.canConvert(QVariant::Color))
|
||||
return false;
|
||||
|
||||
rule->background_ = QColor(value.toString());
|
||||
break;
|
||||
case Qt::ForegroundRole:
|
||||
if (!value.canConvert(QVariant::Color))
|
||||
return false;
|
||||
|
||||
rule->foreground_ = QColor(value.toString());
|
||||
break;
|
||||
case Qt::UserRole:
|
||||
{
|
||||
ColoringRuleItem* new_rule = VariantPointer<ColoringRuleItem>::asPtr(value);
|
||||
*rule = *new_rule;
|
||||
topLeft = index(dataIndex.row(), colName);
|
||||
bottomRight = index(dataIndex.row(), colFilter);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
QVector<int> roles;
|
||||
roles << role;
|
||||
#endif
|
||||
|
||||
emit dataChanged(topLeft, bottomRight
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
, roles
|
||||
#endif
|
||||
);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
QVariant ColoringRulesModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole || orientation != Qt::Horizontal)
|
||||
return QVariant();
|
||||
|
||||
switch ((ColoringRulesColumn)section) {
|
||||
case colName:
|
||||
return tr("Name");
|
||||
case colFilter:
|
||||
return tr("Filter");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::DropActions ColoringRulesModel::supportedDropActions() const
|
||||
{
|
||||
return Qt::MoveAction;
|
||||
}
|
||||
|
||||
QStringList ColoringRulesModel::mimeTypes() const
|
||||
{
|
||||
//Just use plain text to transport data
|
||||
QStringList types;
|
||||
types << color_rule_mime_type_;
|
||||
return types;
|
||||
}
|
||||
|
||||
QMimeData* ColoringRulesModel::mimeData(const QModelIndexList &indexes) const
|
||||
{
|
||||
//if the list is empty, don't return an empty list
|
||||
if (indexes.count() == 0)
|
||||
return NULL;
|
||||
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
QByteArray encodedData;
|
||||
|
||||
QDataStream stream(&encodedData, QIODevice::WriteOnly);
|
||||
|
||||
foreach (const QModelIndex &index, indexes) {
|
||||
//use first column as "filter"
|
||||
if (index.column() == 0) {
|
||||
//Retrieve "native" data to save lots of conversions in the process
|
||||
ColoringRuleItem* item = root_->child(index.row());
|
||||
|
||||
stream << item->disabled_ << item->name_ << item->filter_ << item->foreground_ << item->background_;
|
||||
}
|
||||
}
|
||||
|
||||
mimeData->setData(color_rule_mime_type_, encodedData);
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
bool ColoringRulesModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
|
||||
{
|
||||
//clear any previous dragDrop information
|
||||
dragDropRows_.clear();
|
||||
|
||||
if (action == Qt::IgnoreAction)
|
||||
return true;
|
||||
|
||||
if (!data->hasFormat(color_rule_mime_type_))
|
||||
return false;
|
||||
|
||||
if (column > 0)
|
||||
return false;
|
||||
|
||||
int beginRow;
|
||||
|
||||
if (row != -1)
|
||||
beginRow = row;
|
||||
else if (parent.isValid())
|
||||
beginRow = parent.row();
|
||||
else
|
||||
beginRow = rowCount();
|
||||
|
||||
bool disabled;
|
||||
QString name;
|
||||
QString filter;
|
||||
QColor foreground;
|
||||
QColor background;
|
||||
ColoringRuleItem* item;
|
||||
QList<QVariant> rules;
|
||||
|
||||
QByteArray encodedData = data->data(color_rule_mime_type_);
|
||||
QDataStream stream(&encodedData, QIODevice::ReadOnly);
|
||||
int rows = 0;
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
stream >> disabled >> name >> filter >> foreground >> background;
|
||||
|
||||
item = new ColoringRuleItem(disabled, name, filter, foreground, background, root_);
|
||||
rules.append(VariantPointer<ColoringRuleItem>::asQVariant(item));
|
||||
++rows;
|
||||
}
|
||||
|
||||
insertRows(beginRow, rows, QModelIndex());
|
||||
for (int i = 0; i < rules.count(); i++) {
|
||||
QModelIndex idx = index(beginRow, 0, QModelIndex());
|
||||
setData(idx, rules[i], Qt::UserRole);
|
||||
beginRow++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QModelIndex ColoringRulesModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
ColoringRuleItem *parent_item, *child_item;
|
||||
|
||||
if (!parent.isValid())
|
||||
parent_item = root_;
|
||||
else
|
||||
parent_item = static_cast<ColoringRuleItem*>(parent.internalPointer());
|
||||
|
||||
Q_ASSERT(parent_item);
|
||||
|
||||
child_item = parent_item->child(row);
|
||||
if (child_item) {
|
||||
return createIndex(row, column, child_item);
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex ColoringRulesModel::parent(const QModelIndex& indexItem) const
|
||||
{
|
||||
if (!indexItem.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
ColoringRuleItem* item = static_cast<ColoringRuleItem*>(indexItem.internalPointer());
|
||||
if (item != NULL) {
|
||||
ColoringRuleItem* parent_item = item->parentItem();
|
||||
if (parent_item != NULL) {
|
||||
if (parent_item == root_)
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(parent_item->row(), 0, parent_item);
|
||||
}
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
int ColoringRulesModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
ColoringRuleItem *parent_item;
|
||||
if (parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
if (!parent.isValid())
|
||||
parent_item = root_;
|
||||
else
|
||||
parent_item = static_cast<ColoringRuleItem*>(parent.internalPointer());
|
||||
|
||||
if (parent_item == NULL)
|
||||
return 0;
|
||||
|
||||
return parent_item->childCount();
|
||||
}
|
||||
|
||||
int ColoringRulesModel::columnCount(const QModelIndex&) const
|
||||
{
|
||||
return colColoringRulesMax;
|
||||
}
|
||||
|
||||
/* * 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:
|
||||
*/
|
|
@ -0,0 +1,98 @@
|
|||
/* coloring_rules_model.h
|
||||
* Data model for coloring rules.
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef COLORING_RULES_MODEL_H
|
||||
#define COLORING_RULES_MODEL_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <epan/color_filters.h>
|
||||
|
||||
#include <ui/qt/models/tree_model_helpers.h>
|
||||
|
||||
#include <QList>
|
||||
#include <QColor>
|
||||
#include <QAbstractTableModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class ColoringRuleItem : public ModelHelperTreeItem<ColoringRuleItem>
|
||||
{
|
||||
public:
|
||||
ColoringRuleItem(bool disabled, QString name, QString filter, QColor foreground, QColor background, ColoringRuleItem* parent);
|
||||
virtual ~ColoringRuleItem();
|
||||
|
||||
ColoringRuleItem(color_filter_t *colorf, ColoringRuleItem* parent);
|
||||
ColoringRuleItem(const ColoringRuleItem& item);
|
||||
|
||||
bool disabled_;
|
||||
QString name_;
|
||||
QString filter_;
|
||||
QColor foreground_;
|
||||
QColor background_;
|
||||
};
|
||||
|
||||
class ColoringRulesModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ColoringRulesModel(QColor defaultForeground, QColor defaultBackground, QObject *parent);
|
||||
virtual ~ColoringRulesModel();
|
||||
|
||||
enum ColoringRulesColumn {
|
||||
colName = 0,
|
||||
colFilter,
|
||||
colColoringRulesMax
|
||||
};
|
||||
|
||||
void addColor(color_filter_t* colorf);
|
||||
void addColor(bool disabled, QString filter, QColor foreground, QColor background);
|
||||
bool importColors(QString filename, QString& err);
|
||||
bool exportColors(QString filename, QString& err);
|
||||
bool writeColors(QString& err);
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex & = QModelIndex()) const;
|
||||
QModelIndex parent(const QModelIndex &) const;
|
||||
|
||||
//Drag & drop functionality
|
||||
Qt::DropActions supportedDropActions() const;
|
||||
QStringList mimeTypes() const;
|
||||
QMimeData* mimeData(const QModelIndexList &indexes) const;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||
bool copyRow(int dst_row, int src_row);
|
||||
|
||||
private:
|
||||
void populate();
|
||||
struct _GSList *createColorFilterList();
|
||||
|
||||
ColoringRuleItem* root_;
|
||||
//Save off the conversation colors, do not include in dialog
|
||||
struct _GSList *conversation_colors_;
|
||||
|
||||
QColor defaultForeground_;
|
||||
QColor defaultBackground_;
|
||||
|
||||
QList<int> dragDropRows_;
|
||||
};
|
||||
|
||||
#endif // COLORING_RULES_MODEL_H
|
|
@ -37,11 +37,28 @@ public:
|
|||
childItems_.clear();
|
||||
}
|
||||
|
||||
void appendChild(Item* child)
|
||||
{
|
||||
childItems_.append(VariantPointer<Item>::asQVariant(child));
|
||||
}
|
||||
|
||||
void prependChild(Item* child)
|
||||
{
|
||||
childItems_.prepend(VariantPointer<Item>::asQVariant(child));
|
||||
}
|
||||
|
||||
|
||||
void insertChild(int row, Item* child)
|
||||
{
|
||||
childItems_.insert(row, VariantPointer<Item>::asQVariant(child));
|
||||
}
|
||||
|
||||
void removeChild(int row)
|
||||
{
|
||||
delete VariantPointer<Item>::asPtr(childItems_.value(row));
|
||||
childItems_.removeAt(row);
|
||||
}
|
||||
|
||||
Item* child(int row)
|
||||
{
|
||||
return VariantPointer<Item>::asPtr(childItems_.value(row));
|
||||
|
|
Loading…
Reference in New Issue