aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2012-09-06 22:58:39 +0000
committerGerald Combs <gerald@wireshark.org>2012-09-06 22:58:39 +0000
commit2bda67e82e64510bb254999a90404009b19a3ce4 (patch)
tree262bfefa5e13ffddcfe0480877d0ce2e53af4be5 /ui
parent4333dd03f4e3a669bf93e3d0fbcd1905493cb3c9 (diff)
Implement File→Merge.
The GTK+ and native Win32 versions are slightly different. The GTK+ version lets you select an output file type and the Win32 version uses the existing capture filetype. We do the latter for now. Start documenting significant UI changes in README.qt. This might be better handled on the wiki. svn path=/trunk/; revision=44797
Diffstat (limited to 'ui')
-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
4 files changed, 481 insertions, 153 deletions
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();