1 /* wlan_statistics_dialog.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
10 #include "wlan_statistics_dialog.h"
12 #include <epan/packet.h>
13 #include <epan/strutil.h>
16 #include <epan/dissectors/packet-ieee80211.h>
18 #include <QElapsedTimer>
19 #include <QTreeWidget>
20 #include <QTreeWidgetItem>
22 #include <ui/qt/models/percent_bar_delegate.h>
23 #include <ui/qt/utils/qt_ui_utils.h>
24 #include "main_application.h"
27 // - Add the name resolution checkbox
28 // - Add the "Only show defined networks" checkbox
48 wlan_network_row_type_
= 1000,
49 wlan_station_row_type_
52 class WlanStationTreeWidgetItem
: public QTreeWidgetItem
55 WlanStationTreeWidgetItem(const address
*addr
) :
56 QTreeWidgetItem (wlan_station_row_type_
),
67 copy_address(&addr_
, addr
);
68 setText(col_bssid_
, address_to_qstring(&addr_
));
70 bool isMatch(const address
*addr
) {
71 return addresses_equal(&addr_
, addr
);
73 void update(const wlan_hdr_t
*wlan_hdr
) {
74 bool is_sender
= addresses_equal(&addr_
, &wlan_hdr
->src
);
76 if (wlan_hdr
->stats
.fc_retry
!= 0) {
80 // XXX Should we count received probes and auths? This is what the
81 // GTK+ UI does, but it seems odd.
82 switch (wlan_hdr
->type
) {
92 case MGT_AUTHENTICATION
:
95 case MGT_DEAUTHENTICATION
:
101 case DATA_CF_ACK_POLL
:
103 case DATA_QOS_DATA_CF_ACK
:
104 case DATA_QOS_DATA_CF_POLL
:
105 case DATA_QOS_DATA_CF_ACK_POLL
:
116 if (wlan_hdr
->type
!= MGT_BEACON
) packets_
++;
118 void draw(address
*bssid
, int num_packets
) {
119 if (packets_
&& num_packets
> 0) {
120 setData(col_pct_packets_
, Qt::UserRole
, QVariant::fromValue
<double>(packets_
* 100.0 / num_packets
));
121 setData(col_pct_retry_
, Qt::UserRole
, QVariant::fromValue
<double>(retry_
* 100.0 / packets_
));
123 setData(col_pct_packets_
, Qt::UserRole
, QVariant::fromValue
<double>(0));
124 setData(col_pct_retry_
, Qt::UserRole
, QVariant::fromValue
<double>(0));
126 setText(col_beacons_
, QString::number(sent_
));
127 setText(col_data_packets_
, QString::number(received_
));
128 setText(col_retry_packets_
, QString::number(retry_
));
129 setText(col_probe_reqs_
, QString::number(probe_req_
));
130 setText(col_probe_resps_
, QString::number(probe_resp_
));
131 setText(col_auths_
, QString::number(auth_
));
132 setText(col_deauths_
, QString::number(deauth_
));
133 setText(col_others_
, QString::number(other_
));
135 if (!is_broadcast_bssid(bssid
) && addresses_data_equal(&addr_
, bssid
)) {
136 setText(col_protection_
, QObject::tr("Base station"));
139 bool operator< (const QTreeWidgetItem
&other
) const
141 if (other
.type() != wlan_station_row_type_
) return QTreeWidgetItem::operator< (other
);
142 const WlanStationTreeWidgetItem
*other_row
= static_cast<const WlanStationTreeWidgetItem
*>(&other
);
144 switch (treeWidget()->sortColumn()) {
146 return cmp_address(&addr_
, &other_row
->addr_
) < 0;
147 case col_pct_packets_
:
148 return packets_
< other_row
->packets_
;
150 return sent_
< other_row
->sent_
;
151 case col_data_packets_
:
152 return received_
< other_row
->received_
;
153 case col_probe_reqs_
:
154 return probe_req_
< other_row
->probe_req_
;
155 case col_probe_resps_
:
156 return probe_resp_
< other_row
->probe_resp_
;
158 return auth_
< other_row
->auth_
;
160 return deauth_
< other_row
->deauth_
;
162 return other_
< other_row
->other_
;
163 case col_retry_packets_
:
165 return retry_
< other_row
->retry_
;
170 return QTreeWidgetItem::operator< (other
);
172 QList
<QVariant
> rowData() {
173 return QList
<QVariant
>()
174 << address_to_qstring(&addr_
)
175 << data(col_pct_packets_
, Qt::UserRole
).toDouble()
176 << data(col_pct_retry_
, Qt::UserRole
).toDouble() << retry_
177 << sent_
<< received_
<< probe_req_
<< probe_resp_
178 << auth_
<< deauth_
<< other_
<< text(col_protection_
);
180 const QString
filterExpression() {
181 QString filter_expr
= QStringLiteral("wlan.addr==%1")
182 .arg(address_to_qstring(&addr_
));
200 class WlanNetworkTreeWidgetItem
: public QTreeWidgetItem
203 WlanNetworkTreeWidgetItem(QTreeWidget
*parent
, const wlan_hdr_t
*wlan_hdr
) :
204 QTreeWidgetItem (parent
, wlan_network_row_type_
),
215 updateBssid(wlan_hdr
);
216 channel_
= wlan_hdr
->stats
.channel
;
217 ssid_
= QByteArray::fromRawData((const char *)wlan_hdr
->stats
.ssid
, wlan_hdr
->stats
.ssid_len
);
220 if (wlan_hdr
->stats
.ssid_len
== 0) {
221 ssid_text
= QObject::tr("<Broadcast>");
222 } else if (wlan_hdr
->stats
.ssid_len
== 1 && wlan_hdr
->stats
.ssid
[0] == 0) {
223 ssid_text
= QObject::tr("<Hidden>");
225 char *str
= format_text(NULL
, (const char *)wlan_hdr
->stats
.ssid
, wlan_hdr
->stats
.ssid_len
);
227 wmem_free(NULL
, str
);
230 setText(col_ssid_
, ssid_text
);
233 bool isMatch(const wlan_hdr_t
*wlan_hdr
) {
234 bool is_bssid_match
= false;
235 bool is_ssid_match
= false;
236 bool update_bssid
= false;
237 bool update_ssid
= false;
238 // We want (but might not have) a unicast BSSID and a named SSID. Try
239 // to match the current packet and update our information if possible.
241 if (addresses_equal(&bssid_
, &wlan_hdr
->bssid
)) {
242 is_bssid_match
= true;
245 if ((wlan_hdr
->stats
.ssid_len
> 0) && (wlan_hdr
->stats
.ssid
[0] != 0)) {
246 QByteArray hdr_ssid
= QByteArray::fromRawData((const char *)wlan_hdr
->stats
.ssid
, wlan_hdr
->stats
.ssid_len
);
247 if (ssid_
== hdr_ssid
) {
248 is_ssid_match
= true;
252 if (is_bssid_match
&& is_ssid_match
) return true;
255 if (wlan_hdr
->type
== MGT_PROBE_REQ
) {
256 // Probes with visible SSIDs. Unicast or broadcast.
258 if (is_broadcast_
&& !is_broadcast_bssid(&wlan_hdr
->bssid
)) {
261 // Probes with hidden SSIDs. Unicast.
262 } else if ((wlan_hdr
->stats
.ssid_len
== 1) && (wlan_hdr
->stats
.ssid
[0] == 0)) {
263 if (!is_broadcast_
&& addresses_equal(&bssid_
, &wlan_hdr
->bssid
)) {
264 is_bssid_match
= true;
267 // Probes with no SSID. Broadcast.
268 } else if (ssid_
.isEmpty() && wlan_hdr
->stats
.ssid_len
< 1) {
269 if (is_broadcast_
&& is_broadcast_bssid(&wlan_hdr
->bssid
)) {
273 // Non-probe requests (responses, beacons, etc)
276 if (is_broadcast_
&& !is_broadcast_bssid(&wlan_hdr
->bssid
)) {
279 } else if (wlan_hdr
->stats
.ssid_len
< 1) {
281 is_ssid_match
= true;
283 if (is_bssid_match
) {
284 if ((ssid_
.isEmpty() || ssid_
[0] == '\0') && (wlan_hdr
->stats
.ssid_len
> 0) && (wlan_hdr
->stats
.ssid
[0] != 0)) {
291 updateBssid(wlan_hdr
);
292 is_bssid_match
= true;
297 ssid_
= QByteArray::fromRawData((const char *)wlan_hdr
->stats
.ssid
, wlan_hdr
->stats
.ssid_len
);
298 str
= format_text(NULL
, (const char *)wlan_hdr
->stats
.ssid
, wlan_hdr
->stats
.ssid_len
);
299 setText(col_ssid_
, str
);
300 wmem_free(NULL
, str
);
301 is_ssid_match
= true;
304 return is_bssid_match
&& is_ssid_match
;
307 void update(const wlan_hdr_t
*wlan_hdr
) {
308 if (channel_
== 0 && wlan_hdr
->stats
.channel
!= 0) {
309 channel_
= wlan_hdr
->stats
.channel
;
311 if (text(col_protection_
).isEmpty() && wlan_hdr
->stats
.protection
[0] != 0) {
312 setText(col_protection_
, wlan_hdr
->stats
.protection
);
314 if (wlan_hdr
->stats
.fc_retry
!= 0) {
318 switch (wlan_hdr
->type
) {
328 case MGT_AUTHENTICATION
:
331 case MGT_DEAUTHENTICATION
:
337 case DATA_CF_ACK_POLL
:
339 case DATA_QOS_DATA_CF_ACK
:
340 case DATA_QOS_DATA_CF_POLL
:
341 case DATA_QOS_DATA_CF_ACK_POLL
:
350 WlanStationTreeWidgetItem
* sender_ws_ti
= NULL
;
351 WlanStationTreeWidgetItem
* receiver_ws_ti
= NULL
;
352 foreach (QTreeWidgetItem
*cur_ti
, stations_
) {
353 WlanStationTreeWidgetItem
*cur_ws_ti
= dynamic_cast<WlanStationTreeWidgetItem
*>(cur_ti
);
354 if (cur_ws_ti
&& (cur_ws_ti
->isMatch(&wlan_hdr
->src
))) sender_ws_ti
= cur_ws_ti
;
355 if (cur_ws_ti
&& (cur_ws_ti
->isMatch(&wlan_hdr
->dst
))) receiver_ws_ti
= cur_ws_ti
;
356 if (sender_ws_ti
&& receiver_ws_ti
) break;
359 sender_ws_ti
= new WlanStationTreeWidgetItem(&wlan_hdr
->src
);
360 stations_
<< sender_ws_ti
;
362 if (!receiver_ws_ti
) {
363 receiver_ws_ti
= new WlanStationTreeWidgetItem(&wlan_hdr
->dst
);
364 stations_
<< receiver_ws_ti
;
366 sender_ws_ti
->update(wlan_hdr
);
367 receiver_ws_ti
->update(wlan_hdr
);
370 void draw(int num_packets
) {
371 if (channel_
> 0) setText(col_channel_
, QString::number(channel_
));
372 setData(col_pct_packets_
, Qt::UserRole
, QVariant::fromValue
<double>(packets_
* 100.0 / num_packets
));
373 setData(col_pct_retry_
, Qt::UserRole
, QVariant::fromValue
<double>(retry_packet_
* 100.0 / packets_
));
374 setText(col_retry_packets_
, QString::number(retry_packet_
));
375 setText(col_beacons_
, QString::number(beacon_
));
376 setText(col_data_packets_
, QString::number(data_packet_
));
377 setText(col_probe_reqs_
, QString::number(probe_req_
));
378 setText(col_probe_resps_
, QString::number(probe_resp_
));
379 setText(col_auths_
, QString::number(auth_
));
380 setText(col_deauths_
, QString::number(deauth_
));
381 setText(col_others_
, QString::number(other_
));
385 foreach (QTreeWidgetItem
*cur_ti
, stations_
) {
386 WlanStationTreeWidgetItem
*cur_ws_ti
= dynamic_cast<WlanStationTreeWidgetItem
*>(cur_ti
);
387 cur_ws_ti
->draw(&bssid_
, packets_
- beacon_
);
388 for (int col
= 0; col
< treeWidget()->columnCount(); col
++) {
389 // int QTreeWidgetItem::textAlignment(int column) const
390 // Returns the text alignment for the label in the given column.
391 // Note: This function returns an int for historical reasons. It will be corrected to return Qt::Alignment in Qt 7.
392 cur_ws_ti
->setTextAlignment(col
, static_cast<Qt::Alignment
>(treeWidget()->headerItem()->textAlignment(col
)));
396 addChildren(stations_
);
400 bool operator< (const QTreeWidgetItem
&other
) const
402 if (other
.type() != wlan_network_row_type_
) return QTreeWidgetItem::operator< (other
);
403 const WlanNetworkTreeWidgetItem
*other_row
= static_cast<const WlanNetworkTreeWidgetItem
*>(&other
);
405 switch (treeWidget()->sortColumn()) {
407 return cmp_address(&bssid_
, &other_row
->bssid_
) < 0;
409 return channel_
< other_row
->channel_
;
411 return ssid_
< other_row
->ssid_
;
412 case col_pct_packets_
:
413 return packets_
< other_row
->packets_
;
415 return beacon_
< other_row
->beacon_
;
416 case col_data_packets_
:
417 return data_packet_
< other_row
->data_packet_
;
418 case col_probe_reqs_
:
419 return probe_req_
< other_row
->probe_req_
;
420 case col_probe_resps_
:
421 return probe_resp_
< other_row
->probe_resp_
;
423 return auth_
< other_row
->auth_
;
425 return deauth_
< other_row
->deauth_
;
427 return other_
< other_row
->other_
;
428 case col_protection_
:
433 return QTreeWidgetItem::operator< (other
);
435 QList
<QVariant
> rowData() {
436 return QList
<QVariant
>()
437 << address_to_qstring(&bssid_
) << channel_
<< text(col_ssid_
)
438 << data(col_pct_packets_
, Qt::UserRole
).toDouble()
439 << data(col_pct_retry_
, Qt::UserRole
).toDouble()
440 << retry_packet_
<< beacon_
<< data_packet_
<< probe_req_
441 << probe_resp_
<< auth_
<< deauth_
<< other_
442 << text(col_protection_
);
445 const QString
filterExpression() {
446 QString filter_expr
= QStringLiteral("(wlan.bssid==%1")
447 .arg(address_to_qstring(&bssid_
));
448 if (!ssid_
.isEmpty() && ssid_
[0] != '\0') {
449 filter_expr
+= QStringLiteral(" || wlan.ssid==\"%1\"")
450 .arg(ssid_
.constData());
471 // Adding items one at a time is slow. Gather up the stations in a list
472 // and add them all at once later.
473 QList
<QTreeWidgetItem
*>stations_
;
475 void updateBssid(const wlan_hdr_t
*wlan_hdr
) {
476 copy_address(&bssid_
, &wlan_hdr
->bssid
);
477 is_broadcast_
= is_broadcast_bssid(&bssid_
);
478 setText(col_bssid_
, address_to_qstring(&bssid_
));
482 static const QString network_col_0_title_
= QObject::tr("BSSID");
483 static const QString network_col_6_title_
= QObject::tr("Beacons");
484 static const QString network_col_7_title_
= QObject::tr("Data Pkts");
485 static const QString network_col_13_title_
= QObject::tr("Protection");
487 static const QString node_col_0_title_
= QObject::tr("Address");
488 static const QString node_col_4_title_
= QObject::tr("Pkts Sent");
489 static const QString node_col_5_title_
= QObject::tr("Pkts Received");
490 static const QString node_col_11_title_
= QObject::tr("Comment");
492 WlanStatisticsDialog::WlanStatisticsDialog(QWidget
&parent
, CaptureFile
&cf
, const char *filter
) :
493 TapParameterDialog(parent
, cf
, HELP_STATS_WLAN_TRAFFIC_DIALOG
),
496 add_station_timer_(0)
498 setWindowSubtitle(tr("Wireless LAN Statistics"));
499 loadGeometry(parent
.width() * 4 / 5, parent
.height() * 3 / 4, "WlanStatisticsDialog");
501 QStringList header_labels
= QStringList()
502 << "" << tr("Channel") << tr("SSID") << tr("Percent Packets") << tr("Percent Retry")
503 << tr("Retry") << "" << "" << tr("Probe Reqs") << tr("Probe Resp") << tr("Auths")
504 << tr("Deauths") << tr("Other");
505 statsTreeWidget()->setHeaderLabels(header_labels
);
506 updateHeaderLabels();
507 packets_delegate_
= new PercentBarDelegate();
508 statsTreeWidget()->setItemDelegateForColumn(col_pct_packets_
, packets_delegate_
);
509 retry_delegate_
= new PercentBarDelegate();
510 statsTreeWidget()->setItemDelegateForColumn(col_pct_retry_
, retry_delegate_
);
511 statsTreeWidget()->sortByColumn(col_bssid_
, Qt::AscendingOrder
);
513 // resizeColumnToContents doesn't work well here, so set sizes manually.
514 int one_em
= fontMetrics().height();
515 for (int col
= 0; col
< statsTreeWidget()->columnCount() - 1; col
++) {
518 statsTreeWidget()->setColumnWidth(col
, one_em
* 11);
521 statsTreeWidget()->setColumnWidth(col
, one_em
* 8);
523 case col_pct_packets_
:
525 case col_protection_
:
526 statsTreeWidget()->setColumnWidth(col
, one_em
* 6);
529 // The rest are numeric
530 statsTreeWidget()->setColumnWidth(col
, one_em
* 4);
531 statsTreeWidget()->headerItem()->setTextAlignment(col
, Qt::AlignRight
);
539 setDisplayFilter(filter
);
542 add_station_timer_
= new QElapsedTimer();
544 connect(statsTreeWidget(), SIGNAL(itemSelectionChanged()),
545 this, SLOT(updateHeaderLabels()));
547 // Set handler for when display filter string is changed.
548 connect(this, SIGNAL(updateFilter(QString
)),
549 this, SLOT(filterUpdated(QString
)));
552 WlanStatisticsDialog::~WlanStatisticsDialog()
554 delete packets_delegate_
;
555 delete retry_delegate_
;
556 delete add_station_timer_
;
559 void WlanStatisticsDialog::tapReset(void *ws_dlg_ptr
)
561 WlanStatisticsDialog
*ws_dlg
= static_cast<WlanStatisticsDialog
*>(ws_dlg_ptr
);
564 ws_dlg
->statsTreeWidget()->clear();
565 ws_dlg
->packet_count_
= 0;
568 tap_packet_status
WlanStatisticsDialog::tapPacket(void *ws_dlg_ptr
, _packet_info
*, epan_dissect
*, const void *wlan_hdr_ptr
, tap_flags_t
)
570 WlanStatisticsDialog
*ws_dlg
= static_cast<WlanStatisticsDialog
*>(ws_dlg_ptr
);
571 const wlan_hdr_t
*wlan_hdr
= (const wlan_hdr_t
*)wlan_hdr_ptr
;
572 if (!ws_dlg
|| !wlan_hdr
) return TAP_PACKET_DONT_REDRAW
;
574 uint16_t frame_type
= wlan_hdr
->type
& 0xff0;
575 if (!((frame_type
== 0x0) || (frame_type
== 0x20) || (frame_type
== 0x30))
576 || ((frame_type
== 0x20) && DATA_FRAME_IS_NULL(wlan_hdr
->type
))) {
577 /* Not a management or non null data or extension frame; let's skip it */
578 return TAP_PACKET_DONT_REDRAW
;
581 ws_dlg
->packet_count_
++;
583 // XXX This is very slow for large numbers of networks. We might be
584 // able to store networks in a cache keyed on BSSID+SSID instead.
585 WlanNetworkTreeWidgetItem
*wn_ti
= NULL
;
586 for (int i
= 0; i
< ws_dlg
->statsTreeWidget()->topLevelItemCount(); i
++) {
587 QTreeWidgetItem
*ti
= ws_dlg
->statsTreeWidget()->topLevelItem(i
);
588 if (ti
->type() != wlan_network_row_type_
) continue;
589 WlanNetworkTreeWidgetItem
*cur_wn_ti
= static_cast<WlanNetworkTreeWidgetItem
*>(ti
);
591 if (cur_wn_ti
->isMatch(wlan_hdr
)) {
598 wn_ti
= new WlanNetworkTreeWidgetItem(ws_dlg
->statsTreeWidget(), wlan_hdr
);
599 for (int col
= 0; col
< ws_dlg
->statsTreeWidget()->columnCount(); col
++) {
600 // int QTreeWidgetItem::textAlignment(int column) const
601 // Returns the text alignment for the label in the given column.
602 // Note: This function returns an int for historical reasons. It will be corrected to return Qt::Alignment in Qt 7.
603 wn_ti
->setTextAlignment(col
, static_cast<Qt::Alignment
>(ws_dlg
->statsTreeWidget()->headerItem()->textAlignment(col
)));
607 wn_ti
->update(wlan_hdr
);
608 return TAP_PACKET_REDRAW
;
611 void WlanStatisticsDialog::tapDraw(void *ws_dlg_ptr
)
613 WlanStatisticsDialog
*ws_dlg
= static_cast<WlanStatisticsDialog
*>(ws_dlg_ptr
);
616 for (int i
= 0; i
< ws_dlg
->statsTreeWidget()->topLevelItemCount(); i
++) {
617 QTreeWidgetItem
*ti
= ws_dlg
->statsTreeWidget()->topLevelItem(i
);
618 if (ti
->type() != wlan_network_row_type_
) continue;
620 WlanNetworkTreeWidgetItem
*wn_ti
= static_cast<WlanNetworkTreeWidgetItem
*>(ti
);
621 wn_ti
->draw(ws_dlg
->packet_count_
);
625 const QString
WlanStatisticsDialog::filterExpression()
628 if (statsTreeWidget()->selectedItems().count() > 0) {
629 QTreeWidgetItem
*ti
= statsTreeWidget()->selectedItems()[0];
631 if (ti
->type() == wlan_network_row_type_
) {
632 WlanNetworkTreeWidgetItem
*wn_ti
= static_cast<WlanNetworkTreeWidgetItem
*>(ti
);
633 filter_expr
= wn_ti
->filterExpression();
634 } else if (ti
->type() == wlan_station_row_type_
) {
635 WlanStationTreeWidgetItem
*ws_ti
= static_cast<WlanStationTreeWidgetItem
*>(ti
);
636 filter_expr
= ws_ti
->filterExpression();
642 void WlanStatisticsDialog::fillTree()
644 if (!registerTapListener("wlan",
646 displayFilter_
.toLatin1().data(),
655 statsTreeWidget()->setSortingEnabled(false);
656 cap_file_
.retapPackets();
658 removeTapListeners();
659 statsTreeWidget()->setSortingEnabled(true);
661 // Don't freeze if we have a large number of stations.
663 QTimer::singleShot(0, this, SLOT(addStationTreeItems()));
666 static const int add_station_interval_
= 5; // ms
667 void WlanStatisticsDialog::addStationTreeItems()
669 add_station_timer_
->start();
670 while (add_station_timer_
->elapsed() < add_station_interval_
&& cur_network_
< statsTreeWidget()->topLevelItemCount()) {
671 QTreeWidgetItem
*ti
= statsTreeWidget()->topLevelItem(cur_network_
);
672 if (ti
->type() != wlan_network_row_type_
) continue;
674 WlanNetworkTreeWidgetItem
*wn_ti
= static_cast<WlanNetworkTreeWidgetItem
*>(ti
);
675 wn_ti
->addStations();
679 if (cur_network_
< statsTreeWidget()->topLevelItemCount()) {
680 QTimer::singleShot(0, this, SLOT(addStationTreeItems()));
684 void WlanStatisticsDialog::updateHeaderLabels()
686 if (statsTreeWidget()->selectedItems().count() > 0 && statsTreeWidget()->selectedItems()[0]->type() == wlan_station_row_type_
) {
687 statsTreeWidget()->headerItem()->setText(col_bssid_
, node_col_0_title_
);
688 statsTreeWidget()->headerItem()->setText(col_beacons_
, node_col_4_title_
);
689 statsTreeWidget()->headerItem()->setText(col_data_packets_
, node_col_5_title_
);
690 statsTreeWidget()->headerItem()->setText(col_protection_
, node_col_11_title_
);
692 statsTreeWidget()->headerItem()->setText(col_bssid_
, network_col_0_title_
);
693 statsTreeWidget()->headerItem()->setText(col_beacons_
, network_col_6_title_
);
694 statsTreeWidget()->headerItem()->setText(col_data_packets_
, network_col_7_title_
);
695 statsTreeWidget()->headerItem()->setText(col_protection_
, network_col_13_title_
);
699 void WlanStatisticsDialog::captureFileClosing()
701 remove_tap_listener(this);
703 WiresharkDialog::captureFileClosing();
706 // Store filter from signal.
707 void WlanStatisticsDialog::filterUpdated(QString filter
)
709 displayFilter_
= filter
;
712 // This is how an item is represented for exporting.
713 QList
<QVariant
> WlanStatisticsDialog::treeItemData(QTreeWidgetItem
*it
) const
715 // Cast up to our type.
716 WlanNetworkTreeWidgetItem
*nit
= dynamic_cast<WlanNetworkTreeWidgetItem
*>(it
);
718 return nit
->rowData();
720 // TODO: not going to cast to WlanStationTreeWidgetItem* and do the same as
721 // some of the columns are different...
723 return QList
<QVariant
>();
726 // Stat command + args
729 wlan_statistics_init(const char *args
, void*) {
730 QStringList args_l
= QString(args
).split(',');
732 if (args_l
.length() > 2) {
733 filter
= QStringList(args_l
.mid(2)).join(",").toUtf8();
735 mainApp
->emitStatCommandSignal("WlanStatistics", filter
.constData(), NULL
);
738 static stat_tap_ui wlan_statistics_ui
= {
739 REGISTER_STAT_GROUP_GENERIC
,
742 wlan_statistics_init
,
749 void register_tap_listener_qt_wlan_statistics(void);
752 register_tap_listener_qt_wlan_statistics(void)
754 register_stat_tap_ui(&wlan_statistics_ui
, NULL
);