Fix comment end after SPDX identifier
[metze/wireshark/wip.git] / ui / qt / stats_tree_dialog.cpp
1 /* stats_tree_dialog.cpp
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9
10 #include "stats_tree_dialog.h"
11
12 #include "file.h"
13
14 #include "epan/stats_tree_priv.h"
15
16 #include <ui/qt/utils/qt_ui_utils.h>
17
18 #include <ui/qt/utils/variant_pointer.h>
19
20 #include <QHeaderView>
21 #include <QMessageBox>
22 #include <QTreeWidget>
23 #include <QTreeWidgetItemIterator>
24
25 const int item_col_ = 0;
26
27 const int sn_type_ = 1000;
28 class StatsTreeWidgetItem : public QTreeWidgetItem
29 {
30 public:
31     StatsTreeWidgetItem(int type = sn_type_) : QTreeWidgetItem (type)
32     {
33         for (int col = 1; col < columnCount(); col++) {
34             setTextAlignment(col, Qt::AlignRight);
35         }
36     }
37     bool operator< (const QTreeWidgetItem &other) const
38     {
39         stat_node *thisnode = VariantPointer<stat_node>::asPtr(data(item_col_, Qt::UserRole));
40         stat_node *othernode = VariantPointer<stat_node>::asPtr(other.data(item_col_, Qt::UserRole));
41         Qt::SortOrder order = treeWidget()->header()->sortIndicatorOrder();
42         int result;
43
44         result = stats_tree_sort_compare(thisnode, othernode, treeWidget()->sortColumn(),
45                                          order==Qt::DescendingOrder);
46         if (order==Qt::DescendingOrder) {
47             result = -result;
48         }
49         return result < 0;
50     }
51 };
52
53 StatsTreeDialog::StatsTreeDialog(QWidget &parent, CaptureFile &cf, const char *cfg_abbr) :
54     TapParameterDialog(parent, cf),
55     st_(NULL),
56     st_cfg_(NULL)
57 {
58     loadGeometry(800, height(), cfg_abbr);
59     st_cfg_ = stats_tree_get_cfg_by_abbr(cfg_abbr);
60     memset(&cfg_pr_, 0, sizeof(struct _tree_cfg_pres));
61
62     if (!st_cfg_) {
63         QMessageBox::critical(this, tr("Configuration not found"),
64                              tr("Unable to find configuration for %1.").arg(cfg_abbr));
65         QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection);
66     }
67 }
68
69 StatsTreeDialog::~StatsTreeDialog()
70 {
71     if (st_) {
72         stats_tree_free(st_);
73     }
74 }
75
76 // Adds a node to the QTreeWidget
77 // Note: We're passing QTreeWidgetItem pointers as st_node_pres pointers
78 void StatsTreeDialog::setupNode(stat_node* node)
79 {
80     if (!node || !node->st || !node->st->cfg || !node->st->cfg->pr
81             || !node->st->cfg->pr->st_dlg) return;
82     StatsTreeDialog *st_dlg = node->st->cfg->pr->st_dlg;
83
84     QTreeWidgetItem *ti = new StatsTreeWidgetItem(), *parent = NULL;
85
86     ti->setText(item_col_, node->name);
87     ti->setData(item_col_, Qt::UserRole, VariantPointer<stat_node>::asQVariant(node));
88     node->pr = (st_node_pres *) ti;
89     if (node->parent && node->parent->pr) {
90         parent = (QTreeWidgetItem *) node->parent->pr;
91         parent->setExpanded(true);
92     }
93     if (parent) {
94         parent->addChild(ti);
95     } else {
96         st_dlg->statsTreeWidget()->addTopLevelItem(ti);
97     }
98     st_dlg->statsTreeWidget()->resizeColumnToContents(item_col_);
99 }
100
101 void StatsTreeDialog::fillTree()
102 {
103     if (!st_cfg_ || file_closed_) return;
104
105     QString display_name = gchar_free_to_qstring(stats_tree_get_displayname(st_cfg_->name));
106
107     // The GTK+ UI appends "Stats Tree" to the window title. If we do the same
108     // here we should expand the name completely, e.g. to "Statistics Tree".
109     setWindowSubtitle(display_name);
110
111     st_cfg_->pr = &cfg_pr_;
112     cfg_pr_.st_dlg = this;
113
114     if (st_) {
115         stats_tree_free(st_);
116     }
117     QString display_filter = displayFilter();
118     st_ = stats_tree_new(st_cfg_, NULL, display_filter.toUtf8().constData());
119
120     // Add number of columns for this stats_tree
121     QStringList header_labels;
122     for (int count = 0; count<st_->num_columns; count++) {
123         header_labels.push_back(stats_tree_get_column_name(count));
124     }
125     statsTreeWidget()->setColumnCount(header_labels.count());
126     statsTreeWidget()->setHeaderLabels(header_labels);
127     statsTreeWidget()->setSortingEnabled(false);
128
129     if (!registerTapListener(st_cfg_->tapname,
130                              st_,
131                              st_->filter,
132                              st_cfg_->flags,
133                              resetTap,
134                              stats_tree_packet,
135                              drawTreeItems)) {
136         reject(); // XXX Stay open instead?
137         return;
138     }
139
140     cap_file_.retapPackets();
141     drawTreeItems(st_);
142
143     statsTreeWidget()->setSortingEnabled(true);
144     removeTapListeners();
145
146     st_cfg_->pr = NULL;
147 }
148
149 void StatsTreeDialog::resetTap(void *st_ptr)
150 {
151     stats_tree *st = (stats_tree *) st_ptr;
152     if (!st || !st->cfg || !st->cfg->pr || !st->cfg->pr->st_dlg) return;
153
154     st->cfg->pr->st_dlg->statsTreeWidget()->clear();
155     st->cfg->init(st);
156 }
157
158 void StatsTreeDialog::drawTreeItems(void *st_ptr)
159 {
160     stats_tree *st = (stats_tree *) st_ptr;
161     if (!st || !st->cfg || !st->cfg->pr || !st->cfg->pr->st_dlg) return;
162     TapParameterDialog *st_dlg = st->cfg->pr->st_dlg;
163     QTreeWidgetItemIterator iter(st_dlg->statsTreeWidget());
164     int node_count = 0;
165
166     while (*iter) {
167         stat_node *node = VariantPointer<stat_node>::asPtr((*iter)->data(item_col_, Qt::UserRole));
168         if (node) {
169             gchar **valstrs = stats_tree_get_values_from_node(node);
170             for (int count = 0; count<st->num_columns; count++) {
171                 (*iter)->setText(count,valstrs[count]);
172                 g_free(valstrs[count]);
173             }
174             (*iter)->setExpanded((node->parent==(&st->root)) &&
175                                  (!(node->st_flags&ST_FLG_DEF_NOEXPAND)));
176             g_free(valstrs);
177         }
178         node_count++;
179         ++iter;
180     }
181
182     st_dlg->drawTreeItems();
183 }
184
185 QByteArray StatsTreeDialog::getTreeAsString(st_format_type format)
186 {
187     GString *str_tree;
188
189     // produce output in selected format using current sort information
190     str_tree = stats_tree_format_as_str(st_, format, statsTreeWidget()->sortColumn(),
191                 statsTreeWidget()->header()->sortIndicatorOrder()==Qt::DescendingOrder);
192
193     return gstring_free_to_qbytearray(str_tree);
194 }
195
196 extern "C" {
197 void
198 register_tap_listener_qt_stats_tree_stat(void)
199 {
200     stats_tree_presentation(NULL,
201                 StatsTreeDialog::setupNode,
202                 NULL, NULL);
203 }
204 }
205
206 /*
207  * Editor modelines
208  *
209  * Local Variables:
210  * c-basic-offset: 4
211  * tab-width: 8
212  * indent-tabs-mode: nil
213  * End:
214  *
215  * ex: set shiftwidth=4 tabstop=8 expandtab:
216  * :indentSize=4:tabSize=8:noTabs=true:
217  */