Bug Summary

File:builds/wireshark/wireshark/ui/qt/models/pref_models.cpp
Warning:line 330, column 1
Potential leak of memory pointed to by 'special_item'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pref_models.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-18/lib/clang/18 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/build/ui/qt -isystem /builds/wireshark/wireshark/ui/qt -isystem /usr/include/x86_64-linux-gnu/qt6/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt6 -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore -isystem /usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++ -isystem /usr/include/x86_64-linux-gnu/qt6/QtGui -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore5Compat -isystem /usr/include/x86_64-linux-gnu/qt6/QtConcurrent -isystem /usr/include/x86_64-linux-gnu/qt6/QtPrintSupport -isystem /usr/include/x86_64-linux-gnu/qt6/QtMultimedia -isystem /usr/include/x86_64-linux-gnu/qt6/QtNetwork -isystem /usr/include/x86_64-linux-gnu/qt6/QtDBus -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D QT_CONCURRENT_LIB -D QT_CORE5COMPAT_LIB -D QT_CORE_LIB -D QT_DBUS_LIB -D QT_GUI_LIB -D QT_MULTIMEDIA_LIB -D QT_NETWORK_LIB -D QT_PRINTSUPPORT_LIB -D QT_WIDGETS_LIB -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build/ui/qt/qtui_autogen/include -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -std=c++17 -fdeprecated-macro -ferror-limit 19 -fwrapv -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -fcolor-diagnostics -analyzer-output=html -dwarf-debug-flags /usr/lib/llvm-18/bin/clang --driver-mode=g++ -### --analyze -x c++ -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D QT_CONCURRENT_LIB -D QT_CORE5COMPAT_LIB -D QT_CORE_LIB -D QT_DBUS_LIB -D QT_GUI_LIB -D QT_MULTIMEDIA_LIB -D QT_NETWORK_LIB -D QT_PRINTSUPPORT_LIB -D QT_WIDGETS_LIB -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build/ui/qt/qtui_autogen/include -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/build/ui/qt -isystem /builds/wireshark/wireshark/ui/qt -isystem /usr/include/x86_64-linux-gnu/qt6/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt6 -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore -isystem /usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++ -isystem /usr/include/x86_64-linux-gnu/qt6/QtGui -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore5Compat -isystem /usr/include/x86_64-linux-gnu/qt6/QtConcurrent -isystem /usr/include/x86_64-linux-gnu/qt6/QtPrintSupport -isystem /usr/include/x86_64-linux-gnu/qt6/QtMultimedia -isystem /usr/include/x86_64-linux-gnu/qt6/QtNetwork -isystem /usr/include/x86_64-linux-gnu/qt6/QtDBus -fexcess-precision=fast -fstrict-flex-arrays=3 -fstack-clash-protection -fcf-protection=full -D _GLIBCXX_ASSERTIONS -fstack-protector-strong -fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -fexceptions -Wno-format-truncation -Wno-format-nonliteral -fdiagnostics-color=always -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -std=c++17 -fPIC -fPIC /builds/wireshark/wireshark/ui/qt/models/pref_models.cpp -o /builds/wireshark/wireshark/sbout/2024-11-20-100252-3912-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2024-11-20-100252-3912-1 -x c++ /builds/wireshark/wireshark/ui/qt/models/pref_models.cpp
1/* pref_models.cpp
2 *
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <[email protected]>
5 * Copyright 1998 Gerald Combs
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10#include <ui/qt/models/pref_models.h>
11#include <ui/qt/utils/qt_ui_utils.h>
12#include <epan/prefs-int.h>
13
14#ifdef HAVE_LIBPCAP1
15#ifdef _WIN32
16#include "capture/capture-wpcap.h"
17#endif /* _WIN32 */
18#endif /* HAVE_LIBPCAP */
19
20#include <QFont>
21#include <QColor>
22#include <QRegularExpression>
23#include <QApplication>
24
25// XXX Should we move this to ui/preference_utils?
26static GHashTable * pref_ptr_to_pref_;
27pref_t *prefFromPrefPtr(void *pref_ptr)
28{
29 return (pref_t *)g_hash_table_lookup(pref_ptr_to_pref_, (void *) pref_ptr);
30}
31
32static void prefInsertPrefPtr(void * pref_ptr, pref_t * pref)
33{
34 if (! pref_ptr_to_pref_)
35 pref_ptr_to_pref_ = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL__null, NULL__null);
36
37 void *key = (void *) pref_ptr;
38 void *val = (void *) pref;
39
40 /* Already existing entries will be ignored */
41 if ((void *)g_hash_table_lookup(pref_ptr_to_pref_, key) == NULL__null)
42 g_hash_table_insert(pref_ptr_to_pref_, key, val);
43}
44
45PrefsItem::PrefsItem(module_t *module, pref_t *pref, PrefsItem* parent)
46 : ModelHelperTreeItem<PrefsItem>(parent),
47 pref_(pref),
48 module_(module),
49 name_(module->name ? module->name : module->parent->name),
50 help_(QString()),
51 changed_(false)
52{
53 if (pref_ != NULL__null) {
54 name_ += QStringLiteral(".%1")(QString(QtPrivate::qMakeStringPrivate(u"" ".%1"))).arg(prefs_get_name(pref_));
55 }
56}
57
58PrefsItem::PrefsItem(const QString name, PrefsItem* parent)
59 : ModelHelperTreeItem<PrefsItem>(parent),
60 pref_(NULL__null),
61 module_(NULL__null),
62 name_(name),
63 help_(QString()),
64 changed_(false)
65{
66}
67
68PrefsItem::PrefsItem(PrefsModel::PrefsModelType type, PrefsItem* parent)
69 : ModelHelperTreeItem<PrefsItem>(parent),
70 pref_(NULL__null),
71 module_(NULL__null),
72 name_(PrefsModel::typeToString(type)),
73 help_(PrefsModel::typeToHelp(type)),
74 changed_(false)
75{
76}
77
78PrefsItem::~PrefsItem()
79{
80}
81
82int PrefsItem::getPrefType() const
83{
84 if (pref_ == NULL__null)
85 return 0;
86
87 return prefs_get_type(pref_);
88}
89
90bool PrefsItem::isPrefDefault() const
91{
92 if (pref_ == NULL__null)
93 return true;
94
95 if (changed_ == false)
96 return prefs_pref_is_default(pref_) ? true : false;
97
98 return false;
99}
100
101QString PrefsItem::getPrefTypeName() const
102{
103 if (pref_ == NULL__null)
104 return "";
105
106 return QString(prefs_pref_type_name(pref_));
107}
108
109QString PrefsItem::getModuleName() const
110{
111 if (module_ == NULL__null)
112 return name_;
113
114 return QString(module_->name);
115}
116
117QString PrefsItem::getModuleTitle() const
118{
119 if ((module_ == NULL__null) && (pref_ == NULL__null))
120 return name_;
121
122 Q_ASSERT(module_)((module_) ? static_cast<void>(0) : qt_assert("module_"
, "ui/qt/models/pref_models.cpp", 122))
;
123
124 return QString(module_->title);
125}
126
127QString PrefsItem::getModuleHelp() const
128{
129 if (module_ == nullptr)
130 return help_;
131
132 module_t *pref_module = module_;
133
134 while (pref_module->help == nullptr && pref_module->parent) {
135 pref_module = pref_module->parent;
136 }
137
138 return pref_module->help;
139}
140
141void PrefsItem::setChanged(bool changed)
142{
143 changed_ = changed;
144}
145
146PrefsModel::PrefsModel(QObject *parent) :
147 QAbstractItemModel(parent),
148 root_(new PrefsItem(QStringLiteral("ROOT")(QString(QtPrivate::qMakeStringPrivate(u"" "ROOT"))), NULL__null))
149{
150 populate();
1
Calling 'PrefsModel::populate'
151}
152
153PrefsModel::~PrefsModel()
154{
155 delete root_;
156}
157
158int PrefsModel::rowCount(const QModelIndex &parent) const
159{
160 PrefsItem *parent_item;
161 if (parent.column() > 0)
162 return 0;
163
164 if (!parent.isValid())
165 parent_item = root_;
166 else
167 parent_item = static_cast<PrefsItem*>(parent.internalPointer());
168
169 if (parent_item == NULL__null)
170 return 0;
171
172 return static_cast<int>(parent_item->childCount());
173}
174
175int PrefsModel::columnCount(const QModelIndex&) const
176{
177 return colLast;
178}
179
180
181QModelIndex PrefsModel::parent(const QModelIndex& index) const
182{
183 if (!index.isValid())
184 return QModelIndex();
185
186 PrefsItem* item = static_cast<PrefsItem*>(index.internalPointer());
187 if (item != NULL__null) {
188 PrefsItem* parent_item = item->parentItem();
189 if (parent_item != NULL__null) {
190 if (parent_item == root_)
191 return QModelIndex();
192
193 return createIndex(parent_item->row(), 0, parent_item);
194 }
195 }
196
197 return QModelIndex();
198}
199
200QModelIndex PrefsModel::index(int row, int column, const QModelIndex& parent) const
201{
202 if (!hasIndex(row, column, parent))
203 return QModelIndex();
204
205 PrefsItem *parent_item, *child_item;
206
207 if (!parent.isValid())
208 parent_item = root_;
209 else
210 parent_item = static_cast<PrefsItem*>(parent.internalPointer());
211
212 Q_ASSERT(parent_item)((parent_item) ? static_cast<void>(0) : qt_assert("parent_item"
, "ui/qt/models/pref_models.cpp", 212))
;
213
214 child_item = parent_item->child(row);
215 if (child_item) {
216 return createIndex(row, column, child_item);
217 }
218
219 return QModelIndex();
220}
221
222QVariant PrefsModel::data(const QModelIndex &index, int role) const
223{
224 if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::UserRole))
225 return QVariant();
226
227 PrefsItem* item = static_cast<PrefsItem*>(index.internalPointer());
228 if (item == NULL__null)
229 return QVariant();
230
231 if (role == Qt::UserRole)
232 return VariantPointer<PrefsItem>::asQVariant(item);
233
234 switch ((enum PrefsModelColumn)index.column()) {
235 case colName:
236 return item->getName();
237
238 case colStatus:
239 if (item->getPrefType() == PREF_UAT(1u << 6) || item->getPrefType() == PREF_CUSTOM(1u << 9))
240 return QObject::tr("Unknown");
241
242 if (item->isPrefDefault())
243 return QObject::tr("Default");
244
245 return QObject::tr("Changed");
246 case colType:
247 return item->getPrefTypeName();
248 case colValue:
249 if (item->getPref() == NULL__null)
250 return QVariant();
251
252 return QString(gchar_free_to_qstring(prefs_pref_to_str(item->getPref(), pref_stashed)).remove(QRegularExpression("\n\t")));
253 default:
254 break;
255 }
256
257 return QVariant();
258}
259
260static unsigned
261fill_prefs(module_t *module, void *root_ptr)
262{
263 PrefsItem* root_item = static_cast<PrefsItem*>(root_ptr);
264
265 if ((module == NULL__null) || (root_item == NULL__null))
266 return 1;
267
268 if (module->numprefs < 1 && !prefs_module_has_submodules(module))
269 return 0;
270
271 PrefsItem* module_item = new PrefsItem(module, NULL__null, root_item);
272 root_item->prependChild(module_item);
273
274 for (GList *pref_l = module->prefs; pref_l && pref_l->data; pref_l = gxx_list_next(pref_l)((pref_l) ? ((reinterpret_cast<GList *>(pref_l))->next
) : nullptr)
) {
275 pref_t *pref = gxx_list_data(pref_t *, pref_l)((pref_l) ? ((reinterpret_cast<pref_t *>(pref_l->data
))) : nullptr)
;
276
277 if (prefs_get_type(pref) == PREF_OBSOLETE(1u << 10) || prefs_get_type(pref) == PREF_STATIC_TEXT(1u << 5))
278 continue;
279
280 const char *type_name = prefs_pref_type_name(pref);
281 if (!type_name)
282 continue;
283
284 pref_stash(pref, NULL__null);
285
286 PrefsItem* item = new PrefsItem(module, pref, module_item);
287 module_item->prependChild(item);
288
289 // .uat is a void * so it wins the "useful key value" prize.
290 if (prefs_get_uat_value(pref)) {
291 prefInsertPrefPtr(prefs_get_uat_value(pref), pref);
292 }
293 }
294
295 if (prefs_module_has_submodules(module))
296 return prefs_modules_foreach_submodules(module, fill_prefs, module_item);
297
298 return 0;
299}
300
301void PrefsModel::populate()
302{
303 prefs_modules_foreach_submodules(NULL__null, fill_prefs, (void *)root_);
304
305 //Add the "specially handled" preferences
306 PrefsItem *appearance_item, *appearance_subitem, *special_item;
307
308 appearance_item = new PrefsItem(PrefsModel::Appearance, root_);
309 root_->prependChild(appearance_item);
310
311 appearance_subitem = new PrefsItem(PrefsModel::Layout, appearance_item);
312 appearance_item->prependChild(appearance_subitem);
313 appearance_subitem = new PrefsItem(PrefsModel::Columns, appearance_item);
314 appearance_item->prependChild(appearance_subitem);
315 appearance_subitem = new PrefsItem(PrefsModel::FontAndColors, appearance_item);
316 appearance_item->prependChild(appearance_subitem);
317
318 special_item = new PrefsItem(PrefsModel::Capture, root_);
319 root_->prependChild(special_item);
320 special_item = new PrefsItem(PrefsModel::Expert, root_);
321 root_->prependChild(special_item);
322 special_item = new PrefsItem(PrefsModel::FilterButtons, root_);
323 root_->prependChild(special_item);
324#ifdef HAVE_LIBGNUTLS1
325 special_item = new PrefsItem(PrefsModel::RSAKeys, root_);
326 root_->prependChild(special_item);
327#endif
328 special_item = new PrefsItem(PrefsModel::Advanced, root_);
2
Memory is allocated
329 root_->prependChild(special_item);
330}
3
Potential leak of memory pointed to by 'special_item'
331
332QString PrefsModel::typeToString(int type)
333{
334 QString typeStr;
335
336 switch(type)
337 {
338 case Advanced: typeStr = tr("Advanced"); break;
339 case Appearance: typeStr = tr("Appearance"); break;
340 case Layout: typeStr = tr("Layout"); break;
341 case Columns: typeStr = tr("Columns"); break;
342 case FontAndColors: typeStr = tr("Font and Colors"); break;
343 case Capture: typeStr = tr("Capture"); break;
344 case Expert: typeStr = tr("Expert"); break;
345 case FilterButtons: typeStr = tr("Filter Buttons"); break;
346 case RSAKeys: typeStr = tr("RSA Keys"); break;
347 }
348
349 return typeStr;
350}
351
352QString PrefsModel::typeToHelp(int type)
353{
354 QString helpStr;
355
356 switch(type)
357 {
358 case Appearance:
359 helpStr = QStringLiteral("ChCustPreferencesSection.html#_appearance")(QString(QtPrivate::qMakeStringPrivate(u"" "ChCustPreferencesSection.html#_appearance"
)))
;
360 break;
361 case Columns:
362 helpStr = QStringLiteral("ChCustPreferencesSection.html#_columns")(QString(QtPrivate::qMakeStringPrivate(u"" "ChCustPreferencesSection.html#_columns"
)))
;
363 break;
364 case FontAndColors:
365 helpStr = QStringLiteral("ChCustPreferencesSection.html#_font_and_colors")(QString(QtPrivate::qMakeStringPrivate(u"" "ChCustPreferencesSection.html#_font_and_colors"
)))
;
366 break;
367 case Layout:
368 helpStr = QStringLiteral("ChCustPreferencesSection.html#_layout")(QString(QtPrivate::qMakeStringPrivate(u"" "ChCustPreferencesSection.html#_layout"
)))
;
369 break;
370 case Capture:
371 helpStr = QStringLiteral("ChCustPreferencesSection.html#_capture")(QString(QtPrivate::qMakeStringPrivate(u"" "ChCustPreferencesSection.html#_capture"
)))
;
372 break;
373 case Expert:
374 helpStr = QStringLiteral("ChCustPreferencesSection.html#ChCustPrefsExpertSection")(QString(QtPrivate::qMakeStringPrivate(u"" "ChCustPreferencesSection.html#ChCustPrefsExpertSection"
)))
;
375 break;
376 case FilterButtons:
377 helpStr = QStringLiteral("ChCustPreferencesSection.html#ChCustFilterButtons")(QString(QtPrivate::qMakeStringPrivate(u"" "ChCustPreferencesSection.html#ChCustFilterButtons"
)))
;
378 break;
379 case RSAKeys:
380 helpStr = QStringLiteral("ChCustPreferencesSection.html#ChCustPrefsRSASection")(QString(QtPrivate::qMakeStringPrivate(u"" "ChCustPreferencesSection.html#ChCustPrefsRSASection"
)))
;
381 break;
382 case Advanced:
383 helpStr = QStringLiteral("ChCustPreferencesSection.html#_advanced")(QString(QtPrivate::qMakeStringPrivate(u"" "ChCustPreferencesSection.html#_advanced"
)))
;
384 break;
385 }
386
387 return helpStr;
388}
389
390AdvancedPrefsModel::AdvancedPrefsModel(QObject * parent)
391: QSortFilterProxyModel(parent),
392filter_(),
393show_changed_values_(false),
394passwordChar_(QApplication::style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter))
395{
396}
397
398QVariant AdvancedPrefsModel::headerData(int section, Qt::Orientation orientation, int role) const
399{
400 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
401
402 switch (section) {
403 case colName:
404 return tr("Name");
405 case colStatus:
406 return tr("Status");
407 case colType:
408 return tr("Type");
409 case colValue:
410 return tr("Value");
411 default:
412 break;
413 }
414 }
415 return QVariant();
416}
417
418QVariant AdvancedPrefsModel::data(const QModelIndex &dataindex, int role) const
419{
420 if (!dataindex.isValid())
421 return QVariant();
422
423 QModelIndex modelIndex = mapToSource(dataindex);
424
425 PrefsItem* item = static_cast<PrefsItem*>(modelIndex.internalPointer());
426 if (item == NULL__null)
427 return QVariant();
428
429 switch (role)
430 {
431 case Qt::DisplayRole:
432 switch ((AdvancedPrefsModelColumn)dataindex.column())
433 {
434 case colName:
435 if (item->getPref() == NULL__null)
436 return item->getModule()->title;
437
438 return sourceModel()->data(sourceModel()->index(modelIndex.row(), PrefsModel::colName, modelIndex.parent()), role);
439 case colStatus:
440 if (item->getPref() == NULL__null)
441 return QVariant();
442
443 return sourceModel()->data(sourceModel()->index(modelIndex.row(), PrefsModel::colStatus, modelIndex.parent()), role);
444 case colType:
445 if (item->getPref() == NULL__null)
446 return QVariant();
447
448 return sourceModel()->data(sourceModel()->index(modelIndex.row(), PrefsModel::colType, modelIndex.parent()), role);
449 case colValue:
450 if (item->getPref() == NULL__null)
451 return QVariant();
452
453 if (PREF_PASSWORD(1u << 15) == item->getPrefType())
454 {
455 return QString(sourceModel()->data(sourceModel()->index(modelIndex.row(), PrefsModel::colValue, modelIndex.parent()), role).toString().size(), passwordChar_);
456 } else {
457 return sourceModel()->data(sourceModel()->index(modelIndex.row(), PrefsModel::colValue, modelIndex.parent()), role);
458 }
459 default:
460 break;
461 }
462 break;
463 case Qt::ToolTipRole:
464 switch ((AdvancedPrefsModelColumn)dataindex.column())
465 {
466 case colName:
467 if (item->getPref() == NULL__null)
468 return QStringLiteral("<span>%1</span>")(QString(QtPrivate::qMakeStringPrivate(u"" "<span>%1</span>"
)))
.arg(item->getModule()->description);
469
470 return QStringLiteral("<span>%1</span>")(QString(QtPrivate::qMakeStringPrivate(u"" "<span>%1</span>"
)))
.arg(prefs_get_description(item->getPref()));
471 case colStatus:
472 if (item->getPref() == NULL__null)
473 return QVariant();
474
475 return QObject::tr("Has this preference been changed?");
476 case colType:
477 if (item->getPref() == NULL__null) {
478 return QVariant();
479 } else {
480 QString type_desc = gchar_free_to_qstring(prefs_pref_type_description(item->getPref()));
481 return QStringLiteral("<span>%1</span>")(QString(QtPrivate::qMakeStringPrivate(u"" "<span>%1</span>"
)))
.arg(type_desc);
482 }
483 break;
484 case colValue:
485 if (item->getPref() == NULL__null) {
486 return QVariant();
487 } else {
488 QString default_value = gchar_free_to_qstring(prefs_pref_to_str(item->getPref(), pref_default));
489 return QStringLiteral("<span>%1</span>")(QString(QtPrivate::qMakeStringPrivate(u"" "<span>%1</span>"
)))
.arg(
490 !default_value.isEmpty() ? default_value : QObject::tr("Default value is empty"));
491 }
492 default:
493 break;
494 }
495 break;
496 case Qt::FontRole:
497 if (item->getPref() == NULL__null)
498 return QVariant();
499
500 if (!item->isPrefDefault() &&
501 /* UATs and custom preferences are "unknown", that shouldn't mean that they are always bolded */
502 item->getPrefType() != PREF_UAT(1u << 6) && item->getPrefType() != PREF_CUSTOM(1u << 9)) {
503 QFont font;
504 font.setBold(true);
505 return font;
506 }
507 break;
508 case Qt::UserRole:
509 return sourceModel()->data(modelIndex, role);
510 default:
511 break;
512 }
513
514 return QVariant();
515}
516
517bool AdvancedPrefsModel::setData(const QModelIndex &dataindex, const QVariant &value, int role)
518{
519 if ((!dataindex.isValid()) || (role != Qt::EditRole))
520 return false;
521
522 QModelIndex modelIndex = mapToSource(dataindex);
523
524 PrefsItem* item = static_cast<PrefsItem*>(modelIndex.internalPointer());
525 if (item == NULL__null)
526 return false;
527
528 if (value.isNull()) {
529 //reset preference to default
530 reset_stashed_pref(item->getPref());
531 item->setChanged(false);
532 } else {
533 item->setChanged(true);
534 switch (item->getPrefType())
535 {
536 case PREF_UINT(1u << 0):
537 {
538 bool ok;
539 unsigned new_val = value.toString().toUInt(&ok, prefs_get_uint_base(item->getPref()));
540
541 if (ok)
542 prefs_set_uint_value(item->getPref(), new_val, pref_stashed);
543 }
544 break;
545 case PREF_BOOL(1u << 1):
546 prefs_invert_bool_value(item->getPref(), pref_stashed);
547 break;
548 case PREF_ENUM(1u << 2):
549 prefs_set_enum_value(item->getPref(), value.toInt(), pref_stashed);
550 break;
551 case PREF_STRING(1u << 3):
552 case PREF_DISSECTOR(1u << 17):
553 prefs_set_string_value(item->getPref(), value.toString().toStdString().c_str(), pref_stashed);
554 break;
555 case PREF_PASSWORD(1u << 15):
556 prefs_set_password_value(item->getPref(), value.toString().toStdString().c_str(), pref_stashed);
557 break;
558 case PREF_DECODE_AS_RANGE(1u << 13):
559 case PREF_RANGE(1u << 4):
560 prefs_set_stashed_range_value(item->getPref(), value.toString().toUtf8().constData());
561 break;
562 case PREF_SAVE_FILENAME(1u << 7):
563 case PREF_OPEN_FILENAME(1u << 14):
564 case PREF_DIRNAME(1u << 11):
565 prefs_set_string_value(item->getPref(), value.toString().toStdString().c_str(), pref_stashed);
566 break;
567 case PREF_COLOR(1u << 8):
568 {
569 QColor qc(value.toString());
570 color_t color;
571
572 color.red = qc.red() << 8 | qc.red();
573 color.green = qc.green() << 8 | qc.green();
574 color.blue = qc.blue() << 8 | qc.blue();
575
576 prefs_set_color_value(item->getPref(), color, pref_stashed);
577 break;
578 }
579 case PREF_CUSTOM(1u << 9):
580 prefs_set_custom_value(item->getPref(), value.toString().toStdString().c_str(), pref_stashed);
581 break;
582 }
583 }
584
585 QVector<int> roles;
586 roles << role;
587
588 // The status field may change as well as the value, so mark them for update
589 emit dataChanged(index(dataindex.row(), 0, dataindex.parent()),
590 index(dataindex.row(), columnCount() - 1, dataindex.parent()),
591 roles);
592
593 return true;
594}
595
596Qt::ItemFlags AdvancedPrefsModel::flags(const QModelIndex &index) const
597{
598 if (!index.isValid())
599 return Qt::ItemFlags();
600
601 QModelIndex modelIndex = mapToSource(index);
602
603 PrefsItem* item = static_cast<PrefsItem*>(modelIndex.internalPointer());
604 if (item == NULL__null)
605 return Qt::ItemFlags();
606
607 Qt::ItemFlags flags = QAbstractItemModel::flags(index);
608 if (item->getPref() == NULL__null) {
609 /* Base modules aren't changeable */
610 flags &= ~(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
611 } else {
612 flags |= Qt::ItemIsEditable;
613 }
614
615 return flags;
616}
617
618
619int AdvancedPrefsModel::columnCount(const QModelIndex&) const
620{
621 return colLast;
622}
623
624void AdvancedPrefsModel::setFirstColumnSpanned(QTreeView* tree, const QModelIndex& mIndex)
625{
626 int childCount, row;
627 PrefsItem* item;
628 if (mIndex.isValid()) {
629 item = VariantPointer<PrefsItem>::asPtr(data(mIndex, Qt::UserRole));
630 if (item != NULL__null) {
631 childCount = item->childCount();
632 if (childCount > 0) {
633 tree->setFirstColumnSpanned(mIndex.row(), mIndex.parent(), true);
634 for (row = 0; row < childCount; row++) {
635 setFirstColumnSpanned(tree, index(row, 0, mIndex));
636 }
637 }
638 }
639 } else {
640 for (row = 0; row < rowCount(); row++) {
641 setFirstColumnSpanned(tree, index(row, 0));
642 }
643 }
644}
645
646bool AdvancedPrefsModel::filterAcceptItem(PrefsItem& item) const
647{
648 if (filter_.isEmpty() && !show_changed_values_)
649 return true;
650
651 QString name, tooltip;
652 if (item.getPref() == NULL__null) {
653 name = item.getModule()->title;
654 tooltip = item.getModule()->description;
655 } else {
656 name = QString(item.getModule()->name ? item.getModule()->name : item.getModule()->parent->name);
657 name += QStringLiteral(".%1")(QString(QtPrivate::qMakeStringPrivate(u"" ".%1"))).arg(prefs_get_name(item.getPref()));
658 tooltip = prefs_get_description(item.getPref());
659 }
660
661 if (show_changed_values_ && item.getPref()) {
662 // UATs and custom preferences are "unknown", do not show when show_changed_only.
663 if (item.isPrefDefault() || item.getPrefType() == PREF_UAT(1u << 6) || item.getPrefType() == PREF_CUSTOM(1u << 9)) {
664 return false;
665 } else if (filter_.isEmpty()) {
666 return true;
667 }
668 }
669
670 // Do not match module title or description when having show_changed_only.
671 if (!(filter_.isEmpty() || (show_changed_values_ && !item.getPref())) &&
672 (name.contains(filter_, Qt::CaseInsensitive) || tooltip.contains(filter_, Qt::CaseInsensitive)))
673 return true;
674
675 if (item.getPrefTypeName().contains(filter_, Qt::CaseSensitive)) {
676 return true;
677 }
678
679 PrefsItem *child_item;
680 for (int child_row = 0; child_row < item.childCount(); child_row++)
681 {
682 child_item = item.child(child_row);
683 if ((child_item != NULL__null) && (filterAcceptItem(*child_item)))
684 return true;
685 }
686
687 return false;
688}
689
690bool AdvancedPrefsModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
691{
692 QModelIndex nameIdx = sourceModel()->index(sourceRow, PrefsModel::colName, sourceParent);
693 PrefsItem* item = static_cast<PrefsItem*>(nameIdx.internalPointer());
694 if (item == NULL__null)
695 return true;
696
697 //filter out the "special" preferences
698 if ((item->getModule() == NULL__null) && (item->getPref() == NULL__null))
699 return false;
700
701 if (filterAcceptItem(*item))
702 return true;
703
704 return false;
705}
706
707void AdvancedPrefsModel::setFilter(const QString& filter)
708{
709 filter_ = filter;
710 invalidateFilter();
711}
712
713void AdvancedPrefsModel::setShowChangedValues(bool show_changed_values)
714{
715 show_changed_values_ = show_changed_values;
716 invalidateFilter();
717}
718
719
720
721ModulePrefsModel::ModulePrefsModel(QObject* parent)
722 : QSortFilterProxyModel(parent)
723 , advancedPrefName_(PrefsModel::typeToString(PrefsModel::Advanced))
724{
725}
726
727QVariant ModulePrefsModel::data(const QModelIndex &dataindex, int role) const
728{
729 if (!dataindex.isValid())
730 return QVariant();
731
732 QModelIndex modelIndex = mapToSource(dataindex);
733
734 PrefsItem* item = static_cast<PrefsItem*>(modelIndex.internalPointer());
735 if (item == NULL__null)
736 return QVariant();
737
738 switch (role)
739 {
740 case Qt::DisplayRole:
741 switch ((ModulePrefsModelColumn)dataindex.column())
742 {
743 case colName:
744 return item->getModuleTitle();
745 default:
746 break;
747 }
748 break;
749 case Qt::UserRole:
750 return sourceModel()->data(modelIndex, role);
751 case ModuleName:
752 return item->getModuleName();
753 case ModuleHelp:
754 return item->getModuleHelp();
755 default:
756 break;
757 }
758
759 return QVariant();
760}
761Qt::ItemFlags ModulePrefsModel::flags(const QModelIndex &index) const
762{
763 if (!index.isValid())
764 return Qt::ItemFlags();
765
766 bool disable_capture = true;
767#ifdef HAVE_LIBPCAP1
768#ifdef _WIN32
769 /* Is WPcap loaded? */
770 if (has_wpcap) {
771#endif /* _WIN32 */
772 disable_capture = false;
773#ifdef _WIN32
774 }
775#endif /* _WIN32 */
776#endif /* HAVE_LIBPCAP */
777
778 Qt::ItemFlags flags = QAbstractItemModel::flags(index);
779 if (disable_capture) {
780 QModelIndex modelIndex = mapToSource(index);
781
782 PrefsItem* item = static_cast<PrefsItem*>(modelIndex.internalPointer());
783 if (item == NULL__null)
784 return flags;
785
786 if (item->getName().compare(PrefsModel::typeToString(PrefsModel::Capture)) == 0) {
787 flags &= (~Qt::ItemIsEnabled);
788 }
789 }
790
791 return flags;
792}
793
794int ModulePrefsModel::columnCount(const QModelIndex&) const
795{
796 return colLast;
797}
798
799bool ModulePrefsModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
800{
801 PrefsItem* left_item = static_cast<PrefsItem*>(source_left.internalPointer());
802 PrefsItem* right_item = static_cast<PrefsItem*>(source_right.internalPointer());
803
804 if ((left_item != NULL__null) && (right_item != NULL__null)) {
805 QString left_name = left_item->getModuleTitle(),
806 right_name = right_item->getModuleTitle();
807
808 //Force "Advanced" preferences to be at bottom of model
809 if (source_left.isValid() && !source_left.parent().isValid() &&
810 source_right.isValid() && !source_right.parent().isValid()) {
811 if (left_name.compare(advancedPrefName_) == 0) {
812 return false;
813 }
814 if (right_name.compare(advancedPrefName_) == 0) {
815 return true;
816 }
817 }
818
819 if (left_name.compare(right_name, Qt::CaseInsensitive) < 0)
820 return true;
821 }
822
823 return false;
824}
825
826bool ModulePrefsModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
827{
828 QModelIndex nameIdx = sourceModel()->index(sourceRow, PrefsModel::colName, sourceParent);
829 PrefsItem* item = static_cast<PrefsItem*>(nameIdx.internalPointer());
830 if (item == NULL__null)
831 return true;
832
833 if (item->getPref() != NULL__null)
834 return false;
835
836 if (item->getModule() != NULL__null) {
837 if (!item->getModule()->use_gui) {
838 return false;
839 }
840 }
841
842 return true;
843}