aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStig Bjørlykke <stig@bjorlykke.org>2017-04-28 21:26:53 +0200
committerStig Bjørlykke <stig@bjorlykke.org>2017-05-02 09:34:01 +0000
commit741d4f5898082f29c6732f16dd57139021545c15 (patch)
tree92f378c9557fd526f5469d8a4f30ea6563cd52e4
parentafb4de370a4c54e08e9367b55ae142414efc6e8f (diff)
Qt: Interface Toolbar improvements
- Select one of the capturing interfaces when start capture - Only send user changed control values when start capture - Don't show hidden interfaces - Allow a toolbar with no interfaces - Renamed button role "reset" to "restore" - Improved control number validation - Updated documentation Change-Id: Icc8d04043c95c1f3ef8d7cdc3b251be4471cba0a Reviewed-on: https://code.wireshark.org/review/21445 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>
-rw-r--r--doc/README.extcap16
-rwxr-xr-xdoc/extcap_example.py6
-rw-r--r--extcap_parser.c4
-rw-r--r--ui/iface_toolbar.h2
-rw-r--r--ui/qt/interface_toolbar.cpp178
-rw-r--r--ui/qt/interface_toolbar.h13
-rw-r--r--ui/qt/interface_toolbar.ui3
-rw-r--r--ui/qt/main_window.cpp7
8 files changed, 165 insertions, 64 deletions
diff --git a/doc/README.extcap b/doc/README.extcap
index 50db8f67a3..f1e27ce01c 100644
--- a/doc/README.extcap
+++ b/doc/README.extcap
@@ -238,7 +238,7 @@ TYPE provides the type of control to add to the toolbar and DISPLAY the name in
Additionally TOOLTIP and PLACEHOLDER may be provided, which will give the user an
explanation within the GUI.
-All controls, except from the logger, help and reset buttons, may be disabled
+All controls, except from the logger, help and restore buttons, may be disabled
(and enabled) in GUI by the extcap during capture. This can be because of set-once
operations, or operations which takes some time to complete.
@@ -260,8 +260,9 @@ This TYPEs are defined as controls:
* BUTTON - This provides a button with different ROLEs:
- ** CONTROL - This button will send a signal.
- This is the default role if nothing is configured.
+ ** CONTROL - This button will send a signal when pressed.
+ This is the default if no role is configured.
+ The button is only enabled when capturing.
The extcap utility can set the button text at startup, and can change (set) the
button text and receive button press signals while capturing. The button is
@@ -282,12 +283,13 @@ This TYPEs are defined as controls:
The Set command will clear the log before adding the entry.
** HELP - This button opens the help page, if configured.
- This type has no controls and will not be used in communication.
+ This role has no controls and will not be used in communication.
Valid Commands: NONE.
- ** RESET - This button will restore all control values to default.
- This type has no controls and will not be used in communication.
+ ** RESTORE - This button will restore all control values to default.
+ This role has no controls and will not be used in communication.
+ The button is only enabled when not capturing.
Valid Commands: NONE.
@@ -376,7 +378,7 @@ Control packet:
The length of the following payload. Maximum length is 65535 bytes.
The Initialized command will be sent from the GUI to the extcap utility when all
-initial control values are sent after starting a capture. This is an indication
+user changed control values are sent after starting a capture. This is an indication
that the GUI is ready to receive control values.
The GUI will only send Initialized and Set commands. The extcap utility shall not
diff --git a/doc/extcap_example.py b/doc/extcap_example.py
index e7ea7b2d6b..10c294d940 100755
--- a/doc/extcap_example.py
+++ b/doc/extcap_example.py
@@ -73,7 +73,7 @@ CTRL_ARG_DELAY = 1
CTRL_ARG_VERIFY = 2
CTRL_ARG_BUTTON = 3
CTRL_ARG_HELP = 4
-CTRL_ARG_RESET = 5
+CTRL_ARG_RESTORE = 5
CTRL_ARG_LOGGER = 6
CTRL_ARG_NONE = 255
@@ -161,7 +161,7 @@ def extcap_interfaces():
print ("control {number=%d}{type=boolean}{display=Verify}{default=true}{tooltip=Verify package content}" % CTRL_ARG_VERIFY)
print ("control {number=%d}{type=button}{display=Turn on}{tooltip=Turn on or off}" % CTRL_ARG_BUTTON)
print ("control {number=%d}{type=button}{role=help}{display=Help}{tooltip=Show help}" % CTRL_ARG_HELP)
- print ("control {number=%d}{type=button}{role=reset}{display=Reset}{tooltip=Restore default values}" % CTRL_ARG_RESET)
+ print ("control {number=%d}{type=button}{role=restore}{display=Restore}{tooltip=Restore default values}" % CTRL_ARG_RESTORE)
print ("control {number=%d}{type=button}{role=logger}{display=Log}{tooltip=Show capture log}" % CTRL_ARG_LOGGER)
print ("value {control=%d}{value=1}{display=1}" % CTRL_ARG_DELAY)
print ("value {control=%d}{value=2}{display=2}" % CTRL_ARG_DELAY)
@@ -320,7 +320,7 @@ def control_write_defaults(fn_out):
# Write startup configuration to Toolbar controls
control_write(fn_out, CTRL_ARG_MESSAGE, CTRL_CMD_SET, message)
- control_write(fn_out, CTRL_ARG_DELAY, CTRL_CMD_SET, str(delay))
+ control_write(fn_out, CTRL_ARG_DELAY, CTRL_CMD_SET, str(int(delay)))
control_write(fn_out, CTRL_ARG_VERIFY, CTRL_CMD_SET, struct.pack('B', verify))
for i in range(1,16):
diff --git a/extcap_parser.c b/extcap_parser.c
index 7f7b6ceb0c..2f7a085947 100644
--- a/extcap_parser.c
+++ b/extcap_parser.c
@@ -730,8 +730,8 @@ static iface_toolbar_control *extcap_parse_control_sentence(GList *control_items
control->ctrl_role = INTERFACE_ROLE_HELP;
} else if (g_ascii_strcasecmp(param_value, "logger") == 0) {
control->ctrl_role = INTERFACE_ROLE_LOGGER;
- } else if (g_ascii_strcasecmp(param_value, "reset") == 0) {
- control->ctrl_role = INTERFACE_ROLE_RESET;
+ } else if (g_ascii_strcasecmp(param_value, "restore") == 0) {
+ control->ctrl_role = INTERFACE_ROLE_RESTORE;
} else {
printf("invalid role %s in CONTROL sentence\n", param_value);
control->ctrl_role = INTERFACE_ROLE_UNKNOWN;
diff --git a/ui/iface_toolbar.h b/ui/iface_toolbar.h
index 888c817230..5a5421cad7 100644
--- a/ui/iface_toolbar.h
+++ b/ui/iface_toolbar.h
@@ -41,7 +41,7 @@ typedef enum {
INTERFACE_ROLE_CONTROL,
INTERFACE_ROLE_HELP,
INTERFACE_ROLE_LOGGER,
- INTERFACE_ROLE_RESET
+ INTERFACE_ROLE_RESTORE
} iface_toolbar_ctrl_role;
typedef struct _iface_toolbar_value {
diff --git a/ui/qt/interface_toolbar.cpp b/ui/qt/interface_toolbar.cpp
index 56a1a53b34..dd178c9195 100644
--- a/ui/qt/interface_toolbar.cpp
+++ b/ui/qt/interface_toolbar.cpp
@@ -29,6 +29,8 @@
#include "ui/main_statusbar.h"
#include <ui_interface_toolbar.h>
+#include "capture_opts.h"
+#include "ui/capture_globals.h"
#include "sync_pipe.h"
#include "wsutil/file_util.h"
@@ -69,16 +71,13 @@ InterfaceToolbar::InterfaceToolbar(QWidget *parent, const iface_toolbar *toolbar
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);
@@ -194,7 +193,7 @@ QWidget *InterfaceToolbar::createButton(iface_toolbar_control *control)
{
case INTERFACE_ROLE_CONTROL:
setDefaultValue(control->num, (gchar *)control->display);
- connect(button, SIGNAL(pressed()), this, SLOT(onButtonPressed()));
+ connect(button, SIGNAL(pressed()), this, SLOT(onControlButtonPressed()));
break;
case INTERFACE_ROLE_HELP:
@@ -210,13 +209,12 @@ QWidget *InterfaceToolbar::createButton(iface_toolbar_control *control)
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()));
+ case INTERFACE_ROLE_RESTORE:
+ connect(button, SIGNAL(pressed()), this, SLOT(onRestoreButtonPressed()));
break;
default:
+ // Not supported
break;
}
@@ -237,7 +235,7 @@ QWidget *InterfaceToolbar::createSelector(iface_toolbar_control *control)
{
iface_toolbar_value *val = (iface_toolbar_value *)walker->data;
QString value = QString().fromUtf8((gchar *)val->value);
- if (value.length() == 0)
+ if (value.isEmpty())
{
// Invalid value
continue;
@@ -246,7 +244,7 @@ QWidget *InterfaceToolbar::createSelector(iface_toolbar_control *control)
QByteArray interface_value;
interface_value.append(value);
- if (display.length() == 0)
+ if (display.isEmpty())
{
display = value;
}
@@ -422,6 +420,10 @@ void InterfaceToolbar::setInterfaceValue(QString ifname, QWidget *widget, int nu
switch (command)
{
case commandControlSet:
+ if (interface_[ifname].value[num] != payload)
+ {
+ interface_[ifname].value_changed[num] = false;
+ }
foreach (QByteArray entry, interface_[ifname].list[num])
{
if (entry == payload || entry.startsWith(payload + '\0'))
@@ -462,6 +464,10 @@ void InterfaceToolbar::setInterfaceValue(QString ifname, QWidget *widget, int nu
switch (command)
{
case commandControlSet:
+ if (interface_[ifname].value[num] != payload)
+ {
+ interface_[ifname].value_changed[num] = false;
+ }
interface_[ifname].value[num] = payload;
break;
@@ -492,11 +498,22 @@ void InterfaceToolbar::setInterfaceValue(QString ifname, QWidget *widget, int nu
else if (widget->property(interface_role_property).toInt() == INTERFACE_ROLE_CONTROL)
{
// QCheckBox or QPushButton
- interface_[ifname].value[num] = payload;
+ switch (command)
+ {
+ case commandControlSet:
+ if (interface_[ifname].value[num] != payload)
+ {
+ interface_[ifname].value_changed[num] = false;
+ }
+ interface_[ifname].value[num] = payload;
+ break;
+
+ default:
+ break;
+ }
}
}
-
void InterfaceToolbar::controlReceived(QString ifname, int num, int command, QByteArray payload)
{
switch (command)
@@ -504,8 +521,9 @@ void InterfaceToolbar::controlReceived(QString ifname, int num, int command, QBy
case commandControlSet:
case commandControlAdd:
case commandControlRemove:
- if (QWidget *widget = control_widget_[num])
+ if (control_widget_.contains(num))
{
+ QWidget *widget = control_widget_[num];
setInterfaceValue(ifname, widget, num, command, payload);
if (ifname.compare(ui->interfacesComboBox->currentText()) == 0)
@@ -517,8 +535,9 @@ void InterfaceToolbar::controlReceived(QString ifname, int num, int command, QBy
case commandControlEnable:
case commandControlDisable:
- if (QWidget *widget = control_widget_[num])
+ if (control_widget_.contains(num))
{
+ QWidget *widget = control_widget_[num];
if (widget->property(interface_role_property).toInt() == INTERFACE_ROLE_CONTROL)
{
bool enable = (command == commandControlEnable ? true : false);
@@ -566,7 +585,7 @@ void InterfaceToolbar::controlSend(QString ifname, int num, int command, const Q
return;
}
- if (interface_[ifname].out_fd == -1)
+ if (ifname.isEmpty() || interface_[ifname].out_fd == -1)
{
// Does not have a control out channel
return;
@@ -595,7 +614,7 @@ void InterfaceToolbar::controlSend(QString ifname, int num, int command, const Q
}
}
-void InterfaceToolbar::onButtonPressed()
+void InterfaceToolbar::onControlButtonPressed()
{
const QString &ifname = ui->interfacesComboBox->currentText();
QPushButton *button = static_cast<QPushButton *>(sender());
@@ -613,6 +632,7 @@ void InterfaceToolbar::onCheckBoxChanged(int state)
QByteArray payload(1, state == Qt::Unchecked ? 0 : 1);
controlSend(ifname, num, commandControlSet, payload);
interface_[ifname].value[num] = payload;
+ interface_[ifname].value_changed[num] = true;
}
void InterfaceToolbar::onComboBoxChanged(int idx)
@@ -625,6 +645,7 @@ void InterfaceToolbar::onComboBoxChanged(int idx)
QByteArray payload(value.toUtf8());
controlSend(ifname, num, commandControlSet, payload);
interface_[ifname].value[num] = payload;
+ interface_[ifname].value_changed[num] = true;
}
void InterfaceToolbar::onLineEditChanged()
@@ -636,6 +657,7 @@ void InterfaceToolbar::onLineEditChanged()
QByteArray payload(lineedit->text().toUtf8());
controlSend(ifname, num, commandControlSet, payload);
interface_[ifname].value[num] = payload;
+ interface_[ifname].value_changed[num] = true;
}
void InterfaceToolbar::onLogButtonPressed()
@@ -661,7 +683,8 @@ void InterfaceToolbar::onHelpButtonPressed()
{
QUrl help_url(help_link_);
- if (help_url.scheme().compare("file") != 0) {
+ if (help_url.scheme().compare("file") != 0)
+ {
QDesktopServices::openUrl(help_url);
}
}
@@ -697,24 +720,48 @@ void InterfaceToolbar::startReaderThread(QString ifname, QString control_in)
thread->start();
}
-void InterfaceToolbar::startCapture(QString ifname, QString control_in, QString control_out)
+void InterfaceToolbar::startCapture(GArray *ifaces)
{
- if (!interface_.contains(ifname) || // This interface is not for us
- interface_[ifname].out_fd != -1) // Already have control channels for this interface
- {
+ if (!ifaces || ifaces->len == 0)
return;
- }
- // The reader thread will open control in channel
- startReaderThread(ifname, control_in);
+ const QString &selected_ifname = ui->interfacesComboBox->currentText();
+ QString first_capturing_ifname;
+ bool selected_found = false;
- // Open control out channel
- interface_[ifname].out_fd = ws_open(control_out.toUtf8(), O_WRONLY | O_BINARY, 0);
+ for (guint i = 0; i < ifaces->len; i++)
+ {
+ interface_options interface_opts = g_array_index(ifaces, interface_options, i);
+ QString ifname(interface_opts.name);
- sendChangedValues(ifname);
- controlSend(ifname, 0, commandControlInitialized);
+ if (!interface_.contains(ifname))
+ // This interface is not for us
+ continue;
- updateWidgets();
+ if (first_capturing_ifname.isEmpty())
+ first_capturing_ifname = ifname;
+
+ if (ifname.compare(selected_ifname) == 0)
+ selected_found = true;
+
+ if (interface_[ifname].out_fd != -1)
+ // Already have control channels for this interface
+ continue;
+
+ // The reader thread will open control in channel
+ startReaderThread(ifname, interface_opts.extcap_control_in);
+
+ // Open control out channel
+ interface_[ifname].out_fd = ws_open(interface_opts.extcap_control_out, O_WRONLY | O_BINARY, 0);
+
+ sendChangedValues(ifname);
+ controlSend(ifname, 0, commandControlInitialized);
+ }
+
+ if (!selected_found && !first_capturing_ifname.isEmpty())
+ ui->interfacesComboBox->setCurrentText(first_capturing_ifname);
+ else
+ updateWidgets();
}
void InterfaceToolbar::stopCapture()
@@ -764,7 +811,7 @@ void InterfaceToolbar::sendChangedValues(QString ifname)
foreach (int num, control_widget_.keys())
{
QWidget *widget = control_widget_[num];
- if ((interface_[ifname].value[num] != default_value_[num]) &&
+ if ((interface_[ifname].value_changed[num]) &&
(widget->property(interface_type_property).toInt() != INTERFACE_TYPE_BUTTON) &&
(widget->property(interface_role_property).toInt() == INTERFACE_ROLE_CONTROL))
{
@@ -773,7 +820,7 @@ void InterfaceToolbar::sendChangedValues(QString ifname)
}
}
-void InterfaceToolbar::onResetButtonPressed()
+void InterfaceToolbar::onRestoreButtonPressed()
{
const QString &ifname = ui->interfacesComboBox->currentText();
@@ -799,6 +846,7 @@ void InterfaceToolbar::onResetButtonPressed()
case INTERFACE_ROLE_CONTROL:
setWidgetValue(widget, commandControlSet, default_value_[num]);
interface_[ifname].value[num] = default_value_[num];
+ interface_[ifname].value_changed[num] = false;
break;
case INTERFACE_ROLE_LOGGER:
@@ -828,20 +876,29 @@ void InterfaceToolbar::updateWidgets()
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))
+ bool widget_enabled = true;
+
+ if (ifname.isEmpty() &&
+ (widget->property(interface_role_property).toInt() != INTERFACE_ROLE_HELP))
+ {
+ // No interface selected, disable all but Help button
+ widget_enabled = false;
+ }
+ else if (!is_capturing &&
+ (widget->property(interface_type_property).toInt() == INTERFACE_TYPE_BUTTON) &&
+ (widget->property(interface_role_property).toInt() == INTERFACE_ROLE_CONTROL))
{
- widget->setEnabled(false);
+ widget_enabled = 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);
- }
+ widget_enabled = !interface_[ifname].widget_disabled[num];
+ }
+
+ widget->setEnabled(widget_enabled);
+ if (label_widget_.contains(num))
+ {
+ label_widget_[num]->setEnabled(widget_enabled);
}
}
@@ -849,13 +906,50 @@ void InterfaceToolbar::updateWidgets()
{
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->property(interface_role_property).toInt() == INTERFACE_ROLE_RESTORE))
{
widget->setEnabled(!is_capturing);
}
}
}
+void InterfaceToolbar::interfaceListChanged()
+{
+ const QString &selected_ifname = ui->interfacesComboBox->currentText();
+ bool keep_selected = false;
+
+ ui->interfacesComboBox->blockSignals(true);
+ ui->interfacesComboBox->clear();
+
+ for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++)
+ {
+ interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+ if (device.hidden)
+ continue;
+
+ if (interface_.keys().contains(device.name))
+ {
+ ui->interfacesComboBox->addItem(device.name);
+ if (selected_ifname.compare(device.name) == 0)
+ {
+ // Keep selected interface
+ ui->interfacesComboBox->setCurrentText(device.name);
+ keep_selected = true;
+ }
+ }
+ }
+
+ ui->interfacesComboBox->blockSignals(false);
+
+ if (!keep_selected)
+ {
+ // Select the first interface
+ on_interfacesComboBox_currentIndexChanged(ui->interfacesComboBox->currentText());
+ }
+
+ updateWidgets();
+}
+
void InterfaceToolbar::on_interfacesComboBox_currentIndexChanged(const QString &ifname)
{
foreach (int num, control_widget_.keys())
diff --git a/ui/qt/interface_toolbar.h b/ui/qt/interface_toolbar.h
index ebde37db4d..cdbfb57906 100644
--- a/ui/qt/interface_toolbar.h
+++ b/ui/qt/interface_toolbar.h
@@ -29,6 +29,7 @@
#include "interface_toolbar_reader.h"
#include <QFrame>
+#include <QList>
#include <QMap>
#include <QString>
@@ -42,6 +43,7 @@ struct interface_values
QThread *reader_thread;
int out_fd;
QMap<int, QByteArray> value;
+ QMap<int, bool> value_changed;
QMap<int, QList<QByteArray> > list;
FunnelTextDialog *log_dialog;
QString log_text;
@@ -56,11 +58,12 @@ public:
explicit InterfaceToolbar(QWidget *parent = 0, const iface_toolbar *toolbar = NULL);
~InterfaceToolbar();
- void startCapture(QString ifname, QString control_in, QString control_out);
+ void startCapture(GArray *ifaces);
void stopCapture();
bool hasInterface(QString ifname);
public slots:
+ void interfaceListChanged();
void controlReceived(QString ifname, int num, int command, QByteArray message);
signals:
@@ -70,13 +73,13 @@ private slots:
void startReaderThread(QString ifname, QString control_in);
void updateWidgets();
- void onButtonPressed();
+ void onControlButtonPressed();
+ void onLogButtonPressed();
+ void onHelpButtonPressed();
+ void onRestoreButtonPressed();
void onCheckBoxChanged(int state);
void onComboBoxChanged(int idx);
void onLineEditChanged();
- void onLogButtonPressed();
- void onHelpButtonPressed();
- void onResetButtonPressed();
void closeLog();
diff --git a/ui/qt/interface_toolbar.ui b/ui/qt/interface_toolbar.ui
index 20faae5a57..3c4f47c07d 100644
--- a/ui/qt/interface_toolbar.ui
+++ b/ui/qt/interface_toolbar.ui
@@ -38,6 +38,9 @@
</item>
<item>
<widget class="QComboBox" name="interfacesComboBox">
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToContents</enum>
+ </property>
<property name="toolTip">
<string>Select interface</string>
</property>
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index 500dee87e3..b47b83e34c 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -855,6 +855,8 @@ void MainWindow::addInterfaceToolbar(const iface_toolbar *toolbar_entry)
menu->insertAction(before, action);
InterfaceToolbar *interface_toolbar = new InterfaceToolbar(this, toolbar_entry);
+ connect(wsApp, SIGNAL(appInitialized()), interface_toolbar, SLOT(interfaceListChanged()));
+ connect(wsApp, SIGNAL(localInterfaceListChanged()), interface_toolbar, SLOT(interfaceListChanged()));
QToolBar *toolbar = new QToolBar(this);
toolbar->addWidget(interface_toolbar);
@@ -2483,10 +2485,7 @@ void MainWindow::setForCaptureInProgress(bool capture_in_progress, GArray *iface
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);
- }
+ toolbar->startCapture(ifaces);
} else {
toolbar->stopCapture();
}