summaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
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. */