forked from osmocom/wireshark
Implement "Save" and "Save As".
svn path=/trunk/; revision=45156
This commit is contained in:
parent
0ac06207ce
commit
068815cc67
|
@ -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 (;;) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include <QFileDialog>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QMessageBox>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue