diff options
author | Gerald Combs <gerald@wireshark.org> | 2015-02-04 16:36:19 -0800 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2015-02-07 00:30:30 +0000 |
commit | c8cad99515eeac25faf6ea84795ce6b5fa4afebb (patch) | |
tree | ec72051d71ac3caf9331690a6f34d6255a876576 /ui/qt/coloring_rules_dialog.cpp | |
parent | b3f3dd8d82d9b651f34886a3293056c612958aa2 (diff) | |
download | wireshark-c8cad99515eeac25faf6ea84795ce6b5fa4afebb.tar.gz |
Qt: Add the Coloring Rules dialog.
Merge in the old ColorDialog which was a placeholder for
color_filter_add_cb.
Change-Id: I48d188509f480b8514122b4011ac9d8790fcca10
Reviewed-on: https://code.wireshark.org/review/6996
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Diffstat (limited to 'ui/qt/coloring_rules_dialog.cpp')
-rw-r--r-- | ui/qt/coloring_rules_dialog.cpp | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/ui/qt/coloring_rules_dialog.cpp b/ui/qt/coloring_rules_dialog.cpp new file mode 100644 index 0000000000..054394bf6a --- /dev/null +++ b/ui/qt/coloring_rules_dialog.cpp @@ -0,0 +1,440 @@ +/* coloring_rules_dialog.cpp + * + * 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 "coloring_rules_dialog.h" +#include "ui_coloring_rules_dialog.h" + +#include "config.h" + +#include <glib.h> + +#include "color.h" +#include "color_filters.h" + +#include "ui/utf8_entities.h" + +#include "color_utils.h" +#include "display_filter_combo.h" +#include "syntax_line_edit.h" +#include "wireshark_application.h" + +#include <QColorDialog> +#include <QDir> +#include <QFileDialog> +#include <QMessageBox> +#include <QPushButton> +#include <QTreeWidgetItemIterator> + +/* + * @file Coloring Rules dialog + * + * Coloring rule editor for the current profile. + */ + +// 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); +} + +enum { + name_col_ = 0, + filter_col_ +}; + +const QString new_rule_name_ = QObject::tr("New coloring rule"); + +ColoringRulesDialog::ColoringRulesDialog(QWidget *parent, QString add_filter) : + QDialog(parent), + ui(new Ui::ColoringRulesDialog), + conversation_colors_(NULL) +{ + ui->setupUi(this); + setWindowTitle(wsApp->windowTitleString(tr("Coloring Rules"))); + + // XXX Use recent settings instead + resize(parent->width() * 2 / 3, parent->height() * 4 / 5); + + ui->coloringRulesTreeWidget->setDragEnabled(true); + ui->coloringRulesTreeWidget->viewport()->setAcceptDrops(true); + ui->coloringRulesTreeWidget->setDropIndicatorShown(true); + ui->coloringRulesTreeWidget->setDragDropMode(QAbstractItemView::InternalMove); + + color_filters_clone(this); + + 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); + } + + connect(ui->coloringRulesTreeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), + this, SLOT(updateWidgets())); + + 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(); +} + +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)); + } +} + +void ColoringRulesDialog::showEvent(QShowEvent *) +{ + ui->fGPushButton->setFixedHeight(ui->copyToolButton->geometry().height()); + ui->bGPushButton->setFixedHeight(ui->copyToolButton->geometry().height()); +} + +void ColoringRulesDialog::updateWidgets() +{ + QString hint = "<small><i>"; + int num_selected = ui->coloringRulesTreeWidget->selectedItems().count(); + + 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)); + } + + + ui->copyToolButton->setEnabled(num_selected == 1); + ui->deleteToolButton->setEnabled(num_selected > 0); + ui->fGPushButton->setVisible(num_selected == 1); + ui->bGPushButton->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."); + } + + QString display_filter = item->text(filter_col_); + if (!display_filter.isEmpty()) { + 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."); + } 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; + + QTreeWidgetItem *ti = ui->coloringRulesTreeWidget->currentItem(); + QColorDialog color_dlg; + + color_dlg.setCurrentColor(foreground ? + ti->foreground(0).color() : ti->background(0).color()); + 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(); + } + +} + +void ColoringRulesDialog::on_fGPushButton_clicked() +{ + changeColor(); +} + +void ColoringRulesDialog::on_bGPushButton_clicked() +{ + changeColor(false); +} + +void ColoringRulesDialog::addColoringRule(bool disabled, QString name, QString filter, QColor foreground, QColor background, bool start_editing) +{ + QTreeWidgetItem *ti = new QTreeWidgetItem(ui->coloringRulesTreeWidget); + + ti->setFlags(ti->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsEditable); + 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); + } + + ui->coloringRulesTreeWidget->addTopLevelItem(ti); + + if (start_editing) { + ui->coloringRulesTreeWidget->setCurrentItem(ti); + updateWidgets(); + ui->coloringRulesTreeWidget->editItem(ti, filter_col_); + } +} + +void ColoringRulesDialog::on_newToolButton_clicked() +{ + addColoringRule(false, new_rule_name_, QString(), palette().color(QPalette::Text), + palette().color(QPalette::Base), true); +} + +void ColoringRulesDialog::on_deleteToolButton_clicked() +{ + QList<QTreeWidgetItem*> selected = ui->coloringRulesTreeWidget->selectedItems(); + foreach (QTreeWidgetItem *ti, selected) { + delete ti; + } +} + +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); +} + +void ColoringRulesDialog::on_buttonBox_clicked(QAbstractButton *button) +{ + if (button == import_button_) { + QString file_name = QFileDialog::getOpenFileName(this, wsApp->windowTitleString(tr("Import Coloring Rules")), + wsApp->lastOpenDir().path()); + color_filters_import(file_name.toUtf8().constData(), this); + } else if (button == export_button_) { + int num_items = ui->coloringRulesTreeWidget->selectedItems().count(); + + if (num_items < 1) { + num_items = ui->coloringRulesTreeWidget->topLevelItemCount(); + } + + 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(); + color_filters_export(file_name.toUtf8().constData(), cfl, FALSE); + color_filter_list_delete(&cfl); + } + } +} + +void ColoringRulesDialog::on_buttonBox_accepted() +{ + GSList *cfl = createColorFilterList(); + if (prefs.unknown_colorfilters) { + QMessageBox mb; + mb.setText(tr("Your coloring rules file contains unknown rules")); + mb.setInformativeText(tr("Wireshark doesn't recognize one or more of your coloring rules. " + "Saving will discard them.")); + mb.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel); + mb.setDefaultButton(QMessageBox::Save); + + int result = mb.exec(); + if (result != QMessageBox::Save) return; + } + color_filters_apply(conversation_colors_, cfl); + if (!color_filters_write(cfl)) { + QMessageBox::warning(this, tr("Unable to save coloring rules"), g_strerror(errno)); + } + color_filter_list_delete(&cfl); +} + +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 &option, const QModelIndex &index) const +{ + Q_UNUSED(option); + 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_: + { + SyntaxLineEdit *dfe = new SyntaxLineEdit(parent); + connect(dfe, SIGNAL(textChanged(QString)), dfe, SLOT(checkDisplayFilter(QString))); + connect(dfe, SIGNAL(textChanged(QString)), this, SLOT(ruleFilterChanged(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); + } + + if (tree_->currentItem()) { + tree_->currentItem()->setText(name_col_, name); + } +} + +void ColoringRulesTreeDelegate::ruleFilterChanged(const QString filter) +{ + if (tree_->currentItem()) { + tree_->currentItem()->setText(filter_col_, filter); + } +} + +/* + * 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: + */ |