diff options
Diffstat (limited to 'ui')
-rw-r--r-- | ui/qt/capture_file_dialog.cpp | 336 | ||||
-rw-r--r-- | ui/qt/capture_file_dialog.h | 53 | ||||
-rw-r--r-- | ui/qt/main_window.cpp | 241 | ||||
-rw-r--r-- | ui/qt/main_window.h | 4 |
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(); |