summaryrefslogtreecommitdiff
path: root/ui/qt/additional_toolbar.cpp
diff options
context:
space:
mode:
authorRoland Knall <roland.knall@br-automation.com>2017-01-24 17:34:07 +0100
committerRoland Knall <rknall@gmail.com>2017-02-24 08:12:46 +0000
commit321386e9f49d88b64f48868c6e4079b2073547a1 (patch)
treed30943f392b322b6dd7e1245f7efc3915051ab55 /ui/qt/additional_toolbar.cpp
parentbd9afdddfe45b4c9c6e966df7264d12cdfd85f42 (diff)
downloadwireshark-321386e9f49d88b64f48868c6e4079b2073547a1.tar.gz
PluginIF: AdditionalToolbar
Creates an interface for plugins and other parts of the code, to add a new toolbar to the system and have various widget types interact with this toolbar. All toolbars added via this interface, will be added to an additional submenu called "Additional Toolbars" within Wireshark. Also a demo plugin is being provided, demonstrating various features of the toolbar, including updating the gui elements. It also demonstrates how to update toolbar items. Change-Id: I8d0351224b3d7f4b90220d58970b51695551d7e3 Reviewed-on: https://code.wireshark.org/review/19803 Petri-Dish: Roland Knall <rknall@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Stig Bjørlykke <stig@bjorlykke.org> Reviewed-by: Roland Knall <rknall@gmail.com>
Diffstat (limited to 'ui/qt/additional_toolbar.cpp')
-rw-r--r--ui/qt/additional_toolbar.cpp537
1 files changed, 537 insertions, 0 deletions
diff --git a/ui/qt/additional_toolbar.cpp b/ui/qt/additional_toolbar.cpp
new file mode 100644
index 0000000000..5192fb5312
--- /dev/null
+++ b/ui/qt/additional_toolbar.cpp
@@ -0,0 +1,537 @@
+/* additional_toolbar.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 <additional_toolbar.h>
+#include <config.h>
+
+#include <glib.h>
+
+#include <ui/qt/apply_line_edit.h>
+#include <ui/qt/qt_ui_utils.h>
+#include <ui/qt/variant_pointer.h>
+#include <ui/qt/wireshark_application.h>
+
+#include <QLabel>
+#include <QLineEdit>
+#include <QHBoxLayout>
+#include <QComboBox>
+#include <QWidget>
+#include <QCheckBox>
+#include <QPushButton>
+#include <QStandardItem>
+#include <QStandardItemModel>
+#include <QLayoutItem>
+
+const char * AdditionalToolbarWidgetAction::propertyName = "additional_toolbar_item";
+
+AdditionalToolBar::AdditionalToolBar(ext_toolbar_t * exttoolbar, QWidget * parent)
+: QToolBar(parent),
+ toolbar(exttoolbar)
+{ }
+
+AdditionalToolBar::~AdditionalToolBar()
+{ }
+
+AdditionalToolBar * AdditionalToolBar::create(QWidget * parent, ext_toolbar_t * toolbar)
+{
+ if ( g_list_length( toolbar->children ) == 0 )
+ return NULL;
+
+ AdditionalToolBar * result = new AdditionalToolBar(toolbar, parent);
+ result->setMovable(false);
+ result->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+ result->layout()->setMargin(0);
+ result->layout()->setSpacing(4);
+
+ GList * walker = toolbar->children;
+ bool spacerNeeded = true;
+
+ while ( walker && walker->data )
+ {
+ ext_toolbar_t * item = (ext_toolbar_t *)walker->data;
+ if ( item->type == EXT_TOOLBAR_ITEM )
+ {
+ if ( item->item_type == EXT_TOOLBAR_STRING )
+ spacerNeeded = false;
+
+ QAction * newAction = new AdditionalToolbarWidgetAction(item, result);
+ if ( newAction )
+ {
+ result->addAction(newAction);
+ /* Necessary, because enable state is resetted upon adding the action */
+ result->actions()[result->actions().count() - 1]->setEnabled(!item->capture_only);
+ }
+ }
+
+ walker = g_list_next ( walker );
+ }
+
+ if ( result->children().count() == 0 )
+ return NULL;
+
+ if ( spacerNeeded )
+ {
+ QWidget * empty = new QWidget();
+ empty->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred);
+ result->addWidget(empty);
+
+ }
+
+ return result;
+}
+
+QString AdditionalToolBar::menuName()
+{
+ return (toolbar && toolbar->name) ? QString(toolbar->name) : QString();
+}
+
+AdditionalToolbarWidgetAction::AdditionalToolbarWidgetAction(QObject * parent)
+: QWidgetAction(parent),
+ toolbar_item(0)
+{ }
+
+AdditionalToolbarWidgetAction::AdditionalToolbarWidgetAction(ext_toolbar_t * item, QObject * parent)
+: QWidgetAction(parent),
+ toolbar_item(item)
+{
+ connect(wsApp, SIGNAL(captureActive(int)), this, SLOT(captureActive(int)));
+}
+
+AdditionalToolbarWidgetAction::AdditionalToolbarWidgetAction(const AdditionalToolbarWidgetAction & copy_object)
+: QWidgetAction(copy_object.parent()),
+ toolbar_item(copy_object.toolbar_item)
+{
+ connect(wsApp, SIGNAL(captureActive(int)), this, SLOT(captureActive(int)));
+}
+
+
+void AdditionalToolbarWidgetAction::captureActive(int activeCaptures)
+{
+ if ( toolbar_item && toolbar_item->capture_only )
+ {
+ setEnabled(activeCaptures != 0);
+ }
+}
+
+/* Exists, so a default deconstructor does not call delete on toolbar_item */
+AdditionalToolbarWidgetAction::~AdditionalToolbarWidgetAction() { }
+
+QWidget * AdditionalToolbarWidgetAction::createWidget(QWidget * parent)
+{
+ QWidget * barItem = 0;
+
+ if ( toolbar_item->type != EXT_TOOLBAR_ITEM )
+ return barItem;
+
+ switch ( toolbar_item->item_type )
+ {
+ case EXT_TOOLBAR_BUTTON:
+ barItem = createButton(toolbar_item, parent);
+ break;
+ case EXT_TOOLBAR_BOOLEAN:
+ barItem = createBoolean(toolbar_item, parent);
+ break;
+ case EXT_TOOLBAR_STRING:
+ barItem = createTextEditor(toolbar_item, parent);
+ break;
+ case EXT_TOOLBAR_SELECTOR:
+ barItem = createSelector(toolbar_item, parent);
+ break;
+ }
+
+ if ( ! barItem )
+ return 0;
+
+ barItem->setToolTip(toolbar_item->tooltip);
+ barItem->setProperty(propertyName, VariantPointer<ext_toolbar_t>::asQVariant(toolbar_item));
+
+#ifdef Q_OS_MAC
+ barItem->setAttribute(Qt::WA_MacSmallSize, true);
+#endif
+
+ return barItem;
+}
+
+static void
+toolbar_button_cb(gpointer item, gpointer item_data, gpointer user_data)
+{
+ if ( ! item || ! item_data || ! user_data )
+ return;
+
+ QPushButton * widget = (QPushButton *)(item_data);
+ ext_toolbar_update_t * update_entry = (ext_toolbar_update_t *)user_data;
+
+ if ( widget && update_entry->type == EXT_TOOLBAR_UPDATE_VALUE )
+ widget->setText((gchar *)update_entry->user_data);
+}
+
+QWidget * AdditionalToolbarWidgetAction::createButton(ext_toolbar_t * item, QWidget * parent)
+{
+ if ( ! item || item->type != EXT_TOOLBAR_ITEM || item->item_type != EXT_TOOLBAR_BUTTON )
+ return 0;
+
+ QString defValue = item->defvalue;
+
+ QPushButton * button = new QPushButton(item->name, parent);
+ button->setText(item->name);
+ connect(button, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
+
+ ext_toolbar_register_update_cb(item, (ext_toolbar_action_cb)&toolbar_button_cb, (void *)button);
+
+ return button;
+}
+
+static void
+toolbar_boolean_cb(gpointer item, gpointer item_data, gpointer user_data)
+{
+ if ( ! item || ! item_data || ! user_data )
+ return;
+
+ QCheckBox * widget = (QCheckBox *)(item_data);
+ ext_toolbar_update_t * update_entry = (ext_toolbar_update_t *)user_data;
+
+ if ( widget && update_entry->type == EXT_TOOLBAR_UPDATE_VALUE )
+ {
+ bool oldState = false;
+ if ( update_entry->silent )
+ oldState = widget->blockSignals(true);
+
+ widget->setCheckState(GPOINTER_TO_INT(update_entry->user_data) == 1 ? Qt::Checked : Qt::Unchecked);
+
+ if ( update_entry->silent )
+ widget->blockSignals(oldState);
+ }
+}
+
+QWidget * AdditionalToolbarWidgetAction::createBoolean(ext_toolbar_t * item, QWidget * parent)
+{
+ if ( ! item || item->type != EXT_TOOLBAR_ITEM || item->item_type != EXT_TOOLBAR_BOOLEAN )
+ return 0;
+
+ QString defValue = toolbar_item->defvalue;
+
+ QCheckBox * checkbox = new QCheckBox(item->name, parent);
+ checkbox->setText(item->name);
+ setCheckable(true);
+ checkbox->setCheckState(defValue.compare("true", Qt::CaseInsensitive) == 0 ? Qt::Checked : Qt::Unchecked);
+ connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(onCheckBoxChecked(int)));
+
+ ext_toolbar_register_update_cb(item, (ext_toolbar_action_cb)&toolbar_boolean_cb, (void *)checkbox);
+
+ return checkbox;
+}
+
+QWidget * AdditionalToolbarWidgetAction::createLabelFrame(ext_toolbar_t * item, QWidget * parent)
+{
+ if ( ! item )
+ return new QWidget();
+
+ QWidget * frame = new QWidget(parent);
+
+ QHBoxLayout * frameLayout = new QHBoxLayout(frame);
+ frameLayout->setMargin(0);
+ frameLayout->setSpacing(0);
+
+ QLabel * strLabel = new QLabel(item->name, frame);
+ strLabel->setToolTip(item->tooltip);
+
+#ifdef Q_OS_MAC
+ frame->setAttribute(Qt::WA_MacSmallSize, true);
+ strLabel->setAttribute(Qt::WA_MacSmallSize, true);
+#endif
+
+ frameLayout->addWidget(strLabel);
+
+ frame->setLayout(frameLayout);
+
+ return frame;
+}
+
+static void
+toolbar_string_cb(gpointer item, gpointer item_data, gpointer user_data)
+{
+ if ( ! item || ! item_data || ! user_data )
+ return;
+
+ ApplyLineEdit * edit = (ApplyLineEdit *)(item_data);
+ ext_toolbar_update_t * update_entry = (ext_toolbar_update_t *)user_data;
+
+ if ( edit && update_entry->type == EXT_TOOLBAR_UPDATE_VALUE )
+ {
+ bool oldState = false;
+ if ( update_entry->silent )
+ oldState = edit->blockSignals(true);
+
+ edit->setText((gchar *)update_entry->user_data);
+
+ if ( update_entry->silent )
+ edit->blockSignals(oldState);
+ }
+}
+
+QWidget * AdditionalToolbarWidgetAction::createTextEditor(ext_toolbar_t * item, QWidget * parent)
+{
+ if ( ! item || item->type != EXT_TOOLBAR_ITEM || item->item_type != EXT_TOOLBAR_STRING )
+ return 0;
+
+ QWidget * frame = createLabelFrame(toolbar_item, parent);
+
+ ApplyLineEdit * strEdit = new ApplyLineEdit(toolbar_item->defvalue, frame);
+ strEdit->setToolTip(toolbar_item->tooltip);
+ strEdit->setRegEx(toolbar_item->regex);
+ strEdit->setEmptyAllowed(toolbar_item->is_required);
+ strEdit->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+
+#ifdef Q_OS_MAC
+ strEdit->setAttribute(Qt::WA_MacSmallSize, true);
+#endif
+
+ frame->layout()->addWidget(strEdit);
+
+ connect(strEdit, SIGNAL(textApplied()), this, SLOT(sendTextToCallback()));
+
+ ext_toolbar_register_update_cb(item, (ext_toolbar_action_cb)&toolbar_string_cb, (void *)strEdit);
+
+ return frame;
+}
+
+static void
+toolbar_selector_cb(gpointer item, gpointer item_data, gpointer user_data)
+{
+ if ( ! item || ! item_data || ! user_data )
+ return;
+
+ QComboBox * comboBox = (QComboBox *)(item_data);
+ ext_toolbar_update_t * update_entry = (ext_toolbar_update_t *)user_data;
+
+ bool oldState = false;
+
+ if ( update_entry->silent )
+ oldState = comboBox->blockSignals(true);
+
+ if ( update_entry->type == EXT_TOOLBAR_UPDATE_VALUE )
+ {
+ QString data = QString((gchar *)update_entry->user_data);
+ bool conv_ok = false;
+
+ int dataValue = data.toInt(&conv_ok, 10);
+ if ( conv_ok && dataValue >= 0 && comboBox->model()->rowCount() < dataValue )
+ comboBox->setCurrentIndex(dataValue);
+ else
+ comboBox->setCurrentText(data);
+ }
+ else if ( update_entry->type == EXT_TOOLBAR_UPDATE_DATA )
+ {
+ QStandardItemModel * sourceModel = (QStandardItemModel *)comboBox->model();
+
+ GList * walker = (GList *)update_entry->user_data;
+ if ( g_list_length(walker) == 0 )
+ return;
+
+ sourceModel->clear();
+
+ while ( walker && walker->data )
+ {
+ ext_toolbar_value_t * listvalue = (ext_toolbar_value_t *)walker->data;
+
+ QStandardItem * si = new QStandardItem(listvalue->display);
+ si->setData(VariantPointer<ext_toolbar_value_t>::asQVariant(listvalue), Qt::UserRole);
+ sourceModel->appendRow(si);
+
+ walker = g_list_next(walker);
+ }
+ }
+ else if ( update_entry->type == EXT_TOOLBAR_UPDATE_DATABYINDEX )
+ {
+ QStandardItemModel * sourceModel = (QStandardItemModel *)comboBox->model();
+
+ if ( ! update_entry->user_data || ! update_entry->data_index )
+ return;
+
+ gchar * idx = (gchar *)update_entry->data_index;
+ gchar * display = (gchar *)update_entry->user_data;
+
+ for ( int i = 0; i < sourceModel->rowCount(); i++ )
+ {
+ QStandardItem * item = sourceModel->item(i, 0);
+ ext_toolbar_value_t * entry = VariantPointer<ext_toolbar_value_t>::asPtr(item->data(Qt::UserRole));
+ if ( entry && g_strcmp0( entry->value, idx) == 0 )
+ {
+ item->setText(display);
+ break;
+ }
+ }
+ }
+
+ if ( update_entry->silent )
+ comboBox->blockSignals(oldState);
+
+}
+
+QWidget * AdditionalToolbarWidgetAction::createSelector(ext_toolbar_t * item, QWidget * parent)
+{
+ if ( ! item || item->type != EXT_TOOLBAR_ITEM || item->item_type != EXT_TOOLBAR_SELECTOR )
+ return 0;
+
+ if ( g_list_length(item->values) == 0 )
+ return 0;
+
+ QWidget * frame = createLabelFrame(item, parent);
+
+ QComboBox * myBox = new QComboBox(parent);
+ myBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+
+ QStandardItemModel * sourceModel = new QStandardItemModel();
+
+ GList * walker = item->values;
+ int selIndex = 0;
+ while ( walker && walker->data )
+ {
+ ext_toolbar_value_t * listvalue = (ext_toolbar_value_t *)walker->data;
+
+ QStandardItem * si = new QStandardItem(listvalue->display);
+ si->setData(VariantPointer<ext_toolbar_value_t>::asQVariant(listvalue), Qt::UserRole);
+ sourceModel->appendRow(si);
+
+ if ( listvalue->is_default )
+ selIndex = sourceModel->rowCount();
+
+ walker = g_list_next(walker);
+ }
+
+ myBox->setModel(sourceModel);
+ myBox->setCurrentIndex(selIndex);
+
+#ifdef Q_OS_MAC
+ myBox->setAttribute(Qt::WA_MacSmallSize, true);
+#endif
+
+ frame->layout()->addWidget(myBox);
+
+ connect(myBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onSelectionInWidgetChanged(int)));
+
+ ext_toolbar_register_update_cb(item, (ext_toolbar_action_cb)&toolbar_selector_cb, (void *)myBox);
+
+ return frame;
+}
+
+ext_toolbar_t * AdditionalToolbarWidgetAction::extractToolbarItemFromObject(QObject * object)
+{
+ QWidget * widget = dynamic_cast<QWidget *>(object);
+ if ( ! widget )
+ return 0;
+
+ QVariant propValue = widget->property(propertyName);
+
+ /* If property is invalid, look if our parent has this property */
+ if ( ! propValue.isValid() )
+ {
+ QWidget * frame = dynamic_cast<QWidget *>(widget->parent());
+ if ( ! frame )
+ return 0;
+
+ propValue = frame->property(propertyName);
+ }
+
+ if ( ! propValue.isValid() )
+ return 0;
+
+ return VariantPointer<ext_toolbar_t>::asPtr(propValue);
+}
+
+void AdditionalToolbarWidgetAction::onButtonClicked()
+{
+ ext_toolbar_t * item = extractToolbarItemFromObject(sender());
+ if ( ! item )
+ return;
+
+ item->callback(item, 0, item->user_data);
+}
+
+void AdditionalToolbarWidgetAction::onCheckBoxChecked(int checkState)
+{
+ ext_toolbar_t * item = extractToolbarItemFromObject(sender());
+ if ( ! item )
+ return;
+
+ gboolean value = checkState == Qt::Checked ? true : false;
+
+ item->callback(item, &value, item->user_data);
+}
+
+void AdditionalToolbarWidgetAction::sendTextToCallback()
+{
+ ext_toolbar_t * item = extractToolbarItemFromObject(sender());
+ if ( ! item )
+ return;
+
+ if (item->item_type != EXT_TOOLBAR_STRING )
+ return;
+
+ ApplyLineEdit * editor = dynamic_cast<ApplyLineEdit *>(sender());
+ if ( ! editor )
+ {
+ /* Called from button, searching for acompanying line edit */
+ QWidget * parent = dynamic_cast<QWidget *>(sender()->parent());
+ if ( parent )
+ {
+ QList<ApplyLineEdit *> children = parent->findChildren<ApplyLineEdit *>();
+ if ( children.count() >= 0 )
+ editor = children.at(0);
+ }
+ }
+
+ if ( editor )
+ item->callback(item, qstring_strdup(editor->text()), item->user_data);
+}
+
+void AdditionalToolbarWidgetAction::onSelectionInWidgetChanged(int idx)
+{
+ QComboBox * editor = dynamic_cast<QComboBox *>(sender());
+ ext_toolbar_t * item = extractToolbarItemFromObject(editor);
+ if ( ! item || item->item_type != EXT_TOOLBAR_SELECTOR )
+ return;
+
+ QStandardItemModel * sourceModel = (QStandardItemModel *) editor->model();
+ if ( sourceModel->rowCount() <= idx )
+ return;
+
+ QModelIndex mdIdx = sourceModel->index(idx, 0);
+ QVariant dataSet = sourceModel->data(mdIdx, Qt::UserRole);
+ if ( dataSet.isValid() )
+ {
+ ext_toolbar_value_t * value_entry = VariantPointer<ext_toolbar_value_t>::asPtr(dataSet);
+ item->callback(item, value_entry, item->user_data);
+ }
+}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */