diff options
author | Roland Knall <rknall@gmail.com> | 2019-11-21 15:57:32 +0100 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2019-11-22 05:10:16 +0000 |
commit | 8f90446db55c342b28d2dc8f1ab5f01b366b6993 (patch) | |
tree | cbda3d35136e124264b8f9ddb16f99952df6c97d | |
parent | 06afefad91804f33c4c825764cb045bb50c3842c (diff) |
Qt: Refactor ExportObjectsDialog
Add the following features:
- search now operates live (enter text changes the list live)
- filter by content-types
- Preview certain content types directly from the dialog
Change-Id: If47b64d475dd3e77485a28e8443a3e139e9bd1a4
Reviewed-on: https://code.wireshark.org/review/35182
Reviewed-by: Roland Knall <rknall@gmail.com>
Petri-Dish: Roland Knall <rknall@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
-rw-r--r-- | ui/qt/export_object_dialog.cpp | 114 | ||||
-rw-r--r-- | ui/qt/export_object_dialog.h | 19 | ||||
-rw-r--r-- | ui/qt/export_object_dialog.ui | 55 | ||||
-rw-r--r-- | ui/qt/main_window_slots.cpp | 7 | ||||
-rw-r--r-- | ui/qt/models/export_objects_model.cpp | 40 | ||||
-rw-r--r-- | ui/qt/models/export_objects_model.h | 9 | ||||
-rw-r--r-- | ui/qt/widgets/export_objects_view.cpp | 6 | ||||
-rw-r--r-- | ui/qt/widgets/export_objects_view.h | 2 |
8 files changed, 197 insertions, 55 deletions
diff --git a/ui/qt/export_object_dialog.cpp b/ui/qt/export_object_dialog.cpp index 68e295bc80..6d146513a6 100644 --- a/ui/qt/export_object_dialog.cpp +++ b/ui/qt/export_object_dialog.cpp @@ -15,11 +15,17 @@ #include "wireshark_application.h" #include "ui/qt/widgets/wireshark_file_dialog.h" +#include <ui/qt/widgets/export_objects_view.h> +#include <ui/qt/models/export_objects_model.h> #include <QDialogButtonBox> #include <QMessageBox> #include <QPushButton> - +#include <QComboBox> +#include <QDir> +#include <QFile> +#include <QFileInfo> +#include <QDesktopServices> ExportObjectDialog::ExportObjectDialog(QWidget &parent, CaptureFile &cf, register_eo_t* eo) : WiresharkDialog(parent, cf), @@ -47,15 +53,23 @@ ExportObjectDialog::ExportObjectDialog(QWidget &parent, CaptureFile &cf, registe #endif connect(&model_, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(modelDataChanged(QModelIndex))); + this, SLOT(modelDataChanged(QModelIndex, int, int))); connect(&model_, SIGNAL(modelReset()), this, SLOT(modelRowsReset())); - connect(eo_ui_->filterLine, &QLineEdit::textChanged, - &proxyModel_, &QSortFilterProxyModel::setFilterFixedString); - + connect(eo_ui_->filterLine, &QLineEdit::textChanged, &proxyModel_, &ExportObjectProxyModel::setTextFilterString); + connect(eo_ui_->objectTree, &ExportObjectsTreeView::currentIndexChanged, this, &ExportObjectDialog::currentHasChanged); save_bt_ = eo_ui_->buttonBox->button(QDialogButtonBox::Save); save_all_bt_ = eo_ui_->buttonBox->button(QDialogButtonBox::SaveAll); close_bt = eo_ui_->buttonBox->button(QDialogButtonBox::Close); + if (eo_ui_->buttonBox->button(QDialogButtonBox::Open)) + { + QPushButton * open = eo_ui_->buttonBox->button(QDialogButtonBox::Open); + open->setText(tr("Preview")); + open->setEnabled(false); + } + + contentTypes << tr("All Content-Types"); + eo_ui_->cmbContentType->addItems(contentTypes); setWindowTitle(wsApp->windowTitleString(QStringList() << tr("Export") << tr("%1 object list").arg(proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo)))))); @@ -65,10 +79,6 @@ ExportObjectDialog::ExportObjectDialog(QWidget &parent, CaptureFile &cf, registe connect(&cap_file_, SIGNAL(captureEvent(CaptureEvent)), this, SLOT(captureEvent(CaptureEvent))); - - show(); - raise(); - activateWindow(); } ExportObjectDialog::~ExportObjectDialog() @@ -78,20 +88,54 @@ ExportObjectDialog::~ExportObjectDialog() removeTapListeners(); } -ExportObjectsTreeView* ExportObjectDialog::getExportObjectView() +void ExportObjectDialog::currentHasChanged(QModelIndex current) { - return eo_ui_->objectTree; + if (current.isValid()) + { + QModelIndex sibl = current.sibling(current.row(), ExportObjectModel::colPacket); + if (eo_ui_->buttonBox->button(QDialogButtonBox::Open)) + { + QString cont = sibl.sibling(current.row(), ExportObjectModel::colContent).data().toString(); + /* For security reasons application and unknown are disabled */ + eo_ui_->buttonBox->button(QDialogButtonBox::Open)->setEnabled(! cont.startsWith("application/") && ! cont.startsWith("unknown/")); + } + wsApp->gotoFrame(sibl.data().toInt()); + } } -void ExportObjectDialog::modelDataChanged(const QModelIndex&) +void ExportObjectDialog::modelDataChanged(const QModelIndex&, int from, int to) { bool enabled = (model_.rowCount() > 0); if (save_bt_) save_bt_->setEnabled(enabled); if (save_all_bt_) save_all_bt_->setEnabled(enabled); + + for (int row = from; row <= to; row++) + { + QModelIndex idx = model_.index(row, ExportObjectModel::colContent); + if (idx.isValid()) + { + QString dataType = idx.data().toString(); + if (dataType.length() > 0 && ! contentTypes.contains(dataType)) + { + contentTypes << dataType; + contentTypes.sort(Qt::CaseInsensitive); + QString selType = eo_ui_->cmbContentType->currentText(); + eo_ui_->cmbContentType->clear(); + eo_ui_->cmbContentType->addItems(contentTypes); + if (contentTypes.contains(selType) ) + eo_ui_->cmbContentType->setCurrentText(selType); + } + } + } } void ExportObjectDialog::modelRowsReset() { + contentTypes.clear(); + contentTypes << tr("All Content-Types"); + eo_ui_->cmbContentType->clear(); + eo_ui_->cmbContentType->addItems(contentTypes); + if (save_bt_) save_bt_->setEnabled(false); if (save_all_bt_) save_all_bt_->setEnabled(false); } @@ -115,6 +159,13 @@ void ExportObjectDialog::show() eo_ui_->objectTree->sortByColumn(ExportObjectModel::colPacket, Qt::AscendingOrder); } +void ExportObjectDialog::keyPressEvent(QKeyEvent *evt) +{ + if(evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return) + return; + QDialog::keyPressEvent(evt); +} + void ExportObjectDialog::accept() { // Don't close the dialog. @@ -143,12 +194,28 @@ void ExportObjectDialog::on_buttonBox_clicked(QAbstractButton *button) case QDialogButtonBox::SaveAll: saveAllEntries(); break; + case QDialogButtonBox::Open: + { + QString temp; + saveCurrentEntry(&temp); + + if (temp.length() > 0) + QDesktopServices::openUrl(QUrl(QString("file:///").append(temp), QUrl::TolerantMode)); + break; + } default: // Help, Cancel break; } } -void ExportObjectDialog::saveCurrentEntry() +void ExportObjectDialog::on_cmbContentType_currentIndexChanged(int index) +{ + QString filterString = index <= 0 ? "" : eo_ui_->cmbContentType->currentText(); + proxyModel_.setContentFilterString(filterString); + +} + +void ExportObjectDialog::saveCurrentEntry(QString *tempFile) { QDir path(wsApp->lastOpenDir()); @@ -160,14 +227,25 @@ void ExportObjectDialog::saveCurrentEntry() if (!current.isValid()) return; - QString entry_filename = model_.data(model_.index(current.row(), ExportObjectModel::colFilename), Qt::DisplayRole).toString(); + QString entry_filename = current.sibling(current.row(), ExportObjectModel::colFilename).data().toString(); if (entry_filename.isEmpty()) return; - GString *safe_filename = eo_massage_str(entry_filename.toUtf8().constData(), EXPORT_OBJECT_MAXFILELEN, 0); - QString file_name = WiresharkFileDialog::getSaveFileName(this, wsApp->windowTitleString(tr("Save Object As" UTF8_HORIZONTAL_ELLIPSIS)), - safe_filename->str); - g_string_free(safe_filename, TRUE); + QString file_name; + if (!tempFile) + { + GString *safe_filename = eo_massage_str(entry_filename.toUtf8().constData(), EXPORT_OBJECT_MAXFILELEN, 0); + file_name = WiresharkFileDialog::getSaveFileName(this, wsApp->windowTitleString(tr("Save Object As" UTF8_HORIZONTAL_ELLIPSIS)), + safe_filename->str); + g_string_free(safe_filename, TRUE); + } else { + QString path = QDir::tempPath().append(QDir::separator()).append(entry_filename); + /* This means, the system must remove the file! */ + file_name = path; + if (QFileInfo::exists(path)) + QFile::remove(path); + *tempFile = path; + } model_.saveEntry(current, file_name); } diff --git a/ui/qt/export_object_dialog.h b/ui/qt/export_object_dialog.h index 178a2cf9d1..c1397d52c6 100644 --- a/ui/qt/export_object_dialog.h +++ b/ui/qt/export_object_dialog.h @@ -19,6 +19,8 @@ #include "wireshark_dialog.h" +#include <QKeyEvent> + class QTreeWidgetItem; class QAbstractButton; @@ -34,23 +36,26 @@ public: explicit ExportObjectDialog(QWidget &parent, CaptureFile &cf, register_eo_t* eo); ~ExportObjectDialog(); - ExportObjectsTreeView* getExportObjectView(); - public slots: void show(); +protected: + virtual void keyPressEvent(QKeyEvent *evt); + private slots: void accept(); void captureEvent(CaptureEvent e); void on_buttonBox_helpRequested(); void on_buttonBox_clicked(QAbstractButton *button); + void on_cmbContentType_currentIndexChanged(int index); -private slots: - void modelDataChanged(const QModelIndex &topLeft); + void modelDataChanged(const QModelIndex &topLeft, int from, int to); void modelRowsReset(); + void currentHasChanged(QModelIndex current); + private: - void saveCurrentEntry(); + void saveCurrentEntry(QString *tempFile = Q_NULLPTR); void saveAllEntries(); Ui::ExportObjectDialog *eo_ui_; @@ -59,6 +64,10 @@ private: QPushButton *save_all_bt_; ExportObjectModel model_; ExportObjectProxyModel proxyModel_; + + QStringList contentTypes; + + void updateContentTypes(); }; #endif // EXPORT_OBJECT_DIALOG_H diff --git a/ui/qt/export_object_dialog.ui b/ui/qt/export_object_dialog.ui index 271600b22b..81ea0da0d5 100644 --- a/ui/qt/export_object_dialog.ui +++ b/ui/qt/export_object_dialog.ui @@ -18,10 +18,35 @@ </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Text Filter:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="filterLine"> + <property name="toolTip"> + <string>Only display entries containing this string</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Content Type:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="cmbContentType"/> + </item> + </layout> + </item> + <item> <widget class="ExportObjectsTreeView" name="objectTree"> - <property name="sortingEnabled"> - <bool>true</bool> - </property> <property name="rootIsDecorated"> <bool>false</bool> </property> @@ -31,6 +56,9 @@ <property name="itemsExpandable"> <bool>false</bool> </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> <property name="expandsOnDoubleClick"> <bool>false</bool> </property> @@ -97,30 +125,12 @@ </widget> </item> <item> - <layout class="QHBoxLayout" name="filterLayout" stretch="0,0,0"> - <item alignment="Qt::AlignLeft"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Text Filter:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="filterLine"> - <property name="toolTip"> - <string>Only display entries containing this string</string> - </property> - </widget> - </item> - </layout> - </item> - <item> <widget class="QDialogButtonBox" name="buttonBox"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="standardButtons"> - <set>QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Save|QDialogButtonBox::SaveAll</set> + <set>QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Open|QDialogButtonBox::Save|QDialogButtonBox::SaveAll</set> </property> </widget> </item> @@ -133,6 +143,7 @@ <header>widgets/export_objects_view.h</header> </customwidget> </customwidgets> + <resources/> <connections> <connection> <sender>buttonBox</sender> diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 8d29ce6b8a..ed61fbbe0f 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -2790,10 +2790,9 @@ void MainWindow::applyExportObject() return; ExportObjectDialog* export_dialog = new ExportObjectDialog(*this, capture_file_, export_action->exportObject()); - - connect(export_dialog->getExportObjectView(), SIGNAL(goToPacket(int)), - packet_list_, SLOT(goToPacket(int))); - + export_dialog->setWindowModality(Qt::ApplicationModal); + export_dialog->setAttribute(Qt::WA_DeleteOnClose); + export_dialog->show(); } void MainWindow::on_actionAnalyzeEnabledProtocols_triggered() diff --git a/ui/qt/models/export_objects_model.cpp b/ui/qt/models/export_objects_model.cpp index c3a55185cd..057c6740f4 100644 --- a/ui/qt/models/export_objects_model.cpp +++ b/ui/qt/models/export_objects_model.cpp @@ -267,6 +267,46 @@ bool ExportObjectProxyModel::lessThan(const QModelIndex &source_left, const QMod return QSortFilterProxyModel::lessThan(source_left, source_right); } +void ExportObjectProxyModel::setContentFilterString(QString filter_) +{ + contentFilter_ = filter_; + invalidateFilter(); +} + +void ExportObjectProxyModel::setTextFilterString(QString filter_) +{ + textFilter_ = filter_; + invalidateFilter(); +} + +bool ExportObjectProxyModel::filterAcceptsRow(int source_row, const QModelIndex &/*source_parent*/) const +{ + if (contentFilter_.length() > 0) + { + QModelIndex idx = sourceModel()->index(source_row, ExportObjectModel::colContent); + if (!idx.isValid()) + return false; + + if (contentFilter_.compare(idx.data().toString()) != 0) + return false; + } + + if (textFilter_.length() > 0) + { + QModelIndex hostIdx = sourceModel()->index(source_row, ExportObjectModel::colHostname); + QModelIndex fileIdx = sourceModel()->index(source_row, ExportObjectModel::colFilename); + if (!hostIdx.isValid() || !fileIdx.isValid()) + return false; + + QString host = hostIdx.data().toString(); + QString file = fileIdx.data().toString(); + + if (!host.contains(textFilter_) && !file.contains(textFilter_)) + return false; + } + + return true; +} /* * Editor modelines diff --git a/ui/qt/models/export_objects_model.h b/ui/qt/models/export_objects_model.h index 0df79248dd..f254fca3ff 100644 --- a/ui/qt/models/export_objects_model.h +++ b/ui/qt/models/export_objects_model.h @@ -74,8 +74,17 @@ public: explicit ExportObjectProxyModel(QObject * parent = Q_NULLPTR); + void setContentFilterString(QString contentFilter); + void setTextFilterString(QString textFilter); + protected: bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; + +private: + QString contentFilter_; + QString textFilter_; + }; #endif // EXPORT_OBJECTS_MODEL_H diff --git a/ui/qt/widgets/export_objects_view.cpp b/ui/qt/widgets/export_objects_view.cpp index d426755228..72e0a73e3e 100644 --- a/ui/qt/widgets/export_objects_view.cpp +++ b/ui/qt/widgets/export_objects_view.cpp @@ -17,11 +17,7 @@ ExportObjectsTreeView::ExportObjectsTreeView(QWidget *parent) : QTreeView(parent void ExportObjectsTreeView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { - if (current.isValid()) - { - int packetNum = model()->data(model()->index(current.row(), ExportObjectModel::colPacket)).toInt(); - emit goToPacket(packetNum); - } + emit currentIndexChanged(current); QTreeView::currentChanged(current, previous); } diff --git a/ui/qt/widgets/export_objects_view.h b/ui/qt/widgets/export_objects_view.h index 711321bfde..7275753e33 100644 --- a/ui/qt/widgets/export_objects_view.h +++ b/ui/qt/widgets/export_objects_view.h @@ -21,7 +21,7 @@ public: ExportObjectsTreeView(QWidget *parent = 0); signals: - void goToPacket(int packet_num); + void currentIndexChanged(const QModelIndex ¤t); protected slots: void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); |