wireshark/ui/qt/stats_tree_dialog.cpp

293 lines
8.7 KiB
C++
Raw Normal View History

/* stats_tree_dialog.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "stats_tree_dialog.h"
#include "ui_stats_tree_dialog.h"
#include "file.h"
#include "epan/stats_tree_priv.h"
#include "wireshark_application.h"
#include <QClipboard>
#include <QMessageBox>
#include <QTreeWidget>
#include <QTreeWidgetItemIterator>
// The GTK+ counterpart uses tap_param_dlg, which we don't use. If we
// need tap parameters we should probably create a TapParameterDialog
// class based on QDialog and subclass it here.
// To do:
// - Add help
#include <QDebug>
const int item_col_ = 0;
const int count_col_ = 1;
const int rate_col_ = 2;
const int percent_col_ = 3;
Q_DECLARE_METATYPE(stat_node *);
StatsTreeDialog::StatsTreeDialog(QWidget *parent, capture_file *cf, const char *cfg_abbr) :
QDialog(parent),
ui(new Ui::StatsTreeDialog),
st_(NULL),
st_cfg_(NULL),
cap_file_(cf)
{
ui->setupUi(this);
st_cfg_ = stats_tree_get_cfg_by_abbr(cfg_abbr);
if (!st_cfg_) {
QMessageBox::critical(this, tr("Configuration not found"),
tr("Unable to find configuration for %1.").arg(cfg_abbr));
QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection);
}
ui->statsTreeWidget->addAction(ui->actionCopyAsCSV);
ui->statsTreeWidget->addAction(ui->actionCopyAsYAML);
ui->statsTreeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
QPushButton *copy_as_bt;
copy_as_bt = ui->buttonBox->addButton(tr("Copy as CSV"), QDialogButtonBox::ActionRole);
connect(copy_as_bt, SIGNAL(clicked()), this, SLOT(on_actionCopyAsCSV_triggered()));
copy_as_bt = ui->buttonBox->addButton(tr("Copy as YAML"), QDialogButtonBox::ActionRole);
connect(copy_as_bt, SIGNAL(clicked()), this, SLOT(on_actionCopyAsYAML_triggered()));
fillTree();
}
StatsTreeDialog::~StatsTreeDialog()
{
if (st_) {
stats_tree_free(st_);
}
delete ui;
}
void StatsTreeDialog::setCaptureFile(capture_file *cf)
{
if (!cf) { // We only want to know when the file closes.
cap_file_ = NULL;
ui->displayFilterLineEdit->setEnabled(false);
ui->applyFilterButton->setEnabled(false);
}
}
void StatsTreeDialog::fillTree()
{
GString *error_string;
if (!st_cfg_) return;
setWindowTitle(st_cfg_->name + tr(" Stats Tree"));
if (!cap_file_) return;
if (st_cfg_->in_use) {
QMessageBox::warning(this, tr("%1 already open").arg(st_cfg_->name),
tr("Each type of tree can only be generated one at at time."));
reject();
}
st_cfg_->in_use = TRUE;
st_cfg_->pr = &cfg_pr_;
cfg_pr_.st_dlg = this;
st_ = stats_tree_new(st_cfg_, NULL, ui->displayFilterLineEdit->text().toUtf8().constData());
error_string = register_tap_listener(st_cfg_->tapname,
st_,
st_->filter,
st_cfg_->flags,
resetTap,
stats_tree_packet,
drawTreeItems);
if (error_string) {
QMessageBox::critical(this, tr("%1 failed to attach to tap").arg(st_cfg_->name),
error_string->str);
g_string_free(error_string, TRUE);
reject();
}
cf_retap_packets(cap_file_);
drawTreeItems(st_);
remove_tap_listener(st_);
stats_tree_free(st_);
st_ = NULL;
st_cfg_->in_use = FALSE;
st_cfg_->pr = NULL;
}
void StatsTreeDialog::resetTap(void *st_ptr)
{
stats_tree *st = (stats_tree *) st_ptr;
if (!st || !st->cfg || !st->cfg->pr || !st->cfg->pr->st_dlg) return;
st->cfg->pr->st_dlg->ui->statsTreeWidget->clear();
st->cfg->init(st);
}
// Adds a node to the QTreeWidget
// Note: We're passing QTreeWidgetItem pointers as st_node_pres pointers
void StatsTreeDialog::setupNode(stat_node* node)
{
if (!node || !node->st || !node->st->cfg || !node->st->cfg->pr
|| !node->st->cfg->pr->st_dlg) return;
StatsTreeDialog *st_dlg = node->st->cfg->pr->st_dlg;
QTreeWidgetItem *ti = new QTreeWidgetItem(), *parent = NULL;
ti->setText(item_col_, node->name);
ti->setData(item_col_, Qt::UserRole, qVariantFromValue(node));
node->pr = (st_node_pres *) ti;
if (node->parent && node->parent->pr) {
parent = (QTreeWidgetItem *) node->parent->pr;
parent->setExpanded(true);
}
if (parent) {
parent->addChild(ti);
} else {
st_dlg->ui->statsTreeWidget->addTopLevelItem(ti);
}
st_dlg->ui->statsTreeWidget->resizeColumnToContents(item_col_);
}
void StatsTreeDialog::drawTreeItems(void *st_ptr)
{
stats_tree *st = (stats_tree *) st_ptr;
if (!st || !st->cfg || !st->cfg->pr || !st->cfg->pr->st_dlg) return;
StatsTreeDialog *st_dlg = st->cfg->pr->st_dlg;
QTreeWidgetItemIterator iter(st_dlg->ui->statsTreeWidget);
while (*iter) {
gchar value[NUM_BUF_SIZE];
gchar rate[NUM_BUF_SIZE];
gchar percent[NUM_BUF_SIZE];
stat_node *node = (*iter)->data(item_col_, Qt::UserRole).value<stat_node *>();
if (node) {
stats_tree_get_strs_from_node(node, value, rate,
percent);
(*iter)->setText(count_col_, value);
(*iter)->setText(rate_col_, rate);
(*iter)->setText(percent_col_, percent);
}
++iter;
}
st_dlg->ui->statsTreeWidget->resizeColumnToContents(count_col_);
st_dlg->ui->statsTreeWidget->resizeColumnToContents(rate_col_);
st_dlg->ui->statsTreeWidget->resizeColumnToContents(percent_col_);
}
void StatsTreeDialog::on_applyFilterButton_clicked()
{
fillTree();
}
void StatsTreeDialog::on_actionCopyAsCSV_triggered()
{
QTreeWidgetItemIterator iter(ui->statsTreeWidget);
QString clip = QString("%1,%2,%3,%4\n")
.arg(ui->statsTreeWidget->headerItem()->text(item_col_))
.arg(ui->statsTreeWidget->headerItem()->text(count_col_))
.arg(ui->statsTreeWidget->headerItem()->text(rate_col_))
.arg(ui->statsTreeWidget->headerItem()->text(percent_col_));
while (*iter) {
clip += QString("\"%1\",\"%2\",\"%3\",\"%4\"\n")
.arg((*iter)->text(item_col_))
.arg((*iter)->text(count_col_))
.arg((*iter)->text(rate_col_))
.arg((*iter)->text(percent_col_));
++iter;
}
wsApp->clipboard()->setText(clip);
}
void StatsTreeDialog::on_actionCopyAsYAML_triggered()
{
QTreeWidgetItemIterator iter(ui->statsTreeWidget);
QString clip;
while (*iter) {
QString indent;
if ((*iter)->parent()) {
QTreeWidgetItem *parent = (*iter)->parent();
while (parent) {
indent += " ";
parent = parent->parent();
}
clip += indent + "- description: \"" + (*iter)->text(item_col_) + "\"\n";
indent += " ";
clip += indent + "count: " + (*iter)->text(count_col_) + "\n";
clip += indent + "rate_ms: " + (*iter)->text(rate_col_) + "\n";
clip += indent + "percent: " + (*iter)->text(percent_col_) + "\n";
} else {
// Top level
clip += "description: \"" + (*iter)->text(item_col_) + "\"\n";
clip += "count: " + (*iter)->text(count_col_) + "\n";
clip += "rate_ms: " + (*iter)->text(rate_col_) + "\n";
}
if ((*iter)->childCount() > 0) {
clip += indent + "items:\n";
}
++iter;
}
wsApp->clipboard()->setText(clip);
}
extern "C" {
void
register_tap_listener_stats_tree_stat(void)
{
stats_tree_presentation(NULL,
StatsTreeDialog::setupNode,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
}
}
/*
* Editor modelines
*
* Local Variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* ex: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/