1 /* supported_protocols_model.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 <QSortFilterProxyModel>
11 #include <QStringList>
12 #include <QPalette>
13 #include <QApplication>
14 #include <QBrush>
15
16 #include <ui/qt/models/supported_protocols_model.h>
17
SupportedProtocolsItem(protocol_t * proto,const char * name,const char * filter,ftenum_t ftype,const char * descr,SupportedProtocolsItem * parent)18 SupportedProtocolsItem::SupportedProtocolsItem(protocol_t* proto, const char *name, const char* filter, ftenum_t ftype, const char* descr, SupportedProtocolsItem* parent)
19 : ModelHelperTreeItem<SupportedProtocolsItem>(parent),
20 proto_(proto),
21 name_(name),
22 filter_(filter),
23 ftype_(ftype),
24 descr_(descr)
25 {
26 }
27
~SupportedProtocolsItem()28 SupportedProtocolsItem::~SupportedProtocolsItem()
29 {
30 }
31
32
SupportedProtocolsModel(QObject * parent)33 SupportedProtocolsModel::SupportedProtocolsModel(QObject *parent) :
34 QAbstractItemModel(parent),
35 root_(new SupportedProtocolsItem(NULL, NULL, NULL, FT_NONE, NULL, NULL)),
36 field_count_(0)
37 {
38 }
39
~SupportedProtocolsModel()40 SupportedProtocolsModel::~SupportedProtocolsModel()
41 {
42 delete root_;
43 }
44
rowCount(const QModelIndex & parent) const45 int SupportedProtocolsModel::rowCount(const QModelIndex &parent) const
46 {
47 SupportedProtocolsItem *parent_item;
48 if (parent.column() > 0)
49 return 0;
50
51 if (!parent.isValid())
52 parent_item = root_;
53 else
54 parent_item = static_cast<SupportedProtocolsItem*>(parent.internalPointer());
55
56 if (parent_item == NULL)
57 return 0;
58
59 return parent_item->childCount();
60 }
61
columnCount(const QModelIndex &) const62 int SupportedProtocolsModel::columnCount(const QModelIndex&) const
63 {
64 return colLast;
65 }
66
headerData(int section,Qt::Orientation orientation,int role) const67 QVariant SupportedProtocolsModel::headerData(int section, Qt::Orientation orientation, int role) const
68 {
69 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
70
71 switch ((enum SupportedProtocolsColumn)section) {
72 case colName:
73 return tr("Name");
74 case colFilter:
75 return tr("Filter");
76 case colType:
77 return tr("Type");
78 case colDescription:
79 return tr("Description");
80 default:
81 break;
82 }
83 }
84 return QVariant();
85 }
86
parent(const QModelIndex & index) const87 QModelIndex SupportedProtocolsModel::parent(const QModelIndex& index) const
88 {
89 if (!index.isValid())
90 return QModelIndex();
91
92 SupportedProtocolsItem* item = static_cast<SupportedProtocolsItem*>(index.internalPointer());
93 if (item != NULL) {
94 SupportedProtocolsItem* parent_item = item->parentItem();
95 if (parent_item != NULL) {
96 if (parent_item == root_)
97 return QModelIndex();
98
99 return createIndex(parent_item->row(), 0, parent_item);
100 }
101 }
102
103 return QModelIndex();
104 }
105
index(int row,int column,const QModelIndex & parent) const106 QModelIndex SupportedProtocolsModel::index(int row, int column, const QModelIndex& parent) const
107 {
108 if (!hasIndex(row, column, parent))
109 return QModelIndex();
110
111 SupportedProtocolsItem *parent_item, *child_item;
112
113 if (!parent.isValid())
114 parent_item = root_;
115 else
116 parent_item = static_cast<SupportedProtocolsItem*>(parent.internalPointer());
117
118 Q_ASSERT(parent_item);
119
120 child_item = parent_item->child(row);
121 if (child_item) {
122 return createIndex(row, column, child_item);
123 }
124
125 return QModelIndex();
126 }
127
data(const QModelIndex & index,int role) const128 QVariant SupportedProtocolsModel::data(const QModelIndex &index, int role) const
129 {
130 if (!index.isValid() || role != Qt::DisplayRole)
131 return QVariant();
132
133 SupportedProtocolsItem* item = static_cast<SupportedProtocolsItem*>(index.internalPointer());
134 if (item == NULL)
135 return QVariant();
136
137 switch ((enum SupportedProtocolsColumn)index.column()) {
138 case colName:
139 return item->name();
140 case colFilter:
141 return item->filter();
142 case colType:
143 if (index.parent().isValid())
144 return QString(ftype_pretty_name(item->type()));
145
146 return QVariant();
147 case colDescription:
148 return item->description();
149 default:
150 break;
151 }
152
153 return QVariant();
154 }
155
populate()156 void SupportedProtocolsModel::populate()
157 {
158 void *proto_cookie;
159 void *field_cookie;
160
161 emit beginResetModel();
162
163 SupportedProtocolsItem *protoItem, *fieldItem;
164 protocol_t *protocol;
165
166 for (int proto_id = proto_get_first_protocol(&proto_cookie); proto_id != -1;
167 proto_id = proto_get_next_protocol(&proto_cookie)) {
168
169 protocol = find_protocol_by_id(proto_id);
170 protoItem = new SupportedProtocolsItem(protocol, proto_get_protocol_short_name(protocol), proto_get_protocol_filter_name(proto_id), FT_PROTOCOL, proto_get_protocol_long_name(protocol), root_);
171 root_->prependChild(protoItem);
172
173 for (header_field_info *hfinfo = proto_get_first_protocol_field(proto_id, &field_cookie); hfinfo != NULL;
174 hfinfo = proto_get_next_protocol_field(proto_id, &field_cookie)) {
175 if (hfinfo->same_name_prev_id != -1)
176 continue;
177
178 fieldItem = new SupportedProtocolsItem(protocol, hfinfo->name, hfinfo->abbrev, hfinfo->type, hfinfo->blurb, protoItem);
179 protoItem->prependChild(fieldItem);
180 field_count_++;
181 }
182 }
183
184 emit endResetModel();
185 }
186
187
188
SupportedProtocolsProxyModel(QObject * parent)189 SupportedProtocolsProxyModel::SupportedProtocolsProxyModel(QObject * parent)
190 : QSortFilterProxyModel(parent),
191 filter_()
192 {
193 }
194
lessThan(const QModelIndex & left,const QModelIndex & right) const195 bool SupportedProtocolsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
196 {
197 //Use SupportedProtocolsItem directly for better performance
198 SupportedProtocolsItem* left_item = static_cast<SupportedProtocolsItem*>(left.internalPointer());
199 SupportedProtocolsItem* right_item = static_cast<SupportedProtocolsItem*>(right.internalPointer());
200
201 if ((left_item != NULL) && (right_item != NULL)) {
202 int compare_ret = left_item->name().compare(right_item->name());
203 if (compare_ret < 0)
204 return true;
205 }
206
207 return false;
208 }
209
filterAcceptItem(SupportedProtocolsItem & item) const210 bool SupportedProtocolsProxyModel::filterAcceptItem(SupportedProtocolsItem& item) const
211 {
212 QRegExp regex(filter_, Qt::CaseInsensitive);
213
214 if (item.name().contains(regex))
215 return true;
216
217 if (item.filter().contains(regex))
218 return true;
219
220 if (item.description().contains(regex))
221 return true;
222
223 return false;
224 }
225
filterAcceptsRow(int sourceRow,const QModelIndex & sourceParent) const226 bool SupportedProtocolsProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
227 {
228 QModelIndex nameIdx = sourceModel()->index(sourceRow, SupportedProtocolsModel::colName, sourceParent);
229 SupportedProtocolsItem* item = static_cast<SupportedProtocolsItem*>(nameIdx.internalPointer());
230 if (item == NULL)
231 return true;
232
233 if (!filter_.isEmpty()) {
234 if (filterAcceptItem(*item))
235 return true;
236
237 if (!nameIdx.parent().isValid())
238 {
239 SupportedProtocolsItem* child_item;
240 for (int row = 0; row < item->childCount(); row++)
241 {
242 child_item = item->child(row);
243 if ((child_item != NULL) && (filterAcceptItem(*child_item)))
244 return true;
245 }
246 }
247
248 return false;
249 }
250
251 return true;
252 }
253
setFilter(const QString & filter)254 void SupportedProtocolsProxyModel::setFilter(const QString& filter)
255 {
256 filter_ = filter;
257 invalidateFilter();
258 }
259