forked from osmocom/wireshark
ManageInterfacesDialog: New handling of pipes
This moves the handling of pipes to the new InterfaceTreeModel as well. It also includes a new PathChooserDelegate and cache handling for adding data to an interface list without putting it into storage Change-Id: Id255a81161b4da517e26127abe8ea7f5eb36d55a Reviewed-on: https://code.wireshark.org/review/18497 Reviewed-by: Roland Knall <rknall@gmail.com>
This commit is contained in:
parent
1fae14257a
commit
6500a660c2
|
@ -111,6 +111,7 @@ set(WIRESHARK_QT_HEADERS
|
|||
packet_list.h
|
||||
packet_list_model.h
|
||||
packet_range_group_box.h
|
||||
path_chooser_delegate.h
|
||||
percent_bar_delegate.h
|
||||
preference_editor_frame.h
|
||||
preferences_dialog.h
|
||||
|
@ -273,6 +274,7 @@ set(WIRESHARK_QT_SRC
|
|||
packet_list_model.cpp
|
||||
packet_list_record.cpp
|
||||
packet_range_group_box.cpp
|
||||
path_chooser_delegate.cpp
|
||||
percent_bar_delegate.cpp
|
||||
preference_editor_frame.cpp
|
||||
preferences_dialog.cpp
|
||||
|
|
|
@ -235,6 +235,7 @@ MOC_HDRS = \
|
|||
numeric_value_chooser_delegate.h \
|
||||
overlay_scroll_bar.h \
|
||||
packet_comment_dialog.h \
|
||||
path_chooser_delegate.h \
|
||||
packet_dialog.h \
|
||||
packet_format_group_box.h \
|
||||
packet_list.h \
|
||||
|
@ -517,6 +518,7 @@ WIRESHARK_QT_SRC = \
|
|||
packet_list_model.cpp \
|
||||
packet_list_record.cpp \
|
||||
packet_range_group_box.cpp \
|
||||
path_chooser_delegate.cpp \
|
||||
percent_bar_delegate.cpp \
|
||||
preference_editor_frame.cpp \
|
||||
preferences_dialog.cpp \
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
#include "ui/qt/interface_tree_model.h"
|
||||
#include "ui/qt/interface_tree_cache_model.h"
|
||||
#include "ui/qt/interface_sort_filter_model.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
@ -35,6 +36,11 @@
|
|||
|
||||
InterfaceSortFilterModel::InterfaceSortFilterModel(QObject *parent) :
|
||||
QSortFilterProxyModel(parent)
|
||||
{
|
||||
resetAllFilter();
|
||||
}
|
||||
|
||||
void InterfaceSortFilterModel::resetAllFilter()
|
||||
{
|
||||
_filterHidden = true;
|
||||
_filterTypes = true;
|
||||
|
@ -44,6 +50,9 @@ InterfaceSortFilterModel::InterfaceSortFilterModel(QObject *parent) :
|
|||
/* Adding all columns, to have a default setting */
|
||||
for ( int col = 0; col < IFTREE_COL_MAX; col++ )
|
||||
_columns.append((InterfaceTreeColumns)col);
|
||||
|
||||
invalidateFilter();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void InterfaceSortFilterModel::setStoreOnChange(bool storeOnChange)
|
||||
|
@ -214,8 +223,21 @@ bool InterfaceSortFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex
|
|||
if ( sourceModel()->rowCount() == 0 )
|
||||
return false;
|
||||
|
||||
int type = ((InterfaceTreeModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_TYPE).toInt();
|
||||
bool hidden = ((InterfaceTreeModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_HIDDEN, Qt::UserRole).toBool();
|
||||
int type = -1;
|
||||
bool hidden = false;
|
||||
|
||||
if (dynamic_cast<InterfaceTreeCacheModel*>(sourceModel()) != 0)
|
||||
{
|
||||
type = ((InterfaceTreeCacheModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_TYPE).toInt();
|
||||
hidden = ((InterfaceTreeCacheModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_HIDDEN, Qt::UserRole).toBool();
|
||||
}
|
||||
else if (dynamic_cast<InterfaceTreeModel*>(sourceModel()) != 0)
|
||||
{
|
||||
type = ((InterfaceTreeModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_TYPE).toInt();
|
||||
hidden = ((InterfaceTreeModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_HIDDEN, Qt::UserRole).toBool();
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if ( hidden && _filterHidden )
|
||||
return false;
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
InterfaceSortFilterModel(QObject *parent);
|
||||
|
||||
void setStoreOnChange(bool storeOnChange);
|
||||
void resetAllFilter();
|
||||
|
||||
void setFilterHidden(bool filter);
|
||||
bool filterHidden() const;
|
||||
|
|
|
@ -50,7 +50,7 @@ InterfaceTreeCacheModel::InterfaceTreeCacheModel(QObject *parent) :
|
|||
checkableColumns << IFTREE_COL_MONITOR_MODE;
|
||||
#endif
|
||||
|
||||
editableColumns << IFTREE_COL_INTERFACE_COMMENT << IFTREE_COL_SNAPLEN;
|
||||
editableColumns << IFTREE_COL_INTERFACE_COMMENT << IFTREE_COL_SNAPLEN << IFTREE_COL_PIPE_PATH;
|
||||
|
||||
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
|
||||
editableColumns << IFTREE_COL_BUFFERLEN;
|
||||
|
@ -59,6 +59,13 @@ InterfaceTreeCacheModel::InterfaceTreeCacheModel(QObject *parent) :
|
|||
|
||||
InterfaceTreeCacheModel::~InterfaceTreeCacheModel()
|
||||
{
|
||||
/* This list should only exist, if the dialog is closed, without calling save first */
|
||||
if ( newDevices.size() > 0 )
|
||||
{
|
||||
qDeleteAll(newDevices);
|
||||
newDevices.clear();
|
||||
}
|
||||
|
||||
delete storage;
|
||||
delete sourceModel;
|
||||
}
|
||||
|
@ -82,6 +89,60 @@ QVariant InterfaceTreeCacheModel::getColumnContent(int idx, int col, int role)
|
|||
return InterfaceTreeCacheModel::data(index(idx, col), role);
|
||||
}
|
||||
|
||||
void InterfaceTreeCacheModel::saveNewDevices()
|
||||
{
|
||||
QList<interface_t *>::const_iterator it = newDevices.constBegin();
|
||||
/* idx is used for iterating only over the indices of the new devices. As all new
|
||||
* devices are stored with an index higher then sourceModel->rowCount(), we start
|
||||
* only with those storage indices.
|
||||
* it is just the iterator over the new devices. A new device must not necessarily
|
||||
* have storage, which will lead to that device not being stored in global_capture_opts */
|
||||
for (int idx = sourceModel->rowCount(); it != newDevices.constEnd(); ++it, idx++)
|
||||
{
|
||||
interface_t * device = (interface_t *)(*it);
|
||||
bool useDevice = false;
|
||||
|
||||
QMap<InterfaceTreeColumns, QVariant> * dataField = storage->value(idx, 0);
|
||||
/* When devices are being added, they are added using generic values. So only devices
|
||||
* whose data have been changed should be used from here on out. */
|
||||
if ( dataField != 0 )
|
||||
{
|
||||
if ( device->if_info.type != IF_PIPE )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( device->if_info.type == IF_PIPE )
|
||||
{
|
||||
QVariant saveValue = dataField->value(IFTREE_COL_PIPE_PATH);
|
||||
if ( saveValue.isValid() )
|
||||
{
|
||||
g_free(device->if_info.name);
|
||||
device->if_info.name = qstring_strdup(saveValue.toString());
|
||||
|
||||
g_free(device->name);
|
||||
device->name = qstring_strdup(saveValue.toString());
|
||||
|
||||
g_free(device->display_name);
|
||||
device->display_name = qstring_strdup(saveValue.toString());
|
||||
useDevice = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( useDevice )
|
||||
g_array_append_val(global_capture_opts.all_ifaces, *device);
|
||||
|
||||
}
|
||||
|
||||
/* All entries of this new devices have been considered */
|
||||
storage->remove(idx);
|
||||
delete dataField;
|
||||
}
|
||||
|
||||
qDeleteAll(newDevices);
|
||||
newDevices.clear();
|
||||
}
|
||||
|
||||
void InterfaceTreeCacheModel::save()
|
||||
{
|
||||
if ( storage->count() == 0 )
|
||||
|
@ -89,9 +150,13 @@ void InterfaceTreeCacheModel::save()
|
|||
|
||||
QMap<char**, QStringList> prefStorage;
|
||||
|
||||
/* Storing new devices first including their changed values */
|
||||
saveNewDevices();
|
||||
|
||||
for(unsigned int idx = 0; idx < global_capture_opts.all_ifaces->len; idx++)
|
||||
{
|
||||
interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, idx);
|
||||
|
||||
if (! device.name )
|
||||
continue;
|
||||
|
||||
|
@ -108,7 +173,7 @@ void InterfaceTreeCacheModel::save()
|
|||
QVariant saveValue = it.value();
|
||||
|
||||
/* Setting the field values for each individual saved value cannot be generic, as the
|
||||
* struct cannot be accessed generically. Therefore below, each individually changed
|
||||
* struct cannot be accessed in a generic way. Therefore below, each individually changed
|
||||
* 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 */
|
||||
|
||||
|
@ -226,11 +291,13 @@ void InterfaceTreeCacheModel::save()
|
|||
|
||||
++it;
|
||||
}
|
||||
|
||||
wsApp->emitAppSignal(WiresharkApplication::LocalInterfacesChanged);
|
||||
}
|
||||
|
||||
int InterfaceTreeCacheModel::rowCount(const QModelIndex & parent) const
|
||||
{
|
||||
return sourceModel->rowCount(parent);
|
||||
return sourceModel->rowCount(parent) + newDevices.size();
|
||||
}
|
||||
|
||||
bool InterfaceTreeCacheModel::changeIsAllowed(InterfaceTreeColumns col) const
|
||||
|
@ -240,54 +307,70 @@ bool InterfaceTreeCacheModel::changeIsAllowed(InterfaceTreeColumns col) const
|
|||
return false;
|
||||
}
|
||||
|
||||
interface_t * InterfaceTreeCacheModel::lookup(const QModelIndex &index) const
|
||||
{
|
||||
interface_t * result = 0;
|
||||
|
||||
if ( ! index.isValid() )
|
||||
return result;
|
||||
if ( ! global_capture_opts.all_ifaces && newDevices.size() == 0 )
|
||||
return result;
|
||||
|
||||
int idx = index.row();
|
||||
|
||||
if ( (unsigned int) idx >= global_capture_opts.all_ifaces->len )
|
||||
{
|
||||
idx = idx - global_capture_opts.all_ifaces->len;
|
||||
if ( idx < newDevices.size() )
|
||||
result = newDevices[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = &g_array_index(global_capture_opts.all_ifaces, interface_t, idx);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
interface_t * device = lookup(index);
|
||||
if ( device == 0 )
|
||||
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();
|
||||
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;
|
||||
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;
|
||||
if ( col == IFTREE_COL_BUFFERLEN )
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InterfaceTreeCacheModel::isAllowedToBeChanged(const QModelIndex &index) const
|
||||
{
|
||||
if ( ! index.isValid() || ! global_capture_opts.all_ifaces )
|
||||
return false;
|
||||
interface_t * device = lookup(index);
|
||||
|
||||
int idx = index.row();
|
||||
if ( (unsigned int) idx >= global_capture_opts.all_ifaces->len )
|
||||
if ( device == 0 )
|
||||
return false;
|
||||
|
||||
interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, idx);
|
||||
|
||||
InterfaceTreeColumns col = (InterfaceTreeColumns) index.column();
|
||||
if ( col == IFTREE_COL_HIDDEN )
|
||||
{
|
||||
if ( prefs.capture_device )
|
||||
{
|
||||
if ( ! g_strcmp0(prefs.capture_device, device.display_name) )
|
||||
if ( ! g_strcmp0(prefs.capture_device, device->display_name) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -360,6 +443,7 @@ QVariant InterfaceTreeCacheModel::data(const QModelIndex &index, int role) const
|
|||
return QVariant();
|
||||
|
||||
int row = index.row();
|
||||
|
||||
InterfaceTreeColumns col = (InterfaceTreeColumns)index.column();
|
||||
|
||||
if ( isAllowedToBeEdited(index) )
|
||||
|
@ -385,7 +469,112 @@ QVariant InterfaceTreeCacheModel::data(const QModelIndex &index, int role) const
|
|||
return QString("-");
|
||||
}
|
||||
|
||||
return sourceModel->data(index, role);
|
||||
if ( row >= sourceModel->rowCount() )
|
||||
{
|
||||
/* Handle all fields, which will have to be displayed for new devices. Only pipes
|
||||
* are supported at the moment, so the information to be displayed is pretty limited.
|
||||
* After saving, the devices are stored in global_capture_opts and no longer
|
||||
* classify as new devices. */
|
||||
interface_t * device = lookup(index);
|
||||
|
||||
if ( device != 0 )
|
||||
{
|
||||
if ( role == Qt::DisplayRole || role == Qt::EditRole )
|
||||
{
|
||||
if ( col == IFTREE_COL_PIPE_PATH ||
|
||||
col == IFTREE_COL_NAME ||
|
||||
col == IFTREE_COL_INTERFACE_NAME )
|
||||
{
|
||||
|
||||
QMap<InterfaceTreeColumns, QVariant> * dataField = 0;
|
||||
if ( ( dataField = storage->value(row, 0) ) != 0 &&
|
||||
dataField->contains(IFTREE_COL_PIPE_PATH) )
|
||||
{
|
||||
return dataField->value(IFTREE_COL_PIPE_PATH, QVariant());
|
||||
}
|
||||
else
|
||||
return QString(device->name);
|
||||
}
|
||||
else if ( col == IFTREE_COL_TYPE )
|
||||
{
|
||||
return QVariant::fromValue((int)device->if_info.type);
|
||||
}
|
||||
}
|
||||
else if ( role == Qt::CheckStateRole )
|
||||
{
|
||||
if ( col == IFTREE_COL_HIDDEN )
|
||||
{
|
||||
/* Hidden is a de-selection, therefore inverted logic here */
|
||||
return device->hidden ? Qt::Unchecked : Qt::Checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
return sourceModel->data(index, role);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex InterfaceTreeCacheModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if ( row >= sourceModel->rowCount() && ( row - sourceModel->rowCount() ) < newDevices.count() )
|
||||
{
|
||||
return createIndex(row, column, (void *)0);
|
||||
}
|
||||
|
||||
return sourceModel->index(row, column, parent);
|
||||
}
|
||||
|
||||
void InterfaceTreeCacheModel::addDevice(interface_t * newDevice)
|
||||
{
|
||||
emit beginInsertRows(QModelIndex(), rowCount(), rowCount());
|
||||
newDevices << newDevice;
|
||||
emit endInsertRows();
|
||||
}
|
||||
|
||||
void InterfaceTreeCacheModel::deleteDevice(const QModelIndex &index)
|
||||
{
|
||||
if ( ! index.isValid() )
|
||||
return;
|
||||
|
||||
emit beginRemoveRows(QModelIndex(), index.row(), index.row());
|
||||
|
||||
int row = index.row();
|
||||
|
||||
/* device is in newDevices */
|
||||
if ( row >= sourceModel->rowCount() )
|
||||
{
|
||||
int newDeviceIdx = row - sourceModel->rowCount();
|
||||
|
||||
newDevices.removeAt(newDeviceIdx);
|
||||
if ( storage->contains(index.row()) )
|
||||
storage->remove(index.row());
|
||||
|
||||
/* The storage array has to be resorted, if the index, that was removed
|
||||
* had been in the middle of the array. Can't start at index.row(), as
|
||||
* it may not be contained in storage
|
||||
* We must iterate using a list, not an iterator, otherwise the change
|
||||
* will fold on itself. */
|
||||
QList<int> storageKeys = storage->keys();
|
||||
for ( int i = 0; i < storageKeys.size(); ++i )
|
||||
{
|
||||
int key = storageKeys.at(i);
|
||||
if ( key > index.row() )
|
||||
{
|
||||
storage->insert(key - 1, storage->value(key));
|
||||
storage->remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
emit endRemoveRows();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_array_remove_index(global_capture_opts.all_ifaces, row);
|
||||
emit endRemoveRows();
|
||||
wsApp->emitAppSignal(WiresharkApplication::LocalInterfacesChanged);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -45,16 +45,26 @@ public:
|
|||
|
||||
QVariant getColumnContent(int idx, int col, int role = Qt::DisplayRole);
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
void reset(int row);
|
||||
void save();
|
||||
|
||||
void addDevice(interface_t * newDevice);
|
||||
void deleteDevice(const QModelIndex &index);
|
||||
|
||||
private:
|
||||
InterfaceTreeModel * sourceModel;
|
||||
|
||||
QList<interface_t *> newDevices;
|
||||
|
||||
void saveNewDevices();
|
||||
|
||||
QMap<int, QMap<InterfaceTreeColumns, QVariant> *> * storage;
|
||||
QList<InterfaceTreeColumns> editableColumns;
|
||||
QList<InterfaceTreeColumns> checkableColumns;
|
||||
|
||||
interface_t * lookup(const QModelIndex &index) const;
|
||||
bool changeIsAllowed(InterfaceTreeColumns col) const;
|
||||
bool isAllowedToBeChanged(const QModelIndex &index) const;
|
||||
bool isAllowedToBeEdited(const QModelIndex &index) const;
|
||||
|
|
|
@ -135,6 +135,10 @@ QVariant InterfaceTreeModel::data(const QModelIndex &index, int role) const
|
|||
{
|
||||
return QString(device.name);
|
||||
}
|
||||
else if ( col == IFTREE_COL_PIPE_PATH )
|
||||
{
|
||||
return QString(device.if_info.name);
|
||||
}
|
||||
else if ( col == IFTREE_COL_CAPTURE_FILTER )
|
||||
{
|
||||
if ( device.cfilter && strlen(device.cfilter) > 0 )
|
||||
|
@ -264,10 +268,14 @@ QVariant InterfaceTreeModel::headerData(int section, Qt::Orientation orientation
|
|||
{
|
||||
return tr("Friendly Name");
|
||||
}
|
||||
else if ( section == IFTREE_COL_INTERFACE_NAME )
|
||||
else if ( section == IFTREE_COL_NAME )
|
||||
{
|
||||
return tr("Interface Name");
|
||||
}
|
||||
else if ( section == IFTREE_COL_PIPE_PATH )
|
||||
{
|
||||
return tr("Local Pipe Path");
|
||||
}
|
||||
else if ( section == IFTREE_COL_INTERFACE_COMMENT )
|
||||
{
|
||||
return tr("Comment");
|
||||
|
|
|
@ -61,6 +61,7 @@ enum InterfaceTreeColumns
|
|||
IFTREE_COL_MONITOR_MODE,
|
||||
#endif
|
||||
IFTREE_COL_CAPTURE_FILTER,
|
||||
IFTREE_COL_PIPE_PATH,
|
||||
IFTREE_COL_MAX /* is not being displayed, it is the definition for the maximum numbers of columns */
|
||||
};
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
#include <glib.h>
|
||||
#include "manage_interfaces_dialog.h"
|
||||
#include <ui_manage_interfaces_dialog.h>
|
||||
|
||||
#include "epan/prefs.h"
|
||||
#include "epan/to_str.h"
|
||||
#include "ui/last_open_dir.h"
|
||||
#include "capture_opts.h"
|
||||
#include "ui/capture_globals.h"
|
||||
#include "ui/qt/capture_interfaces_dialog.h"
|
||||
|
@ -49,6 +49,8 @@
|
|||
|
||||
#include "ui/capture_ui_utils.h"
|
||||
|
||||
#include "ui/qt/path_chooser_delegate.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QFileDialog>
|
||||
#include <QHBoxLayout>
|
||||
|
@ -90,7 +92,7 @@ ManageInterfacesDialog::ManageInterfacesDialog(QWidget *parent) :
|
|||
|
||||
#ifdef Q_OS_MAC
|
||||
ui->addPipe->setAttribute(Qt::WA_MacSmallSize, true);
|
||||
ui->addPipe->setAttribute(Qt::WA_MacSmallSize, true);
|
||||
ui->delPipe->setAttribute(Qt::WA_MacSmallSize, true);
|
||||
ui->addRemote->setAttribute(Qt::WA_MacSmallSize, true);
|
||||
ui->delRemote->setAttribute(Qt::WA_MacSmallSize, true);
|
||||
#endif
|
||||
|
@ -110,14 +112,27 @@ ManageInterfacesDialog::ManageInterfacesDialog(QWidget *parent) :
|
|||
proxyModel->setFilterHidden(false);
|
||||
proxyModel->setFilterByType(false);
|
||||
|
||||
|
||||
ui->localView->setModel(proxyModel);
|
||||
ui->localView->resizeColumnToContents(proxyModel->mapSourceToColumn(IFTREE_COL_HIDDEN));
|
||||
ui->localView->resizeColumnToContents(proxyModel->mapSourceToColumn(IFTREE_COL_INTERFACE_NAME));
|
||||
ui->pipeList->setItemDelegateForColumn(col_p_pipe_, &new_pipe_item_delegate_);
|
||||
new_pipe_item_delegate_.setTree(ui->pipeList);
|
||||
|
||||
showPipes();
|
||||
pipeProxyModel = new InterfaceSortFilterModel(this);
|
||||
columns.clear();
|
||||
columns.append(IFTREE_COL_PIPE_PATH);
|
||||
pipeProxyModel->setColumns(columns);
|
||||
pipeProxyModel->setSourceModel(sourceModel);
|
||||
pipeProxyModel->setFilterHidden(true);
|
||||
pipeProxyModel->setFilterByType(true, true);
|
||||
pipeProxyModel->setInterfaceTypeVisible(IF_PIPE, false);
|
||||
ui->pipeView->setModel(pipeProxyModel);
|
||||
ui->delPipe->setEnabled(pipeProxyModel->rowCount() > 0);
|
||||
|
||||
ui->pipeView->setItemDelegateForColumn(
|
||||
pipeProxyModel->mapSourceToColumn(IFTREE_COL_PIPE_PATH), new PathChooserDelegate()
|
||||
);
|
||||
connect(ui->pipeView->selectionModel(),
|
||||
SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this,
|
||||
SLOT(onSelectionChanged(const QItemSelection &, const QItemSelection &)));
|
||||
|
||||
#if defined(HAVE_PCAP_REMOTE)
|
||||
// The default indentation (20) means our checkboxes are shifted too far on Windows.
|
||||
|
@ -128,7 +143,7 @@ ManageInterfacesDialog::ManageInterfacesDialog(QWidget *parent) :
|
|||
ui->remoteSettings->setEnabled(false);
|
||||
showRemoteInterfaces();
|
||||
#else
|
||||
ui->remoteTab->setEnabled(false);
|
||||
ui->tabWidget->removeTab(tab_remote_);
|
||||
#endif
|
||||
|
||||
connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(updateWidgets()));
|
||||
|
@ -149,16 +164,15 @@ ManageInterfacesDialog::~ManageInterfacesDialog()
|
|||
delete ui;
|
||||
}
|
||||
|
||||
void ManageInterfacesDialog::onSelectionChanged(const QItemSelection &sel, const QItemSelection &)
|
||||
{
|
||||
ui->delPipe->setEnabled( sel.count() > 0 );
|
||||
}
|
||||
|
||||
void ManageInterfacesDialog::updateWidgets()
|
||||
{
|
||||
QString hint;
|
||||
|
||||
if (ui->pipeList->selectedItems().length() > 0) {
|
||||
ui->delPipe->setEnabled(true);
|
||||
} else {
|
||||
ui->delPipe->setEnabled(false);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PCAP_REMOTE
|
||||
bool enable_del_remote = false;
|
||||
bool enable_remote_settings = false;
|
||||
|
@ -195,30 +209,8 @@ void ManageInterfacesDialog::updateWidgets()
|
|||
ui->hintLabel->setText(hint);
|
||||
}
|
||||
|
||||
void ManageInterfacesDialog::showPipes()
|
||||
{
|
||||
ui->pipeList->clear();
|
||||
|
||||
if (global_capture_opts.all_ifaces->len > 0) {
|
||||
interface_t device;
|
||||
|
||||
for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
|
||||
device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
|
||||
|
||||
/* Continue if capture device is hidden */
|
||||
if (device.hidden || device.type != IF_PIPE) {
|
||||
continue;
|
||||
}
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(ui->pipeList);
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
item->setText(col_p_pipe_, device.display_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ManageInterfacesDialog::on_buttonBox_accepted()
|
||||
{
|
||||
pipeAccepted();
|
||||
sourceModel->save();
|
||||
#ifdef HAVE_PCAP_REMOTE
|
||||
remoteAccepted();
|
||||
|
@ -228,97 +220,37 @@ void ManageInterfacesDialog::on_buttonBox_accepted()
|
|||
emit ifsChanged();
|
||||
}
|
||||
|
||||
const QString new_pipe_default_ = QObject::tr("New Pipe");
|
||||
void ManageInterfacesDialog::on_addPipe_clicked()
|
||||
{
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(ui->pipeList);
|
||||
item->setText(col_p_pipe_, new_pipe_default_);
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
ui->pipeList->setCurrentItem(item);
|
||||
ui->pipeList->editItem(item, col_p_pipe_);
|
||||
}
|
||||
interface_t * device = g_new0(interface_t, 1);
|
||||
|
||||
void ManageInterfacesDialog::pipeAccepted()
|
||||
{
|
||||
interface_t device;
|
||||
|
||||
// First clear the current pipes
|
||||
for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
|
||||
device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
|
||||
/* Continue if capture device is hidden or not a pipe */
|
||||
if (device.hidden || device.type != IF_PIPE) {
|
||||
continue;
|
||||
}
|
||||
global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
|
||||
capture_opts_free_interface_t(&device);
|
||||
}
|
||||
|
||||
// Next rebuild a fresh list
|
||||
QTreeWidgetItemIterator it(ui->pipeList);
|
||||
while (*it) {
|
||||
QString pipe_name = (*it)->text(col_p_pipe_);
|
||||
if (pipe_name.isEmpty() || pipe_name == new_pipe_default_) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
|
||||
// Instead of just deleting the device we might want to add a hint label
|
||||
// and let the user know what's going to happen.
|
||||
device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
|
||||
if (pipe_name.compare(device.name) == 0) { // Duplicate
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&device, 0, sizeof(device));
|
||||
device.name = qstring_strdup(pipe_name);
|
||||
device.display_name = g_strdup(device.name);
|
||||
device.hidden = FALSE;
|
||||
device.selected = TRUE;
|
||||
device.type = IF_PIPE;
|
||||
device.pmode = global_capture_opts.default_options.promisc_mode;
|
||||
device.has_snaplen = global_capture_opts.default_options.has_snaplen;
|
||||
device.snaplen = global_capture_opts.default_options.snaplen;
|
||||
device.cfilter = g_strdup(global_capture_opts.default_options.cfilter);
|
||||
device.addresses = NULL;
|
||||
device.no_addresses = 0;
|
||||
device.last_packets = 0;
|
||||
device.links = NULL;
|
||||
device->name = qstring_strdup(tr("New Pipe"));
|
||||
device->display_name = g_strdup(device->name);
|
||||
device->hidden = FALSE;
|
||||
device->selected = TRUE;
|
||||
device->pmode = global_capture_opts.default_options.promisc_mode;
|
||||
device->has_snaplen = global_capture_opts.default_options.has_snaplen;
|
||||
device->snaplen = global_capture_opts.default_options.snaplen;
|
||||
device->cfilter = g_strdup(global_capture_opts.default_options.cfilter);
|
||||
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
|
||||
device.buffer = DEFAULT_CAPTURE_BUFFER_SIZE;
|
||||
device->buffer = DEFAULT_CAPTURE_BUFFER_SIZE;
|
||||
#endif
|
||||
device.active_dlt = -1;
|
||||
device.locked = FALSE;
|
||||
device.if_info.name = g_strdup(device.name);
|
||||
device.if_info.friendly_name = NULL;
|
||||
device.if_info.vendor_description = NULL;
|
||||
device.if_info.addrs = NULL;
|
||||
device.if_info.loopback = FALSE;
|
||||
device.if_info.type = IF_PIPE;
|
||||
#ifdef HAVE_EXTCAP
|
||||
device.if_info.extcap = NULL;
|
||||
device.external_cap_args_settings = NULL;
|
||||
#endif
|
||||
#if defined(HAVE_PCAP_CREATE)
|
||||
device.monitor_mode_enabled = FALSE;
|
||||
device.monitor_mode_supported = FALSE;
|
||||
#endif
|
||||
global_capture_opts.num_selected++;
|
||||
g_array_append_val(global_capture_opts.all_ifaces, device);
|
||||
++it;
|
||||
}
|
||||
device->active_dlt = -1;
|
||||
device->if_info.name = g_strdup(device->name);
|
||||
device->if_info.type = IF_PIPE;
|
||||
|
||||
sourceModel->addDevice(device);
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
void ManageInterfacesDialog::on_delPipe_clicked()
|
||||
{
|
||||
// We're just managing a list of strings at this point.
|
||||
delete ui->pipeList->currentItem();
|
||||
}
|
||||
/* Get correct selection and tell the source model to delete the itm. pipe view only
|
||||
* displays IF_PIPE devices, therefore this will only delete pipes, and this is set
|
||||
* to only select single items. */
|
||||
QModelIndex selIndex = ui->pipeView->selectionModel()->selectedIndexes().at(0);
|
||||
|
||||
void ManageInterfacesDialog::on_pipeList_currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)
|
||||
{
|
||||
sourceModel->deleteDevice( pipeProxyModel->mapToSource(selIndex) );
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
|
@ -638,89 +570,6 @@ void ManageInterfacesDialog::setRemoteSettings(interface_t *iface)
|
|||
}
|
||||
#endif // HAVE_PCAP_REMOTE
|
||||
|
||||
PathChooserDelegate::PathChooserDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent), tree_(NULL), path_item_(NULL), path_editor_(NULL), path_le_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
PathChooserDelegate::~PathChooserDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
QWidget* PathChooserDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &) const
|
||||
{
|
||||
QTreeWidgetItem *item = tree_->currentItem();
|
||||
if (!item) {
|
||||
return NULL;
|
||||
}
|
||||
path_item_ = item;
|
||||
|
||||
path_editor_ = new QWidget(parent);
|
||||
QHBoxLayout *hbox = new QHBoxLayout(path_editor_);
|
||||
path_editor_->setLayout(hbox);
|
||||
path_le_ = new QLineEdit(path_editor_);
|
||||
QPushButton *pb = new QPushButton(path_editor_);
|
||||
|
||||
path_le_->setText(item->text(col_p_pipe_));
|
||||
pb->setText(QString(tr("Browse" UTF8_HORIZONTAL_ELLIPSIS)));
|
||||
|
||||
hbox->setContentsMargins(0, 0, 0, 0);
|
||||
hbox->addWidget(path_le_);
|
||||
hbox->addWidget(pb);
|
||||
hbox->setSizeConstraint(QLayout::SetMinimumSize);
|
||||
|
||||
// Grow the item to match the editor. According to the QAbstractItemDelegate
|
||||
// documenation we're supposed to reimplement sizeHint but this seems to work.
|
||||
QSize size = option.rect.size();
|
||||
size.setHeight(qMax(option.rect.height(), hbox->sizeHint().height()));
|
||||
item->setData(col_p_pipe_, Qt::SizeHintRole, size);
|
||||
|
||||
path_le_->selectAll();
|
||||
path_editor_->setFocusProxy(path_le_);
|
||||
path_editor_->setFocusPolicy(path_le_->focusPolicy());
|
||||
|
||||
connect(path_le_, SIGNAL(destroyed()), this, SLOT(stopEditor()));
|
||||
connect(pb, SIGNAL(pressed()), this, SLOT(browse_button_clicked()));
|
||||
return path_editor_;
|
||||
}
|
||||
|
||||
void PathChooserDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const
|
||||
{
|
||||
QRect rect = option.rect;
|
||||
|
||||
// Make sure the editor doesn't get squashed.
|
||||
editor->adjustSize();
|
||||
rect.setHeight(qMax(option.rect.height(), editor->height()));
|
||||
editor->setGeometry(rect);
|
||||
}
|
||||
|
||||
void PathChooserDelegate::stopEditor()
|
||||
{
|
||||
path_item_->setData(col_p_pipe_, Qt::SizeHintRole, QVariant());
|
||||
path_item_->setText(col_p_pipe_, path_le_->text());
|
||||
}
|
||||
|
||||
void PathChooserDelegate::browse_button_clicked()
|
||||
{
|
||||
char *open_dir = NULL;
|
||||
|
||||
switch (prefs.gui_fileopen_style) {
|
||||
|
||||
case FO_STYLE_LAST_OPENED:
|
||||
open_dir = get_last_open_dir();
|
||||
break;
|
||||
|
||||
case FO_STYLE_SPECIFIED:
|
||||
if (prefs.gui_fileopen_dir[0] != '\0')
|
||||
open_dir = prefs.gui_fileopen_dir;
|
||||
break;
|
||||
}
|
||||
QString file_name = QFileDialog::getOpenFileName(tree_, tr("Open Pipe"), open_dir);
|
||||
if (!file_name.isEmpty()) {
|
||||
path_le_->setText(file_name);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBPCAP */
|
||||
|
||||
/*
|
||||
|
|
|
@ -39,31 +39,6 @@ class QStandardItemModel;
|
|||
|
||||
class QLineEdit;
|
||||
|
||||
class PathChooserDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QTreeWidget* tree_;
|
||||
mutable QTreeWidgetItem *path_item_;
|
||||
mutable QWidget *path_editor_;
|
||||
mutable QLineEdit *path_le_;
|
||||
|
||||
public:
|
||||
PathChooserDelegate(QObject *parent = 0);
|
||||
~PathChooserDelegate();
|
||||
|
||||
void setTree(QTreeWidget* tree) { tree_ = tree; }
|
||||
|
||||
protected:
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
void updateEditorGeometry (QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const;
|
||||
|
||||
private slots:
|
||||
void stopEditor();
|
||||
void browse_button_clicked();
|
||||
};
|
||||
|
||||
|
||||
namespace Ui {
|
||||
class ManageInterfacesDialog;
|
||||
|
@ -79,11 +54,11 @@ public:
|
|||
|
||||
private:
|
||||
Ui::ManageInterfacesDialog *ui;
|
||||
PathChooserDelegate new_pipe_item_delegate_;
|
||||
|
||||
InterfaceTreeCacheModel * sourceModel;
|
||||
InterfaceSortFilterModel * proxyModel;
|
||||
void showPipes();
|
||||
InterfaceSortFilterModel * pipeProxyModel;
|
||||
|
||||
void showRemoteInterfaces();
|
||||
|
||||
signals:
|
||||
|
@ -100,9 +75,8 @@ private slots:
|
|||
|
||||
void on_addPipe_clicked();
|
||||
void on_delPipe_clicked();
|
||||
void pipeAccepted();
|
||||
void on_pipeList_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
|
||||
|
||||
void onSelectionChanged(const QItemSelection &sel, const QItemSelection &desel);
|
||||
|
||||
#ifdef HAVE_PCAP_REMOTE
|
||||
void on_addRemote_clicked();
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="pipeList">
|
||||
<widget class="QTreeView" name="pipeView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -91,11 +91,6 @@
|
|||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Named Pipe Path</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/* path_chooser_delegate.cpp
|
||||
* Delegate to select a file path 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 "epan/prefs.h"
|
||||
#include "ui/last_open_dir.h"
|
||||
|
||||
#include "ui/qt/path_chooser_delegate.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QFileDialog>
|
||||
#include <QWidget>
|
||||
#include <QLineEdit>
|
||||
|
||||
PathChooserDelegate::PathChooserDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QWidget* PathChooserDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &) const
|
||||
{
|
||||
QWidget * pathEditor = new QWidget(parent);
|
||||
QHBoxLayout *hbox = new QHBoxLayout(pathEditor);
|
||||
pathEditor->setLayout(hbox);
|
||||
QLineEdit * lineEdit = new QLineEdit(pathEditor);
|
||||
QPushButton *btnBrowse = new QPushButton(pathEditor);
|
||||
|
||||
btnBrowse->setText(tr("Browse"));
|
||||
|
||||
hbox->setContentsMargins(0, 0, 0, 0);
|
||||
hbox->addWidget(lineEdit);
|
||||
hbox->addWidget(btnBrowse);
|
||||
hbox->setSizeConstraint(QLayout::SetMinimumSize);
|
||||
|
||||
// Grow the item to match the editor. According to the QAbstractItemDelegate
|
||||
// documenation we're supposed to reimplement sizeHint but this seems to work.
|
||||
QSize size = option.rect.size();
|
||||
size.setHeight(qMax(option.rect.height(), hbox->sizeHint().height()));
|
||||
|
||||
lineEdit->selectAll();
|
||||
pathEditor->setFocusProxy(lineEdit);
|
||||
pathEditor->setFocusPolicy(lineEdit->focusPolicy());
|
||||
|
||||
connect(btnBrowse, SIGNAL(pressed()), this, SLOT(browse_button_clicked()));
|
||||
return pathEditor;
|
||||
}
|
||||
|
||||
void PathChooserDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const
|
||||
{
|
||||
QRect rect = option.rect;
|
||||
|
||||
// Make sure the editor doesn't get squashed.
|
||||
editor->adjustSize();
|
||||
rect.setHeight(qMax(option.rect.height(), editor->height()));
|
||||
editor->setGeometry(rect);
|
||||
}
|
||||
|
||||
void PathChooserDelegate::browse_button_clicked()
|
||||
{
|
||||
char *open_dir = NULL;
|
||||
|
||||
switch ( prefs.gui_fileopen_style )
|
||||
{
|
||||
|
||||
case FO_STYLE_LAST_OPENED:
|
||||
open_dir = get_last_open_dir();
|
||||
break;
|
||||
|
||||
case FO_STYLE_SPECIFIED:
|
||||
if ( prefs.gui_fileopen_dir[0] != '\0' )
|
||||
open_dir = prefs.gui_fileopen_dir;
|
||||
break;
|
||||
}
|
||||
|
||||
QString file_name = QFileDialog::getOpenFileName(new QWidget(), tr("Open Pipe"), open_dir);
|
||||
if ( !file_name.isEmpty() )
|
||||
{
|
||||
QWidget * parent = ((QPushButton *)sender())->parentWidget();
|
||||
QLineEdit * lineEdit = parent->findChild<QLineEdit*>();
|
||||
if ( lineEdit )
|
||||
{
|
||||
lineEdit->setText(file_name);
|
||||
emit commitData(parent);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PathChooserDelegate::setEditorData(QWidget *editor, const QModelIndex &idx) const
|
||||
{
|
||||
if ( idx.isValid() )
|
||||
{
|
||||
QString content = idx.data().toString();
|
||||
QLineEdit * lineEdit = editor->findChild<QLineEdit*>();
|
||||
if ( lineEdit )
|
||||
{
|
||||
lineEdit->setText(content);
|
||||
}
|
||||
}
|
||||
else
|
||||
QStyledItemDelegate::setEditorData(editor, idx);
|
||||
}
|
||||
|
||||
void PathChooserDelegate::setModelData(QWidget *editor, QAbstractItemModel * model, const QModelIndex &idx) const
|
||||
{
|
||||
if ( idx.isValid() )
|
||||
{
|
||||
QLineEdit * lineEdit = editor->findChild<QLineEdit*>();
|
||||
if ( lineEdit )
|
||||
{
|
||||
model->setData(idx, lineEdit->text());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QStyledItemDelegate::setModelData(editor, model, idx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
|
@ -0,0 +1,58 @@
|
|||
/* path_chooser_delegate.h
|
||||
* Delegate to select a file path 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 PATH_CHOOSER_DELEGATE_H_
|
||||
#define PATH_CHOOSER_DELEGATE_H_
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class PathChooserDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PathChooserDelegate(QObject *parent = 0);
|
||||
|
||||
protected:
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &idx) const;
|
||||
void updateEditorGeometry (QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & idx) const;
|
||||
void setEditorData(QWidget *editor, const QModelIndex &idx) const;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &idx) const;
|
||||
|
||||
private slots:
|
||||
void browse_button_clicked();
|
||||
};
|
||||
|
||||
#endif /* PATH_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:
|
||||
*/
|
Loading…
Reference in New Issue