summaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
authorStig Bjørlykke <stig@bjorlykke.org>2017-04-15 23:30:30 +0200
committerStig Bjørlykke <stig@bjorlykke.org>2017-04-25 06:19:39 +0000
commit77751c94f17e2c110ae9e88b1780e279d610b96b (patch)
treecd3a06ccf7944b3e131234ac86ae7b26ced8ea6b /ui
parentcd55bd29258b8e0ffae9ea9471059b457ebb59ae (diff)
downloadwireshark-77751c94f17e2c110ae9e88b1780e279d610b96b.tar.gz
Qt: Add interface toolbar support
An extcap utility can provide configuration for controls to use in a GUI interface toolbar. This controls are bidirectional and can be used to control the extcap utility while capturing. This is useful in scenarios where configuration can be done based on findings in the capture process, setting temporary values or give other inputs without restarting current capture. Todo: - Add support for Windows Change-Id: Ie15fa67f92eb27d8b73df6bb36f66b9a7d81932d Reviewed-on: https://code.wireshark.org/review/19982 Petri-Dish: Stig Bjørlykke <stig@bjorlykke.org> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Stig Bjørlykke <stig@bjorlykke.org>
Diffstat (limited to 'ui')
-rw-r--r--ui/CMakeLists.txt1
-rw-r--r--ui/Makefile.am2
-rw-r--r--ui/iface_toolbar.c68
-rw-r--r--ui/iface_toolbar.h105
-rw-r--r--ui/qt/CMakeLists.txt7
-rw-r--r--ui/qt/Makefile.am10
-rw-r--r--ui/qt/funnel_text_dialog.cpp2
-rw-r--r--ui/qt/interface_toolbar.cpp895
-rw-r--r--ui/qt/interface_toolbar.h120
-rw-r--r--ui/qt/interface_toolbar.ui69
-rw-r--r--ui/qt/interface_toolbar_lineedit.cpp149
-rw-r--r--ui/qt/interface_toolbar_lineedit.h71
-rw-r--r--ui/qt/interface_toolbar_reader.cpp140
-rw-r--r--ui/qt/interface_toolbar_reader.h65
-rw-r--r--ui/qt/main_window.cpp126
-rw-r--r--ui/qt/main_window.h6
-rw-r--r--ui/qt/main_window.ui6
-rw-r--r--ui/qt/main_window_slots.cpp40
-rw-r--r--ui/recent.c14
-rw-r--r--ui/recent.h1
20 files changed, 1890 insertions, 7 deletions
diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt
index 8a52ef9463..e02eab1c6e 100644
--- a/ui/CMakeLists.txt
+++ b/ui/CMakeLists.txt
@@ -34,6 +34,7 @@ set(COMMON_UI_SRC
failure_message.c
filter_files.c
firewall_rules.c
+ iface_toolbar.c
iface_lists.c
io_graph_item.c
language.c
diff --git a/ui/Makefile.am b/ui/Makefile.am
index 776ad4230b..49699c6615 100644
--- a/ui/Makefile.am
+++ b/ui/Makefile.am
@@ -60,6 +60,7 @@ WIRESHARK_UI_SRC = \
failure_message.c \
filter_files.c \
firewall_rules.c \
+ iface_toolbar.c \
iface_lists.c \
io_graph_item.c \
language.c \
@@ -109,6 +110,7 @@ WIRESHARK_UI_INCLUDES = \
help_url.h \
packet_list_utils.h \
firewall_rules.h \
+ iface_toolbar.h \
iface_lists.h \
io_graph_item.h \
language.h \
diff --git a/ui/iface_toolbar.c b/ui/iface_toolbar.c
new file mode 100644
index 0000000000..0e16456ee4
--- /dev/null
+++ b/ui/iface_toolbar.c
@@ -0,0 +1,68 @@
+/* iface_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 "config.h"
+
+#include <glib.h>
+
+#include "iface_toolbar.h"
+
+
+static iface_toolbar_add_cb_t iface_toolbar_add_cb;
+static iface_toolbar_remove_cb_t iface_toolbar_remove_cb;
+
+void iface_toolbar_add(const iface_toolbar *toolbar)
+{
+ if (iface_toolbar_add_cb) {
+ iface_toolbar_add_cb(toolbar);
+ }
+}
+
+void iface_toolbar_remove(const gchar *menu_title)
+{
+ if (iface_toolbar_remove_cb) {
+ iface_toolbar_remove_cb(menu_title);
+ }
+}
+
+gboolean iface_toolbar_use(void)
+{
+ return iface_toolbar_add_cb ? TRUE : FALSE;
+}
+
+void iface_toolbar_register_cb(iface_toolbar_add_cb_t add_cb, iface_toolbar_remove_cb_t remove_cb)
+{
+ iface_toolbar_add_cb = add_cb;
+ iface_toolbar_remove_cb = remove_cb;
+}
+
+/*
+ * 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:
+ */
diff --git a/ui/iface_toolbar.h b/ui/iface_toolbar.h
new file mode 100644
index 0000000000..888c817230
--- /dev/null
+++ b/ui/iface_toolbar.h
@@ -0,0 +1,105 @@
+/* iface_toolbar.h
+ *
+ * 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.
+ */
+
+#ifndef __IFACE_TOOLBAR_H__
+#define __IFACE_TOOLBAR_H__
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+ INTERFACE_TYPE_UNKNOWN,
+ INTERFACE_TYPE_BOOLEAN,
+ INTERFACE_TYPE_BUTTON,
+ INTERFACE_TYPE_SELECTOR,
+ INTERFACE_TYPE_STRING
+} iface_toolbar_ctrl_type;
+
+typedef enum {
+ INTERFACE_ROLE_UNKNOWN,
+ INTERFACE_ROLE_CONTROL,
+ INTERFACE_ROLE_HELP,
+ INTERFACE_ROLE_LOGGER,
+ INTERFACE_ROLE_RESET
+} iface_toolbar_ctrl_role;
+
+typedef struct _iface_toolbar_value {
+ int num;
+ gchar *value;
+ gchar *display;
+ gboolean is_default;
+} iface_toolbar_value;
+
+typedef struct _iface_toolbar_control {
+ int num;
+ iface_toolbar_ctrl_type ctrl_type;
+ iface_toolbar_ctrl_role ctrl_role;
+ gchar *display;
+ gchar *validation;
+ gboolean is_required;
+ gchar *tooltip;
+ gchar *placeholder;
+ union {
+ gboolean boolean;
+ gchar *string;
+ } default_value;
+ GList *values;
+} iface_toolbar_control;
+
+typedef struct _iface_toolbar {
+ gchar *menu_title;
+ gchar *help;
+ GList *ifnames;
+ GList *controls;
+} iface_toolbar;
+
+typedef void (*iface_toolbar_add_cb_t)(const iface_toolbar *);
+typedef void (*iface_toolbar_remove_cb_t)(const gchar *);
+
+void iface_toolbar_add(const iface_toolbar *toolbar);
+
+void iface_toolbar_remove(const gchar *menu_title);
+
+gboolean iface_toolbar_use(void);
+
+void iface_toolbar_register_cb(iface_toolbar_add_cb_t, iface_toolbar_remove_cb_t);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __IFACE_TOOLBAR_H__ */
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index e8936e9119..ca3d67f530 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -87,6 +87,9 @@ set(WIRESHARK_QT_HEADERS
gsm_map_summary_dialog.h
iax2_analysis_dialog.h
import_text_dialog.h
+ interface_toolbar.h
+ interface_toolbar_reader.h
+ interface_toolbar_lineedit.h
interface_tree_model.h
interface_tree_cache_model.h
interface_sort_filter_model.h
@@ -257,6 +260,9 @@ set(WIRESHARK_QT_SRC
geometry_state_dialog.cpp
iax2_analysis_dialog.cpp
import_text_dialog.cpp
+ interface_toolbar.cpp
+ interface_toolbar_reader.cpp
+ interface_toolbar_lineedit.cpp
interface_tree_model.cpp
interface_tree_cache_model.cpp
interface_sort_filter_model.cpp
@@ -418,6 +424,7 @@ set(WIRESHARK_QT_UI
iax2_analysis_dialog.ui
import_text_dialog.ui
interface_frame.ui
+ interface_toolbar.ui
io_graph_dialog.ui
layout_preferences_frame.ui
lbm_lbtrm_transport_dialog.ui
diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am
index 77d17ea449..7f52918fcf 100644
--- a/ui/qt/Makefile.am
+++ b/ui/qt/Makefile.am
@@ -70,6 +70,7 @@ NODIST_GENERATED_HEADER_FILES = \
ui_iax2_analysis_dialog.h \
ui_import_text_dialog.h \
ui_interface_frame.h \
+ ui_interface_toolbar.h \
ui_io_graph_dialog.h \
ui_layout_preferences_frame.h \
ui_lbm_lbtrm_transport_dialog.h \
@@ -215,6 +216,9 @@ MOC_HDRS = \
iax2_analysis_dialog.h \
import_text_dialog.h \
interface_frame.h \
+ interface_toolbar.h \
+ interface_toolbar_lineedit.h \
+ interface_toolbar_reader.h \
interface_tree_model.h \
interface_tree_cache_model.h \
interface_sort_filter_model.h \
@@ -340,6 +344,7 @@ UI_FILES = \
iax2_analysis_dialog.ui \
import_text_dialog.ui \
interface_frame.ui \
+ interface_toolbar.ui \
io_graph_dialog.ui \
layout_preferences_frame.ui \
lbm_lbtrm_transport_dialog.ui \
@@ -499,6 +504,9 @@ WIRESHARK_QT_SRC = \
iax2_analysis_dialog.cpp \
import_text_dialog.cpp \
interface_frame.cpp \
+ interface_toolbar.cpp \
+ interface_toolbar_lineedit.cpp \
+ interface_toolbar_reader.cpp \
interface_tree_model.cpp \
interface_tree_cache_model.cpp \
interface_sort_filter_model.cpp \
@@ -822,6 +830,8 @@ io_graph_dialog.$(OBJEXT): ui_io_graph_dialog.h
interface_frame.$(OBJEXT): ui_interface_frame.h
+interface_toolbar.$(OBJEXT): ui_interface_toolbar.h
+
layout_preferences_frame.$(OBJEXT): ui_layout_preferences_frame.h
lbm_lbtrm_transport_dialog.$(OBJEXT): ui_lbm_lbtrm_transport_dialog.h
diff --git a/ui/qt/funnel_text_dialog.cpp b/ui/qt/funnel_text_dialog.cpp
index 6ba873f451..8be47b032c 100644
--- a/ui/qt/funnel_text_dialog.cpp
+++ b/ui/qt/funnel_text_dialog.cpp
@@ -47,6 +47,7 @@ FunnelTextDialog::FunnelTextDialog(const QString &title) :
if (!title.isEmpty()) {
loadGeometry(0, 0, QString("Funnel %1").arg(title));
}
+ setWindowTitle(wsApp->windowTitleString(title));
funnel_text_window_.funnel_text_dialog = this;
@@ -75,7 +76,6 @@ void FunnelTextDialog::reject()
struct _funnel_text_window_t *FunnelTextDialog::textWindowNew(const QString title)
{
FunnelTextDialog *ftd = new FunnelTextDialog(title);
- ftd->setWindowTitle(wsApp->windowTitleString(title));
ftd->show();
return &ftd->funnel_text_window_;
}
diff --git a/ui/qt/interface_toolbar.cpp b/ui/qt/interface_toolbar.cpp
new file mode 100644
index 0000000000..56a1a53b34
--- /dev/null
+++ b/ui/qt/interface_toolbar.cpp
@@ -0,0 +1,895 @@
+/* interface_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 "config.h"
+
+#include <errno.h>
+
+#include "interface_toolbar.h"
+#include "interface_toolbar_lineedit.h"
+#include "simple_dialog.h"
+#include "ui/main_statusbar.h"
+#include <ui_interface_toolbar.h>
+
+#include "sync_pipe.h"
+#include "wsutil/file_util.h"
+
+#include <QCheckBox>
+#include <QComboBox>
+#include <QDesktopServices>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QThread>
+#include <QUrl>
+
+static const char *interface_type_property = "control_type";
+static const char *interface_role_property = "control_role";
+
+// From interface control protocol.
+enum InterfaceControlCommand {
+ commandControlInitialized = 0,
+ commandControlSet = 1,
+ commandControlAdd = 2,
+ commandControlRemove = 3,
+ commandControlEnable = 4,
+ commandControlDisable = 5,
+ commandStatusMessage = 6,
+ commandInformationMessage = 7,
+ commandWarningMessage = 8,
+ commandErrorMessage = 9,
+};
+
+// To do:
+// - Move control pipe handling to extcap
+
+InterfaceToolbar::InterfaceToolbar(QWidget *parent, const iface_toolbar *toolbar) :
+ QFrame(parent),
+ ui(new Ui::InterfaceToolbar),
+ help_link_(toolbar->help),
+ use_spacer_(true)
+{
+ ui->setupUi(this);
+
+ // Fill inn interfaces list and initialize default interface values
+ ui->interfacesComboBox->blockSignals(true);
+ for (GList *walker = toolbar->ifnames; walker; walker = walker->next)
+ {
+ QString ifname((gchar *)walker->data);
+ ui->interfacesComboBox->addItem(ifname);
+ interface_[ifname].reader_thread = NULL;
+ interface_[ifname].out_fd = -1;
+ interface_[ifname].log_dialog = NULL;
+ }
+ ui->interfacesComboBox->blockSignals(false);
+
+ initializeControls(toolbar);
+
+#ifdef Q_OS_MAC
+ foreach (QWidget *w, findChildren<QWidget *>())
+ {
+ w->setAttribute(Qt::WA_MacSmallSize, true);
+ }
+#endif
+
+ if (!use_spacer_)
+ {
+ ui->horizontalSpacer->changeSize(0,0, QSizePolicy::Fixed, QSizePolicy::Fixed);
+ }
+
+ updateWidgets();
+}
+
+InterfaceToolbar::~InterfaceToolbar()
+{
+ foreach (QString ifname, interface_.keys())
+ {
+ if (interface_[ifname].log_dialog)
+ {
+ interface_[ifname].log_dialog->close();
+ }
+ }
+
+ delete ui;
+}
+
+void InterfaceToolbar::initializeControls(const iface_toolbar *toolbar)
+{
+ for (GList *walker = toolbar->controls; walker; walker = walker->next)
+ {
+ iface_toolbar_control *control = (iface_toolbar_control *)walker->data;
+
+ if (control_widget_.contains(control->num))
+ {
+ // Already have a widget with this number
+ continue;
+ }
+
+ QWidget *widget = NULL;
+ switch (control->ctrl_type)
+ {
+ case INTERFACE_TYPE_BOOLEAN:
+ widget = createCheckbox(control);
+ break;
+
+ case INTERFACE_TYPE_BUTTON:
+ widget = createButton(control);
+ break;
+
+ case INTERFACE_TYPE_SELECTOR:
+ widget = createSelector(control);
+ break;
+
+ case INTERFACE_TYPE_STRING:
+ widget = createString(control);
+ break;
+
+ default:
+ // Not supported
+ break;
+ }
+
+ if (widget)
+ {
+ widget->setProperty(interface_type_property, control->ctrl_type);
+ widget->setProperty(interface_role_property, control->ctrl_role);
+ control_widget_[control->num] = widget;
+ }
+ }
+}
+
+void InterfaceToolbar::setDefaultValue(int num, const QByteArray &value)
+{
+ foreach (QString ifname, interface_.keys())
+ {
+ // Adding default value to all interfaces
+ interface_[ifname].value[num] = value;
+ }
+ default_value_[num] = value;
+}
+
+QWidget *InterfaceToolbar::createCheckbox(iface_toolbar_control *control)
+{
+ QCheckBox *checkbox = new QCheckBox(QString().fromUtf8(control->display));
+ checkbox->setToolTip(QString().fromUtf8(control->tooltip));
+
+ if (control->default_value.boolean)
+ {
+ checkbox->setCheckState(Qt::Checked);
+ QByteArray default_value(1, 1);
+ setDefaultValue(control->num, default_value);
+ }
+
+ connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(onCheckBoxChanged(int)));
+
+ ui->leftLayout->addWidget(checkbox);
+
+ return checkbox;
+}
+
+QWidget *InterfaceToolbar::createButton(iface_toolbar_control *control)
+{
+ QPushButton *button = new QPushButton(QString().fromUtf8((gchar *)control->display));
+ button->setMaximumHeight(27);
+ button->setToolTip(QString().fromUtf8(control->tooltip));
+
+ switch (control->ctrl_role)
+ {
+ case INTERFACE_ROLE_CONTROL:
+ setDefaultValue(control->num, (gchar *)control->display);
+ connect(button, SIGNAL(pressed()), this, SLOT(onButtonPressed()));
+ break;
+
+ case INTERFACE_ROLE_HELP:
+ connect(button, SIGNAL(pressed()), this, SLOT(onHelpButtonPressed()));
+ if (help_link_.isEmpty())
+ {
+ // No help URL provided
+ button->hide();
+ }
+ break;
+
+ case INTERFACE_ROLE_LOGGER:
+ connect(button, SIGNAL(pressed()), this, SLOT(onLogButtonPressed()));
+ break;
+
+ case INTERFACE_ROLE_RESET:
+ button->setText("Reset");
+ button->setToolTip("Restore default values");
+ connect(button, SIGNAL(pressed()), this, SLOT(onResetButtonPressed()));
+ break;
+
+ default:
+ break;
+ }
+
+ ui->rightLayout->addWidget(button);
+
+ return button;
+}
+
+QWidget *InterfaceToolbar::createSelector(iface_toolbar_control *control)
+{
+ QLabel *label = new QLabel(QString().fromUtf8(control->display));
+ label->setToolTip(QString().fromUtf8(control->tooltip));
+ QComboBox *combobox = new QComboBox();
+ combobox->setToolTip(QString().fromUtf8(control->tooltip));
+ combobox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+
+ for (GList *walker = control->values; walker; walker = walker->next)
+ {
+ iface_toolbar_value *val = (iface_toolbar_value *)walker->data;
+ QString value = QString().fromUtf8((gchar *)val->value);
+ if (value.length() == 0)
+ {
+ // Invalid value
+ continue;
+ }
+ QString display = QString().fromUtf8((gchar *)val->display);
+ QByteArray interface_value;
+
+ interface_value.append(value);
+ if (display.length() == 0)
+ {
+ display = value;
+ }
+ else
+ {
+ interface_value.append('\0' + display);
+ }
+ combobox->addItem(display, value);
+ if (val->is_default)
+ {
+ combobox->setCurrentText(display);
+ setDefaultValue(control->num, value.toUtf8());
+ }
+ foreach (QString ifname, interface_.keys())
+ {
+ // Adding values to all interfaces
+ interface_[ifname].list[control->num].append(interface_value);
+ }
+ default_list_[control->num].append(interface_value);
+ }
+
+ connect(combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(onComboBoxChanged(int)));
+
+ ui->leftLayout->addWidget(label);
+ ui->leftLayout->addWidget(combobox);
+ label_widget_[control->num] = label;
+
+ return combobox;
+}
+
+QWidget *InterfaceToolbar::createString(iface_toolbar_control *control)
+{
+ QLabel *label = new QLabel(QString().fromUtf8(control->display));
+ label->setToolTip(QString().fromUtf8(control->tooltip));
+ InterfaceToolbarLineEdit *lineedit = new InterfaceToolbarLineEdit(NULL, control->validation, control->is_required);
+ lineedit->setToolTip(QString().fromUtf8(control->tooltip));
+ lineedit->setPlaceholderText(QString().fromUtf8(control->placeholder));
+
+ if (control->default_value.string)
+ {
+ lineedit->setText(QString().fromUtf8(control->default_value.string));
+ setDefaultValue(control->num, control->default_value.string);
+ }
+
+ connect(lineedit, SIGNAL(editedTextApplied()), this, SLOT(onLineEditChanged()));
+
+ ui->leftLayout->addWidget(label);
+ ui->leftLayout->addWidget(lineedit);
+ label_widget_[control->num] = label;
+ use_spacer_ = false;
+
+ return lineedit;
+}
+
+void InterfaceToolbar::setWidgetValue(QWidget *widget, int command, QByteArray payload)
+{
+ if (QComboBox *combobox = dynamic_cast<QComboBox *>(widget))
+ {
+ combobox->blockSignals(true);
+ switch (command)
+ {
+ case commandControlSet:
+ {
+ int idx = combobox->findData(payload);
+ if (idx != -1)
+ {
+ combobox->setCurrentIndex(idx);
+ }
+ break;
+ }
+
+ case commandControlAdd:
+ {
+ QString value;
+ QString display;
+ if (payload.contains('\0'))
+ {
+ // The payload contains "value\0display"
+ QList<QByteArray> values = payload.split('\0');
+ value = values[0];
+ display = values[1];
+ }
+ else
+ {
+ value = display = payload;
+ }
+
+ int idx = combobox->findData(value);
+ if (idx != -1)
+ {
+ // The value already exists, update item text
+ combobox->setItemText(idx, display);
+ }
+ else
+ {
+ combobox->addItem(display, value);
+ }
+ break;
+ }
+
+ case commandControlRemove:
+ {
+ if (payload.size() == 0)
+ {
+ combobox->clear();
+ }
+ else
+ {
+ int idx = combobox->findData(payload);
+ if (idx != -1)
+ {
+ combobox->removeItem(idx);
+ }
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ combobox->blockSignals(false);
+ }
+ else if (InterfaceToolbarLineEdit *lineedit = dynamic_cast<InterfaceToolbarLineEdit *>(widget))
+ {
+ // We don't block signals here because changes are applied with enter or apply button,
+ // and we want InterfaceToolbarLineEdit to always syntax check the text.
+ switch (command)
+ {
+ case commandControlSet:
+ lineedit->setText(payload);
+ lineedit->disableApplyButton();
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (QCheckBox *checkbox = dynamic_cast<QCheckBox *>(widget))
+ {
+ checkbox->blockSignals(true);
+ switch (command)
+ {
+ case commandControlSet:
+ {
+ Qt::CheckState state = Qt::Unchecked;
+ if (payload.size() > 0 && payload.at(0) != 0)
+ {
+ state = Qt::Checked;
+ }
+ checkbox->setCheckState(state);
+ break;
+ }
+
+ default:
+ break;
+ }
+ checkbox->blockSignals(false);
+ }
+ else if (QPushButton *button = dynamic_cast<QPushButton *>(widget))
+ {
+ if ((command == commandControlSet) &&
+ widget->property(interface_role_property).toInt() == INTERFACE_ROLE_CONTROL)
+ {
+ button->setText(payload);
+ }
+ }
+}
+
+void InterfaceToolbar::setInterfaceValue(QString ifname, QWidget *widget, int num, int command, QByteArray payload)
+{
+ if (dynamic_cast<QComboBox *>(widget))
+ {
+ switch (command)
+ {
+ case commandControlSet:
+ foreach (QByteArray entry, interface_[ifname].list[num])
+ {
+ if (entry == payload || entry.startsWith(payload + '\0'))
+ {
+ interface_[ifname].value[num] = payload;
+ }
+ }
+ break;
+
+ case commandControlAdd:
+ interface_[ifname].list[num].append(payload);
+ break;
+
+ case commandControlRemove:
+ if (payload.size() == 0)
+ {
+ interface_[ifname].value[num].clear();
+ interface_[ifname].list[num].clear();
+ }
+ else
+ {
+ foreach (QByteArray entry, interface_[ifname].list[num])
+ {
+ if (entry == payload || entry.startsWith(payload + '\0'))
+ {
+ interface_[ifname].list[num].removeAll(entry);
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (dynamic_cast<InterfaceToolbarLineEdit *>(widget))
+ {
+ switch (command)
+ {
+ case commandControlSet:
+ interface_[ifname].value[num] = payload;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if ((widget->property(interface_type_property).toInt() == INTERFACE_TYPE_BUTTON) &&
+ (widget->property(interface_role_property).toInt() == INTERFACE_ROLE_LOGGER))
+ {
+ if (command == commandControlSet)
+ {
+ if (interface_[ifname].log_dialog)
+ {
+ interface_[ifname].log_dialog->clearText();
+ }
+ interface_[ifname].log_text.clear();
+ }
+ if (command == commandControlSet || command == commandControlAdd)
+ {
+ if (interface_[ifname].log_dialog)
+ {
+ interface_[ifname].log_dialog->appendText(payload);
+ }
+ interface_[ifname].log_text.append(payload);
+ }
+ }
+ else if (widget->property(interface_role_property).toInt() == INTERFACE_ROLE_CONTROL)
+ {
+ // QCheckBox or QPushButton
+ interface_[ifname].value[num] = payload;
+ }
+}
+
+
+void InterfaceToolbar::controlReceived(QString ifname, int num, int command, QByteArray payload)
+{
+ switch (command)
+ {
+ case commandControlSet:
+ case commandControlAdd:
+ case commandControlRemove:
+ if (QWidget *widget = control_widget_[num])
+ {
+ setInterfaceValue(ifname, widget, num, command, payload);
+
+ if (ifname.compare(ui->interfacesComboBox->currentText()) == 0)
+ {
+ setWidgetValue(widget, command, payload);
+ }
+ }
+ break;
+
+ case commandControlEnable:
+ case commandControlDisable:
+ if (QWidget *widget = control_widget_[num])
+ {
+ if (widget->property(interface_role_property).toInt() == INTERFACE_ROLE_CONTROL)
+ {
+ bool enable = (command == commandControlEnable ? true : false);
+ interface_[ifname].widget_disabled[num] = !enable;
+
+ if (ifname.compare(ui->interfacesComboBox->currentText()) == 0)
+ {
+ widget->setEnabled(enable);
+ if (label_widget_.contains(num))
+ {
+ label_widget_[num]->setEnabled(enable);
+ }
+ }
+ }
+ }
+ break;
+
+ case commandStatusMessage:
+ statusbar_push_temporary_msg("%s", payload.data());
+ break;
+
+ case commandInformationMessage:
+ simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "%s", payload.data());
+ break;
+
+ case commandWarningMessage:
+ simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK, "%s", payload.data());
+ break;
+
+ case commandErrorMessage:
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", payload.data());
+ break;
+
+ default:
+ // Unknown commands are silently ignored
+ break;
+ }
+}
+
+void InterfaceToolbar::controlSend(QString ifname, int num, int command, const QByteArray &payload = QByteArray())
+{
+ if (payload.length() > 65535)
+ {
+ // Not supported
+ return;
+ }
+
+ if (interface_[ifname].out_fd == -1)
+ {
+ // Does not have a control out channel
+ return;
+ }
+
+ ssize_t payload_length = payload.length() + 2;
+ unsigned char high_nibble = (payload_length >> 16) & 0xFF;
+ unsigned char mid_nibble = (payload_length >> 8) & 0xFF;
+ unsigned char low_nibble = (payload_length >> 0) & 0xFF;
+
+ QByteArray ba;
+
+ ba.append(SP_TOOLBAR_CTRL);
+ ba.append(high_nibble);
+ ba.append(mid_nibble);
+ ba.append(low_nibble);
+ ba.append(num);
+ ba.append(command);
+ ba.append(payload);
+
+ if (ws_write(interface_[ifname].out_fd, ba.data(), ba.length()) != ba.length())
+ {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Unable to send control message:\n%s.",
+ g_strerror(errno));
+ }
+}
+
+void InterfaceToolbar::onButtonPressed()
+{
+ const QString &ifname = ui->interfacesComboBox->currentText();
+ QPushButton *button = static_cast<QPushButton *>(sender());
+ int num = control_widget_.key(button);
+
+ controlSend(ifname, num, commandControlSet);
+}
+
+void InterfaceToolbar::onCheckBoxChanged(int state)
+{
+ const QString &ifname = ui->interfacesComboBox->currentText();
+ QCheckBox *checkbox = static_cast<QCheckBox *>(sender());
+ int num = control_widget_.key(checkbox);
+
+ QByteArray payload(1, state == Qt::Unchecked ? 0 : 1);
+ controlSend(ifname, num, commandControlSet, payload);
+ interface_[ifname].value[num] = payload;
+}
+
+void InterfaceToolbar::onComboBoxChanged(int idx)
+{
+ const QString &ifname = ui->interfacesComboBox->currentText();
+ QComboBox *combobox = static_cast<QComboBox *>(sender());
+ int num = control_widget_.key(combobox);
+ QString value = combobox->itemData(idx).toString();
+
+ QByteArray payload(value.toUtf8());
+ controlSend(ifname, num, commandControlSet, payload);
+ interface_[ifname].value[num] = payload;
+}
+
+void InterfaceToolbar::onLineEditChanged()
+{
+ const QString &ifname = ui->interfacesComboBox->currentText();
+ InterfaceToolbarLineEdit *lineedit = static_cast<InterfaceToolbarLineEdit *>(sender());
+ int num = control_widget_.key(lineedit);
+
+ QByteArray payload(lineedit->text().toUtf8());
+ controlSend(ifname, num, commandControlSet, payload);
+ interface_[ifname].value[num] = payload;
+}
+
+void InterfaceToolbar::onLogButtonPressed()
+{
+ const QString &ifname = ui->interfacesComboBox->currentText();
+
+ if (!interface_[ifname].log_dialog)
+ {
+ QPushButton *button = static_cast<QPushButton *>(sender());
+ interface_[ifname].log_dialog = new FunnelTextDialog(ifname + " " + button->text());
+ connect(interface_[ifname].log_dialog, SIGNAL(accepted()), this, SLOT(closeLog()));
+ connect(interface_[ifname].log_dialog, SIGNAL(rejected()), this, SLOT(closeLog()));
+
+ interface_[ifname].log_dialog->setText(interface_[ifname].log_text);
+ }
+
+ interface_[ifname].log_dialog->show();
+ interface_[ifname].log_dialog->raise();
+ interface_[ifname].log_dialog->activateWindow();
+}
+
+void InterfaceToolbar::onHelpButtonPressed()
+{
+ QUrl help_url(help_link_);
+
+ if (help_url.scheme().compare("file") != 0) {
+ QDesktopServices::openUrl(help_url);
+ }
+}
+
+void InterfaceToolbar::closeLog()
+{
+ FunnelTextDialog *log_dialog = static_cast<FunnelTextDialog *>(sender());
+
+ foreach (QString ifname, interface_.keys())
+ {
+ if (interface_[ifname].log_dialog == log_dialog)
+ {
+ interface_[ifname].log_dialog = NULL;
+ }
+ }
+}
+
+void InterfaceToolbar::startReaderThread(QString ifname, QString control_in)
+{
+ QThread *thread = new QThread;
+ InterfaceToolbarReader *reader = new InterfaceToolbarReader(ifname, control_in);
+ reader->moveToThread(thread);
+
+ connect(thread, SIGNAL(started()), reader, SLOT(loop()));
+ connect(reader, SIGNAL(finished()), thread, SLOT(quit()));
+ connect(reader, SIGNAL(finished()), reader, SLOT(deleteLater()));
+ connect(thread, SIGNAL(finished()), reader, SLOT(deleteLater()));
+ connect(reader, SIGNAL(received(QString, int, int, QByteArray)),
+ this, SLOT(controlReceived(QString, int, int, QByteArray)));
+
+ interface_[ifname].reader_thread = thread;
+
+ thread->start();
+}
+
+void InterfaceToolbar::startCapture(QString ifname, QString control_in, QString control_out)
+{
+ if (!interface_.contains(ifname) || // This interface is not for us
+ interface_[ifname].out_fd != -1) // Already have control channels for this interface
+ {
+ return;
+ }
+
+ // The reader thread will open control in channel
+ startReaderThread(ifname, control_in);
+
+ // Open control out channel
+ interface_[ifname].out_fd = ws_open(control_out.toUtf8(), O_WRONLY | O_BINARY, 0);
+
+ sendChangedValues(ifname);
+ controlSend(ifname, 0, commandControlInitialized);
+
+ updateWidgets();
+}
+
+void InterfaceToolbar::stopCapture()
+{
+ foreach (QString ifname, interface_.keys())
+ {
+ if (interface_[ifname].reader_thread)
+ {
+#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
+ interface_[ifname].reader_thread->requestInterruption();
+#endif
+ interface_[ifname].reader_thread = NULL;
+ }
+
+ if (interface_[ifname].out_fd != -1)
+ {
+ ws_close (interface_[ifname].out_fd);
+ interface_[ifname].out_fd = -1;
+ }
+
+ foreach (int num, control_widget_.keys())
+ {
+ // Reset disabled property for all widgets
+ interface_[ifname].widget_disabled[num] = false;
+
+ QWidget *widget = control_widget_[num];
+ if ((widget->property(interface_type_property).toInt() == INTERFACE_TYPE_BUTTON) &&
+ (widget->property(interface_role_property).toInt() == INTERFACE_ROLE_CONTROL))
+ {
+ // Reset default value for control buttons
+ interface_[ifname].value[num] = default_value_[num];
+
+ if (ifname.compare(ui->interfacesComboBox->currentText()) == 0)
+ {
+ setWidgetValue(widget, commandControlSet, default_value_[num]);
+ }
+ }
+ }
+ }
+
+ updateWidgets();
+}
+
+void InterfaceToolbar::sendChangedValues(QString ifname)
+{
+ // Send all values which has changed
+ foreach (int num, control_widget_.keys())
+ {
+ QWidget *widget = control_widget_[num];
+ if ((interface_[ifname].value[num] != default_value_[num]) &&
+ (widget->property(interface_type_property).toInt() != INTERFACE_TYPE_BUTTON) &&
+ (widget->property(interface_role_property).toInt() == INTERFACE_ROLE_CONTROL))
+ {
+ controlSend(ifname, num, commandControlSet, interface_[ifname].value[num]);
+ }
+ }
+}
+
+void InterfaceToolbar::onResetButtonPressed()
+{
+ const QString &ifname = ui->interfacesComboBox->currentText();
+
+ // Set default values to all widgets and interfaces
+ foreach (int num, control_widget_.keys())
+ {
+ QWidget *widget = control_widget_[num];
+ if (default_list_[num].size() > 0)
+ {
+ // This is a QComboBox. Clear list and add new entries.
+ setWidgetValue(widget, commandControlRemove, QByteArray());
+ interface_[ifname].list[num].clear();
+
+ foreach (QByteArray value, default_list_[num])
+ {
+ setWidgetValue(widget, commandControlAdd, value);
+ interface_[ifname].list[num].append(value);
+ }
+ }
+
+ switch (widget->property(interface_role_property).toInt())
+ {
+ case INTERFACE_ROLE_CONTROL:
+ setWidgetValue(widget, commandControlSet, default_value_[num]);
+ interface_[ifname].value[num] = default_value_[num];
+ break;
+
+ case INTERFACE_ROLE_LOGGER:
+ if (interface_[ifname].log_dialog)
+ {
+ interface_[ifname].log_dialog->clearText();
+ }
+ interface_[ifname].log_text.clear();
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+bool InterfaceToolbar::hasInterface(QString ifname)
+{
+ return interface_.contains(ifname);
+}
+
+void InterfaceToolbar::updateWidgets()
+{
+ const QString &ifname = ui->interfacesComboBox->currentText();
+ bool is_capturing = (interface_[ifname].out_fd == -1 ? false : true);
+
+ foreach (int num, control_widget_.keys())
+ {
+ QWidget *widget = control_widget_[num];
+ if (!is_capturing &&
+ (widget->property(interface_type_property).toInt() == INTERFACE_TYPE_BUTTON) &&
+ (widget->property(interface_role_property).toInt() == INTERFACE_ROLE_CONTROL))
+ {
+ widget->setEnabled(false);
+ }
+ else if (widget->property(interface_role_property).toInt() == INTERFACE_ROLE_CONTROL)
+ {
+ bool widget_enabled = !interface_[ifname].widget_disabled[num];
+ widget->setEnabled(widget_enabled);
+ if (label_widget_.contains(num))
+ {
+ label_widget_[num]->setEnabled(widget_enabled);
+ }
+ }
+ }
+
+ foreach (int num, control_widget_.keys())
+ {
+ QWidget *widget = control_widget_[num];
+ if ((widget->property(interface_type_property).toInt() == INTERFACE_TYPE_BUTTON) &&
+ (widget->property(interface_role_property).toInt() == INTERFACE_ROLE_RESET))
+ {
+ widget->setEnabled(!is_capturing);
+ }
+ }
+}
+
+void InterfaceToolbar::on_interfacesComboBox_currentIndexChanged(const QString &ifname)
+{
+ foreach (int num, control_widget_.keys())
+ {
+ QWidget *widget = control_widget_[num];
+ if (interface_[ifname].list[num].size() > 0)
+ {
+ // This is a QComboBox. Clear list and add new entries.
+ setWidgetValue(widget, commandControlRemove, QByteArray());
+
+ foreach (QByteArray value, interface_[ifname].list[num])
+ {
+ setWidgetValue(widget, commandControlAdd, value);
+ }
+ }
+
+ if (widget->property(interface_role_property).toInt() == INTERFACE_ROLE_CONTROL)
+ {
+ setWidgetValue(widget, commandControlSet, interface_[ifname].value[num]);
+ }
+ }
+
+ updateWidgets();
+}
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/interface_toolbar.h b/ui/qt/interface_toolbar.h
new file mode 100644
index 0000000000..ebde37db4d
--- /dev/null
+++ b/ui/qt/interface_toolbar.h
@@ -0,0 +1,120 @@
+/* interface_toolbar.h
+ *
+ * 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.
+ */
+
+#ifndef INTERFACE_TOOLBAR_H
+#define INTERFACE_TOOLBAR_H
+
+#include <glib.h>
+
+#include "ui/iface_toolbar.h"
+#include "funnel_text_dialog.h"
+#include "interface_toolbar_reader.h"
+
+#include <QFrame>
+#include <QMap>
+#include <QString>
+
+
+namespace Ui {
+class InterfaceToolbar;
+}
+
+struct interface_values
+{
+ QThread *reader_thread;
+ int out_fd;
+ QMap<int, QByteArray> value;
+ QMap<int, QList<QByteArray> > list;
+ FunnelTextDialog *log_dialog;
+ QString log_text;
+ QMap<int, bool> widget_disabled;
+};
+
+class InterfaceToolbar : public QFrame
+{
+ Q_OBJECT
+
+public:
+ explicit InterfaceToolbar(QWidget *parent = 0, const iface_toolbar *toolbar = NULL);
+ ~InterfaceToolbar();
+
+ void startCapture(QString ifname, QString control_in, QString control_out);
+ void stopCapture();
+ bool hasInterface(QString ifname);
+
+public slots:
+ void controlReceived(QString ifname, int num, int command, QByteArray message);
+
+signals:
+ void closeReader();
+
+private slots:
+ void startReaderThread(QString ifname, QString control_in);
+ void updateWidgets();
+
+ void onButtonPressed();
+ void onCheckBoxChanged(int state);
+ void onComboBoxChanged(int idx);
+ void onLineEditChanged();
+ void onLogButtonPressed();
+ void onHelpButtonPressed();
+ void onResetButtonPressed();
+
+ void closeLog();
+
+ void on_interfacesComboBox_currentIndexChanged(const QString &ifname);
+
+private:
+ void initializeControls(const iface_toolbar *toolbar);
+ void setDefaultValue(int num, const QByteArray &value);
+ void sendChangedValues(QString ifname);
+ QWidget *createCheckbox(iface_toolbar_control *control);
+ QWidget *createButton(iface_toolbar_control *control);
+ QWidget *createSelector(iface_toolbar_control *control);
+ QWidget *createString(iface_toolbar_control *control);
+ void controlSend(QString ifname, int num, int type, const QByteArray &payload);
+ void setWidgetValue(QWidget *widget, int type, QByteArray payload);
+ void setInterfaceValue(QString ifname, QWidget *widget, int num, int type, QByteArray payload);
+
+ Ui::InterfaceToolbar *ui;
+ QMap<QString, struct interface_values> interface_;
+ QMap<int, QByteArray> default_value_;
+ QMap<int, QList<QByteArray> > default_list_;
+ QMap<int, QWidget *> control_widget_;
+ QMap<int, QWidget *> label_widget_;
+ QString help_link_;
+ bool use_spacer_;
+};
+
+#endif // INTERFACE_TOOLBAR_H
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/interface_toolbar.ui b/ui/qt/interface_toolbar.ui
new file mode 100644
index 0000000000..20faae5a57
--- /dev/null
+++ b/ui/qt/interface_toolbar.ui
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>InterfaceToolbar</class>
+ <widget class="QFrame" name="InterfaceToolbar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>32</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Frame</string>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="interfacesLabel">
+ <property name="toolTip">
+ <string>Select interface</string>
+ </property>
+ <property name="text">
+ <string>Interface</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="interfacesComboBox">
+ <property name="toolTip">
+ <string>Select interface</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="leftLayout"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="rightLayout"/>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/ui/qt/interface_toolbar_lineedit.cpp b/ui/qt/interface_toolbar_lineedit.cpp
new file mode 100644
index 0000000000..181bcb3be5
--- /dev/null
+++ b/ui/qt/interface_toolbar_lineedit.cpp
@@ -0,0 +1,149 @@
+/* interface_toolbar_lineedit.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 "config.h"
+
+#include "interface_toolbar_lineedit.h"
+#include "stock_icon_tool_button.h"
+#include "epan/prefs.h"
+#include "color_utils.h"
+
+#include <QStyle>
+
+// To do:
+// - Make a narrower apply button
+
+InterfaceToolbarLineEdit::InterfaceToolbarLineEdit(QWidget *parent, QString validation_regex, bool is_required) :
+ QLineEdit(parent),
+ validation_regex_(validation_regex),
+ is_required_(is_required),
+ text_edited_(false)
+{
+ apply_button_ = new StockIconToolButton(this, "x-filter-apply");
+ apply_button_->setCursor(Qt::ArrowCursor);
+ apply_button_->setEnabled(false);
+ apply_button_->setToolTip(tr("Apply changes"));
+ apply_button_->setIconSize(QSize(24, 14));
+ apply_button_->setStyleSheet(
+ "QToolButton {"
+ " border: none;"
+ " background: transparent;" // Disables platform style on Windows.
+ " padding: 0 0 0 0;"
+ "}"
+ );
+
+ updateStyleSheet(isValid());
+
+ connect(this, SIGNAL(textChanged(const QString &)), this, SLOT(validateText()));
+ connect(this, SIGNAL(textEdited(const QString &)), this, SLOT(validateEditedText()));
+ connect(this, SIGNAL(returnPressed()), this, SLOT(applyEditedText()));
+ connect(apply_button_, SIGNAL(clicked()), this, SLOT(applyEditedText()));
+}
+
+void InterfaceToolbarLineEdit::validateText()
+{
+ bool valid = isValid();
+
+ apply_button_->setEnabled(valid);
+ updateStyleSheet(valid);
+}
+
+void InterfaceToolbarLineEdit::validateEditedText()
+{
+ text_edited_ = true;
+}
+
+void InterfaceToolbarLineEdit::applyEditedText()
+{
+ if (text_edited_ && isValid())
+ {
+ emit editedTextApplied();
+ disableApplyButton();
+ }
+}
+
+void InterfaceToolbarLineEdit::disableApplyButton()
+{
+ apply_button_->setEnabled(false);
+ text_edited_ = false;
+}
+
+bool InterfaceToolbarLineEdit::isValid()
+{
+ bool valid = true;
+
+ if (is_required_ && text().length() == 0)
+ {
+ valid = false;
+ }
+
+ if (!validation_regex_.isEmpty() && text().length() > 0)
+ {
+ QRegExp expr(validation_regex_);
+ if (!expr.isValid() || expr.indexIn(text(), 0) == -1)
+ {
+ valid = false;
+ }
+ }
+
+ return valid;
+}
+
+void InterfaceToolbarLineEdit::updateStyleSheet(bool is_valid)
+{
+ int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ QSize apsz = apply_button_->sizeHint();
+
+ QString style_sheet = QString(
+ "InterfaceToolbarLineEdit {"
+ " padding-right: %1px;"
+ " background-color: %2;"
+ "}"
+ )
+ .arg(apsz.width() + frameWidth)
+ .arg(is_valid ? QString("") : ColorUtils::fromColorT(prefs.gui_text_invalid).name());
+
+ setStyleSheet(style_sheet);
+}
+
+void InterfaceToolbarLineEdit::resizeEvent(QResizeEvent *)
+{
+ int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ QSize apsz = apply_button_->sizeHint();
+
+ apply_button_->move(contentsRect().right() - frameWidth - apsz.width() + 2,
+ contentsRect().top());
+ apply_button_->setMinimumHeight(contentsRect().height());
+ apply_button_->setMaximumHeight(contentsRect().height());
+}
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/interface_toolbar_lineedit.h b/ui/qt/interface_toolbar_lineedit.h
new file mode 100644
index 0000000000..e26a50c976
--- /dev/null
+++ b/ui/qt/interface_toolbar_lineedit.h
@@ -0,0 +1,71 @@
+/* interface_toolbar_lineedit.h
+ *
+ * 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.
+ */
+
+#ifndef INTERFACE_TOOLBAR_LINEEDIT_H
+#define INTERFACE_TOOLBAR_LINEEDIT_H
+
+#include <QLineEdit>
+
+class StockIconToolButton;
+
+class InterfaceToolbarLineEdit : public QLineEdit
+{
+ Q_OBJECT
+
+public:
+ explicit InterfaceToolbarLineEdit(QWidget *parent = 0, QString validation_regex = QString(), bool is_required = false);
+ void disableApplyButton();
+
+protected:
+ void resizeEvent(QResizeEvent *);
+
+signals:
+ void editedTextApplied();
+
+private slots:
+ void validateText();
+ void validateEditedText();
+ void applyEditedText();
+
+private:
+ bool isValid();
+ void updateStyleSheet(bool is_valid);
+
+ StockIconToolButton *apply_button_;
+ QString validation_regex_;
+ bool is_required_;
+ bool text_edited_;
+};
+
+#endif // INTERFACE_TOOLBAR_LINEEDIT_H
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/interface_toolbar_reader.cpp b/ui/qt/interface_toolbar_reader.cpp
new file mode 100644
index 0000000000..5c8c52a247
--- /dev/null
+++ b/ui/qt/interface_toolbar_reader.cpp
@@ -0,0 +1,140 @@
+/* interface_toolbar_reader.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 "config.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+
+#include "interface_toolbar_reader.h"
+#include "sync_pipe.h"
+#include "wsutil/file_util.h"
+
+#include <QThread>
+
+const int header_size = 6;
+
+// To do:
+// - Add support for WIN32
+
+void InterfaceToolbarReader::loop()
+{
+#ifndef _WIN32
+ struct timeval timeout;
+ QByteArray header;
+ QByteArray payload;
+ fd_set readfds;
+
+ int fd = ws_open(control_in_.toUtf8(), O_RDONLY | O_BINARY | O_NONBLOCK, 0);
+ if (fd == -1)
+ {
+ emit finished();
+ return;
+ }
+
+ forever
+ {
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+
+ timeout.tv_sec = 2;
+ timeout.tv_usec = 0;
+
+ int ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
+ if (ret == -1)
+ {
+ break;
+ }
+#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
+ if (QThread::currentThread()->isInterruptionRequested())
+ {
+ break;
+ }
+#endif
+
+ if (ret > 0 && FD_ISSET(fd, &readfds))
+ {
+ header.resize(header_size);
+ if (ws_read(fd, header.data(), header_size) != header_size)
+ {
+ break;
+ }
+
+ unsigned char high_nibble = header[1] & 0xFF;
+ unsigned char mid_nibble = header[2] & 0xFF;
+ unsigned char low_nibble = header[3] & 0xFF;
+ ssize_t payload_len = (ssize_t)((high_nibble << 16) + (mid_nibble << 8) + low_nibble) - 2;
+
+ payload.resize(payload_len);
+ if (payload_len > 0)
+ {
+ ssize_t total_len = 0;
+ while (total_len < payload_len)
+ {
+ ssize_t read_len = ws_read(fd, payload.data() + total_len, payload_len - total_len);
+ if (read_len == -1)
+ {
+ if (errno != EAGAIN)
+ {
+ break;
+ }
+ }
+ else
+ {
+ total_len += read_len;
+ }
+ }
+ if (total_len != payload_len)
+ {
+ break;
+ }
+ }
+ if (header[0] == SP_TOOLBAR_CTRL)
+ {
+ emit received(ifname_, (unsigned char)header[4], (unsigned char)header[5], payload);
+ }
+ }
+ }
+
+ ws_close(fd);
+#endif
+ emit finished();
+}
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/interface_toolbar_reader.h b/ui/qt/interface_toolbar_reader.h
new file mode 100644
index 0000000000..1b34db4fb0
--- /dev/null
+++ b/ui/qt/interface_toolbar_reader.h
@@ -0,0 +1,65 @@
+/* interface_toolbar_reader.h
+ *
+ * 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.
+ */
+
+#ifndef INTERFACE_TOOLBAR_READER_H
+#define INTERFACE_TOOLBAR_READER_H
+
+#include <QObject>
+#include <QByteArray>
+
+namespace Ui {
+class InterfaceToolbarReader;
+}
+
+class InterfaceToolbarReader : public QObject
+{
+ Q_OBJECT
+
+public:
+ InterfaceToolbarReader(QString ifname, QString control_in, QObject *parent = 0) :
+ QObject(parent), ifname_(ifname), control_in_(control_in) {}
+
+public slots:
+ void loop();
+
+signals:
+ void received(QString ifname, int num, int command, QByteArray payload);
+ void finished();
+
+private:
+ QString ifname_;
+ QString control_in_;
+};
+
+#endif // INTERFACE_TOOLBAR_READER_H
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index 1570b4f4cc..0952594516 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -33,6 +33,7 @@
#include <epan/export_object.h>
#include "ui/commandline.h"
+#include "ui/iface_toolbar.h"
#ifdef HAVE_LIBPCAP
#include "ui/capture.h"
@@ -61,6 +62,7 @@
#include "file_set_dialog.h"
#include "funnel_statistics.h"
#include "import_text_dialog.h"
+#include "interface_toolbar.h"
#include "packet_list.h"
#include "proto_tree.h"
#include "simple_dialog.h"
@@ -205,6 +207,23 @@ static void plugin_if_mainwindow_update_toolbars(gconstpointer user_data)
if (g_hash_table_lookup_extended(data_set, "toolbar_name", NULL, NULL)) {
QString toolbarName((const char *)g_hash_table_lookup(data_set, "toolbar_name"));
gbl_cur_main_window_->removeAdditionalToolbar(toolbarName);
+
+ }
+}
+
+static void mainwindow_add_toolbar(const iface_toolbar *toolbar_entry)
+{
+ if (gbl_cur_main_window_ && toolbar_entry)
+ {
+ gbl_cur_main_window_->addInterfaceToolbar(toolbar_entry);
+ }
+}
+
+static void mainwindow_remove_toolbar(const gchar *menu_title)
+{
+ if (gbl_cur_main_window_ && menu_title)
+ {
+ gbl_cur_main_window_->removeInterfaceToolbar(menu_title);
}
}
@@ -759,6 +778,17 @@ MainWindow::MainWindow(QWidget *parent) :
#endif
plugin_if_register_gui_cb(PLUGIN_IF_REMOVE_TOOLBAR, plugin_if_mainwindow_update_toolbars);
+#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) && !defined(_WIN32)
+ // Register Interface Toolbar callbacks
+ //
+ // Qt version must be 5.2 or higher because the use of
+ // QThread::requestInterruption() in interface_toolbar.cpp and
+ // QThread::isInterruptionRequested() in interface_toolbar_reader.cpp
+ //
+ // The toolbar in/out control pipes are not supported on WIN32 yet.
+ iface_toolbar_register_cb(mainwindow_add_toolbar, mainwindow_remove_toolbar);
+#endif
+
main_ui_->mainStack->setCurrentWidget(main_welcome_);
}
@@ -779,6 +809,13 @@ QMenu *MainWindow::createPopupMenu()
menu->addAction(main_ui_->actionViewFilterToolbar);
menu->addAction(main_ui_->actionViewWirelessToolbar);
+ if (!main_ui_->menuInterfaceToolbars->actions().isEmpty()) {
+ QMenu *submenu = menu->addMenu(main_ui_->menuInterfaceToolbars->title());
+ foreach (QAction *action, main_ui_->menuInterfaceToolbars->actions()) {
+ submenu->addAction(action);
+ }
+ }
+
if (!main_ui_->menuAdditionalToolbars->actions().isEmpty()) {
QMenu *subMenu = menu->addMenu(main_ui_->menuAdditionalToolbars->title());
foreach (QAction *action, main_ui_->menuAdditionalToolbars->actions()) {
@@ -795,6 +832,76 @@ QMenu *MainWindow::createPopupMenu()
return menu;
}
+void MainWindow::addInterfaceToolbar(const iface_toolbar *toolbar_entry)
+{
+ QMenu *menu = main_ui_->menuInterfaceToolbars;
+ bool visible = g_list_find_custom(recent.interface_toolbars, toolbar_entry->menu_title, (GCompareFunc) strcmp) ? true : false;
+
+ QString title = QString().fromUtf8(toolbar_entry->menu_title);
+ QAction *action = new QAction(title, menu);
+ action->setEnabled(true);
+ action->setCheckable(true);
+ action->setChecked(visible);
+ action->setToolTip(tr("Show or hide the toolbar"));
+
+ QAction *before = NULL;
+ foreach (QAction *action, menu->actions()) {
+ // Ensure we add the menu entries in sorted order
+ if (action->text().compare(title, Qt::CaseInsensitive) > 0) {
+ before = action;
+ break;
+ }
+ }
+ menu->insertAction(before, action);
+
+ InterfaceToolbar *interface_toolbar = new InterfaceToolbar(this, toolbar_entry);
+
+ QToolBar *toolbar = new QToolBar(this);
+ toolbar->addWidget(interface_toolbar);
+ toolbar->setMovable(false);
+ toolbar->setVisible(visible);
+
+ action->setData(qVariantFromValue(toolbar));
+
+ addToolBar(Qt::TopToolBarArea, toolbar);
+ insertToolBarBreak(toolbar);
+
+ if (show_hide_actions_) {
+ show_hide_actions_->addAction(action);
+ }
+
+ menu->menuAction()->setVisible(true);
+}
+
+void MainWindow::removeInterfaceToolbar(const gchar *menu_title)
+{
+ QMenu *menu = main_ui_->menuInterfaceToolbars;
+ QAction *action = NULL;
+ QMap<QAction *, QWidget *>::iterator i;
+
+ QString title = QString().fromUtf8(menu_title);
+ foreach (action, menu->actions()) {
+ if (title.compare(action->text()) == 0) {
+ break;
+ }
+ }
+
+ if (action) {
+ if (show_hide_actions_) {
+ show_hide_actions_->removeAction(action);
+ }
+ menu->removeAction(action);
+
+ QToolBar *toolbar = action->data().value<QToolBar *>();
+ removeToolBar(toolbar);
+
+ delete action;
+ delete toolbar;
+ }
+
+ menu->menuAction()->setVisible(!menu->actions().isEmpty());
+}
+
void MainWindow::setPipeInputHandler(gint source, gpointer user_data, ws_process_id *child_process, pipe_input_cb_t input_cb)
{
pipe_source_ = source;
@@ -1895,6 +2002,9 @@ void MainWindow::initShowHideMainWidgets()
showHideMainWidgets(shmwa);
}
+ // Initial hide the Interface Toolbar submenu
+ main_ui_->menuInterfaceToolbars->menuAction()->setVisible(false);
+
/* Initially hide the additional toolbars menus */
main_ui_->menuAdditionalToolbars->menuAction()->setVisible(false);
@@ -2356,7 +2466,7 @@ void MainWindow::resizeEvent(QResizeEvent *event)
}
/* Update main window items based on whether there's a capture in progress. */
-void MainWindow::setForCaptureInProgress(bool capture_in_progress)
+void MainWindow::setForCaptureInProgress(bool capture_in_progress, GArray *ifaces)
{
setMenusForCaptureInProgress(capture_in_progress);
@@ -2368,6 +2478,20 @@ void MainWindow::setForCaptureInProgress(bool capture_in_progress)
// set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
#endif
+
+#ifdef HAVE_EXTCAP
+ QList<InterfaceToolbar *> toolbars = findChildren<InterfaceToolbar *>();
+ foreach (InterfaceToolbar *toolbar, toolbars) {
+ if (capture_in_progress && ifaces) {
+ for (guint i = 0; i < ifaces->len; i++) {
+ interface_options interface_opts = g_array_index(ifaces, interface_options, i);
+ toolbar->startCapture(interface_opts.name, interface_opts.extcap_control_in, interface_opts.extcap_control_out);
+ }
+ } else {
+ toolbar->stopCapture();
+ }
+ }
+#endif
}
static QList<register_stat_group_t> menu_groups = QList<register_stat_group_t>()
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index aeb3a18052..23e1de7cce 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -31,6 +31,7 @@
#include "file.h"
#include "ui/ui_util.h"
+#include "ui/iface_toolbar.h"
#include <epan/prefs.h>
#include <epan/plugin_if.h>
@@ -100,6 +101,9 @@ public:
void removeAdditionalToolbar(QString toolbarName);
+ void addInterfaceToolbar(const iface_toolbar *toolbar_entry);
+ void removeInterfaceToolbar(const gchar *menu_title);
+
protected:
virtual bool eventFilter(QObject *obj, QEvent *event);
virtual void keyPressEvent(QKeyEvent *event);
@@ -224,7 +228,7 @@ private:
void externalMenuHelper(ext_menu_t * menu, QMenu * subMenu, gint depth);
- void setForCaptureInProgress(bool capture_in_progress = false);
+ void setForCaptureInProgress(bool capture_in_progress = false, GArray *ifaces = NULL);
QMenu* findOrAddMenu(QMenu *parent_menu, QString& menu_text);
void recursiveCopyProtoTreeItems(QTreeWidgetItem *item, QString &clip, int ident_level);
diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui
index 39bfc55cb1..8ee6ec69c9 100644
--- a/ui/qt/main_window.ui
+++ b/ui/qt/main_window.ui
@@ -268,6 +268,11 @@
<property name="title">
<string>&amp;View</string>
</property>
+ <widget class="QMenu" name="menuInterfaceToolbars">
+ <property name="title">
+ <string>Interface Toolbars</string>
+ </property>
+ </widget>
<widget class="QMenu" name="menuZoom">
<property name="title">
<string>&amp;Zoom</string>
@@ -345,6 +350,7 @@
<addaction name="actionViewMainToolbar"/>
<addaction name="actionViewFilterToolbar"/>
<addaction name="actionViewWirelessToolbar"/>
+ <addaction name="menuInterfaceToolbars"/>
<addaction name="menuAdditionalToolbars" />
<addaction name="actionViewStatusBar"/>
<addaction name="separator"/>
diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp
index 4103da00b8..33eaa56318 100644
--- a/ui/qt/main_window_slots.cpp
+++ b/ui/qt/main_window_slots.cpp
@@ -119,6 +119,7 @@
#include "funnel_statistics.h"
#include "gsm_map_summary_dialog.h"
#include "iax2_analysis_dialog.h"
+#include "interface_toolbar.h"
#include "io_graph_dialog.h"
#include <additional_toolbar.h>
#include "lbm_stream_dialog.h"
@@ -486,6 +487,15 @@ void MainWindow::layoutToolbars()
main_ui_->wirelessToolBar->setVisible(recent.wireless_toolbar_show);
main_ui_->statusBar->setVisible(recent.statusbar_show);
+ foreach (QAction *action, main_ui_->menuInterfaceToolbars->actions()) {
+ QToolBar *toolbar = action->data().value<QToolBar *>();
+ if (g_list_find_custom(recent.interface_toolbars, action->text().toUtf8(), (GCompareFunc) strcmp)) {
+ toolbar->setVisible(true);
+ } else {
+ toolbar->setVisible(false);
+ }
+ }
+
QList<QToolBar *> toolbars = findChildren<QToolBar *>();
foreach (QToolBar *bar, toolbars) {
AdditionalToolBar *iftoolbar = dynamic_cast<AdditionalToolBar *>(bar);
@@ -495,6 +505,7 @@ void MainWindow::layoutToolbars()
visible = true;
iftoolbar->setVisible(visible);
+
}
}
}
@@ -523,6 +534,14 @@ void MainWindow::updateRecentActions()
main_ui_->actionViewPacketDetails->setChecked(recent.tree_view_show && prefs_has_layout_pane_content(layout_pane_content_pdetails));
main_ui_->actionViewPacketBytes->setChecked(recent.byte_view_show && prefs_has_layout_pane_content(layout_pane_content_pbytes));
+ foreach (QAction *action, main_ui_->menuInterfaceToolbars->actions()) {
+ if (g_list_find_custom(recent.interface_toolbars, action->text().toUtf8(), (GCompareFunc) strcmp)) {
+ action->setChecked(true);
+ } else {
+ action->setChecked(false);
+ }
+ }
+
foreach (QAction * action, main_ui_->menuAdditionalToolbars->actions()) {
ext_toolbar_t * toolbar = VariantPointer<ext_toolbar_t>::asPtr(action->data());
bool checked = false;
@@ -628,7 +647,7 @@ void MainWindow::queuedFilterAction(QString action_filter, FilterAction::Action
// Capture callbacks
-void MainWindow::captureCapturePrepared(capture_session *) {
+void MainWindow::captureCapturePrepared(capture_session *session) {
#ifdef HAVE_LIBPCAP
setTitlebarForCaptureInProgress();
@@ -636,7 +655,7 @@ void MainWindow::captureCapturePrepared(capture_session *) {
/* Disable menu items that make no sense if you're currently running
a capture. */
- setForCaptureInProgress(true);
+ setForCaptureInProgress(true, session->capture_opts->ifaces);
// set_capture_if_dialog_for_capture_in_progress(TRUE);
// /* Don't set up main window for a capture file. */
@@ -645,14 +664,14 @@ void MainWindow::captureCapturePrepared(capture_session *) {
#endif // HAVE_LIBPCAP
}
-void MainWindow::captureCaptureUpdateStarted(capture_session *) {
+void MainWindow::captureCaptureUpdateStarted(capture_session *session) {
#ifdef HAVE_LIBPCAP
/* We've done this in "prepared" above, but it will be cleared while
switching to the next multiple file. */
setTitlebarForCaptureInProgress();
- setForCaptureInProgress(true);
+ setForCaptureInProgress(true, session->capture_opts->ifaces);
setForCapturedPackets(true);
#endif // HAVE_LIBPCAP
@@ -2257,6 +2276,19 @@ void MainWindow::showHideMainWidgets(QAction *action)
recent.byte_view_show = show;
main_ui_->actionViewPacketBytes->setChecked(show);
} else {
+ foreach (QAction *action, main_ui_->menuInterfaceToolbars->actions()) {
+ QToolBar *toolbar = action->data().value<QToolBar *>();
+ if (widget == toolbar) {
+ GList *entry = g_list_find_custom(recent.interface_toolbars, action->text().toUtf8(), (GCompareFunc) strcmp);
+ if (show && !entry) {
+ recent.interface_toolbars = g_list_append(recent.interface_toolbars, g_strdup(action->text().toUtf8()));
+ } else if (!show && entry) {
+ recent.interface_toolbars = g_list_remove(recent.interface_toolbars, entry->data);
+ }
+ action->setChecked(show);
+ }
+ }
+
ext_toolbar_t * toolbar = VariantPointer<ext_toolbar_t>::asPtr(action->data());
if (toolbar) {
GList *entry = g_list_find_custom(recent.gui_additional_toolbars, toolbar->name, (GCompareFunc) strcmp);
diff --git a/ui/recent.c b/ui/recent.c
index 30c44f485a..898296c1c0 100644
--- a/ui/recent.c
+++ b/ui/recent.c
@@ -75,6 +75,7 @@
#define RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES "gui.rlc_pdus_from_mac_frames"
#define RECENT_GUI_CUSTOM_COLORS "gui.custom_colors"
#define RECENT_GUI_TOOLBAR_SHOW "gui.additional_toolbar_show"
+#define RECENT_GUI_INTERFACE_TOOLBAR_SHOW "gui.interface_toolbar_show"
#define RECENT_GUI_GEOMETRY "gui.geom."
@@ -866,6 +867,12 @@ write_profile_recent(void)
fprintf(rf, RECENT_GUI_TOOLBAR_SHOW ": %s\n", string_list);
g_free(string_list);
+ fprintf(rf, "\n# Interface Toolbars show.\n");
+ fprintf(rf, "# List of interface toolbars to show.\n");
+ string_list = join_string_list(recent.interface_toolbars);
+ fprintf(rf, RECENT_GUI_INTERFACE_TOOLBAR_SHOW ": %s\n", string_list);
+ g_free(string_list);
+
fclose(rf);
/* XXX - catch I/O errors (e.g. "ran out of disk space") and return
@@ -1121,6 +1128,8 @@ read_set_recent_pair_static(gchar *key, const gchar *value,
recent.gui_fileopen_remembered_dir = g_strdup(value);
} else if (strcmp(key, RECENT_GUI_TOOLBAR_SHOW) == 0) {
recent.gui_additional_toolbars = prefs_get_string_list(value);
+ } else if (strcmp(key, RECENT_GUI_INTERFACE_TOOLBAR_SHOW) == 0) {
+ recent.interface_toolbars = prefs_get_string_list(value);
}
return PREFS_SET_OK;
@@ -1294,6 +1303,11 @@ recent_read_profile_static(char **rf_path_return, int *rf_errno_return)
recent.gui_additional_toolbars = NULL;
}
+ if (recent.interface_toolbars) {
+ g_list_free_full (recent.interface_toolbars, g_free);
+ recent.interface_toolbars = NULL;
+ }
+
/* Construct the pathname of the user's profile recent file. */
rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE);
diff --git a/ui/recent.h b/ui/recent.h
index 2f33302b9b..d41dd60d3d 100644
--- a/ui/recent.h
+++ b/ui/recent.h
@@ -111,6 +111,7 @@ typedef struct recent_settings_tag {
gboolean gui_rlc_use_pdus_from_mac;
GList *custom_colors;
GList *gui_additional_toolbars;
+ GList *interface_toolbars;
} recent_settings_t;
/** Global recent settings. */