1 /* proto_tree_model.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 <ui/qt/models/proto_tree_model.h>
12 #include <epan/prefs.h>
13 #include <wsutil/wslog.h>
15 #include <ui/qt/utils/color_utils.h>
17 #include <QApplication>
22 // - Add ProtoTreeDelegate
23 // - Add ProtoTreeModel to CaptureFile
25 ProtoTreeModel::ProtoTreeModel(QObject
* parent
) :
26 QAbstractItemModel(parent
)
28 root_node_
= new ProtoNode(NULL
);
31 ProtoTreeModel::~ProtoTreeModel()
36 Qt::ItemFlags
ProtoTreeModel::flags(const QModelIndex
&index
) const
38 Qt::ItemFlags item_flags
= QAbstractItemModel::flags(index
);
39 if (rowCount(index
) < 1) {
40 item_flags
|= Qt::ItemNeverHasChildren
;
46 QModelIndex
ProtoTreeModel::index(int row
, int, const QModelIndex
&parent
) const
48 ProtoNode
*parent_node
= root_node_
;
50 if (parent
.isValid()) {
51 // index is not a top level item.
52 parent_node
= protoNodeFromIndex(parent
);
55 if (! parent_node
->isValid())
58 ProtoNode
*child
= parent_node
->child(row
);
63 return createIndex(row
, 0, static_cast<void *>(child
));
66 QModelIndex
ProtoTreeModel::parent(const QModelIndex
&index
) const
71 ProtoNode
*parent_node
= protoNodeFromIndex(index
)->parentNode();
72 return indexFromProtoNode(parent_node
);
75 int ProtoTreeModel::rowCount(const QModelIndex
&parent
) const
77 if (parent
.isValid()) {
78 return protoNodeFromIndex(parent
)->childrenCount();
80 return root_node_
->childrenCount();
83 // The QItemDelegate documentation says
84 // "When displaying items from a custom model in a standard view, it is
85 // often sufficient to simply ensure that the model returns appropriate
86 // data for each of the roles that determine the appearance of items in
88 // We might want to move this to a delegate regardless.
89 QVariant
ProtoTreeModel::data(const QModelIndex
&index
, int role
) const
94 ProtoNode
*index_node
= protoNodeFromIndex(index
);
95 FieldInformation
finfo(index_node
);
96 if (!finfo
.isValid()) {
101 case Qt::DisplayRole
:
102 return index_node
->labelText();
103 case Qt::BackgroundRole
:
105 switch(finfo
.flag(PI_SEVERITY_MASK
)) {
109 return ColorUtils::expert_color_comment
;
111 return ColorUtils::expert_color_chat
;
113 return ColorUtils::expert_color_note
;
115 return ColorUtils::expert_color_warn
;
117 return ColorUtils::expert_color_error
;
119 ws_warning("Unhandled severity flag: %u", finfo
.flag(PI_SEVERITY_MASK
));
121 if (finfo
.headerInfo().type
== FT_PROTOCOL
) {
122 return QApplication::palette().window();
124 return QApplication::palette().base();
126 case Qt::ForegroundRole
:
128 if (finfo
.flag(PI_SEVERITY_MASK
)) {
129 return ColorUtils::expert_color_foreground
;
131 if (finfo
.isLink()) {
132 return ColorUtils::themeLinkBrush();
134 if (finfo
.headerInfo().type
== FT_PROTOCOL
) {
135 return QApplication::palette().windowText();
137 return QApplication::palette().text();
140 if (finfo
.isLink()) {
142 font
.setUnderline(true);
152 void ProtoTreeModel::setRootNode(proto_node
*root_node
)
156 root_node_
= new ProtoNode(root_node
);
158 if (!root_node
) return;
160 int row_count
= root_node_
->childrenCount();
161 if (row_count
< 1) return;
162 beginInsertRows(QModelIndex(), 0, row_count
- 1);
166 ProtoNode
* ProtoTreeModel::protoNodeFromIndex(const QModelIndex
&index
) const
168 return static_cast<ProtoNode
*>(index
.internalPointer());
171 QModelIndex
ProtoTreeModel::indexFromProtoNode(ProtoNode
*index_node
) const
174 return QModelIndex();
177 int row
= index_node
->row();
179 if (!index_node
->isValid() || row
< 0) {
180 return QModelIndex();
183 return createIndex(row
, 0, static_cast<void *>(index_node
));
191 // NOLINTNEXTLINE(misc-no-recursion)
192 bool ProtoTreeModel::foreachFindHfid(ProtoNode
*node
, void *find_hfid_ptr
)
194 struct find_hfid_
*find_hfid
= (struct find_hfid_
*) find_hfid_ptr
;
195 if (PNODE_FINFO(node
->protoNode()) && PNODE_FINFO(node
->protoNode())->hfinfo
->id
== find_hfid
->hfid
) {
196 find_hfid
->node
= node
;
199 for (int i
= 0; i
< node
->childrenCount(); i
++) {
200 // We recurse here, but we're limited by tree depth checks in epan
201 if (foreachFindHfid(node
->child(i
), find_hfid
)) {
208 QModelIndex
ProtoTreeModel::findFirstHfid(int hf_id
)
210 if (!root_node_
|| hf_id
< 0) return QModelIndex();
212 struct find_hfid_ find_hfid
;
213 find_hfid
.hfid
= hf_id
;
215 if (foreachFindHfid(root_node_
, &find_hfid
) && find_hfid
.node
->isValid()) {
216 return indexFromProtoNode(find_hfid
.node
);
218 return QModelIndex();
221 struct find_field_info_
{
226 // NOLINTNEXTLINE(misc-no-recursion)
227 bool ProtoTreeModel::foreachFindField(ProtoNode
*node
, void *find_finfo_ptr
)
229 struct find_field_info_
*find_finfo
= (struct find_field_info_
*) find_finfo_ptr
;
230 if (PNODE_FINFO(node
->protoNode()) == find_finfo
->fi
) {
231 find_finfo
->node
= node
;
234 for (int i
= 0; i
< node
->childrenCount(); i
++) {
235 // We recurse here, but we're limited by tree depth checks in epan
236 if (foreachFindField(node
->child(i
), find_finfo
)) {
243 QModelIndex
ProtoTreeModel::findFieldInformation(FieldInformation
*finfo
)
245 if (!root_node_
|| !finfo
) return QModelIndex();
246 field_info
* fi
= finfo
->fieldInfo();
247 if (!fi
) return QModelIndex();
249 struct find_field_info_ find_finfo
;
252 if (foreachFindField(root_node_
, &find_finfo
) && find_finfo
.node
->isValid()) {
253 return indexFromProtoNode(find_finfo
.node
);
255 return QModelIndex();