aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Knall <rknall@gmail.com>2019-11-21 15:57:32 +0100
committerAnders Broman <a.broman58@gmail.com>2019-11-22 05:10:16 +0000
commit8f90446db55c342b28d2dc8f1ab5f01b366b6993 (patch)
treecbda3d35136e124264b8f9ddb16f99952df6c97d
parent06afefad91804f33c4c825764cb045bb50c3842c (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.cpp114
-rw-r--r--ui/qt/export_object_dialog.h19
-rw-r--r--ui/qt/export_object_dialog.ui55
-rw-r--r--ui/qt/main_window_slots.cpp7
-rw-r--r--ui/qt/models/export_objects_model.cpp40
-rw-r--r--ui/qt/models/export_objects_model.h9
-rw-r--r--ui/qt/widgets/export_objects_view.cpp6
-rw-r--r--ui/qt/widgets/export_objects_view.h2
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 &current, 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 &current);
protected slots:
void currentChanged(const QModelIndex &current, const QModelIndex &previous);