diff options
author | Roland Knall <rknall@gmail.com> | 2016-10-25 14:27:56 +0200 |
---|---|---|
committer | Roland Knall <rknall@gmail.com> | 2016-10-27 23:54:04 +0000 |
commit | 6500a660c2285aa558be58b084de9554fccdfc09 (patch) | |
tree | bc5e12962c7864464f6ac9350c17110eefaf21f8 /ui | |
parent | 1fae14257a8a7ade813930097a12dd3e555a9f76 (diff) | |
download | wireshark-6500a660c2285aa558be58b084de9554fccdfc09.tar.gz wireshark-6500a660c2285aa558be58b084de9554fccdfc09.tar.bz2 wireshark-6500a660c2285aa558be58b084de9554fccdfc09.zip |
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>
Diffstat (limited to 'ui')
-rw-r--r-- | ui/qt/CMakeLists.txt | 2 | ||||
-rw-r--r-- | ui/qt/Makefile.am | 2 | ||||
-rw-r--r-- | ui/qt/interface_sort_filter_model.cpp | 26 | ||||
-rw-r--r-- | ui/qt/interface_sort_filter_model.h | 1 | ||||
-rw-r--r-- | ui/qt/interface_tree_cache_model.cpp | 247 | ||||
-rw-r--r-- | ui/qt/interface_tree_cache_model.h | 10 | ||||
-rw-r--r-- | ui/qt/interface_tree_model.cpp | 10 | ||||
-rw-r--r-- | ui/qt/interface_tree_model.h | 1 | ||||
-rw-r--r-- | ui/qt/manage_interfaces_dialog.cpp | 249 | ||||
-rw-r--r-- | ui/qt/manage_interfaces_dialog.h | 32 | ||||
-rw-r--r-- | ui/qt/manage_interfaces_dialog.ui | 7 | ||||
-rw-r--r-- | ui/qt/path_chooser_delegate.cpp | 152 | ||||
-rw-r--r-- | ui/qt/path_chooser_delegate.h | 58 |
13 files changed, 530 insertions, 267 deletions
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index 3220c835d6..3cd9d2e503 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -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 diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am index d674fc2e98..f543f42c0a 100644 --- a/ui/qt/Makefile.am +++ b/ui/qt/Makefile.am @@ -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 \ diff --git a/ui/qt/interface_sort_filter_model.cpp b/ui/qt/interface_sort_filter_model.cpp index fab21ec6e0..9b850e151b 100644 --- a/ui/qt/interface_sort_filter_model.cpp +++ b/ui/qt/interface_sort_filter_model.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> @@ -36,6 +37,11 @@ InterfaceSortFilterModel::InterfaceSortFilterModel(QObject *parent) : QSortFilterProxyModel(parent) { + resetAllFilter(); +} + +void InterfaceSortFilterModel::resetAllFilter() +{ _filterHidden = true; _filterTypes = true; _invertTypeFilter = false; @@ -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; diff --git a/ui/qt/interface_sort_filter_model.h b/ui/qt/interface_sort_filter_model.h index dd062acfb7..7f28eb0151 100644 --- a/ui/qt/interface_sort_filter_model.h +++ b/ui/qt/interface_sort_filter_model.h @@ -38,6 +38,7 @@ public: InterfaceSortFilterModel(QObject *parent); void setStoreOnChange(bool storeOnChange); + void resetAllFilter(); void setFilterHidden(bool filter); bool filterHidden() const; diff --git a/ui/qt/interface_tree_cache_model.cpp b/ui/qt/interface_tree_cache_model.cpp index 842697204b..126d9be074 100644 --- a/ui/qt/interface_tree_cache_model.cpp +++ b/ui/qt/interface_tree_cache_model.cpp @@ -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; - - 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); + interface_t * device = lookup(index); + if ( device == 0 ) + return false; - 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); + } } /* diff --git a/ui/qt/interface_tree_cache_model.h b/ui/qt/interface_tree_cache_model.h index fffa0ebb84..74163b12e7 100644 --- a/ui/qt/interface_tree_cache_model.h +++ b/ui/qt/interface_tree_cache_model.h @@ -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; diff --git a/ui/qt/interface_tree_model.cpp b/ui/qt/interface_tree_model.cpp index 062ef4e792..bae432be0b 100644 --- a/ui/qt/interface_tree_model.cpp +++ b/ui/qt/interface_tree_model.cpp @@ -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"); diff --git a/ui/qt/interface_tree_model.h b/ui/qt/interface_tree_model.h index 3d0816bfed..5517308791 100644 --- a/ui/qt/interface_tree_model.h +++ b/ui/qt/interface_tree_model.h @@ -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 */ }; diff --git a/ui/qt/manage_interfaces_dialog.cpp b/ui/qt/manage_interfaces_dialog.cpp index 1f33ce77db..eb053c45d2 100644 --- a/ui/qt/manage_interfaces_dialog.cpp +++ b/ui/qt/manage_interfaces_dialog.cpp @@ -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_); -} - -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; + interface_t * device = g_new0(interface_t, 1); + + 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; -#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; + device->buffer = DEFAULT_CAPTURE_BUFFER_SIZE; #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 */ /* diff --git a/ui/qt/manage_interfaces_dialog.h b/ui/qt/manage_interfaces_dialog.h index 1a812a583a..63b07c77c3 100644 --- a/ui/qt/manage_interfaces_dialog.h +++ b/ui/qt/manage_interfaces_dialog.h @@ -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(); diff --git a/ui/qt/manage_interfaces_dialog.ui b/ui/qt/manage_interfaces_dialog.ui index 8e09fa477a..417c4c8477 100644 --- a/ui/qt/manage_interfaces_dialog.ui +++ b/ui/qt/manage_interfaces_dialog.ui @@ -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> diff --git a/ui/qt/path_chooser_delegate.cpp b/ui/qt/path_chooser_delegate.cpp new file mode 100644 index 0000000000..0fe2130ffd --- /dev/null +++ b/ui/qt/path_chooser_delegate.cpp @@ -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: + */ diff --git a/ui/qt/path_chooser_delegate.h b/ui/qt/path_chooser_delegate.h new file mode 100644 index 0000000000..32ecd96eab --- /dev/null +++ b/ui/qt/path_chooser_delegate.h @@ -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: + */ |