Qt: Add methods to CaptureFile and WiresharkApplication.

Add isValid, fileTitle, and retapPackets methods to CaptureFile. Add
application name and title separator convenience methods to
WiresharkApplication.

Convert traffic tables, conversations, and endpoints to use CaptureFile
directly and to let the user know when the capture file is closed. Set
the file dialog titles while we're here.

Change-Id: I990392786d3833e1e0b3638aa2d34a5ada39fa13
Reviewed-on: https://code.wireshark.org/review/5957
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Reviewed-by: Gerald Combs <gerald@wireshark.org>
This commit is contained in:
Gerald Combs 2014-12-21 13:23:02 -08:00 committed by Gerald Combs
parent 30c3d394ad
commit 5cdad9fe42
11 changed files with 136 additions and 86 deletions

View File

@ -35,15 +35,18 @@ capture_file cfile;
#include "ui/capture.h"
#include <QFileInfo>
// To do:
// - Add isValid or isOpen methods instead of checking capFile() for NULL.
// - Add getters and (if needed) setters:
// - Base filename
// - Full filename
QString CaptureFile::no_capture_file_ = QObject::tr("[no capture file]");
CaptureFile::CaptureFile(QObject *parent, capture_file *cap_file) :
QObject(parent),
cap_file_(cap_file)
cap_file_(cap_file),
file_title_(no_capture_file_)
{
#ifdef HAVE_LIBPCAP
capture_callback_add(captureCallback, (gpointer) this);
@ -56,6 +59,21 @@ CaptureFile::~CaptureFile()
cf_callback_remove(captureFileCallback, this);
}
bool CaptureFile::isValid() const
{
if (cap_file_ && cap_file_->state != FILE_CLOSED) { // XXX FILE_READ_IN_PROGRESS as well?
return true;
}
return false;
}
void CaptureFile::retapPackets()
{
if (cap_file_) {
cf_retap_packets(cap_file_);
}
}
capture_file *CaptureFile::globalCapFile()
{
return &cfile;
@ -89,18 +107,24 @@ void CaptureFile::captureFileEvent(int event, gpointer data)
{
switch(event) {
case(cf_cb_file_opened):
{
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Opened");
cap_file_ = (capture_file *) data;
QFileInfo cfi(QString::fromUtf8(cap_file_->filename));
file_title_ = cfi.baseName();
emit captureFileOpened();
break;
}
case(cf_cb_file_closing):
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
file_title_.append(tr(" [closed]"));
emit captureFileClosing();
break;
case(cf_cb_file_closed):
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
emit captureFileClosed();
cap_file_ = NULL;
file_title_ = no_capture_file_;
break;
case(cf_cb_file_read_started):
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");

View File

@ -40,6 +40,23 @@ public:
capture_file *capFile() const { return cap_file_; }
void setCapFile(capture_file *cap_file) { cap_file_ = cap_file; }
/** Check capture file validity
*
* @return true if the file is open, readable, and tappable. false if the file
* is closed.
*/
bool isValid() const;
/** Return a filename suitable for use in a window title.
*
* @return One of: the basename of the capture file without an extension,
* the basename followed by "[closed]", or "[no capture file]".
*/
const QString & fileTitle() { return file_title_; }
/** Retap the capture file
*/
void retapPackets();
// XXX This shouldn't be needed.
static capture_file *globalCapFile();
@ -73,7 +90,10 @@ private:
void captureFileEvent(int event, gpointer data);
void captureEvent(int event, capture_session *cap_session);
static QString no_capture_file_;
capture_file *cap_file_;
QString file_title_;
};
#endif // CAPTURE_FILE_H

View File

@ -57,7 +57,7 @@
// - Misleading bps calculation https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8703
const QString table_name_ = QObject::tr("Conversation");
ConversationDialog::ConversationDialog(QWidget *parent, capture_file *cf, int cli_proto_id, const char *filter) :
ConversationDialog::ConversationDialog(QWidget *parent, CaptureFile &cf, int cli_proto_id, const char *filter) :
TrafficTableDialog(parent, cf, filter, table_name_)
{
follow_bt_ = buttonBox()->addButton(tr("Follow Stream..."), QDialogButtonBox::ActionRole);
@ -96,9 +96,7 @@ ConversationDialog::ConversationDialog(QWidget *parent, capture_file *cf, int cl
updateWidgets();
itemSelectionChanged();
if (cap_file_) {
cf_retap_packets(cap_file_);
}
cap_file_.retapPackets();
}
ConversationDialog::~ConversationDialog()
@ -120,21 +118,21 @@ ConversationDialog::~ConversationDialog()
}
}
void ConversationDialog::setCaptureFile(capture_file *cf)
void ConversationDialog::captureFileClosing()
{
if (!cf) { // We only want to know when the file closes.
cap_file_ = NULL;
for (int i = 0; i < trafficTableTabWidget()->count(); i++) {
ConversationTreeWidget *cur_tree = qobject_cast<ConversationTreeWidget *>(trafficTableTabWidget()->widget(i));
remove_tap_listener(cur_tree->trafficTreeHash());
disconnect(cur_tree, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
this, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
}
displayFilterCheckBox()->setEnabled(false);
enabledTypesPushButton()->setEnabled(false);
follow_bt_->setEnabled(false);
graph_bt_->setEnabled(false);
// Keep the dialog around but disable any controls that depend
// on a live capture file.
for (int i = 0; i < trafficTableTabWidget()->count(); i++) {
ConversationTreeWidget *cur_tree = qobject_cast<ConversationTreeWidget *>(trafficTableTabWidget()->widget(i));
remove_tap_listener(cur_tree->trafficTreeHash());
disconnect(cur_tree, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
this, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
}
displayFilterCheckBox()->setEnabled(false);
enabledTypesPushButton()->setEnabled(false);
follow_bt_->setEnabled(false);
graph_bt_->setEnabled(false);
TrafficTableDialog::captureFileClosing();
}
bool ConversationDialog::addTrafficTable(register_ct_t* table)
@ -165,7 +163,7 @@ bool ConversationDialog::addTrafficTable(register_ct_t* table)
QByteArray filter_utf8;
const char *filter = NULL;
if (displayFilterCheckBox()->isChecked()) {
filter = cap_file_->dfilter;
filter = cap_file_.capFile()->dfilter;
} else if (!filter_.isEmpty()) {
filter_utf8 = filter_.toUtf8();
filter = filter_utf8.constData();
@ -200,7 +198,7 @@ conv_item_t *ConversationDialog::currentConversation()
void ConversationDialog::followStream()
{
if (!cap_file_) {
if (read_only_) {
return;
}
@ -233,7 +231,7 @@ void ConversationDialog::followStream()
void ConversationDialog::graphTcp()
{
if (!cap_file_) {
if (read_only_) {
return;
}
@ -261,7 +259,7 @@ void ConversationDialog::itemSelectionChanged()
bool follow_enable = false, graph_enable = false;
conv_item_t *conv_item = currentConversation();
if (cap_file_ && conv_item) {
if (!read_only_ && conv_item) {
switch (conv_item->ptype) {
case PT_TCP:
graph_enable = true;
@ -287,14 +285,14 @@ void ConversationDialog::on_nameResolutionCheckBox_toggled(bool checked)
void ConversationDialog::on_displayFilterCheckBox_toggled(bool checked)
{
if (!cap_file_) {
if (read_only_) {
return;
}
QByteArray filter_utf8;
const char *filter = NULL;
if (checked) {
filter = cap_file_->dfilter;
filter = cap_file_.capFile()->dfilter;
} else if (!filter_.isEmpty()) {
filter_utf8 = filter_.toUtf8();
filter = filter_utf8.constData();
@ -304,7 +302,7 @@ void ConversationDialog::on_displayFilterCheckBox_toggled(bool checked)
set_tap_dfilter(trafficTableTabWidget()->widget(i), filter);
}
cf_retap_packets(cap_file_);
cap_file_.retapPackets();
}
void ConversationDialog::on_buttonBox_helpRequested()

View File

@ -56,11 +56,11 @@ public:
* @param cli_proto_id If valid, add this protocol and bring it to the front.
* @param filter Display filter to apply.
*/
explicit ConversationDialog(QWidget *parent = 0, capture_file *cf = NULL, int cli_proto_id = -1, const char *filter = NULL);
explicit ConversationDialog(QWidget *parent, CaptureFile &cf, int cli_proto_id = -1, const char *filter = NULL);
~ConversationDialog();
public slots:
void setCaptureFile(capture_file *cf);
void captureFileClosing();
signals:
void filterAction(QString& filter, FilterAction::Action action, FilterAction::ActionType type);

View File

@ -41,7 +41,7 @@
#include <QUrl>
const QString table_name_ = QObject::tr("Endpoint");
EndpointDialog::EndpointDialog(QWidget *parent, capture_file *cf, int cli_proto_id, const char *filter) :
EndpointDialog::EndpointDialog(QWidget *parent, CaptureFile &cf, int cli_proto_id, const char *filter) :
TrafficTableDialog(parent, cf, filter, table_name_)
{
#ifdef HAVE_GEOIP
@ -82,9 +82,7 @@ EndpointDialog::EndpointDialog(QWidget *parent, capture_file *cf, int cli_proto_
#endif
itemSelectionChanged();
if (cap_file_) {
cf_retap_packets(cap_file_);
}
cap_file_.retapPackets();
}
EndpointDialog::~EndpointDialog()
@ -106,19 +104,19 @@ EndpointDialog::~EndpointDialog()
}
}
void EndpointDialog::setCaptureFile(capture_file *cf)
void EndpointDialog::captureFileClosing()
{
if (!cf) { // We only want to know when the file closes.
cap_file_ = NULL;
for (int i = 0; i < trafficTableTabWidget()->count(); i++) {
EndpointTreeWidget *cur_tree = qobject_cast<EndpointTreeWidget *>(trafficTableTabWidget()->widget(i));
remove_tap_listener(cur_tree->trafficTreeHash());
disconnect(cur_tree, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
this, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
}
displayFilterCheckBox()->setEnabled(false);
enabledTypesPushButton()->setEnabled(false);
// Keep the dialog around but disable any controls that depend
// on a live capture file.
for (int i = 0; i < trafficTableTabWidget()->count(); i++) {
EndpointTreeWidget *cur_tree = qobject_cast<EndpointTreeWidget *>(trafficTableTabWidget()->widget(i));
remove_tap_listener(cur_tree->trafficTreeHash());
disconnect(cur_tree, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
this, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
}
displayFilterCheckBox()->setEnabled(false);
enabledTypesPushButton()->setEnabled(false);
TrafficTableDialog::captureFileClosing();
}
bool EndpointDialog::addTrafficTable(register_ct_t *table)
@ -149,7 +147,7 @@ bool EndpointDialog::addTrafficTable(register_ct_t *table)
QByteArray filter_utf8;
const char *filter = NULL;
if (displayFilterCheckBox()->isChecked()) {
filter = cap_file_->dfilter;
filter = cap_file_.capFile()->dfilter;
} else if (!filter_.isEmpty()) {
filter_utf8 = filter_.toUtf8();
filter = filter_utf8.constData();

View File

@ -68,13 +68,13 @@ public:
* @param cli_proto_id If valid, add this protocol and bring it to the front.
* @param filter Display filter to apply.
*/
explicit EndpointDialog(QWidget *parent = 0, capture_file *cf = NULL, int cli_proto_id = -1, const char *filter = NULL);
explicit EndpointDialog(QWidget *parent, CaptureFile &cf, int cli_proto_id = -1, const char *filter = NULL);
~EndpointDialog();
signals:
public slots:
void setCaptureFile(capture_file *cf);
void captureFileClosing();
private:
#ifdef HAVE_GEOIP

View File

@ -2297,15 +2297,13 @@ void MainWindow::on_actionStatisticsCollectd_triggered()
void MainWindow::statCommandConversations(const char *arg, void *userdata)
{
ConversationDialog *conv_dialog = new ConversationDialog(this, capture_file_.capFile(), GPOINTER_TO_INT(userdata), arg);
ConversationDialog *conv_dialog = new ConversationDialog(this, capture_file_, GPOINTER_TO_INT(userdata), arg);
connect(conv_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
connect(conv_dialog, SIGNAL(openFollowStreamDialog(follow_type_t)),
this, SLOT(openFollowStreamDialog(follow_type_t)));
connect(conv_dialog, SIGNAL(openTcpStreamGraph(int)),
this, SLOT(openTcpStreamDialog(int)));
connect(this, SIGNAL(setCaptureFile(capture_file*)),
conv_dialog, SLOT(setCaptureFile(capture_file*)));
conv_dialog->show();
}
@ -2316,15 +2314,13 @@ void MainWindow::on_actionStatisticsConversations_triggered()
void MainWindow::statCommandEndpoints(const char *arg, void *userdata)
{
EndpointDialog *endp_dialog = new EndpointDialog(this, capture_file_.capFile(), GPOINTER_TO_INT(userdata), arg);
EndpointDialog *endp_dialog = new EndpointDialog(this, capture_file_, GPOINTER_TO_INT(userdata), arg);
connect(endp_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
connect(endp_dialog, SIGNAL(openFollowStreamDialog(follow_type_t)),
this, SLOT(openFollowStreamDialog(follow_type_t)));
connect(endp_dialog, SIGNAL(openTcpStreamGraph(int)),
this, SLOT(openTcpStreamDialog(int)));
connect(this, SIGNAL(setCaptureFile(capture_file*)),
endp_dialog, SLOT(setCaptureFile(capture_file*)));
endp_dialog->show();
}

View File

@ -49,17 +49,19 @@
// - Columns don't resize correctly.
// - Closing the capture file clears conversation data.
TrafficTableDialog::TrafficTableDialog(QWidget *parent, capture_file *cf, const char *filter, const QString &table_name) :
TrafficTableDialog::TrafficTableDialog(QWidget *parent, CaptureFile &cf, const char *filter, const QString &table_name) :
QDialog(parent),
ui(new Ui::TrafficTableDialog),
cap_file_(cf),
read_only_(false),
filter_(filter)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose, true);
// setAttribute(Qt::WA_DeleteOnClose, true);
setWindowTitle(tr("Wireshark: %1s").arg(table_name));
ui->enabledTypesPushButton->setText(tr("%1 Types").arg(table_name));
window_name_ = QString("%1s").arg(table_name);
setWindowTitle();
ui->enabledTypesPushButton->setText(tr("%1 Types").arg(window_name_));
// XXX Use recent settings instead
if (parent) {
@ -83,7 +85,7 @@ TrafficTableDialog::TrafficTableDialog(QWidget *parent, capture_file *cf, const
connect(ui->trafficTableTabWidget, SIGNAL(currentChanged(int)),
this, SLOT(itemSelectionChanged()));
connect(&cap_file_, SIGNAL(captureFileClosing()), this, SLOT(captureFileClosing()));
}
TrafficTableDialog::~TrafficTableDialog()
@ -91,6 +93,12 @@ TrafficTableDialog::~TrafficTableDialog()
delete ui;
}
void TrafficTableDialog::captureFileClosing()
{
setWindowTitle();
read_only_ = true;
}
const QList<int> TrafficTableDialog::defaultProtos() const
{
// Reasonable defaults?
@ -150,14 +158,14 @@ void TrafficTableDialog::on_nameResolutionCheckBox_toggled(bool checked)
void TrafficTableDialog::on_displayFilterCheckBox_toggled(bool checked)
{
if (!cap_file_) {
if (!cap_file_.isValid()) {
return;
}
QByteArray filter_utf8;
const char *filter = NULL;
if (checked) {
filter = cap_file_->dfilter;
filter = cap_file_.capFile()->dfilter;
} else if (!filter_.isEmpty()) {
filter_utf8 = filter_.toUtf8();
filter = filter_utf8.constData();
@ -167,7 +175,7 @@ void TrafficTableDialog::on_displayFilterCheckBox_toggled(bool checked)
set_tap_dfilter(ui->trafficTableTabWidget->widget(i), filter);
}
cf_retap_packets(cap_file_);
cap_file_.retapPackets();
}
void TrafficTableDialog::setTabText(QWidget *tree, const QString &text)
@ -197,9 +205,7 @@ void TrafficTableDialog::toggleTable()
}
if (new_table) {
if (cap_file_) {
cf_retap_packets(cap_file_);
}
cap_file_.retapPackets();
}
}
@ -220,6 +226,16 @@ void TrafficTableDialog::updateWidgets()
ui->trafficTableTabWidget->setUpdatesEnabled(true);
}
void TrafficTableDialog::setWindowTitle()
{
QDialog::setWindowTitle(tr("%1 %2 %3 %4")
.arg(wsApp->windowTitlePrefix())
.arg(window_name_)
.arg(wsApp->windowTitleSeparator())
.arg(cap_file_.fileTitle())
);
}
QList<QVariant> TrafficTableDialog::curTreeRowData(int row) const
{
TrafficTableTreeWidget *cur_tree = qobject_cast<TrafficTableTreeWidget *>(ui->trafficTableTabWidget->currentWidget());

View File

@ -30,6 +30,7 @@
#include "ui/follow.h"
#include "capture_file.h"
#include "filter_action.h"
#include <QPushButton>
@ -102,11 +103,11 @@ public:
* @param filter Display filter to apply.
* @param table_name If valid, add this protocol and bring it to the front.
*/
explicit TrafficTableDialog(QWidget *parent = 0, capture_file *cf = NULL, const char *filter = NULL, const QString &table_name = tr("Unknown"));
explicit TrafficTableDialog(QWidget *parent, CaptureFile &cf, const char *filter = NULL, const QString &table_name = tr("Unknown"));
~TrafficTableDialog();
public slots:
virtual void setCaptureFile(capture_file *cf) { Q_UNUSED(cf) }
virtual void captureFileClosing();
signals:
void filterAction(QString& filter, FilterAction::Action action, FilterAction::ActionType type);
@ -116,7 +117,8 @@ signals:
protected:
Ui::TrafficTableDialog *ui;
capture_file *cap_file_;
CaptureFile &cap_file_;
bool read_only_;
QString filter_;
QMenu traffic_type_menu_;
QPushButton *copy_bt_;
@ -139,7 +141,9 @@ protected slots:
void updateWidgets();
private:
void setWindowTitle();
QList<QVariant> curTreeRowData(int row) const;
QString window_name_;
private slots:
void on_nameResolutionCheckBox_toggled(bool checked);

View File

@ -51,6 +51,7 @@
#include "ui/software_update.h"
#include "ui/last_open_dir.h"
#include "ui/recent_utils.h"
#include "ui/utf8_entities.h"
#ifdef _WIN32
# include "ui/win32/console_win32.h"
@ -81,6 +82,12 @@ static char *last_open_dir = NULL;
static bool updated_last_open_dir = FALSE;
static QList<recent_item_status *> recent_items_;
QString WiresharkApplication::application_name_ = QString("Wireshark");
QString WiresharkApplication::window_title_separator_ = QString::fromUtf8(UTF8_MIDDLE_DOT);
QString WiresharkApplication::window_title_prefix_ = QString("%1 %2")
.arg(WiresharkApplication::application_name_)
.arg(WiresharkApplication::window_title_separator_);
void
topic_action(topic_action_e action)
{

View File

@ -93,6 +93,9 @@ public:
bool isInitialized() { return initialized_; }
const QIcon &normalIcon() const { return normal_icon_; }
const QIcon &captureIcon() const { return capture_icon_; }
const QString &applicationName() const { return application_name_; }
const QString &windowTitleSeparator() const { return window_title_separator_; }
const QString &windowTitlePrefix() const { return window_title_prefix_; }
QTranslator translator;
QTranslator translatorQt;
@ -108,6 +111,9 @@ private:
QSocketNotifier *if_notifier_;
QIcon normal_icon_;
QIcon capture_icon_;
static QString application_name_;
static QString window_title_separator_;
static QString window_title_prefix_;
protected:
bool event(QEvent *event);
@ -128,25 +134,6 @@ signals:
void addressResolutionChanged();
void fieldsChanged();
#if 0
void captureCapturePrepared(capture_session *cap_session);
void captureCaptureUpdateStarted(capture_session *cap_session);
void captureCaptureUpdateContinue(capture_session *cap_session);
void captureCaptureUpdateFinished(capture_session *cap_session);
void captureCaptureFixedStarted(capture_session *cap_session);
void captureCaptureFixedFinished(capture_session *cap_session);
void captureCaptureStopping(capture_session *cap_session);
void captureCaptureFailed(capture_session *cap_session);
#endif
#if 0
void captureFileOpened(const capture_file *cf);
void captureFileReadStarted(const capture_file *cf);
void captureFileReadFinished(const capture_file *cf);
void captureFileClosing(const capture_file *cf);
void captureFileClosed(const capture_file *cf);
#endif
void openStatCommandDialog(const QString &menu_path, const char *arg, void *userdata);
public slots: