summaryrefslogtreecommitdiff
path: root/ui/qt/coloring_rules_dialog.cpp
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2015-02-04 16:36:19 -0800
committerGerald Combs <gerald@wireshark.org>2015-02-07 00:30:30 +0000
commitc8cad99515eeac25faf6ea84795ce6b5fa4afebb (patch)
treeec72051d71ac3caf9331690a6f34d6255a876576 /ui/qt/coloring_rules_dialog.cpp
parentb3f3dd8d82d9b651f34886a3293056c612958aa2 (diff)
downloadwireshark-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.cpp440
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:
+ */