wireshark/ui/qt/interface_tree.cpp
Gerald Combs 186babc6ba When we close a main window, delete the welcome screen, which in turn
deletes the interface list, which in turn kills off the dumpcap process
it may be running. This should hopefully keep us from leaving dumpcap
processes running in the background on Windows. (Am I the only one
running QtShark on that platform?)

svn path=/trunk/; revision=51485
2013-08-23 02:34:51 +00:00

266 lines
8.2 KiB
C++

/* interface_tree.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 "interface_tree.h"
#include "ui/capture_globals.h"
#include "ui/iface_lists.h"
#include "ui/utf8_entities.h"
#include "ui/ui_util.h"
#include "sparkline_delegate.h"
#include "wireshark_application.h"
#include <QLabel>
#include <QHeaderView>
#include <QTimer>
const int stat_update_interval_ = 1000; // ms
InterfaceTree::InterfaceTree(QWidget *parent) :
QTreeWidget(parent),
stat_cache_(NULL),
stat_timer_(NULL)
{
QTreeWidgetItem *ti;
header()->setVisible(false);
setRootIsDecorated(false);
setUniformRowHeights(true);
setColumnCount(2);
setSelectionMode(QAbstractItemView::ExtendedSelection);
setAccessibleName(tr("Welcome screen list"));
setItemDelegateForColumn(1, new SparkLineDelegate());
setDisabled(true);
ti = new QTreeWidgetItem();
ti->setText(0, tr("Waiting for startup" UTF8_HORIZONTAL_ELLIPSIS));
addTopLevelItem(ti);
resizeColumnToContents(0);
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(getInterfaceList()));
connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(updateSelectedInterfaces()));
}
InterfaceTree::~InterfaceTree() {
QTreeWidgetItemIterator iter(this);
if (stat_cache_) {
capture_stat_stop(stat_cache_);
stat_cache_ = NULL;
}
while (*iter) {
QList<int> *points;
points = (*iter)->data(1, Qt::UserRole).value<QList<int> *>();
delete(points);
++iter;
}
}
void InterfaceTree::hideEvent(QHideEvent *evt) {
Q_UNUSED(evt);
if (stat_timer_) stat_timer_->stop();
if (stat_cache_) {
capture_stat_stop(stat_cache_);
stat_cache_ = NULL;
}
}
void InterfaceTree::showEvent(QShowEvent *evt) {
Q_UNUSED(evt);
if (stat_timer_) stat_timer_->start(stat_update_interval_);
}
void InterfaceTree::resizeEvent(QResizeEvent *evt)
{
Q_UNUSED(evt);
int max_if_width = width() * 2 / 3; // Arbitrary
setUpdatesEnabled(false);
resizeColumnToContents(0);
if (columnWidth(0) > max_if_width) {
setColumnWidth(0, max_if_width);
}
setUpdatesEnabled(true);
}
void InterfaceTree::getInterfaceList()
{
GList *if_list;
int err;
gchar *err_str = NULL;
clear();
if_list = capture_interface_list(&err, &err_str,main_window_update);
if_list = g_list_sort(if_list, if_list_comparator_alph);
if (if_list == NULL) {
QTreeWidgetItem *ti = new QTreeWidgetItem();
ti->setText(0, QString(tr("%1")).arg(QString().fromUtf8(err_str)));
g_free(err_str);
addTopLevelItem(ti);
resizeColumnToContents(0);
return;
} else if (err_str) {
g_free(err_str);
}
// XXX Do we need to check for this? capture_interface_list returns an error if the length is 0.
if (g_list_length(if_list) > 0) {
interface_t device;
setDisabled(false);
for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
QList<int> *points;
device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
/* Continue if capture device is hidden */
if (device.hidden) {
continue;
}
QTreeWidgetItem *ti = new QTreeWidgetItem();
ti->setText(0, QString().fromUtf8(device.display_name));
ti->setData(0, Qt::UserRole, QString(device.name));
points = new QList<int>();
ti->setData(1, Qt::UserRole, qVariantFromValue(points));
addTopLevelItem(ti);
// XXX Add other device information
resizeColumnToContents(1);
if (strstr(prefs.capture_device, device.name) != NULL) {
device.selected = TRUE;
global_capture_opts.num_selected++;
global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
g_array_insert_val(global_capture_opts.all_ifaces, i, device);
}
if (device.selected) {
ti->setSelected(true);
}
}
}
free_interface_list(if_list);
resizeEvent(NULL);
if (!stat_timer_) {
updateStatistics();
stat_timer_ = new QTimer(this);
connect(stat_timer_, SIGNAL(timeout()), this, SLOT(updateStatistics()));
stat_timer_->start(stat_update_interval_);
}
}
void InterfaceTree::updateStatistics(void) {
interface_t device;
guint diff, if_idx;
struct pcap_stat stats;
if (!stat_cache_) {
// Start gathering statistics using dumpcap
// We crash (on OS X at least) if we try to do this from ::showEvent.
stat_cache_ = capture_stat_start(&global_capture_opts);
}
if (!stat_cache_) return;
QTreeWidgetItemIterator iter(this);
while (*iter) {
QList<int> *points;
for (if_idx = 0; if_idx < global_capture_opts.all_ifaces->len; if_idx++) {
device = g_array_index(global_capture_opts.all_ifaces, interface_t, if_idx);
QString device_name = (*iter)->data(0, Qt::UserRole).value<QString>();
if (device_name.compare(device.name) || device.hidden || device.type == IF_PIPE)
continue;
diff = 0;
if (capture_stats(stat_cache_, device.name, &stats)) {
if ((int)(stats.ps_recv - device.last_packets) >= 0) {
diff = stats.ps_recv - device.last_packets;
}
device.last_packets = stats.ps_recv;
}
points = (*iter)->data(1, Qt::UserRole).value<QList<int> *>();
points->append(diff);
update(indexFromItem((*iter), 1));
global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, if_idx);
g_array_insert_val(global_capture_opts.all_ifaces, if_idx, device);
}
iter++;
}
}
void InterfaceTree::updateSelectedInterfaces()
{
QTreeWidgetItemIterator iter(this);
global_capture_opts.num_selected = 0;
while (*iter) {
for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
QString device_name = (*iter)->data(0, Qt::UserRole).value<QString>();
interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
if (device_name.compare(QString().fromUtf8(device.name)) == 0) {
if (!device.locked) {
if ((*iter)->isSelected()) {
device.selected = TRUE;
global_capture_opts.num_selected++;
} else {
device.selected = FALSE;
}
device.locked = TRUE;
global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
g_array_insert_val(global_capture_opts.all_ifaces, i, device);
emit interfaceUpdated(device.name, device.selected);
device.locked = FALSE;
global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
g_array_insert_val(global_capture_opts.all_ifaces, i, device);
}
break;
}
}
iter++;
}
}
/*
* 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:
*/