InterfaceTreeList: Enable all editable columns

In preparation for moving to the new interface list, adding all
necessary editors and changes to allow all columns, which are being
handled by CaptureInterfacesDialog or ManageInterfacesDialog to be
edited correctly

Change-Id: I8bfabff92a07950c74a4d7243dadd99ecd2024f4
Reviewed-on: https://code.wireshark.org/review/18446
Petri-Dish: Roland Knall <rknall@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Roland Knall <rknall@gmail.com>
This commit is contained in:
Roland Knall 2016-10-25 11:26:26 +02:00
parent dcb49539dd
commit 6eee29bf2a
8 changed files with 430 additions and 22 deletions

View File

@ -102,6 +102,7 @@ set(WIRESHARK_QT_HEADERS
manage_interfaces_dialog.h
module_preferences_scroll_area.h
mtp3_summary_dialog.h
numeric_value_chooser_delegate.h
multicast_statistics_dialog.h
overlay_scroll_bar.h
packet_comment_dialog.h
@ -263,6 +264,7 @@ set(WIRESHARK_QT_SRC
main_window_slots.cpp
manage_interfaces_dialog.cpp
module_preferences_scroll_area.cpp
numeric_value_chooser_delegate.cpp
overlay_scroll_bar.cpp
packet_comment_dialog.cpp
packet_dialog.cpp

View File

@ -232,6 +232,7 @@ MOC_HDRS = \
module_preferences_scroll_area.h \
multicast_statistics_dialog.h \
mtp3_summary_dialog.h \
numeric_value_chooser_delegate.h \
overlay_scroll_bar.h \
packet_comment_dialog.h \
packet_dialog.h \
@ -507,6 +508,7 @@ WIRESHARK_QT_SRC = \
main_window_slots.cpp \
manage_interfaces_dialog.cpp \
module_preferences_scroll_area.cpp \
numeric_value_chooser_delegate.cpp \
overlay_scroll_bar.cpp \
packet_comment_dialog.cpp \
packet_dialog.cpp \

View File

@ -29,6 +29,9 @@
#include "qt_ui_utils.h"
#include "ui/capture_globals.h"
#include "wiretap/wtap.h"
#include "wireshark_application.h"
InterfaceTreeCacheModel::InterfaceTreeCacheModel(QObject *parent) :
@ -42,9 +45,13 @@ InterfaceTreeCacheModel::InterfaceTreeCacheModel(QObject *parent) :
QIdentityProxyModel::setSourceModel(sourceModel);
storage = new QMap<int, QMap<InterfaceTreeColumns, QVariant> *>();
checkableColumns << IFTREE_COL_HIDDEN;
checkableColumns << IFTREE_COL_HIDDEN << IFTREE_COL_PROMISCUOUSMODE << IFTREE_COL_MONITOR_MODE;
editableColumns << IFTREE_COL_INTERFACE_COMMENT;
editableColumns << IFTREE_COL_INTERFACE_COMMENT << IFTREE_COL_SNAPLEN;
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
editableColumns << IFTREE_COL_BUFFERLEN;
#endif
}
InterfaceTreeCacheModel::~InterfaceTreeCacheModel()
@ -77,8 +84,7 @@ void InterfaceTreeCacheModel::save()
if ( storage->count() == 0 )
return;
QStringList hideList;
QStringList commentList;
QMap<char**, QStringList> prefStorage;
for(unsigned int idx = 0; idx < global_capture_opts.all_ifaces->len; idx++)
{
@ -100,12 +106,51 @@ void InterfaceTreeCacheModel::save()
/* Setting the field values for each individual saved value cannot be generic, as the
* struct cannot be accessed generically. Therefore below, each individually changed
* value has to be handled separately */
* value has to be handled separately. Comments are stored only in the preference file
* and applied to the data name during loading. Therefore comments are not handled here */
if ( col == IFTREE_COL_HIDDEN )
{
device.hidden = saveValue.toBool();
}
#ifdef HAVE_EXTCAP
else if ( device.if_info.type == IF_EXTCAP )
{
/* extcap interfaces do not have the following columns.
* ATTENTION: all generic columns must be added, BEFORE this
* if-clause, or they will be ignored for extcap interfaces */
}
#endif
else if ( col == IFTREE_COL_PROMISCUOUSMODE )
{
device.pmode = saveValue.toBool();
}
#ifdef HAVE_PCAP_CREATE
else if ( col == IFTREE_COL_MONITOR_MODE )
{
device.monitor_mode_enabled = saveValue.toBool();
}
#endif
else if ( col == IFTREE_COL_SNAPLEN )
{
int iVal = saveValue.toInt();
if ( iVal != WTAP_MAX_PACKET_SIZE )
{
device.has_snaplen = true;
device.snaplen = iVal;
}
else
{
device.has_snaplen = false;
device.snaplen = WTAP_MAX_PACKET_SIZE;
}
}
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
else if ( col == IFTREE_COL_BUFFERLEN )
{
device.buffer = saveValue.toInt();
}
#endif
global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, idx);
g_array_insert_val(global_capture_opts.all_ifaces, idx, device);
@ -116,18 +161,68 @@ void InterfaceTreeCacheModel::save()
QVariant content = getColumnContent(idx, IFTREE_COL_HIDDEN, Qt::CheckStateRole);
if ( content.isValid() && static_cast<Qt::CheckState>(content.toInt()) == Qt::Unchecked )
hideList << QString(device.name);
prefStorage[&prefs.capture_devices_hide] << QString(device.name);
content = getColumnContent(idx, IFTREE_COL_INTERFACE_COMMENT);
if ( content.isValid() && content.toString().size() > 0 )
commentList << QString("%1(%2)").arg(device.name).arg(content.toString());
prefStorage[&prefs.capture_devices_descr] << QString("%1(%2)").arg(device.name).arg(content.toString());
bool allowExtendedColumns = true;
#ifdef HAVE_EXTCAP
if ( device.if_info.type == IF_EXTCAP )
allowExtendedColumns = false;
#endif
if ( allowExtendedColumns )
{
content = getColumnContent(idx, IFTREE_COL_PROMISCUOUSMODE, Qt::CheckStateRole);
if ( content.isValid() )
{
bool value = static_cast<Qt::CheckState>(content.toInt()) == Qt::Checked;
prefStorage[&prefs.capture_devices_pmode] << QString("%1(%2)").arg(device.name).arg(value ? 1 : 0);
}
#ifdef HAVE_PCAP_CREATE
content = getColumnContent(idx, IFTREE_COL_MONITOR_MODE, Qt::CheckStateRole);
if ( content.isValid() && static_cast<Qt::CheckState>(content.toInt()) == Qt::Checked )
prefStorage[&prefs.capture_devices_monitor_mode] << QString(device.name);
#endif
content = getColumnContent(idx, IFTREE_COL_SNAPLEN);
if ( content.isValid() )
{
int value = content.toInt();
prefStorage[&prefs.capture_devices_snaplen] <<
QString("%1:%2(%3)").arg(device.name).
arg(device.has_snaplen ? 1 : 0).
arg(device.has_snaplen ? value : WTAP_MAX_PACKET_SIZE);
}
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
content = getColumnContent(idx, IFTREE_COL_BUFFERLEN);
if ( content.isValid() )
{
int value = content.toInt();
if ( value != -1 )
{
prefStorage[&prefs.capture_devices_buffersize] <<
QString("%1(%2)").arg(device.name).
arg(value);
}
}
#endif
}
}
g_free(prefs.capture_devices_hide);
prefs.capture_devices_hide = qstring_strdup(hideList.join(","));
QMap<char**, QStringList>::const_iterator it = prefStorage.constBegin();
while ( it != prefStorage.constEnd() )
{
char ** key = it.key();
g_free(prefs.capture_devices_descr);
prefs.capture_devices_descr = qstring_strdup(commentList.join(","));
g_free(*key);
*key = qstring_strdup(it.value().join(","));
++it;
}
}
int InterfaceTreeCacheModel::rowCount(const QModelIndex & parent) const
@ -142,6 +237,37 @@ bool InterfaceTreeCacheModel::changeIsAllowed(InterfaceTreeColumns col) const
return false;
}
/* This checks if the column can be edited for the given index. This differs from
* isAllowedToBeChanged in such a way, that it is only used in flags and not any
* other method.*/
bool InterfaceTreeCacheModel::isAllowedToBeEdited(const QModelIndex &index) const
{
if ( ! index.isValid() || ! global_capture_opts.all_ifaces )
return false;
int idx = index.row();
if ( (unsigned int) idx >= global_capture_opts.all_ifaces->len )
return false;
interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, idx);
InterfaceTreeColumns col = (InterfaceTreeColumns) index.column();
#ifdef HAVE_EXTCAP
if ( device.if_info.type == IF_EXTCAP )
{
/* extcap interfaces do not have those settings */
if ( col == IFTREE_COL_PROMISCUOUSMODE || col == IFTREE_COL_SNAPLEN )
return false;
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
if ( col == IFTREE_COL_BUFFERLEN )
return false;
#endif
}
#endif
return true;
}
bool InterfaceTreeCacheModel::isAllowedToBeChanged(const QModelIndex &index) const
{
if ( ! index.isValid() || ! global_capture_opts.all_ifaces )
@ -175,15 +301,15 @@ Qt::ItemFlags InterfaceTreeCacheModel::flags(const QModelIndex &index) const
InterfaceTreeColumns col = (InterfaceTreeColumns) index.column();
if ( changeIsAllowed(col) && isAllowedToBeChanged(index) )
if ( changeIsAllowed(col) && isAllowedToBeChanged(index) && isAllowedToBeEdited(index) )
{
if ( checkableColumns.contains(col) )
{
flags = Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
flags |= Qt::ItemIsUserCheckable;
}
else
{
flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
flags |= Qt::ItemIsEditable;
}
}
@ -205,6 +331,8 @@ bool InterfaceTreeCacheModel::setData(const QModelIndex &index, const QVariant &
{
if ( changeIsAllowed( col ) )
{
QVariant saveValue = value;
QMap<InterfaceTreeColumns, QVariant> * dataField = 0;
/* obtain the list of already stored changes for this row. If none exist
* create a new storage row for this entry */
@ -214,7 +342,7 @@ bool InterfaceTreeCacheModel::setData(const QModelIndex &index, const QVariant &
storage->insert(row, dataField);
}
dataField->insert(col, value);
dataField->insert(col, saveValue);
return true;
}
@ -231,18 +359,28 @@ QVariant InterfaceTreeCacheModel::data(const QModelIndex &index, int role) const
int row = index.row();
InterfaceTreeColumns col = (InterfaceTreeColumns)index.column();
if ( ( ( role == Qt::DisplayRole || role == Qt::EditRole ) && editableColumns.contains(col) ) ||
( role == Qt::CheckStateRole && checkableColumns.contains(col) ) )
if ( isAllowedToBeEdited(index) )
{
QMap<InterfaceTreeColumns, QVariant> * dataField = 0;
if ( ( dataField = storage->value(row, 0) ) != 0 )
if ( ( ( role == Qt::DisplayRole || role == Qt::EditRole ) && editableColumns.contains(col) ) ||
( role == Qt::CheckStateRole && checkableColumns.contains(col) ) )
{
if ( dataField->contains(col) )
QMap<InterfaceTreeColumns, QVariant> * dataField = 0;
if ( ( dataField = storage->value(row, 0) ) != 0 )
{
return dataField->value(col, QVariant());
if ( dataField->contains(col) )
{
return dataField->value(col, QVariant());
}
}
}
}
else
{
if ( role == Qt::CheckStateRole )
return QVariant();
else if ( role == Qt::DisplayRole )
return QString("-");
}
return sourceModel->data(index, role);
}

View File

@ -57,6 +57,7 @@ private:
bool changeIsAllowed(InterfaceTreeColumns col) const;
bool isAllowedToBeChanged(const QModelIndex &index) const;
bool isAllowedToBeEdited(const QModelIndex &index) const;
};
#endif /* INTERFACE_TREE_CACHE_MODEL_H_ */

View File

@ -45,6 +45,8 @@
#include "extcap.h"
#endif
const QString InterfaceTreeModel::DefaultNumericValue = tr("default");
/**
* This is the data model for interface trees. It implies, that the index within
* global_capture_opts.all_ifaces is identical to the row. This is always the case, even
@ -133,13 +135,27 @@ QVariant InterfaceTreeModel::data(const QModelIndex &index, int role) const
{
return QString(device.name);
}
else if ( col == IFTREE_COL_CAPTURE_FILTER )
{
if ( device.cfilter && strlen(device.cfilter) > 0 )
return html_escape(QString(device.cfilter));
}
#ifdef HAVE_EXTCAP
else if ( col == IFTREE_COL_EXTCAP_PATH )
{
return QString(device.if_info.extcap);
}
#endif
else if ( col == IFTREE_COL_SNAPLEN )
{
return device.has_snaplen ? QString::number(device.snaplen) : DefaultNumericValue;
}
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
else if ( col == IFTREE_COL_BUFFERLEN )
{
return QString::number(device.buffer);
}
#endif
else if ( col == IFTREE_COL_TYPE )
{
return QVariant::fromValue((int)device.if_info.type);
@ -152,6 +168,19 @@ QVariant InterfaceTreeModel::data(const QModelIndex &index, int role) const
else
return QString(device.if_info.vendor_description);
}
else if ( col == IFTREE_COL_DLT )
{
QString linkname = QObject::tr("DLT %1").arg(device.active_dlt);
for (GList *list = device.links; list != NULL; list = g_list_next(list)) {
link_row *linkr = (link_row*)(list->data);
if (linkr->dlt != -1 && linkr->dlt == device.active_dlt) {
linkname = linkr->name;
break;
}
}
return linkname;
}
else
{
/* Return empty string for every other DisplayRole */
@ -165,6 +194,16 @@ QVariant InterfaceTreeModel::data(const QModelIndex &index, int role) const
/* Hidden is a de-selection, therefore inverted logic here */
return device.hidden ? Qt::Unchecked : Qt::Checked;
}
else if ( col == IFTREE_COL_PROMISCUOUSMODE )
{
return device.pmode ? Qt::Checked : Qt::Unchecked;
}
#ifdef HAVE_PCAP_CREATE
else if ( col == IFTREE_COL_MONITOR_MODE )
{
return device.monitor_mode_enabled ? Qt::Checked : Qt::Unchecked;
}
#endif
}
/* Used by SparkLineDelegate for loading the data for the statistics line */
else if ( role == Qt::UserRole )
@ -233,6 +272,34 @@ QVariant InterfaceTreeModel::headerData(int section, Qt::Orientation orientation
{
return tr("Comment");
}
else if ( section == IFTREE_COL_DLT )
{
return tr("Link-Layer Header");
}
else if ( section == IFTREE_COL_PROMISCUOUSMODE )
{
return tr("Promiscuous");
}
else if ( section == IFTREE_COL_SNAPLEN )
{
return tr("Snaplen (B)");
}
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
else if ( section == IFTREE_COL_BUFFERLEN )
{
return tr("Buffer (MB)");
}
#endif
#ifdef HAVE_PCAP_CREATE
else if ( section == IFTREE_COL_MONITOR_MODE )
{
return tr("Monitor Mode");
}
#endif
else if ( section == IFTREE_COL_CAPTURE_FILTER )
{
return tr("Capture Filter");
}
}
}

View File

@ -49,8 +49,18 @@ enum InterfaceTreeColumns
IFTREE_COL_INTERFACE_NAME,
IFTREE_COL_INTERFACE_COMMENT,
IFTREE_COL_HIDDEN,
IFTREE_COL_DLT,
IFTREE_COL_PROMISCUOUSMODE,
IFTREE_COL_TYPE,
IFTREE_COL_STATS,
IFTREE_COL_SNAPLEN,
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
IFTREE_COL_BUFFERLEN,
#endif
#ifdef HAVE_PCAP_CREATE
IFTREE_COL_MONITOR_MODE,
#endif
IFTREE_COL_CAPTURE_FILTER,
IFTREE_COL_MAX /* is not being displayed, it is the definition for the maximum numbers of columns */
};
@ -77,6 +87,8 @@ public:
QVariant getColumnContent(int idx, int col, int role = Qt::DisplayRole);
static const QString DefaultNumericValue;
public slots:
void getPoints(int idx, PointList *pts);

View File

@ -0,0 +1,117 @@
/* numeric_value_chooser_delegate.cpp
* Delegate to select a numeric value for a treeview entry
*
* 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 "ui/qt/numeric_value_chooser_delegate.h"
#include <QStyledItemDelegate>
#include <QSpinBox>
NumericValueChooserDelegate::NumericValueChooserDelegate(int min, int max, QObject *parent)
: QStyledItemDelegate(parent)
{
_min = min;
_max = max;
_default = min;
}
NumericValueChooserDelegate::~NumericValueChooserDelegate()
{
}
void NumericValueChooserDelegate::setMinMaxRange(int min, int max)
{
_min = qMin(min, max);
_max = qMax(min, max);
/* ensure, that the default value is within the new min<->max */
_default = qMin(_max, qMax(_min, _default));
_defReturn = qVariantFromValue(_default);
}
void NumericValueChooserDelegate::setDefaultValue(int defValue, QVariant defaultReturn)
{
/* ensure, that the new default value is within min<->max */
_default = qMin(_max, qMax(_min, defValue));
_defReturn = defaultReturn;
}
QWidget* NumericValueChooserDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (!index.isValid()) {
return QStyledItemDelegate::createEditor(parent, option, index);
}
QSpinBox * editor = new QSpinBox(parent);
editor->setMinimum(_min);
editor->setMaximum(_max);
editor->setWrapping(true);
connect(editor, SIGNAL(valueChanged(int)), this, SLOT(onValueChanged(int)));
return editor;
}
void NumericValueChooserDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if ( index.isValid() )
{
bool canConvert = false;
int val = index.data().toInt(&canConvert);
if ( ! canConvert )
val = _default;
QSpinBox * spinBox = qobject_cast<QSpinBox *>(editor);
spinBox->setValue(val);
}
else
QStyledItemDelegate::setEditorData(editor, index);
}
void NumericValueChooserDelegate::setModelData(QWidget *editor, QAbstractItemModel * model, const QModelIndex &index) const
{
if ( index.isValid() ) {
QSpinBox * spinBox = qobject_cast<QSpinBox *>(editor);
model->setData(index, _default == spinBox->value() ? _defReturn : qVariantFromValue(spinBox->value()));
} else {
QStyledItemDelegate::setModelData(editor, model, index);
}
}
void NumericValueChooserDelegate::onValueChanged(int)
{
QSpinBox * spinBox = qobject_cast<QSpinBox *>(sender());
emit commitData(spinBox);
}
/*
* 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:
*/

View File

@ -0,0 +1,69 @@
/* numeric_value_chooser_delegate.h
* Delegate to select a numeric value for a treeview entry
*
* 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 NUMERIC_VALUE_CHOOSER_DELEGATE_H_
#define NUMERIC_VALUE_CHOOSER_DELEGATE_H_
#include <QStyledItemDelegate>
class NumericValueChooserDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
NumericValueChooserDelegate(int min = 0, int max = 0, QObject *parent = 0);
~NumericValueChooserDelegate();
void setMinMaxRange(int min, int max);
void setDefaultValue(int defValue, QVariant defaultReturn);
protected:
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
private:
int _min;
int _max;
int _default;
QVariant _defReturn;
private slots:
void onValueChanged(int i);
};
#endif /* NUMERIC_VALUE_CHOOSER_DELEGATE_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:
*/