summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/README.qt13
-rw-r--r--ui/qt/capture_file_dialog.cpp336
-rw-r--r--ui/qt/capture_file_dialog.h53
-rw-r--r--ui/qt/main_window.cpp241
-rw-r--r--ui/qt/main_window.h4
5 files changed, 492 insertions, 155 deletions
diff --git a/doc/README.qt b/doc/README.qt
index 5e538e48ce..da9bd31421 100644
--- a/doc/README.qt
+++ b/doc/README.qt
@@ -132,6 +132,15 @@ DO NOT simply port things over. Every feature, window, and element should be
re-thought. For example, should the user have to navigate two dialogs to get
HTTP request statistics?
+2.1 Changes
+
+- The display filter entry has been significantly reworked.
+
+- The welcome screen has been reworked. The interface list includes sparklines
+
+- "Go to packet" pops up a text entry in the main window instead of a separate dialog.
+
+
3. Translations (i18n)
For make your own translation of QtShark ! it is easy !
@@ -139,7 +148,7 @@ For make your own translation of QtShark ! it is easy !
- Launch "lupdate QtShark.pro" to generate/update your translation file
- Translate with Qt Linguist
- Launch "lrelease QtShark.pro" to create/update qtshark_xx.qm file
-- Attach your modification ("svn diff") in Wireshark Bug Tracker
+- Attach your modification ("svn diff") in Wireshark Bug Tracker
-More information about Qt Linguist
+More information about Qt Linguist
http://qt-project.org/doc/qt-4.8/linguist-manual.html
diff --git a/ui/qt/capture_file_dialog.cpp b/ui/qt/capture_file_dialog.cpp
index 25ca2a1d90..7d80b4f741 100644
--- a/ui/qt/capture_file_dialog.cpp
+++ b/ui/qt/capture_file_dialog.cpp
@@ -33,8 +33,6 @@
#ifdef Q_WS_WIN
#include <windows.h>
-#include "packet_list_record.h"
-#include "cfile.h"
#include "ui/win32/file_dlg_win32.h"
#else
#include <errno.h>
@@ -121,98 +119,49 @@ extern void topic_cb(gpointer *widget, int topic) {
// End stub routines
#endif // Q_WS_WIN
-CaptureFileDialog::CaptureFileDialog(QWidget *parent, QString &fileName, QString &displayFilter) :
- QFileDialog(parent), m_fileName(fileName), m_displayFilter(displayFilter)
+CaptureFileDialog::CaptureFileDialog(QWidget *parent, QString &display_filter) :
+ QFileDialog(parent), display_filter_(display_filter)
{
#if !defined(Q_WS_WIN)
- setWindowTitle(tr("Wireshark: Open Capture File"));
- setNameFilters(build_file_open_type_list());
- setFileMode(QFileDialog::ExistingFile);
-
- if (!m_fileName.isEmpty()) {
- selectFile(m_fileName);
- }
// Add extra widgets
// http://qt-project.org/faq/answer/how_can_i_add_widgets_to_my_qfiledialog_instance
setOption(QFileDialog::DontUseNativeDialog, true);
- QGridLayout *fdGrid = qobject_cast<QGridLayout*>(layout());
- QHBoxLayout *hBox = new QHBoxLayout();
- QVBoxLayout *controlsBox = new QVBoxLayout();
- QGridLayout *previewGrid = new QGridLayout();
- QLabel *lbl;
-
- fdGrid->addWidget(new QLabel(tr("Display Filter:")), fdGrid->rowCount(), 0, 1, 1);
-
- m_displayFilterEdit = new DisplayFilterEdit(this, true);
- m_displayFilterEdit->setText(m_displayFilter);
- fdGrid->addWidget(m_displayFilterEdit, fdGrid->rowCount() - 1, 1, 1, 1);
+ QGridLayout *fd_grid = qobject_cast<QGridLayout*>(layout());
+ QHBoxLayout *h_box = new QHBoxLayout();
- fdGrid->addLayout(hBox, fdGrid->rowCount(), 1, 1, -1);
+ fd_grid->addWidget(new QLabel(tr("Display Filter:")), fd_grid->rowCount(), 0, 1, 1);
- // Filter and resolution controls
- hBox->addLayout(controlsBox);
+ display_filter_edit_ = new DisplayFilterEdit(this, true);
+ display_filter_edit_->setText(display_filter_);
+ fd_grid->addWidget(display_filter_edit_, fd_grid->rowCount() - 1, 1, 1, 1);
- m_macRes.setText(tr("&MAC name resolution"));
- m_macRes.setChecked(gbl_resolv_flags.mac_name);
- controlsBox->addWidget(&m_macRes);
+ fd_grid->addLayout(h_box, fd_grid->rowCount(), 1, 1, -1);
- m_transportRes.setText(tr("&Transport name resolution"));
- m_transportRes.setChecked(gbl_resolv_flags.transport_name);
- controlsBox->addWidget(&m_transportRes);
+ // Left and right boxes for controls and preview
+ h_box->addLayout(&left_v_box_);
+ h_box->addLayout(&right_v_box_);
- m_networkRes.setText(tr("&Network name resolution"));
- m_networkRes.setChecked(gbl_resolv_flags.network_name);
- controlsBox->addWidget(&m_networkRes);
-
- m_externalRes.setText(tr("&External name resolver"));
- m_externalRes.setChecked(gbl_resolv_flags.use_external_net_name_resolver);
- controlsBox->addWidget(&m_externalRes);
-
- // Preview
- hBox->addLayout(previewGrid);
-
- previewGrid->setColumnStretch(0, 0);
- previewGrid->setColumnStretch(1, 10);
-
- lbl = new QLabel("Format:");
- previewGrid->addWidget(lbl, 0, 0);
- previewGrid->addWidget(&m_previewFormat, 0, 1);
- m_previewLabels << lbl << &m_previewFormat;
-
- lbl = new QLabel("Size:");
- previewGrid->addWidget(lbl, 1, 0);
- previewGrid->addWidget(&m_previewSize, 1, 1);
- m_previewLabels << lbl << &m_previewSize;
- lbl = new QLabel("Packets:");
- previewGrid->addWidget(lbl, 2, 0);
- previewGrid->addWidget(&m_previewPackets, 2, 1);
- m_previewLabels << lbl << &m_previewPackets;
-
- lbl = new QLabel("First Packet:");
- previewGrid->addWidget(lbl, 3, 0);
- previewGrid->addWidget(&m_previewFirst, 3, 1);
- m_previewLabels << lbl << &m_previewFirst;
-
- lbl = new QLabel("Elapsed Time:");
- previewGrid->addWidget(lbl, 4, 0);
- previewGrid->addWidget(&m_previewElapsed, 4, 1);
- m_previewLabels << lbl << &m_previewElapsed;
-
- // Grow the dialog to account for the extra widgets.
- resize(width(), height() + hBox->minimumSize().height() + m_displayFilterEdit->minimumSize().height());
+#endif
+}
- connect(this, SIGNAL(currentChanged(const QString &)), this, SLOT(preview(const QString &)));
+int CaptureFileDialog::selectedFileType() {
+ return type_hash_.value(selectedNameFilter(), -1);
+}
- preview("");
+int CaptureFileDialog::mergeType() {
+ if (merge_prepend_.isChecked())
+ return -1;
+ else if (merge_append_.isChecked())
+ return 1;
-#endif
+ return 0;
}
// Windows
#ifdef Q_WS_WIN
-int CaptureFileDialog::exec() {
+int CaptureFileDialog::open() {
GString *file_name = g_string_new(m_fileName.toUtf8().constData());
GString *display_filter = g_string_new(m_displayFilter.toUtf8().constData());
gboolean wof_status;
@@ -230,18 +179,118 @@ int CaptureFileDialog::exec() {
}
#else // not Q_WS_WINDOWS
+
+void CaptureFileDialog::addDisplayFilterEdit() {
+
+}
+
+void CaptureFileDialog::addResolutionControls(QVBoxLayout &v_box) {
+ mac_res_.setText(tr("&MAC name resolution"));
+ mac_res_.setChecked(gbl_resolv_flags.mac_name);
+ v_box.addWidget(&mac_res_);
+
+ transport_res_.setText(tr("&Transport name resolution"));
+ transport_res_.setChecked(gbl_resolv_flags.transport_name);
+ v_box.addWidget(&transport_res_);
+
+ network_res_.setText(tr("&Network name resolution"));
+ network_res_.setChecked(gbl_resolv_flags.network_name);
+ v_box.addWidget(&network_res_);
+
+ external_res_.setText(tr("&External name resolver"));
+ external_res_.setChecked(gbl_resolv_flags.use_external_net_name_resolver);
+ v_box.addWidget(&external_res_);
+}
+
+void CaptureFileDialog::addMergeControls(QVBoxLayout &v_box) {
+
+ merge_prepend_.setText("Prepend packets");
+ merge_prepend_.setToolTip("Insert packets from the selected file before the current file. Packet timestamps will be ignored.");
+ v_box.addWidget(&merge_prepend_);
+
+ merge_chrono_.setText("Merge chronologically");
+ merge_chrono_.setToolTip("Insert packets in chronological order.");
+ merge_chrono_.setChecked(true);
+ v_box.addWidget(&merge_chrono_);
+
+ merge_append_.setText("Append packets");
+ merge_append_.setToolTip("Insert packets from the selected file after the current file. Packet timestamps will be ignored.");
+ v_box.addWidget(&merge_append_);
+}
+
+void CaptureFileDialog::addPreview(QVBoxLayout &v_box) {
+ QGridLayout *preview_grid = new QGridLayout();
+ QLabel *lbl;
+
+ preview_labels_.clear();
+ v_box.addLayout(preview_grid);
+
+ preview_grid->setColumnStretch(0, 0);
+ preview_grid->setColumnStretch(1, 10);
+
+ lbl = new QLabel("Format:");
+ preview_grid->addWidget(lbl, 0, 0);
+ preview_grid->addWidget(&preview_format_, 0, 1);
+ preview_labels_ << lbl << &preview_format_;
+
+ lbl = new QLabel("Size:");
+ preview_grid->addWidget(lbl, 1, 0);
+ preview_grid->addWidget(&preview_size_, 1, 1);
+ preview_labels_ << lbl << &preview_size_;
+
+ lbl = new QLabel("Packets:");
+ preview_grid->addWidget(lbl, 2, 0);
+ preview_grid->addWidget(&preview_packets_, 2, 1);
+ preview_labels_ << lbl << &preview_packets_;
+
+ lbl = new QLabel("First Packet:");
+ preview_grid->addWidget(lbl, 3, 0);
+ preview_grid->addWidget(&preview_first_, 3, 1);
+ preview_labels_ << lbl << &preview_first_;
+
+ lbl = new QLabel("Elapsed Time:");
+ preview_grid->addWidget(lbl, 4, 0);
+ preview_grid->addWidget(&preview_elapsed_, 4, 1);
+ preview_labels_ << lbl << &preview_elapsed_;
+
+ connect(this, SIGNAL(currentChanged(const QString &)), this, SLOT(preview(const QString &)));
+
+ preview("");
+}
+
+
+// You have to use open, merge, saveAs, or exportPackets. We should
+// probably just make each type a subclass.
int CaptureFileDialog::exec() {
- m_fileName.clear();
- m_displayFilter.clear();
+ return QDialog::Rejected;
+}
+
+int CaptureFileDialog::open(QString &file_name) {
+ setWindowTitle(tr("Wireshark: Open Capture File"));
+ setNameFilters(buildFileOpenTypeList());
+ setFileMode(QFileDialog::ExistingFile);
+
+ file_name.clear();
+ display_filter_.clear();
+
+ addResolutionControls(left_v_box_);
+ addPreview(right_v_box_);
+
+ // Grow the dialog to account for the extra widgets.
+ resize(width(), height() + left_v_box_.minimumSize().height() + display_filter_edit_->minimumSize().height());
+
+ if (!file_name.isEmpty()) {
+ selectFile(file_name);
+ }
if (QFileDialog::exec() && selectedFiles().length() > 0) {
- m_fileName.append(selectedFiles()[0]);
- m_displayFilter.append(m_displayFilterEdit->text());
+ file_name.append(selectedFiles()[0]);
+ display_filter_.append(display_filter_edit_->text());
- gbl_resolv_flags.mac_name = m_macRes.isChecked();
- gbl_resolv_flags.transport_name = m_transportRes.isChecked();
- gbl_resolv_flags.network_name = m_networkRes.isChecked();
- gbl_resolv_flags.use_external_net_name_resolver = m_externalRes.isChecked();
+ gbl_resolv_flags.mac_name = mac_res_.isChecked();
+ gbl_resolv_flags.transport_name = transport_res_.isChecked();
+ gbl_resolv_flags.network_name = network_res_.isChecked();
+ gbl_resolv_flags.use_external_net_name_resolver = external_res_.isChecked();
return QDialog::Accepted;
} else {
@@ -249,14 +298,42 @@ int CaptureFileDialog::exec() {
}
}
-void CaptureFileDialog::append_file_type(QStringList &filters, int ft)
+int CaptureFileDialog::merge(QString &file_name) {
+ setWindowTitle(tr("Wireshark: Merge Capture File"));
+ setNameFilters(buildFileOpenTypeList());
+ setFileMode(QFileDialog::ExistingFile);
+
+ file_name.clear();
+ display_filter_.clear();
+
+ addMergeControls(left_v_box_);
+ addPreview(right_v_box_);
+
+ // Grow the dialog to account for the extra widgets.
+ resize(width(), height() + right_v_box_.minimumSize().height() + display_filter_edit_->minimumSize().height());
+
+ if (QFileDialog::exec() && selectedFiles().length() > 0) {
+ file_name.append(selectedFiles()[0]);
+ display_filter_.append(display_filter_edit_->text());
+
+ return QDialog::Accepted;
+ } else {
+ return QDialog::Rejected;
+ }
+}
+
+QString CaptureFileDialog::fileType(int ft, bool extension_globs)
{
QString filter;
- bool first;
GSList *extensions_list, *extension;
filter = wtap_file_type_string(ft);
+
+ if (!extension_globs)
+ return filter;
+
filter += " (";
+
extensions_list = wtap_get_file_extensions_list(ft, TRUE);
if (extensions_list == NULL) {
/* This file type doesn't have any particular extension
@@ -269,28 +346,24 @@ void CaptureFileDialog::append_file_type(QStringList &filters, int ft)
filter += "*.*";
} else {
/* Construct the list of patterns. */
- first = true;
for (extension = extensions_list; extension != NULL;
extension = g_slist_next(extension)) {
- /* XXX - the documentation says the separator is a blank */
- if (!first)
- filter += ';';
+ if (!filter.endsWith('('))
+ filter += ' ';
filter += "*.";
filter += (char *)extension->data;
- first = false;
}
wtap_free_file_extensions_list(extensions_list);
}
filter += ')';
- filters += filter;
+ return filter;
/* XXX - does QStringList's destructor destroy the strings in the list? */
}
-QStringList CaptureFileDialog::build_file_open_type_list(void) {
- QStringList filters; /* XXX - new? */
+QStringList CaptureFileDialog::buildFileOpenTypeList() {
+ QStringList filters;
int ft;
-
/* Add the "All Files" entry. */
filters << QString(tr("All Files (*.*)"));
@@ -299,7 +372,40 @@ QStringList CaptureFileDialog::build_file_open_type_list(void) {
if (ft == WTAP_FILE_UNKNOWN)
continue; /* not a real file type */
- append_file_type(filters, ft);
+ filters << fileType(ft);
+ }
+
+ return filters;
+}
+
+QStringList CaptureFileDialog::buildFileSaveAsTypeList(capture_file *cf, bool must_support_comments) {
+ QStringList filters;
+ GArray *savable_file_types;
+ guint i;
+ int ft;
+ int default_ft = -1;
+
+ type_hash_.clear();
+ savable_file_types = wtap_get_savable_file_types(cf->cd_t, cf->linktypes);
+
+ if (savable_file_types != NULL) {
+ QString file_type;
+ /* OK, we have at least one file type we can save this file as.
+ (If we didn't, we shouldn't have gotten here in the first
+ place.) Add them all to the combo box. */
+ for (i = 0; i < savable_file_types->len; i++) {
+ ft = g_array_index(savable_file_types, int, i);
+ if (must_support_comments) {
+ if (ft != WTAP_FILE_PCAPNG)
+ continue;
+ }
+ if (default_ft == -1)
+ default_ft = ft; /* first file type is the default */
+ file_type = fileType(ft, false);
+ filters << file_type;
+ type_hash_[file_type] = ft;
+ }
+ g_array_free(savable_file_types, TRUE);
}
return filters;
@@ -326,45 +432,45 @@ void CaptureFileDialog::preview(const QString & path)
// Follow the same steps as ui/win32/file_dlg_win32.c
- foreach (QLabel *lbl, m_previewLabels) {
+ foreach (QLabel *lbl, preview_labels_) {
lbl->setEnabled(false);
}
- m_previewFormat.setText(tr("-"));
- m_previewSize.setText(tr("-"));
- m_previewPackets.setText(tr("-"));
- m_previewFirst.setText(tr("-"));
- m_previewElapsed.setText(tr("-"));
+ preview_format_.setText(tr("-"));
+ preview_size_.setText(tr("-"));
+ preview_packets_.setText(tr("-"));
+ preview_first_.setText(tr("-"));
+ preview_elapsed_.setText(tr("-"));
if (path.length() < 1) {
return;
}
if (test_for_directory(path.toUtf8().data()) == EISDIR) {
- m_previewFormat.setText(tr("directory"));
+ preview_format_.setText(tr("directory"));
return;
}
wth = wtap_open_offline(path.toUtf8().data(), &err, &err_info, TRUE);
if (wth == NULL) {
if(err == WTAP_ERR_FILE_UNKNOWN_FORMAT) {
- m_previewFormat.setText(tr("unknown file format"));
+ preview_format_.setText(tr("unknown file format"));
} else {
- m_previewFormat.setText(tr("error opening file"));
+ preview_format_.setText(tr("error opening file"));
}
return;
}
// Success!
- foreach (QLabel *lbl, m_previewLabels) {
+ foreach (QLabel *lbl, preview_labels_) {
lbl->setEnabled(true);
}
// Format
- m_previewFormat.setText(QString::fromUtf8(wtap_file_type_string(wtap_file_type(wth))));
+ preview_format_.setText(QString::fromUtf8(wtap_file_type_string(wtap_file_type(wth))));
// Size
- m_previewSize.setText(QString("%1 bytes").arg(wtap_file_size(wth, &err)));
+ preview_size_.setText(QString("%1 bytes").arg(wtap_file_size(wth, &err)));
time(&time_preview);
while ( (wtap_read(wth, &err, &err_info, &data_offset)) ) {
@@ -393,22 +499,22 @@ void CaptureFileDialog::preview(const QString & path)
}
if(err != 0) {
- m_previewPackets.setText(QString("error after reading %1 packets").arg(packets));
+ preview_packets_.setText(QString("error after reading %1 packets").arg(packets));
return;
}
// Packet count
if(timed_out) {
- m_previewPackets.setText(QString("more than %1 (preview timeout)").arg(packets));
+ preview_packets_.setText(QString("more than %1 (preview timeout)").arg(packets));
} else {
- m_previewPackets.setText(QString("%1").arg(packets));
+ preview_packets_.setText(QString("%1").arg(packets));
}
// First packet
ti_time = (long)start_time;
ti_tm = localtime( &ti_time );
if(ti_tm) {
- m_previewFirst.setText(QString().sprintf(
+ preview_first_.setText(QString().sprintf(
"%04d-%02d-%02d %02d:%02d:%02d",
ti_tm->tm_year + 1900,
ti_tm->tm_mon + 1,
@@ -418,18 +524,18 @@ void CaptureFileDialog::preview(const QString & path)
ti_tm->tm_sec
));
} else {
- m_previewFirst.setText(tr("?"));
+ preview_first_.setText(tr("?"));
}
// Elapsed time
elapsed_time = (unsigned int)(stop_time-start_time);
if(timed_out) {
- m_previewElapsed.setText(tr("unknown"));
+ preview_elapsed_.setText(tr("unknown"));
} else if(elapsed_time/86400) {
- m_previewElapsed.setText(QString().sprintf("%02u days %02u:%02u:%02u",
+ preview_elapsed_.setText(QString().sprintf("%02u days %02u:%02u:%02u",
elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60));
} else {
- m_previewElapsed.setText(QString().sprintf("%02u:%02u:%02u",
+ preview_elapsed_.setText(QString().sprintf("%02u:%02u:%02u",
elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60));
}
diff --git a/ui/qt/capture_file_dialog.h b/ui/qt/capture_file_dialog.h
index 9118e0df9c..9c87cdd701 100644
--- a/ui/qt/capture_file_dialog.h
+++ b/ui/qt/capture_file_dialog.h
@@ -26,6 +26,9 @@
#include "display_filter_edit.h"
+#include "packet_list_record.h"
+#include "cfile.h"
+
#include <QFileDialog>
class CaptureFileDialog : public QFileDialog
@@ -56,35 +59,53 @@ class CaptureFileDialog : public QFileDialog
Q_OBJECT
public:
- explicit CaptureFileDialog(QWidget *parent, QString &fileName, QString &displayFilter);
+ explicit CaptureFileDialog(QWidget *parent = NULL, QString &display_filter = *new QString());
+ int selectedFileType();
+ int mergeType();
private:
#if !defined(Q_WS_WIN)
- void append_file_type(QStringList &filters, int ft);
- QStringList build_file_open_type_list(void);
+ void addDisplayFilterEdit();
+ void addResolutionControls(QVBoxLayout &v_box);
+ void addMergeControls(QVBoxLayout &v_box);
+ void addPreview(QVBoxLayout &v_box);
+
+ QString fileType(int ft, bool extension_globs = true);
+ QStringList buildFileOpenTypeList(void);
+ QStringList buildFileSaveAsTypeList(capture_file *cf, bool must_support_comments);
#endif // Q_WS_WIN
- QString &m_fileName;
- QString &m_displayFilter;
- QCheckBox m_macRes;
- QCheckBox m_transportRes;
- QCheckBox m_networkRes;
- QCheckBox m_externalRes;
+ QVBoxLayout left_v_box_;
+ QVBoxLayout right_v_box_;
+
+ DisplayFilterEdit* display_filter_edit_;
+ QString &display_filter_;
+
+ QCheckBox mac_res_;
+ QCheckBox transport_res_;
+ QCheckBox network_res_;
+ QCheckBox external_res_;
+
+ QLabel preview_format_;
+ QLabel preview_size_;
+ QLabel preview_packets_;
+ QLabel preview_first_;
+ QLabel preview_elapsed_;
+ QList<QLabel *> preview_labels_;
- QLabel m_previewFormat;
- QLabel m_previewSize;
- QLabel m_previewPackets;
- QLabel m_previewFirst;
- QLabel m_previewElapsed;
- QList<QLabel *> m_previewLabels;
+ QRadioButton merge_prepend_;
+ QRadioButton merge_chrono_;
+ QRadioButton merge_append_;
- DisplayFilterEdit* m_displayFilterEdit;
+ QHash<QString, int>type_hash_;
signals:
public slots:
int exec();
+ int open(QString &file_name);
+ int merge(QString &file_name);
private slots:
#if !defined(Q_WS_WIN)
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index 78cdb6192f..907f6558e8 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -316,10 +316,10 @@ void MainWindow::closeEvent(QCloseEvent *event) {
}
}
-void MainWindow::openCaptureFile(QString &cfPath)
+void MainWindow::openCaptureFile(QString &cf_path)
{
- QString fileName = "";
- QString displayFilter = "";
+ QString file_name = "";
+ QString display_filter = "";
dfilter_t *rfcode = NULL;
int err;
@@ -329,11 +329,31 @@ void MainWindow::openCaptureFile(QString &cfPath)
for (;;) {
- if (cfPath.isEmpty()) {
- CaptureFileDialog cfDlg(this, fileName, displayFilter);
+ if (cf_path.isEmpty()) {
+ CaptureFileDialog open_dlg(this, display_filter);
- if (cfDlg.exec()) {
- if (dfilter_compile(displayFilter.toUtf8().constData(), &rfcode)) {
+ switch (prefs.gui_fileopen_style) {
+
+ case FO_STYLE_LAST_OPENED:
+ /* The user has specified that we should start out in the last directory
+ we looked in. If we've already opened a file, use its containing
+ directory, if we could determine it, as the directory, otherwise
+ use the "last opened" directory saved in the preferences file if
+ there was one. */
+ /* This is now the default behaviour in file_selection_new() */
+ break;
+
+ case FO_STYLE_SPECIFIED:
+ /* The user has specified that we should always start out in a
+ specified directory; if they've specified that directory,
+ start out by showing the files in that dir. */
+ if (prefs.gui_fileopen_dir[0] != '\0')
+ open_dlg.setDirectory(prefs.gui_fileopen_dir);
+ break;
+ }
+
+ if (open_dlg.open(file_name)) {
+ if (dfilter_compile(display_filter.toUtf8().constData(), &rfcode)) {
cf_set_rfcode(&cfile, rfcode);
} else {
/* Not valid. Tell the user, and go back and run the file
@@ -341,31 +361,30 @@ void MainWindow::openCaptureFile(QString &cfPath)
//bad_dfilter_alert_box(top_level, display_filter->str);
QMessageBox::warning(this, tr("Invalid Display Filter"),
QString("The filter expression ") +
- displayFilter +
+ display_filter +
QString(" isn't a valid display filter. (") +
dfilter_error_msg + QString(")."),
QMessageBox::Ok);
continue;
}
- cfPath = fileName;
+ cf_path = file_name;
} else {
return;
}
}
/* Try to open the capture file. */
- if (cf_open(&cfile, cfPath.toUtf8().constData(), FALSE, &err) != CF_OK) {
+ if (cf_open(&cfile, cf_path.toUtf8().constData(), FALSE, &err) != CF_OK) {
/* We couldn't open it; don't dismiss the open dialog box,
just leave it around so that the user can, after they
dismiss the alert box popped up for the open error,
try again. */
if (rfcode != NULL)
dfilter_free(rfcode);
- cfPath.clear();
+ cf_path.clear();
continue;
}
- cap_file_ = &cfile;
cfile.window = this;
switch (cf_read(&cfile, FALSE)) {
@@ -388,12 +407,184 @@ void MainWindow::openCaptureFile(QString &cfPath)
break;
}
// get_dirname overwrites its path. Hopefully this isn't a problem.
- set_last_open_dir(get_dirname(cfPath.toUtf8().data()));
- df_combo_box_->setEditText(displayFilter);
+ set_last_open_dir(get_dirname(cf_path.toUtf8().data()));
+ df_combo_box_->setEditText(display_filter);
main_ui_->statusBar->showExpert();
}
+void MainWindow::mergeCaptureFile()
+{
+ QString file_name = "";
+ QString display_filter = "";
+ dfilter_t *rfcode = NULL;
+ int err;
+
+ if (!cap_file_)
+ return;
+
+ if (prefs.gui_ask_unsaved) {
+ if (cap_file_->is_tempfile || cap_file_->unsaved_changes) {
+ QMessageBox msg_dialog;
+ gchar *display_basename;
+ int response;
+
+ msg_dialog.setIcon(QMessageBox::Question);
+ /* This is a temporary capture file or has unsaved changes; ask the
+ user whether to save the capture. */
+ if (cap_file_->is_tempfile) {
+ msg_dialog.setText("Save packets before merging?");
+ msg_dialog.setInformativeText("A temporary capture file can't be merged.");
+ } else {
+ /*
+ * Format the message.
+ */
+ display_basename = g_filename_display_basename(cap_file_->filename);
+ msg_dialog.setText(QString("Save changes in \"%1\" before merging?").arg(display_basename));
+ g_free(display_basename);
+ msg_dialog.setInformativeText("Changes must be saved before the files can be merged.");
+ }
+
+ msg_dialog.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
+ msg_dialog.setDefaultButton(QMessageBox::Save);
+
+ response = msg_dialog.exec();
+
+ switch (response) {
+
+ case QMessageBox::Save:
+ /* Save the file but don't close it */
+ saveCapture(cap_file_, FALSE);
+ break;
+
+ case QMessageBox::Cancel:
+ default:
+ /* Don't do the merge. */
+ return;
+ }
+ }
+ }
+
+ for (;;) {
+ CaptureFileDialog merge_dlg(this, display_filter);
+ int file_type;
+ cf_status_t merge_status;
+ char *in_filenames[2];
+ char *tmpname;
+
+ switch (prefs.gui_fileopen_style) {
+
+ case FO_STYLE_LAST_OPENED:
+ /* The user has specified that we should start out in the last directory
+ we looked in. If we've already opened a file, use its containing
+ directory, if we could determine it, as the directory, otherwise
+ use the "last opened" directory saved in the preferences file if
+ there was one. */
+ /* This is now the default behaviour in file_selection_new() */
+ break;
+
+ case FO_STYLE_SPECIFIED:
+ /* The user has specified that we should always start out in a
+ specified directory; if they've specified that directory,
+ start out by showing the files in that dir. */
+ if (prefs.gui_fileopen_dir[0] != '\0')
+ merge_dlg.setDirectory(prefs.gui_fileopen_dir);
+ break;
+ }
+
+ if (merge_dlg.merge(file_name)) {
+ if (dfilter_compile(display_filter.toUtf8().constData(), &rfcode)) {
+ cf_set_rfcode(cap_file_, rfcode);
+ } else {
+ /* Not valid. Tell the user, and go back and run the file
+ selection box again once they dismiss the alert. */
+ //bad_dfilter_alert_box(top_level, display_filter->str);
+ QMessageBox::warning(this, tr("Invalid Display Filter"),
+ QString("The filter expression ") +
+ display_filter +
+ QString(" isn't a valid display filter. (") +
+ dfilter_error_msg + QString(")."),
+ QMessageBox::Ok);
+ continue;
+ }
+ } else {
+ return;
+ }
+
+ file_type = cap_file_->cd_t;
+
+ /* Try to merge or append the two files */
+ tmpname = NULL;
+ if (merge_dlg.mergeType() == 0) {
+ /* chronological order */
+ in_filenames[0] = cap_file_->filename;
+ in_filenames[1] = file_name.toUtf8().data();
+ merge_status = cf_merge_files(&tmpname, 2, in_filenames, file_type, FALSE);
+ } else if (merge_dlg.mergeType() <= 0) {
+ /* prepend file */
+ in_filenames[0] = file_name.toUtf8().data();
+ in_filenames[1] = cap_file_->filename;
+ merge_status = cf_merge_files(&tmpname, 2, in_filenames, file_type, TRUE);
+ } else {
+ /* append file */
+ in_filenames[0] = cap_file_->filename;
+ in_filenames[1] = file_name.toUtf8().data();
+ merge_status = cf_merge_files(&tmpname, 2, in_filenames, file_type, TRUE);
+ }
+
+ if (merge_status != CF_OK) {
+ if (rfcode != NULL)
+ dfilter_free(rfcode);
+ g_free(tmpname);
+ continue;
+ }
+
+ cf_close(cap_file_);
+
+ /* Try to open the merged capture file. */
+ if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) != CF_OK) {
+ /* We couldn't open it; fail. */
+ if (rfcode != NULL)
+ dfilter_free(rfcode);
+ g_free(tmpname);
+ return;
+ }
+
+ /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
+ it closed the previous capture file, and thus destroyed any
+ previous read filter attached to "cf"). */
+ cfile.rfcode = rfcode;
+
+ switch (cf_read(&cfile, FALSE)) {
+
+ case CF_READ_OK:
+ case CF_READ_ERROR:
+ /* Just because we got an error, that doesn't mean we were unable
+ to read any of the file; we handle what we could get from the
+ file. */
+ break;
+
+ case CF_READ_ABORTED:
+ /* The user bailed out of re-reading the capture file; the
+ capture file has been closed - just free the capture file name
+ string and return (without changing the last containing
+ directory). */
+ g_free(tmpname);
+ return;
+ }
+
+ /* Save the name of the containing directory specified in the path name,
+ if any; we can write over cf_merged_name, which is a good thing, given that
+ "get_dirname()" does write over its argument. */
+ set_last_open_dir(get_dirname(tmpname));
+ g_free(tmpname);
+ df_combo_box_->setEditText(display_filter);
+ main_ui_->statusBar->showExpert();
+ return;
+ }
+
+}
+
void MainWindow::saveCapture(capture_file *cf, bool close_capture) {
Q_UNUSED(cf);
Q_UNUSED(close_capture);
@@ -432,7 +623,7 @@ bool MainWindow::testCaptureFileClose(capture_file *cf, bool from_quit, QString
if (cf->is_tempfile) {
msg_dialog.setText("You have unsaved packets");
- msg_dialog.setDetailedText("They will be lost if you don't save them.");
+ msg_dialog.setInformativeText("They will be lost if you don't save them.");
if (capture_in_progress) {
question.append("Do you want to stop the capture and save the captured packets");
@@ -450,7 +641,7 @@ bool MainWindow::testCaptureFileClose(capture_file *cf, bool from_quit, QString
if (capture_in_progress) {
question.append("Do you want to stop the capture and save the captured packets");
question.append(before_what).append("?");
- msg_dialog.setDetailedText("Your captured packets will be lost if you don't save them.");
+ msg_dialog.setInformativeText("Your captured packets will be lost if you don't save them.");
} else {
gchar *display_basename = g_filename_display_basename(cf->filename);
question.append(QString("Do you want to save the changes you've made to the capture file \"%1\"%2?")
@@ -458,7 +649,7 @@ bool MainWindow::testCaptureFileClose(capture_file *cf, bool from_quit, QString
.arg(before_what)
);
g_free(display_basename);
- msg_dialog.setDetailedText("Your changes will be lost if you don't save them.");
+ msg_dialog.setInformativeText("Your changes will be lost if you don't save them.");
}
}
@@ -674,7 +865,7 @@ void MainWindow::setForCaptureInProgress(gboolean capture_in_progress)
// Capture callbacks
#ifdef HAVE_LIBPCAP
-void MainWindow::captureCapturePrepared(capture_options * /*capture_opts*/) {
+void MainWindow::captureCapturePrepared(capture_options *capture_opts) {
qDebug() << "FIX captureCapturePrepared";
// main_capture_set_main_window_title(capture_opts);
@@ -691,13 +882,16 @@ void MainWindow::captureCapturePrepared(capture_options * /*capture_opts*/) {
// /* Don't set up main window for a capture file. */
// main_set_for_capture_file(FALSE);
main_ui_->mainStack->setCurrentWidget(packet_splitter_);
+ cap_file_ = (capture_file *) capture_opts->cf;
}
-void MainWindow::captureCaptureUpdateStarted(capture_options * /*capture_opts*/) {
+void MainWindow::captureCaptureUpdateStarted(capture_options *capture_opts) {
+ Q_UNUSED(capture_opts);
+
qDebug() << "captureCaptureUpdateStarted";
setForCaptureInProgress(true);
}
-void MainWindow::captureCaptureUpdateFinished(capture_options * /*capture_opts*/) {
- qDebug() << "captureCaptureUpdateFinished";
+void MainWindow::captureCaptureUpdateFinished(capture_options *capture_opts) {
+ Q_UNUSED(capture_opts);
/* The capture isn't stopping any more - it's stopped. */
capture_stopping_ = false;
@@ -1009,6 +1203,11 @@ void MainWindow::on_actionFileOpen_triggered()
openCaptureFile();
}
+void MainWindow::on_actionFileMerge_triggered()
+{
+ mergeCaptureFile();
+}
+
void MainWindow::on_actionFileClose_triggered() {
testCaptureFileClose(&cfile);
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index 1bac66cdcb..da2a829605 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -94,7 +94,8 @@ private:
QSocketNotifier *pipe_notifier_;
#endif
- void openCaptureFile(QString& cfPath = *new QString());
+ void openCaptureFile(QString& cf_path = *new QString());
+ void mergeCaptureFile();
void saveCapture(capture_file *cf, bool close_capture);
bool testCaptureFileClose(capture_file *cf, bool from_quit = false, QString& before_what = *new QString());
void captureStop(capture_file *cf);
@@ -138,6 +139,7 @@ private slots:
void openRecentCaptureFile(QString& cfPath = *new QString());
void on_actionFileOpen_triggered();
+ void on_actionFileMerge_triggered();
void on_actionFileClose_triggered();
void on_actionGoGoToPacket_triggered();
void resetPreviousFocus();