aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2012-09-26 19:52:53 +0000
committerGerald Combs <gerald@wireshark.org>2012-09-26 19:52:53 +0000
commit068815cc674e678c74d31eae7a1eb82a21f163e4 (patch)
treee8a796550698e0c637f81cd587ccae1b621bf5c0 /ui
parent0ac06207ce940a92f406419a7ed3dbfe56a9aaa0 (diff)
Implement "Save" and "Save As".
svn path=/trunk/; revision=45156
Diffstat (limited to 'ui')
-rw-r--r--ui/gtk/capture_file_dlg.c2
-rw-r--r--ui/qt/capture_file_dialog.cpp203
-rw-r--r--ui/qt/capture_file_dialog.h17
-rw-r--r--ui/qt/import_text_dialog.cpp1
-rw-r--r--ui/qt/main_window.cpp270
-rw-r--r--ui/qt/main_window.h5
6 files changed, 463 insertions, 35 deletions
diff --git a/ui/gtk/capture_file_dlg.c b/ui/gtk/capture_file_dlg.c
index 5243657d79..41e654cf22 100644
--- a/ui/gtk/capture_file_dlg.c
+++ b/ui/gtk/capture_file_dlg.c
@@ -1723,7 +1723,7 @@ file_save_as_cmd(capture_file *cf, gboolean must_support_comments,
gchar *dirname;
gboolean discard_comments = FALSE;
- /*
+ /*
* Loop until the user either selects a file or gives up.
*/
for (;;) {
diff --git a/ui/qt/capture_file_dialog.cpp b/ui/qt/capture_file_dialog.cpp
index 411488d78d..d72a358400 100644
--- a/ui/qt/capture_file_dialog.cpp
+++ b/ui/qt/capture_file_dialog.cpp
@@ -35,6 +35,7 @@
#endif
#include <errno.h>
+#include "file.h"
#include "../../epan/addr_resolv.h"
#include "../../epan/prefs.h"
#include "../../epan/filesystem.h"
@@ -46,6 +47,7 @@
#include <QLineEdit>
#include <QCheckBox>
#include <QFileInfo>
+#include <QMessageBox>
#include <QDebug>
@@ -119,20 +121,20 @@ extern void topic_cb(gpointer *widget, int topic) {
CaptureFileDialog::CaptureFileDialog(QWidget *parent, QString &display_filter) :
QFileDialog(parent), display_filter_(display_filter)
+#if !defined(Q_WS_WIN)
+ , default_ft_(-1)
+#else
+ , file_type_(-1)
+#endif
{
#if !defined(Q_WS_WIN)
-
// Add extra widgets
// http://qt-project.org/faq/answer/how_can_i_add_widgets_to_my_qfiledialog_instance
setOption(QFileDialog::DontUseNativeDialog, true);
QGridLayout *fd_grid = qobject_cast<QGridLayout*>(layout());
QHBoxLayout *h_box = new QHBoxLayout();
- fd_grid->addWidget(new QLabel(tr("Display Filter:")), fd_grid->rowCount(), 0, 1, 1);
-
- 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);
+ df_row_ = fd_grid->rowCount();
fd_grid->addLayout(h_box, fd_grid->rowCount(), 1, 1, -1);
@@ -146,6 +148,89 @@ CaptureFileDialog::CaptureFileDialog(QWidget *parent, QString &display_filter) :
#endif // Q_WS_WIN
}
+#if !defined(Q_WS_WIN)
+check_savability_t CaptureFileDialog::checkSaveAsWithComments(capture_file *cf, int file_type) {
+ QMessageBox msg_dialog;
+ int response;
+
+ /* Do we have any comments? */
+ if (!cf_has_comments(cf)) {
+ /* No. Let the save happen; no comments to delete. */
+ return SAVE;
+ }
+
+ /* XXX - for now, we "know" that pcap-ng is the only format for which
+ we support comments. We should really ask Wiretap what the
+ format in question supports (and handle different types of
+ comments, some but not all of which some file formats might
+ not support). */
+ if (file_type == WTAP_FILE_PCAPNG) {
+ /* Yes - they selected pcap-ng. Let the save happen; we can
+ save the comments, so no need to delete them. */
+ return SAVE;
+ }
+ /* No. Is pcap-ng one of the formats in which we can write this file? */
+ if (wtap_dump_can_write_encaps(WTAP_FILE_PCAPNG, cf->linktypes)) {
+ QPushButton *default_button;
+ /* Yes. Offer the user a choice of "Save in a format that
+ supports comments", "Discard comments and save in the
+ format you selected", or "Cancel", meaning "don't bother
+ saving the file at all". */
+ msg_dialog.setIcon(QMessageBox::Question);
+ msg_dialog.setText("This capture file contains comments.");
+ msg_dialog.setInformativeText("The file format you chose doesn't support comments. "
+ "Do you want to save the capture in a format that supports comments "
+ "or discard the comments and save in the format you chose?");
+ msg_dialog.setStandardButtons(QMessageBox::Cancel);
+ // The predefined roles don't really match the tasks at hand...
+ msg_dialog.addButton("Discard comments and save", QMessageBox::DestructiveRole);
+ default_button = msg_dialog.addButton("Save in another format", QMessageBox::AcceptRole);
+ msg_dialog.setDefaultButton(default_button);
+ } else {
+ /* No. Offer the user a choice of "Discard comments and
+ save in the format you selected" or "Cancel". */
+ msg_dialog.setIcon(QMessageBox::Question);
+ msg_dialog.setText("This capture file contains comments.");
+ msg_dialog.setInformativeText("No file format in which it can be saved supports comments. "
+ "Do you want to discard the comments and save in the format you chose?");
+ msg_dialog.setStandardButtons(QMessageBox::Cancel);
+ msg_dialog.addButton("Discard comments and save", QMessageBox::DestructiveRole);
+ msg_dialog.setDefaultButton(QMessageBox::Cancel);
+ }
+
+ response = msg_dialog.exec();
+
+ switch (response) {
+
+ case QMessageBox::Save:
+ /* OK, the only other format we support is pcap-ng. Make that
+ the one and only format in the combo box, and return to
+ let the user continue with the dialog.
+
+ XXX - removing all the formats from the combo box will clear
+ the compressed checkbox; get the current value and restore
+ it.
+
+ XXX - we know pcap-ng can be compressed; if we ever end up
+ supporting saving comments in a format that *can't* be
+ compressed, such as NetMon format, we must check this. */
+ /* XXX - need a compressed checkbox here! */
+ return SAVE_IN_ANOTHER_FORMAT;
+
+ case QMessageBox::Discard:
+ /* Save without the comments and, if that succeeds, delete the
+ comments. */
+ return SAVE_WITHOUT_COMMENTS;
+
+ case QMessageBox::Cancel:
+ default:
+ /* Just give up. */
+ break;
+ }
+ return CANCELLED;
+}
+#endif // Q_WS_WIN
+
void CaptureFileDialog::addPreview(QVBoxLayout &v_box) {
QGridLayout *preview_grid = new QGridLayout();
QLabel *lbl;
@@ -215,8 +300,9 @@ QString CaptureFileDialog::fileType(int ft, bool extension_globs)
filter = wtap_file_type_string(ft);
- if (!extension_globs)
+ if (!extension_globs) {
return filter;
+ }
filter += " (";
@@ -267,15 +353,22 @@ QStringList CaptureFileDialog::buildFileOpenTypeList() {
// Windows
#ifdef Q_WS_WIN
+int CaptureFileDialog::selectedFileType() {
+ return file_type_;
+}
+
+int CaptureFileDialog::isCompressed() {
+ return compressed_;
+}
+
int CaptureFileDialog::open(QString &file_name) {
GString *fname = g_string_new(file_name.toUtf8().constData());
GString *dfilter = g_string_new(display_filter_.toUtf8().constData());
gboolean wof_status;
wof_status = win32_open_file(parentWidget()->effectiveWinId(), fname, dfilter);
- file_name.append(QString::fromUtf8(fname->str));
- display_filter_.clear();
- display_filter_.append(QString::fromUtf8(dfilter->str));
+ file_name = fname->str;
+ display_filter_ = dfilter->str;
g_string_free(fname, TRUE);
g_string_free(dfilter, TRUE);
@@ -283,15 +376,30 @@ int CaptureFileDialog::open(QString &file_name) {
return (int) wof_status;
}
+check_savability_t CaptureFileDialog::saveAs(capture_file *cf, QString &file_name, bool must_support_comments) {
+ GString *fname = g_string_new(file_name.toUtf8().constData());
+ gboolean wsf_status;
+
+ wsf_status = win32_save_as_file(parentWidget()->effectiveWinId(), cf, fname, &file_type_, &compressed_, must_support_comments);
+ file_name = fname->str;
+
+ g_string_free(fname, TRUE);
+
+ if (wsf_status) {
+ return win32_check_save_as_with_comments(parentWidget()->effectiveWinId(), cf, file_type);
+ }
+
+ return CANCELLED;
+}
+
int CaptureFileDialog::merge(QString &file_name) {
GString *fname = g_string_new(file_name.toUtf8().constData());
GString *dfilter = g_string_new(display_filter_.toUtf8().constData());
gboolean wmf_status;
wmf_status = win32_merge_file(parentWidget()->effectiveWinId(), fname, dfilter, &merge_type_);
- file_name.append(QString::fromUtf8(fname->str));
- display_filter_.clear();
- display_filter_.append(QString::fromUtf8(dfilter->str));
+ file_name = fname->str;
+ display_filter_ = dfilter->str;
g_string_free(fname, TRUE);
g_string_free(dfilter, TRUE);
@@ -308,7 +416,18 @@ int CaptureFileDialog::selectedFileType() {
return type_hash_.value(selectedNameFilter(), -1);
}
+bool CaptureFileDialog::isCompressed() {
+ return compress_.isChecked();
+}
+
void CaptureFileDialog::addDisplayFilterEdit() {
+ QGridLayout *fd_grid = qobject_cast<QGridLayout*>(layout());
+
+ fd_grid->addWidget(new QLabel(tr("Display Filter:")), df_row_, 0, 1, 1);
+
+ display_filter_edit_ = new DisplayFilterEdit(this, true);
+ display_filter_edit_->setText(display_filter_);
+ fd_grid->addWidget(display_filter_edit_, df_row_, 1, 1, 1);
}
@@ -330,26 +449,37 @@ void CaptureFileDialog::addResolutionControls(QVBoxLayout &v_box) {
v_box.addWidget(&external_res_);
}
+void CaptureFileDialog::addGzipControls(QVBoxLayout &v_box, capture_file *cf) {
+ compress_.setText(tr("Compress with g&zip"));
+ if (cf->iscompressed && wtap_dump_can_compress(default_ft_)) {
+ compress_.setChecked(true);
+ } else {
+ compress_.setChecked(false);
+ }
+ v_box.addWidget(&compress_);
+
+}
+
int CaptureFileDialog::open(QString &file_name) {
setWindowTitle(tr("Wireshark: Open Capture File"));
setNameFilters(buildFileOpenTypeList());
setFileMode(QFileDialog::ExistingFile);
- file_name.clear();
- display_filter_.clear();
-
+ addDisplayFilterEdit();
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());
+ display_filter_.clear();
+
if (!file_name.isEmpty()) {
selectFile(file_name);
}
if (QFileDialog::exec() && selectedFiles().length() > 0) {
- file_name.append(selectedFiles()[0]);
+ file_name = selectedFiles()[0];
display_filter_.append(display_filter_edit_->text());
gbl_resolv_flags.mac_name = mac_res_.isChecked();
@@ -363,17 +493,43 @@ int CaptureFileDialog::open(QString &file_name) {
}
}
+check_savability_t CaptureFileDialog::saveAs(capture_file *cf, QString &file_name, bool must_support_comments) {
+ setWindowTitle(tr("Wireshark: Save Capture File As"));
+ // XXX There doesn't appear to be a way to use setNameFilters without restricting
+ // what the user can select. We might want to use our own combobox instead and
+ // let the user select anything.
+ setNameFilters(buildFileSaveAsTypeList(cf, must_support_comments));
+ setAcceptMode(QFileDialog::AcceptSave);
+ setLabelText(FileType, "Save as:");
+
+ addGzipControls(left_v_box_, cf);
+
+ // Grow the dialog to account for the extra widgets.
+ resize(width(), height() + left_v_box_.minimumSize().height());
+
+ if (!file_name.isEmpty()) {
+ selectFile(file_name);
+ }
+
+ if (QFileDialog::exec() && selectedFiles().length() > 0) {
+ file_name = selectedFiles()[0];
+ return checkSaveAsWithComments(cf, selectedFileType());
+ }
+ return CANCELLED;
+}
+
int CaptureFileDialog::merge(QString &file_name) {
setWindowTitle(tr("Wireshark: Merge Capture File"));
setNameFilters(buildFileOpenTypeList());
setFileMode(QFileDialog::ExistingFile);
- file_name.clear();
- display_filter_.clear();
-
+ addDisplayFilterEdit();
addMergeControls(left_v_box_);
addPreview(right_v_box_);
+ file_name.clear();
+ display_filter_.clear();
+
// Grow the dialog to account for the extra widgets.
resize(width(), height() + right_v_box_.minimumSize().height() + display_filter_edit_->minimumSize().height());
@@ -392,7 +548,6 @@ QStringList CaptureFileDialog::buildFileSaveAsTypeList(capture_file *cf, bool mu
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);
@@ -408,9 +563,9 @@ QStringList CaptureFileDialog::buildFileSaveAsTypeList(capture_file *cf, bool mu
if (ft != WTAP_FILE_PCAPNG)
continue;
}
- if (default_ft == -1)
- default_ft = ft; /* first file type is the default */
- file_type = fileType(ft, false);
+ if (default_ft_ < 1)
+ default_ft_ = ft; /* first file type is the default */
+ file_type = fileType(ft);
filters << file_type;
type_hash_[file_type] = ft;
}
diff --git a/ui/qt/capture_file_dialog.h b/ui/qt/capture_file_dialog.h
index c2a1205b5f..94d1dbadbe 100644
--- a/ui/qt/capture_file_dialog.h
+++ b/ui/qt/capture_file_dialog.h
@@ -29,6 +29,8 @@
#include "packet_list_record.h"
#include "cfile.h"
+#include "ui/file_dialog.h"
+
#include <QFileDialog>
class CaptureFileDialog : public QFileDialog
@@ -60,10 +62,12 @@ class CaptureFileDialog : public QFileDialog
Q_OBJECT
public:
explicit CaptureFileDialog(QWidget *parent = NULL, QString &display_filter = *new QString());
- int mergeType();
#if !defined(Q_WS_WIN)
- int selectedFileType();
+ static check_savability_t checkSaveAsWithComments(capture_file *cf, int file_type);
#endif // Q_WS_WIN
+ int mergeType();
+ int selectedFileType();
+ bool isCompressed();
private:
void addMergeControls(QVBoxLayout &v_box);
@@ -77,6 +81,7 @@ private:
QString &display_filter_;
DisplayFilterEdit* display_filter_edit_;
+ int df_row_;
QLabel preview_format_;
QLabel preview_size_;
@@ -93,15 +98,22 @@ private:
#if !defined(Q_WS_WIN)
void addResolutionControls(QVBoxLayout &v_box);
+ void addGzipControls(QVBoxLayout &v_box, capture_file *cf);
QStringList buildFileSaveAsTypeList(capture_file *cf, bool must_support_comments);
+ int default_ft_;
+
QCheckBox mac_res_;
QCheckBox transport_res_;
QCheckBox network_res_;
QCheckBox external_res_;
+
+ QCheckBox compress_;
#else // Q_WS_WIN
+ int file_type_;
int merge_type_;
+ bool compressed_;
#endif // Q_WS_WIN
signals:
@@ -110,6 +122,7 @@ public slots:
int exec();
int open(QString &file_name);
+ check_savability_t saveAs(capture_file *cf, QString &file_name, bool must_support_comments);
int merge(QString &file_name);
private slots:
diff --git a/ui/qt/import_text_dialog.cpp b/ui/qt/import_text_dialog.cpp
index ba367fad97..e40f6502b8 100644
--- a/ui/qt/import_text_dialog.cpp
+++ b/ui/qt/import_text_dialog.cpp
@@ -47,7 +47,6 @@
#include <QFileDialog>
#include <QDebug>
#include <QFile>
-#include <QMessageBox>
#include <QDesktopServices>
#include <QUrl>
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index 97389a311d..63b6e3efe8 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -470,7 +470,7 @@ void MainWindow::mergeCaptureFile()
case QMessageBox::Save:
/* Save the file but don't close it */
- saveCapture(cap_file_, FALSE);
+ saveCaptureFile(cap_file_, FALSE);
break;
case QMessageBox::Cancel:
@@ -617,10 +617,258 @@ void MainWindow::importCaptureFile() {
openCaptureFile(import_dlg.capfileName());
}
-void MainWindow::saveCapture(capture_file *cf, bool close_capture) {
- Q_UNUSED(cf);
- Q_UNUSED(close_capture);
- g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: saveCapture");
+void MainWindow::saveCaptureFile(capture_file *cf, bool stay_closed) {
+ QString file_name;
+ gboolean discard_comments;
+ cf_write_status_t status;
+
+ if (cf->is_tempfile) {
+ /* This is a temporary capture file, so saving it means saving
+ it to a permanent file. Prompt the user for a location
+ to which to save it. Don't require that the file format
+ support comments - if it's a temporary capture file, it's
+ probably pcap-ng, which supports comments and, if it's
+ not pcap-ng, let the user decide what they want to do
+ if they've added comments. */
+ saveAsCaptureFile(cf, FALSE, stay_closed);
+ } else {
+ if (cf->unsaved_changes) {
+ /* This is not a temporary capture file, but it has unsaved
+ changes, so saving it means doing a "safe save" on top
+ of the existing file, in the same format - no UI needed
+ unless the file has comments and the file's format doesn't
+ support them.
+
+ If the file has comments, does the file's format support them?
+ If not, ask the user whether they want to discard the comments
+ or choose a different format. */
+ switch (CaptureFileDialog::checkSaveAsWithComments(cf, cf->cd_t)) {
+
+ case SAVE:
+ /* The file can be saved in the specified format as is;
+ just drive on and save in the format they selected. */
+ discard_comments = FALSE;
+ break;
+
+ case SAVE_WITHOUT_COMMENTS:
+ /* The file can't be saved in the specified format as is,
+ but it can be saved without the comments, and the user
+ said "OK, discard the comments", so save it in the
+ format they specified without the comments. */
+ discard_comments = TRUE;
+ break;
+
+ case SAVE_IN_ANOTHER_FORMAT:
+ /* There are file formats in which we can save this that
+ support comments, and the user said not to delete the
+ comments. Do a "Save As" so the user can select
+ one of those formats and choose a file name. */
+ saveAsCaptureFile(cf, TRUE, stay_closed);
+ return;
+
+ case CANCELLED:
+ /* The user said "forget it". Just return. */
+ return;
+
+ default:
+ /* Squelch warnings that discard_comments is being used
+ uninitialized. */
+ g_assert_not_reached();
+ return;
+ }
+
+ /* XXX - cf->filename might get freed out from under us, because
+ the code path through which cf_save_packets() goes currently
+ closes the current file and then opens and reloads the saved file,
+ so make a copy and free it later. */
+ file_name = cf->filename;
+ status = cf_save_packets(cf, file_name.toUtf8().constData(), cf->cd_t, cf->iscompressed,
+ discard_comments, stay_closed);
+ switch (status) {
+
+ case CF_WRITE_OK:
+ /* The save succeeded; we're done.
+ If we discarded comments, redraw the packet list to reflect
+ any packets that no longer have comments. */
+ if (discard_comments)
+ packet_list_queue_draw();
+ break;
+
+ case CF_WRITE_ERROR:
+ /* The write failed.
+ XXX - OK, what do we do now? Let them try a
+ "Save As", in case they want to try to save to a
+ different directory r file system? */
+ break;
+
+ case CF_WRITE_ABORTED:
+ /* The write was aborted; just drive on. */
+ break;
+ }
+ }
+ /* Otherwise just do nothing. */
+ }
+}
+
+void MainWindow::saveAsCaptureFile(capture_file *cf, bool must_support_comments, bool stay_closed) {
+ QString file_name = "";
+ int file_type;
+ gboolean compressed;
+ cf_write_status_t status;
+ QString file_name_lower;
+ QString file_suffix;
+ GSList *extensions_list, *extension;
+ gboolean add_extension;
+ gchar *dirname;
+ gboolean discard_comments = FALSE;
+
+ if (!cf) {
+ return;
+ }
+
+ for (;;) {
+ CaptureFileDialog save_as_dlg(this);
+
+ 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')
+ save_as_dlg.setDirectory(prefs.gui_fileopen_dir);
+ break;
+ }
+
+ /* If the file has comments, does the format the user selected
+ support them? If not, ask the user whether they want to
+ discard the comments or choose a different format. */
+ switch(save_as_dlg.saveAs(cf, file_name, must_support_comments)) {
+
+ case SAVE:
+ /* The file can be saved in the specified format as is;
+ just drive on and save in the format they selected. */
+ discard_comments = FALSE;
+ break;
+
+ case SAVE_WITHOUT_COMMENTS:
+ /* The file can't be saved in the specified format as is,
+ but it can be saved without the comments, and the user
+ said "OK, discard the comments", so save it in the
+ format they specified without the comments. */
+ discard_comments = TRUE;
+ break;
+
+ case SAVE_IN_ANOTHER_FORMAT:
+ /* There are file formats in which we can save this that
+ support comments, and the user said not to delete the
+ comments. The combo box of file formats has had the
+ formats that don't support comments trimmed from it,
+ so run the dialog again, to let the user decide
+ whether to save in one of those formats or give up. */
+ discard_comments = FALSE;
+ must_support_comments = TRUE;
+ continue;
+
+ case CANCELLED:
+ /* The user said "forget it". Just get rid of the dialog box
+ and return. */
+ return;
+ }
+ file_type = save_as_dlg.selectedFileType();
+ compressed = save_as_dlg.isCompressed();
+
+ /*
+ * Append the default file extension if there's none given by
+ * the user or if they gave one that's not one of the valid
+ * extensions for the file type.
+ */
+ file_name_lower = file_name.toLower();
+ extensions_list = wtap_get_file_extensions_list(file_type, FALSE);
+ if (extensions_list != NULL) {
+ /* We have one or more extensions for this file type.
+ Start out assuming we need to add the default one. */
+ add_extension = TRUE;
+
+ /* OK, see if the file has one of those extensions. */
+ for (extension = extensions_list; extension != NULL;
+ extension = g_slist_next(extension)) {
+ file_suffix += tr(".") + (char *)extension->data;
+ if (file_name_lower.endsWith(file_suffix)) {
+ /*
+ * The file name has one of the extensions for
+ * this file type.
+ */
+ add_extension = FALSE;
+ break;
+ }
+ file_suffix += ".gz";
+ if (file_name_lower.endsWith(file_suffix)) {
+ /*
+ * The file name has one of the extensions for
+ * this file type.
+ */
+ add_extension = FALSE;
+ break;
+ }
+ }
+ } else {
+ /* We have no extensions for this file type. Don't add one. */
+ add_extension = FALSE;
+ }
+ if (add_extension) {
+ if (wtap_default_file_extension(file_type) != NULL) {
+ file_name += tr(".") + wtap_default_file_extension(file_type);
+ if (compressed) {
+ file_name += ".gz";
+ }
+ }
+ }
+
+//#ifndef _WIN32
+// /* If the file exists and it's user-immutable or not writable,
+// ask the user whether they want to override that. */
+// if (!file_target_unwritable_ui(top_level, file_name.toUtf8().constData())) {
+// /* They don't. Let them try another file name or cancel. */
+// continue;
+// }
+//#endif
+
+ /* Attempt to save the file */
+ status = cf_save_packets(&cfile, file_name.toUtf8().constData(), file_type, compressed,
+ discard_comments, stay_closed);
+ switch (status) {
+
+ case CF_WRITE_OK:
+ /* The save succeeded; we're done. */
+ /* Save the directory name for future file dialogs. */
+ dirname = get_dirname(file_name.toUtf8().data()); /* Overwrites cf_name */
+ set_last_open_dir(dirname);
+ /* If we discarded comments, redraw the packet list to reflect
+ any packets that no longer have comments. */
+ if (discard_comments)
+ packet_list_queue_draw();
+ return;
+
+ case CF_WRITE_ERROR:
+ /* The save failed; let the user try again. */
+ continue;
+
+ case CF_WRITE_ABORTED:
+ /* The user aborted the save; just return. */
+ return;
+ }
+ }
+ return;
}
bool MainWindow::testCaptureFileClose(capture_file *cf, bool from_quit, QString &before_what) {
@@ -725,7 +973,7 @@ bool MainWindow::testCaptureFileClose(capture_file *cf, bool from_quit, QString
captureStop(cf);
#endif
/* Save the file and close it */
- saveCapture(cf, TRUE);
+ saveCaptureFile(cf, TRUE);
break;
case QMessageBox::Discard:
@@ -1253,6 +1501,16 @@ void MainWindow::on_actionFileClose_triggered() {
main_ui_->mainStack->setCurrentWidget(main_welcome_);
}
+void MainWindow::on_actionFileSave_triggered()
+{
+ saveCaptureFile(cap_file_, FALSE);
+}
+
+void MainWindow::on_actionFileSaveAs_triggered()
+{
+ saveAsCaptureFile(cap_file_, FALSE, TRUE);
+}
+
// View Menu
// Expand / collapse slots in proto_tree
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index 37dba2285a..c8e784edf8 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -97,7 +97,8 @@ private:
void openCaptureFile(QString& cf_path = *new QString());
void mergeCaptureFile();
void importCaptureFile();
- void saveCapture(capture_file *cf, bool close_capture);
+ void saveCaptureFile(capture_file *cf, bool stay_closed);
+ void saveAsCaptureFile(capture_file *cf, bool must_support_comments, bool stay_closed);
bool testCaptureFileClose(capture_file *cf, bool from_quit = false, QString& before_what = *new QString());
void captureStop(capture_file *cf);
@@ -143,6 +144,8 @@ private slots:
void on_actionFileMerge_triggered();
void on_actionFileImport_triggered();
void on_actionFileClose_triggered();
+ void on_actionFileSave_triggered();
+ void on_actionFileSaveAs_triggered();
void on_actionGoGoToPacket_triggered();
void resetPreviousFocus();