2012-01-04 22:13:01 +00:00
|
|
|
/* main_window.cpp
|
|
|
|
*
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "main_window.h"
|
|
|
|
#include "ui_main_window.h"
|
|
|
|
|
2012-01-14 00:16:16 +00:00
|
|
|
#include "globals.h"
|
2012-01-04 22:13:01 +00:00
|
|
|
|
2012-01-14 00:16:16 +00:00
|
|
|
#include <epan/filesystem.h>
|
2012-01-04 22:13:01 +00:00
|
|
|
#include <epan/prefs.h>
|
|
|
|
|
2012-01-24 19:04:05 +00:00
|
|
|
#include <wiretap/wtap.h>
|
|
|
|
|
2012-01-16 01:18:56 +00:00
|
|
|
#include "ui/main_statusbar.h"
|
2012-01-14 00:16:16 +00:00
|
|
|
|
2012-01-04 22:13:01 +00:00
|
|
|
#include "wireshark_application.h"
|
|
|
|
#include "packet_list.h"
|
2012-01-14 00:16:16 +00:00
|
|
|
#include "proto_tree.h"
|
2012-01-04 22:13:01 +00:00
|
|
|
#include "byte_view_tab.h"
|
|
|
|
#include "capture_file_dialog.h"
|
2012-01-14 00:16:16 +00:00
|
|
|
#include "display_filter_edit.h"
|
2012-01-04 22:13:01 +00:00
|
|
|
|
|
|
|
#include "qt_ui_utils.h"
|
|
|
|
|
|
|
|
#include <QTreeWidget>
|
|
|
|
#include <QTabWidget>
|
|
|
|
#include <QAction>
|
|
|
|
#include <QToolButton>
|
|
|
|
#include <QKeyEvent>
|
|
|
|
|
|
|
|
//menu_recent_file_write_all
|
|
|
|
|
|
|
|
// If we ever add support for multiple windows this will need to be replaced.
|
|
|
|
static MainWindow *cur_main_window = NULL;
|
|
|
|
|
|
|
|
MainWindow::MainWindow(QWidget *parent) :
|
|
|
|
QMainWindow(parent),
|
|
|
|
ui(new Ui::MainWindow)
|
|
|
|
{
|
2012-01-14 00:16:16 +00:00
|
|
|
capFile = NULL;
|
2012-01-04 22:13:01 +00:00
|
|
|
cur_main_window = this;
|
|
|
|
ui->setupUi(this);
|
|
|
|
|
|
|
|
connect(wsApp, SIGNAL(updateRecentItemStatus(const QString &, qint64, bool)), this, SLOT(updateRecentFiles()));
|
|
|
|
updateRecentFiles();
|
|
|
|
|
|
|
|
dfComboBox = new DisplayFilterCombo();
|
2012-01-14 00:16:16 +00:00
|
|
|
const DisplayFilterEdit *dfEdit = dynamic_cast<DisplayFilterEdit *>(dfComboBox->lineEdit());
|
|
|
|
connect(dfEdit, SIGNAL(pushFilterSyntaxStatus(QString&)), ui->statusBar, SLOT(pushFilterStatus(QString&)));
|
|
|
|
connect(dfEdit, SIGNAL(popFilterSyntaxStatus()), ui->statusBar, SLOT(popFilterStatus()));
|
|
|
|
connect(dfEdit, SIGNAL(pushFilterSyntaxWarning(QString&)), ui->statusBar, SLOT(pushTemporaryStatus(QString&)));
|
2012-01-04 22:13:01 +00:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
// Qt <= 4.7 doesn't seem to style Windows toolbars. If we wanted to be really fancy we could use Blur Behind:
|
|
|
|
// http://labs.qt.nokia.com/2009/09/15/using-blur-behind-on-windows/
|
|
|
|
setStyleSheet(
|
|
|
|
"QToolBar {"
|
|
|
|
" background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255,255,255,127), stop:0.37 rgba(234,234,234,127), stop:1 rgba(155,155,155,91));"
|
|
|
|
"}"
|
|
|
|
);
|
|
|
|
#endif
|
|
|
|
ui->mainToolBar->addWidget(dfComboBox);
|
|
|
|
|
|
|
|
splitterV = new QSplitter(ui->mainStack);
|
|
|
|
splitterV->setObjectName(QString::fromUtf8("splitterV"));
|
|
|
|
splitterV->setOrientation(Qt::Vertical);
|
|
|
|
|
|
|
|
PacketList *packetList = new PacketList(splitterV);
|
|
|
|
|
2012-01-14 00:16:16 +00:00
|
|
|
ProtoTree *protoTree = new ProtoTree(splitterV);
|
2012-01-04 22:13:01 +00:00
|
|
|
protoTree->setHeaderHidden(true);
|
|
|
|
|
|
|
|
ByteViewTab *byteViewTab = new ByteViewTab(splitterV);
|
|
|
|
byteViewTab->setTabPosition(QTabWidget::South);
|
|
|
|
byteViewTab->setDocumentMode(true);
|
|
|
|
|
|
|
|
packetList->setProtoTree(protoTree);
|
|
|
|
packetList->setByteViewTab(byteViewTab);
|
|
|
|
|
|
|
|
splitterV->addWidget(packetList);
|
|
|
|
splitterV->addWidget(protoTree);
|
|
|
|
splitterV->addWidget(byteViewTab);
|
|
|
|
|
|
|
|
ui->mainStack->addWidget(splitterV);
|
|
|
|
|
|
|
|
mainWelcome = new MainWelcome(ui->mainStack);
|
|
|
|
ui->mainStack->addWidget(mainWelcome);
|
2012-01-14 00:16:16 +00:00
|
|
|
connect(mainWelcome, SIGNAL(recentFileActivated(QString&)),
|
|
|
|
this, SLOT(openCaptureFile(QString&)));
|
|
|
|
|
|
|
|
connect(wsApp, SIGNAL(captureFileReadStarted(const capture_file*)),
|
|
|
|
this, SLOT(captureFileReadStarted(const capture_file*)));
|
|
|
|
connect(wsApp, SIGNAL(captureFileReadFinished(const capture_file*)),
|
|
|
|
this, SLOT(captureFileReadFinished(const capture_file*)));
|
|
|
|
connect(wsApp, SIGNAL(captureFileClosing(const capture_file*)),
|
|
|
|
this, SLOT(captureFileClosing(const capture_file*)));
|
|
|
|
connect(wsApp, SIGNAL(captureFileClosed(const capture_file*)),
|
|
|
|
this, SLOT(captureFileClosed(const capture_file*)));
|
|
|
|
|
|
|
|
connect(protoTree, SIGNAL(protoItemSelected(QString&)),
|
|
|
|
ui->statusBar, SLOT(pushFieldStatus(QString&)));
|
|
|
|
connect(protoTree, SIGNAL(protoItemUnselected()),
|
|
|
|
ui->statusBar, SLOT(popFieldStatus()));
|
2012-01-04 22:13:01 +00:00
|
|
|
|
|
|
|
ui->mainStack->setCurrentWidget(mainWelcome);
|
|
|
|
}
|
|
|
|
|
|
|
|
MainWindow::~MainWindow()
|
|
|
|
{
|
|
|
|
delete ui;
|
|
|
|
}
|
|
|
|
|
2012-01-14 00:16:16 +00:00
|
|
|
void MainWindow::keyPressEvent(QKeyEvent *event) {
|
|
|
|
|
|
|
|
if (event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_Slash) {
|
|
|
|
dfComboBox->setFocus(Qt::ShortcutFocusReason);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QMainWindow::keyPressEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::captureFileReadStarted(const capture_file *cf) {
|
|
|
|
if (cf != capFile) return;
|
|
|
|
// tap_param_dlg_update();
|
|
|
|
|
|
|
|
/* Set up main window for a capture file. */
|
|
|
|
// main_set_for_capture_file(TRUE);
|
|
|
|
|
|
|
|
ui->statusBar->popFileStatus();
|
2012-03-07 11:58:05 +00:00
|
|
|
//TODO:i18n
|
2012-01-14 00:16:16 +00:00
|
|
|
QString msg = QString().sprintf("Loading: %s", get_basename(cf->filename));
|
|
|
|
ui->statusBar->pushFileStatus(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::captureFileReadFinished(const capture_file *cf) {
|
|
|
|
if (cf != capFile) return;
|
|
|
|
|
|
|
|
// gchar *dir_path;
|
|
|
|
|
|
|
|
// if (!cf->is_tempfile && cf->filename) {
|
|
|
|
// /* Add this filename to the list of recent files in the "Recent Files" submenu */
|
|
|
|
// add_menu_recent_capture_file(cf->filename);
|
|
|
|
|
|
|
|
// /* Remember folder for next Open dialog and save it in recent */
|
|
|
|
// dir_path = get_dirname(g_strdup(cf->filename));
|
|
|
|
// set_last_open_dir(dir_path);
|
|
|
|
// g_free(dir_path);
|
|
|
|
// }
|
|
|
|
// set_display_filename(cf);
|
|
|
|
|
|
|
|
// /* Enable menu items that make sense if you have a capture file you've
|
|
|
|
// finished reading. */
|
|
|
|
// set_menus_for_capture_file(cf);
|
|
|
|
|
|
|
|
// /* Enable menu items that make sense if you have some captured packets. */
|
|
|
|
// set_menus_for_captured_packets(TRUE);
|
|
|
|
|
|
|
|
ui->statusBar->popFileStatus();
|
|
|
|
QString msg = QString().sprintf("%s", get_basename(cf->filename));
|
|
|
|
ui->statusBar->pushFileStatus(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::captureFileClosing(const capture_file *cf) {
|
|
|
|
if (cf != capFile) return;
|
|
|
|
|
|
|
|
/* reset expert info indicator */
|
|
|
|
// status_expert_hide();
|
|
|
|
// gtk_widget_show(expert_info_none);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::captureFileClosed(const capture_file *cf) {
|
|
|
|
if (cf != capFile) return;
|
|
|
|
packets_bar_update();
|
|
|
|
|
|
|
|
ui->statusBar->popFileStatus();
|
|
|
|
capFile = NULL;
|
|
|
|
}
|
|
|
|
|
2012-01-04 22:13:01 +00:00
|
|
|
void MainWindow::closeCaptureFile() {
|
|
|
|
cf_close(&cfile);
|
|
|
|
ui->mainStack->setCurrentWidget(mainWelcome);
|
|
|
|
}
|
|
|
|
|
2012-01-24 19:04:05 +00:00
|
|
|
static void
|
|
|
|
append_file_type(QStringList &filters, int ft)
|
|
|
|
{
|
|
|
|
QString filter;
|
|
|
|
bool first;
|
|
|
|
GSList *extensions_list, *extension;
|
|
|
|
|
|
|
|
filter = wtap_file_type_string(ft);
|
|
|
|
filter += " (";
|
|
|
|
extensions_list = wtap_get_file_extensions_list(ft);
|
|
|
|
if (extensions_list == NULL) {
|
|
|
|
/* This file type doesn't have any particular extension
|
|
|
|
conventionally used for it, so we'll just use "*.*"
|
|
|
|
as the pattern; on Windows, that matches all file names
|
|
|
|
- even those with no extension - so we don't need to
|
|
|
|
worry about compressed file extensions. (It does not
|
|
|
|
do so on UN*X; the right pattern on UN*X would just
|
|
|
|
be "*".) */
|
|
|
|
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 += ';';
|
|
|
|
filter += "*.";
|
|
|
|
filter += (char *)extension->data;
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
wtap_free_file_extensions_list(extensions_list);
|
|
|
|
}
|
|
|
|
filter += ')';
|
|
|
|
filters += filter;
|
|
|
|
/* XXX - does QStringList's destructor destroy the strings in the list? */
|
|
|
|
}
|
|
|
|
|
|
|
|
static QStringList
|
|
|
|
build_file_open_type_list(void) {
|
|
|
|
QStringList filters; /* XXX - new? */
|
|
|
|
int ft;
|
|
|
|
|
|
|
|
|
|
|
|
/* Add the "All Files" entry. */
|
2012-01-27 16:49:54 +00:00
|
|
|
filters << QString("All Files (*.*)");
|
2012-01-24 19:04:05 +00:00
|
|
|
|
|
|
|
/* Include all the file types Wireshark supports. */
|
|
|
|
for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
|
|
|
|
if (ft == WTAP_FILE_UNKNOWN)
|
|
|
|
continue; /* not a real file type */
|
|
|
|
|
|
|
|
append_file_type(filters, ft);
|
|
|
|
}
|
|
|
|
|
|
|
|
return filters;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
static QStringList
|
|
|
|
build_file_save_type_list(GArray *savable_file_types) {
|
|
|
|
QStringList filters = new QStringList;
|
|
|
|
guint i;
|
|
|
|
int ft;
|
|
|
|
|
|
|
|
/* Get only the file types as which we can save this file. */
|
|
|
|
if (savable_file_types != NULL) {
|
|
|
|
/* 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 filter list. */
|
|
|
|
for (i = 0; i < savable_file_types->len; i++) {
|
|
|
|
ft = g_array_index(savable_file_types, int, i);
|
|
|
|
append_file_type(filters, ft);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return filters;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-01-04 22:13:01 +00:00
|
|
|
void MainWindow::openCaptureFile(QString &cfPath)
|
|
|
|
{
|
|
|
|
dfilter_t *rfcode = NULL;
|
|
|
|
|
|
|
|
if (cfPath.isEmpty()) {
|
|
|
|
QStringList cfNames;
|
|
|
|
CaptureFileDialog cfDlg(this);
|
|
|
|
|
|
|
|
cfDlg.setLabelText(QFileDialog::FileName, tr("Wireshark: Open Capture File"));
|
|
|
|
cfDlg.setDirectory("/Users/gcombs/Documents/Captures");
|
2012-01-24 19:04:05 +00:00
|
|
|
cfDlg.setNameFilters(build_file_open_type_list());
|
2012-01-04 22:13:01 +00:00
|
|
|
cfDlg.setFileMode(QFileDialog::ExistingFile);
|
|
|
|
|
|
|
|
if (cfDlg.exec()) {
|
|
|
|
cfNames = cfDlg.selectedFiles();
|
|
|
|
if (cfNames.length() > 0) {
|
|
|
|
cfPath = cfNames[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cfPath.length() > 0) {
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/* Try to open the capture file. */
|
|
|
|
if (cf_open(&cfile, cfPath.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);
|
2012-01-14 00:16:16 +00:00
|
|
|
capFile = NULL;
|
2012-01-04 22:13:01 +00:00
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
ui->mainStack->setCurrentWidget(splitterV);
|
2012-01-14 00:16:16 +00:00
|
|
|
capFile = &cfile;
|
2012-01-04 22:13:01 +00:00
|
|
|
cf_read(&cfile, FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::recentActionTriggered() {
|
|
|
|
QAction *ra = qobject_cast<QAction*>(sender());
|
|
|
|
|
|
|
|
if (ra) {
|
|
|
|
QString cfPath = ra->data().toString();
|
|
|
|
openCaptureFile(cfPath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-15 21:59:11 +00:00
|
|
|
// XXX - Copied from ui/gtk/menus.c
|
2012-01-04 22:13:01 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Add the capture filename (with an absolute path) to the "Recent Files" menu.
|
|
|
|
*
|
|
|
|
* @param cf_name Absolute path to the file.
|
|
|
|
* @param first Prepend the filename if true, otherwise append it. Default is false (append).
|
|
|
|
*/
|
|
|
|
// XXX - We should probably create a RecentFile class.
|
|
|
|
void MainWindow::updateRecentFiles() {
|
|
|
|
QAction *ra;
|
|
|
|
QMenu *recentMenu = ui->menuOpenRecentCaptureFile;
|
|
|
|
QString action_cf_name;
|
|
|
|
|
|
|
|
if (!recentMenu) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
recentMenu->clear();
|
|
|
|
|
|
|
|
/* Iterate through the actions in menuOpenRecentCaptureFile,
|
|
|
|
* removing special items, a maybe duplicate entry and every item above count_max */
|
|
|
|
int shortcut = Qt::Key_0;
|
|
|
|
foreach (recent_item_status *ri, wsApp->recent_item_list()) {
|
|
|
|
// Add the new item
|
|
|
|
ra = new QAction(recentMenu);
|
|
|
|
ra->setData(ri->filename);
|
|
|
|
// XXX - Needs get_recent_item_status or equivalent
|
|
|
|
ra->setEnabled(ri->accessible);
|
|
|
|
recentMenu->insertAction(NULL, ra);
|
|
|
|
action_cf_name = ra->data().toString();
|
|
|
|
if (shortcut <= Qt::Key_9) {
|
|
|
|
ra->setShortcut(Qt::META | shortcut);
|
|
|
|
shortcut++;
|
|
|
|
}
|
|
|
|
ra->setText(action_cf_name);
|
|
|
|
connect(ra, SIGNAL(triggered()), this, SLOT(recentActionTriggered()));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (recentMenu->actions().count() > 0) {
|
|
|
|
// Separator + "Clear"
|
|
|
|
// XXX - Do we really need this?
|
|
|
|
ra = new QAction(recentMenu);
|
|
|
|
ra->setSeparator(true);
|
|
|
|
recentMenu->insertAction(NULL, ra);
|
|
|
|
|
|
|
|
ra = new QAction(recentMenu);
|
2012-03-07 10:16:33 +00:00
|
|
|
ra->setText(tr("Clear Menu"));
|
2012-01-04 22:13:01 +00:00
|
|
|
recentMenu->insertAction(NULL, ra);
|
|
|
|
connect(ra, SIGNAL(triggered()), wsApp, SLOT(clearRecentItems()));
|
|
|
|
} else {
|
|
|
|
if (ui->actionDummyNoFilesFound) {
|
|
|
|
recentMenu->addAction(ui->actionDummyNoFilesFound);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|