File: | builds/wireshark/wireshark/ui/qt/models/coloring_rules_model.cpp |
Warning: | line 495, column 9 Potential leak of memory pointed to by 'item' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* coloring_rules_model.cpp | |||
2 | * Data model for coloring rules. | |||
3 | * | |||
4 | * Wireshark - Network traffic analyzer | |||
5 | * By Gerald Combs <[email protected]> | |||
6 | * Copyright 1998 Gerald Combs | |||
7 | * | |||
8 | * SPDX-License-Identifier: GPL-2.0-or-later | |||
9 | */ | |||
10 | #include "config.h" | |||
11 | ||||
12 | #include "coloring_rules_model.h" | |||
13 | ||||
14 | #include <errno(*__errno_location ()).h> | |||
15 | ||||
16 | #include "ui/ws_ui_util.h" //for color_filter_add_cb | |||
17 | ||||
18 | #include <ui/qt/utils/color_utils.h> | |||
19 | #include <ui/qt/utils/qt_ui_utils.h> | |||
20 | #include <ui/qt/utils/variant_pointer.h> | |||
21 | #include <ui/qt/utils/wireshark_mime_data.h> | |||
22 | ||||
23 | #include <QMimeData> | |||
24 | #include <QJsonDocument> | |||
25 | #include <QJsonObject> | |||
26 | #include <QJsonArray> | |||
27 | ||||
28 | ColoringRuleItem::ColoringRuleItem(bool disabled, QString name, QString filter, QColor foreground, QColor background, ColoringRuleItem* parent) | |||
29 | : ModelHelperTreeItem<ColoringRuleItem>(parent), | |||
30 | disabled_(disabled), | |||
31 | name_(name), | |||
32 | filter_(filter), | |||
33 | foreground_(foreground), | |||
34 | background_(background) | |||
35 | { | |||
36 | } | |||
37 | ||||
38 | ColoringRuleItem::~ColoringRuleItem() | |||
39 | { | |||
40 | ||||
41 | } | |||
42 | ||||
43 | ColoringRuleItem::ColoringRuleItem(color_filter_t *colorf, ColoringRuleItem* parent) | |||
44 | : ModelHelperTreeItem<ColoringRuleItem>(parent), | |||
45 | disabled_(colorf->disabled), | |||
46 | name_(colorf->filter_name), | |||
47 | filter_(colorf->filter_text), | |||
48 | foreground_(ColorUtils::fromColorT(colorf->fg_color)), | |||
49 | background_(ColorUtils::fromColorT(colorf->bg_color)) | |||
50 | { | |||
51 | } | |||
52 | ||||
53 | ColoringRuleItem::ColoringRuleItem(const ColoringRuleItem& item) | |||
54 | : ModelHelperTreeItem<ColoringRuleItem>(item.parent_), | |||
55 | disabled_(item.disabled_), | |||
56 | name_(item.name_), | |||
57 | filter_(item.filter_), | |||
58 | foreground_(item.foreground_), | |||
59 | background_(item.background_) | |||
60 | { | |||
61 | } | |||
62 | ||||
63 | ColoringRuleItem& ColoringRuleItem::operator=(ColoringRuleItem& rhs) | |||
64 | { | |||
65 | disabled_ = rhs.disabled_; | |||
66 | name_ = rhs.name_; | |||
67 | filter_ = rhs.filter_; | |||
68 | foreground_ = rhs.foreground_; | |||
69 | background_ = rhs.background_; | |||
70 | return *this; | |||
71 | } | |||
72 | ||||
73 | // Callback for color_filters_clone. | |||
74 | void | |||
75 | color_filter_add_cb(color_filter_t *colorf, void *user_data) | |||
76 | { | |||
77 | ColoringRulesModel *model = (ColoringRulesModel*)user_data; | |||
78 | ||||
79 | if (model == NULL__null) | |||
80 | return; | |||
81 | ||||
82 | model->addColor(colorf); | |||
83 | } | |||
84 | ||||
85 | ColoringRulesModel::ColoringRulesModel(QColor defaultForeground, QColor defaultBackground, QObject *parent) : | |||
86 | QAbstractItemModel(parent), | |||
87 | root_(new ColoringRuleItem(false, "", "", QColor(), QColor(), NULL__null)), | |||
88 | conversation_colors_(NULL__null), | |||
89 | defaultForeground_(defaultForeground), | |||
90 | defaultBackground_(defaultBackground) | |||
91 | ||||
92 | { | |||
93 | color_filters_clone(this, color_filter_add_cb); | |||
94 | } | |||
95 | ||||
96 | ColoringRulesModel::~ColoringRulesModel() | |||
97 | { | |||
98 | delete root_; | |||
99 | color_filter_list_delete(&conversation_colors_); | |||
100 | } | |||
101 | ||||
102 | GSList *ColoringRulesModel::createColorFilterList() | |||
103 | { | |||
104 | GSList *cfl = NULL__null; | |||
105 | for (int row = 0; row < root_->childCount(); row++) | |||
106 | { | |||
107 | ColoringRuleItem* rule = root_->child(row); | |||
108 | if (rule == NULL__null) | |||
109 | continue; | |||
110 | ||||
111 | color_t fg = ColorUtils::toColorT(rule->foreground_); | |||
112 | color_t bg = ColorUtils::toColorT(rule->background_); | |||
113 | color_filter_t *colorf = color_filter_new(rule->name_.toUtf8().constData(), | |||
114 | rule->filter_.toUtf8().constData(), | |||
115 | &bg, &fg, rule->disabled_); | |||
116 | cfl = g_slist_append(cfl, colorf); | |||
117 | } | |||
118 | ||||
119 | return cfl; | |||
120 | } | |||
121 | ||||
122 | void ColoringRulesModel::addColor(color_filter_t* colorf) | |||
123 | { | |||
124 | if (!colorf) return; | |||
125 | ||||
126 | if (strstr(colorf->filter_name, CONVERSATION_COLOR_PREFIX"___conversation_color_filter___") != NULL__null) { | |||
127 | conversation_colors_ = g_slist_append(conversation_colors_, colorf); | |||
128 | } else { | |||
129 | int count = root_->childCount(); | |||
130 | ||||
131 | beginInsertRows(QModelIndex(), count, count); | |||
132 | ColoringRuleItem* item = new ColoringRuleItem(colorf, root_); | |||
133 | color_filter_delete(colorf); | |||
134 | root_->appendChild(item); | |||
135 | endInsertRows(); | |||
136 | } | |||
137 | } | |||
138 | ||||
139 | void ColoringRulesModel::addColor(bool disabled, QString filter, QColor foreground, QColor background) | |||
140 | { | |||
141 | //add rule to top of the list | |||
142 | beginInsertRows(QModelIndex(), 0, 0); | |||
143 | ColoringRuleItem* item = new ColoringRuleItem(disabled, tr("New coloring rule"), filter, foreground, background, root_); | |||
144 | root_->prependChild(item); | |||
145 | endInsertRows(); | |||
146 | } | |||
147 | ||||
148 | ||||
149 | bool ColoringRulesModel::importColors(QString filename, QString& err) | |||
150 | { | |||
151 | bool success = true; | |||
152 | char* err_msg = NULL__null; | |||
153 | if (!color_filters_import(filename.toUtf8().constData(), this, &err_msg, color_filter_add_cb)) { | |||
154 | err = gchar_free_to_qstring(err_msg); | |||
155 | success = false; | |||
156 | } | |||
157 | ||||
158 | return success; | |||
159 | } | |||
160 | ||||
161 | bool ColoringRulesModel::exportColors(QString filename, QString& err) | |||
162 | { | |||
163 | GSList *cfl = createColorFilterList(); | |||
164 | bool success = true; | |||
165 | char* err_msg = NULL__null; | |||
166 | if (!color_filters_export(filename.toUtf8().constData(), cfl, false, &err_msg)) { | |||
167 | err = gchar_free_to_qstring(err_msg); | |||
168 | success = false; | |||
169 | } | |||
170 | color_filter_list_delete(&cfl); | |||
171 | ||||
172 | return success; | |||
173 | } | |||
174 | ||||
175 | bool ColoringRulesModel::writeColors(QString& err) | |||
176 | { | |||
177 | GSList *cfl = createColorFilterList(); | |||
178 | bool success = true; | |||
179 | char* err_msg = NULL__null; | |||
180 | if (!color_filters_apply(conversation_colors_, cfl, &err_msg)) { | |||
181 | err = gchar_free_to_qstring(err_msg); | |||
182 | success = false; | |||
183 | } | |||
184 | if (!color_filters_write(cfl, &err_msg)) { | |||
185 | err = tr("Unable to save coloring rules: %1").arg(g_strerror(errno(*__errno_location ()))); | |||
186 | success = false; | |||
187 | g_free(err_msg); | |||
188 | } | |||
189 | color_filter_list_delete(&cfl); | |||
190 | ||||
191 | return success; | |||
192 | } | |||
193 | ||||
194 | bool ColoringRulesModel::insertRows(int row, int count, const QModelIndex& parent) | |||
195 | { | |||
196 | // sanity check insertion | |||
197 | if (row < 0) | |||
198 | return false; | |||
199 | ||||
200 | beginInsertRows(parent, row, row+(count-1)); | |||
201 | ||||
202 | for (int i = row; i < row + count; i++) | |||
203 | { | |||
204 | ColoringRuleItem* item = new ColoringRuleItem(true, tr("New coloring rule"), "", defaultForeground_, defaultBackground_, root_); | |||
205 | root_->insertChild(i, item); | |||
206 | /* Automatically enable the new coloring rule */ | |||
207 | setData(index(i, colName, parent), Qt::Checked, Qt::CheckStateRole); | |||
208 | } | |||
209 | ||||
210 | endInsertRows(); | |||
211 | return true; | |||
212 | } | |||
213 | ||||
214 | bool ColoringRulesModel::removeRows(int row, int count, const QModelIndex& parent) | |||
215 | { | |||
216 | if (row < 0) | |||
217 | return false; | |||
218 | ||||
219 | beginRemoveRows(parent, row, row+(count-1)); | |||
220 | for (int i = row; i < row + count; i++) | |||
221 | { | |||
222 | root_->removeChild(row); | |||
223 | } | |||
224 | endRemoveRows(); | |||
225 | ||||
226 | return true; | |||
227 | } | |||
228 | ||||
229 | bool ColoringRulesModel::copyRow(int dst_row, int src_row) | |||
230 | { | |||
231 | if (src_row < 0 || src_row >= rowCount() || dst_row < 0 || dst_row >= rowCount()) { | |||
232 | return false; | |||
233 | } | |||
234 | ||||
235 | ColoringRuleItem* src_item = root_->child(src_row); | |||
236 | if (src_item == NULL__null) | |||
237 | return false; | |||
238 | ||||
239 | ColoringRuleItem* dst_item = new ColoringRuleItem(*src_item); | |||
240 | if (dst_item == NULL__null) | |||
241 | return false; | |||
242 | ||||
243 | beginInsertRows(QModelIndex(), dst_row, dst_row); | |||
244 | root_->insertChild(dst_row, dst_item); | |||
245 | endInsertRows(); | |||
246 | ||||
247 | return true; | |||
248 | } | |||
249 | ||||
250 | Qt::ItemFlags ColoringRulesModel::flags(const QModelIndex &index) const | |||
251 | { | |||
252 | Qt::ItemFlags flags = QAbstractItemModel::flags(index); | |||
253 | switch (index.column()) | |||
254 | { | |||
255 | case colName: | |||
256 | flags |= (Qt::ItemIsUserCheckable|Qt::ItemIsEditable); | |||
257 | break; | |||
258 | case colFilter: | |||
259 | flags |= Qt::ItemIsEditable; | |||
260 | break; | |||
261 | } | |||
262 | ||||
263 | if (index.isValid()) | |||
264 | flags |= (Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); | |||
265 | else | |||
266 | flags |= Qt::ItemIsDropEnabled; | |||
267 | ||||
268 | return flags; | |||
269 | } | |||
270 | ||||
271 | ||||
272 | QVariant ColoringRulesModel::data(const QModelIndex &index, int role) const | |||
273 | { | |||
274 | if (!index.isValid()) | |||
275 | return QVariant(); | |||
276 | ||||
277 | ColoringRuleItem* rule = root_->child(index.row()); | |||
278 | if (rule == NULL__null) | |||
279 | return QVariant(); | |||
280 | ||||
281 | switch (role) | |||
282 | { | |||
283 | case Qt::DisplayRole: | |||
284 | case Qt::EditRole: | |||
285 | switch(index.column()) | |||
286 | { | |||
287 | case colName: | |||
288 | return rule->name_; | |||
289 | case colFilter: | |||
290 | return rule->filter_; | |||
291 | } | |||
292 | break; | |||
293 | case Qt::CheckStateRole: | |||
294 | switch(index.column()) | |||
295 | { | |||
296 | case colName: | |||
297 | return rule->disabled_ ? Qt::Unchecked : Qt::Checked; | |||
298 | } | |||
299 | break; | |||
300 | case Qt::BackgroundRole: | |||
301 | return rule->background_; | |||
302 | case Qt::ForegroundRole: | |||
303 | return rule->foreground_; | |||
304 | } | |||
305 | return QVariant(); | |||
306 | } | |||
307 | ||||
308 | bool ColoringRulesModel::setData(const QModelIndex &dataIndex, const QVariant &value, int role) | |||
309 | { | |||
310 | if (!dataIndex.isValid()) | |||
311 | return false; | |||
312 | ||||
313 | if (data(dataIndex, role) == value) { | |||
314 | // Data appears unchanged, do not do additional checks. | |||
315 | return true; | |||
316 | } | |||
317 | ||||
318 | ColoringRuleItem* rule = root_->child(dataIndex.row()); | |||
319 | if (rule == NULL__null) | |||
320 | return false; | |||
321 | ||||
322 | QModelIndex topLeft = dataIndex, | |||
323 | bottomRight = dataIndex; | |||
324 | ||||
325 | switch (role) | |||
326 | { | |||
327 | case Qt::EditRole: | |||
328 | switch (dataIndex.column()) | |||
329 | { | |||
330 | case colName: | |||
331 | rule->name_ = value.toString(); | |||
332 | break; | |||
333 | case colFilter: | |||
334 | rule->filter_ = value.toString(); | |||
335 | break; | |||
336 | default: | |||
337 | return false; | |||
338 | } | |||
339 | break; | |||
340 | case Qt::CheckStateRole: | |||
341 | switch (dataIndex.column()) | |||
342 | { | |||
343 | case colName: | |||
344 | rule->disabled_ = (value.toInt() == Qt::Checked) ? false : true; | |||
345 | break; | |||
346 | default: | |||
347 | return false; | |||
348 | } | |||
349 | break; | |||
350 | case Qt::BackgroundRole: | |||
351 | #if (QT_VERSION((6<<16)|(4<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0))) | |||
352 | if (!value.canConvert<QColor>()) | |||
353 | #else | |||
354 | if (!value.canConvert(QVariant::Color)) | |||
355 | #endif | |||
356 | return false; | |||
357 | ||||
358 | rule->background_ = QColor(value.toString()); | |||
359 | break; | |||
360 | case Qt::ForegroundRole: | |||
361 | #if (QT_VERSION((6<<16)|(4<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0))) | |||
362 | if (!value.canConvert<QColor>()) | |||
363 | #else | |||
364 | if (!value.canConvert(QVariant::Color)) | |||
365 | #endif | |||
366 | return false; | |||
367 | ||||
368 | rule->foreground_ = QColor(value.toString()); | |||
369 | break; | |||
370 | case Qt::UserRole: | |||
371 | { | |||
372 | ColoringRuleItem* new_rule = VariantPointer<ColoringRuleItem>::asPtr(value); | |||
373 | *rule = *new_rule; | |||
374 | topLeft = index(dataIndex.row(), colName); | |||
375 | bottomRight = index(dataIndex.row(), colFilter); | |||
376 | break; | |||
377 | } | |||
378 | default: | |||
379 | return false; | |||
380 | } | |||
381 | ||||
382 | QVector<int> roles; | |||
383 | roles << role; | |||
384 | ||||
385 | emit dataChanged(topLeft, bottomRight, roles); | |||
386 | ||||
387 | return true; | |||
388 | ||||
389 | } | |||
390 | ||||
391 | QVariant ColoringRulesModel::headerData(int section, Qt::Orientation orientation, int role) const | |||
392 | { | |||
393 | if (role != Qt::DisplayRole || orientation != Qt::Horizontal) | |||
394 | return QVariant(); | |||
395 | ||||
396 | switch ((ColoringRulesColumn)section) { | |||
397 | case colName: | |||
398 | return tr("Name"); | |||
399 | case colFilter: | |||
400 | return tr("Filter"); | |||
401 | default: | |||
402 | break; | |||
403 | } | |||
404 | ||||
405 | return QVariant(); | |||
406 | } | |||
407 | ||||
408 | Qt::DropActions ColoringRulesModel::supportedDropActions() const | |||
409 | { | |||
410 | return Qt::MoveAction | Qt::CopyAction; | |||
411 | } | |||
412 | ||||
413 | QStringList ColoringRulesModel::mimeTypes() const | |||
414 | { | |||
415 | return QStringList() << WiresharkMimeData::ColoringRulesMimeType; | |||
416 | } | |||
417 | ||||
418 | QMimeData* ColoringRulesModel::mimeData(const QModelIndexList &indexes) const | |||
419 | { | |||
420 | //if the list is empty, don't return an empty list | |||
421 | if (indexes.count() == 0) | |||
422 | return NULL__null; | |||
423 | ||||
424 | QMimeData *mimeData = new QMimeData(); | |||
425 | ||||
426 | QJsonArray data; | |||
427 | foreach (const QModelIndex & index, indexes)for (auto _container_427 = QtPrivate::qMakeForeachContainer(indexes ); _container_427.i != _container_427.e; ++_container_427.i) if (const QModelIndex & index = *_container_427.i; false) { } else | |||
428 | { | |||
429 | if (index.column() == 0) | |||
430 | { | |||
431 | ColoringRuleItem * item = root_->child(index.row()); | |||
432 | QJsonObject entry; | |||
433 | entry["disabled"] = item->disabled_; | |||
434 | entry["name"] = item->name_; | |||
435 | entry["filter"] = item->filter_; | |||
436 | entry["foreground"] = QVariant::fromValue(item->foreground_).toString(); | |||
437 | entry["background"] = QVariant::fromValue(item->background_).toString(); | |||
438 | data.append(entry); | |||
439 | } | |||
440 | } | |||
441 | ||||
442 | QJsonObject dataSet; | |||
443 | dataSet["coloringrules"] = data; | |||
444 | QByteArray encodedData = QJsonDocument(dataSet).toJson(); | |||
445 | ||||
446 | mimeData->setData(WiresharkMimeData::ColoringRulesMimeType, encodedData); | |||
447 | return mimeData; | |||
448 | } | |||
449 | ||||
450 | bool ColoringRulesModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) | |||
451 | { | |||
452 | //clear any previous dragDrop information | |||
453 | dragDropRows_.clear(); | |||
454 | ||||
455 | if (action == Qt::IgnoreAction) | |||
| ||||
456 | return true; | |||
457 | ||||
458 | if (!data->hasFormat(WiresharkMimeData::ColoringRulesMimeType) || column > 0) | |||
459 | return false; | |||
460 | ||||
461 | int beginRow; | |||
462 | ||||
463 | if (row != -1) | |||
464 | beginRow = row; | |||
465 | else if (parent.isValid()) | |||
466 | beginRow = parent.row(); | |||
467 | else | |||
468 | beginRow = rowCount(); | |||
469 | ||||
470 | QList<QVariant> rules; | |||
471 | ||||
472 | QJsonDocument encodedData = QJsonDocument::fromJson(data->data(WiresharkMimeData::ColoringRulesMimeType)); | |||
473 | if (! encodedData.isObject() || ! encodedData.object().contains("coloringrules")) | |||
474 | return false; | |||
475 | ||||
476 | QJsonArray dataArray = encodedData.object()["coloringrules"].toArray(); | |||
477 | ||||
478 | for (int datarow = 0; datarow < dataArray.count(); datarow++) | |||
479 | { | |||
480 | QJsonObject entry = dataArray.at(datarow).toObject(); | |||
481 | ||||
482 | if (! entry.contains("foreground") || ! entry.contains("background") || ! entry.contains("filter")) | |||
483 | continue; | |||
484 | ||||
485 | QColor fgColor = entry["foreground"].toVariant().value<QColor>(); | |||
486 | QColor bgColor = entry["background"].toVariant().value<QColor>(); | |||
487 | ||||
488 | ColoringRuleItem * item = new ColoringRuleItem( | |||
489 | entry["disabled"].toVariant().toBool(), | |||
490 | entry["name"].toString(), | |||
491 | entry["filter"].toString(), | |||
492 | fgColor, | |||
493 | bgColor, | |||
494 | root_); | |||
495 | rules.append(VariantPointer<ColoringRuleItem>::asQVariant(item)); | |||
| ||||
496 | } | |||
497 | ||||
498 | insertRows(beginRow, static_cast<int>(rules.count()), QModelIndex()); | |||
499 | for (int i = 0; i < rules.count(); i++) { | |||
500 | QModelIndex idx = index(beginRow, 0, QModelIndex()); | |||
501 | setData(idx, rules[i], Qt::UserRole); | |||
502 | beginRow++; | |||
503 | } | |||
504 | ||||
505 | return true; | |||
506 | } | |||
507 | ||||
508 | QModelIndex ColoringRulesModel::index(int row, int column, const QModelIndex &parent) const | |||
509 | { | |||
510 | if (!hasIndex(row, column, parent)) | |||
511 | return QModelIndex(); | |||
512 | ||||
513 | ColoringRuleItem *parent_item, *child_item; | |||
514 | ||||
515 | if (!parent.isValid()) | |||
516 | parent_item = root_; | |||
517 | else | |||
518 | parent_item = static_cast<ColoringRuleItem*>(parent.internalPointer()); | |||
519 | ||||
520 | Q_ASSERT(parent_item)((parent_item) ? static_cast<void>(0) : qt_assert("parent_item" , "ui/qt/models/coloring_rules_model.cpp", 520)); | |||
521 | ||||
522 | child_item = parent_item->child(row); | |||
523 | if (child_item) { | |||
524 | return createIndex(row, column, child_item); | |||
525 | } | |||
526 | ||||
527 | return QModelIndex(); | |||
528 | } | |||
529 | ||||
530 | QModelIndex ColoringRulesModel::parent(const QModelIndex& indexItem) const | |||
531 | { | |||
532 | if (!indexItem.isValid()) | |||
533 | return QModelIndex(); | |||
534 | ||||
535 | ColoringRuleItem* item = static_cast<ColoringRuleItem*>(indexItem.internalPointer()); | |||
536 | if (item != NULL__null) { | |||
537 | ColoringRuleItem* parent_item = item->parentItem(); | |||
538 | if (parent_item != NULL__null) { | |||
539 | if (parent_item == root_) | |||
540 | return QModelIndex(); | |||
541 | ||||
542 | return createIndex(parent_item->row(), 0, parent_item); | |||
543 | } | |||
544 | } | |||
545 | ||||
546 | return QModelIndex(); | |||
547 | } | |||
548 | ||||
549 | int ColoringRulesModel::rowCount(const QModelIndex& parent) const | |||
550 | { | |||
551 | ColoringRuleItem *parent_item; | |||
552 | if (parent.column() > 0) | |||
553 | return 0; | |||
554 | ||||
555 | if (!parent.isValid()) | |||
556 | parent_item = root_; | |||
557 | else | |||
558 | parent_item = static_cast<ColoringRuleItem*>(parent.internalPointer()); | |||
559 | ||||
560 | if (parent_item == NULL__null) | |||
561 | return 0; | |||
562 | ||||
563 | return parent_item->childCount(); | |||
564 | } | |||
565 | ||||
566 | int ColoringRulesModel::columnCount(const QModelIndex&) const | |||
567 | { | |||
568 | return colColoringRulesMax; | |||
569 | } |
1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QJSONVALUE_H |
5 | #define QJSONVALUE_H |
6 | |
7 | #include <QtCore/qglobal.h> |
8 | #include <QtCore/qstring.h> |
9 | #include <QtCore/qshareddata.h> |
10 | #include <QtCore/qcborvalue.h> |
11 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | class QVariant; |
15 | class QJsonArray; |
16 | class QJsonObject; |
17 | class QCborContainerPrivate; |
18 | |
19 | namespace QJsonPrivate { |
20 | class Value; |
21 | } |
22 | |
23 | class Q_CORE_EXPORT__attribute__((visibility("default"))) QJsonValue |
24 | { |
25 | public: |
26 | enum Type { |
27 | Null = 0x0, |
28 | Bool = 0x1, |
29 | Double = 0x2, |
30 | String = 0x3, |
31 | Array = 0x4, |
32 | Object = 0x5, |
33 | Undefined = 0x80 |
34 | }; |
35 | |
36 | QJsonValue(Type = Null); |
37 | QJsonValue(bool b); |
38 | QJsonValue(double n); |
39 | QJsonValue(int n); |
40 | QJsonValue(qint64 v); |
41 | QJsonValue(const QString &s); |
42 | QJsonValue(QLatin1StringView s); |
43 | #ifndef QT_NO_CAST_FROM_ASCII |
44 | QT_ASCII_CAST_WARN inline QJsonValue(const char *s) |
45 | : QJsonValue(QString::fromUtf8(s)) {} |
46 | #endif |
47 | QJsonValue(const QJsonArray &a); |
48 | QJsonValue(QJsonArray &&a) noexcept; |
49 | QJsonValue(const QJsonObject &o); |
50 | QJsonValue(QJsonObject &&o) noexcept; |
51 | |
52 | ~QJsonValue(); |
53 | |
54 | QJsonValue(const QJsonValue &other); |
55 | QJsonValue &operator =(const QJsonValue &other); |
56 | |
57 | QJsonValue(QJsonValue &&other) noexcept; |
58 | |
59 | QJsonValue &operator =(QJsonValue &&other) noexcept |
60 | { |
61 | swap(other); |
62 | return *this; |
63 | } |
64 | |
65 | void swap(QJsonValue &other) noexcept; |
66 | |
67 | static QJsonValue fromVariant(const QVariant &variant); |
68 | QVariant toVariant() const; |
69 | |
70 | Type type() const; |
71 | inline bool isNull() const { return type() == Null; } |
72 | inline bool isBool() const { return type() == Bool; } |
73 | inline bool isDouble() const { return type() == Double; } |
74 | inline bool isString() const { return type() == String; } |
75 | inline bool isArray() const { return type() == Array; } |
76 | inline bool isObject() const { return type() == Object; } |
77 | inline bool isUndefined() const { return type() == Undefined; } |
78 | |
79 | bool toBool(bool defaultValue = false) const; |
80 | int toInt(int defaultValue = 0) const; |
81 | qint64 toInteger(qint64 defaultValue = 0) const; |
82 | double toDouble(double defaultValue = 0) const; |
83 | QString toString() const; |
84 | QString toString(const QString &defaultValue) const; |
85 | QJsonArray toArray() const; |
86 | QJsonArray toArray(const QJsonArray &defaultValue) const; |
87 | QJsonObject toObject() const; |
88 | QJsonObject toObject(const QJsonObject &defaultValue) const; |
89 | |
90 | const QJsonValue operator[](const QString &key) const; |
91 | const QJsonValue operator[](QStringView key) const; |
92 | const QJsonValue operator[](QLatin1StringView key) const; |
93 | const QJsonValue operator[](qsizetype i) const; |
94 | |
95 | bool operator==(const QJsonValue &other) const; |
96 | bool operator!=(const QJsonValue &other) const; |
97 | |
98 | private: |
99 | // avoid implicit conversions from char * to bool |
100 | QJsonValue(const void *) = delete; |
101 | friend class QJsonPrivate::Value; |
102 | friend class QJsonArray; |
103 | friend class QJsonObject; |
104 | friend class QCborValue; |
105 | friend Q_CORE_EXPORT__attribute__((visibility("default"))) QDebug operator<<(QDebug, const QJsonValue &); |
106 | friend Q_CORE_EXPORT__attribute__((visibility("default"))) QDataStream &operator<<(QDataStream &, const QJsonValue &); |
107 | |
108 | QCborValue value; |
109 | |
110 | // Assert binary compatibility with pre-5.15 QJsonValue |
111 | static_assert(sizeof(QExplicitlySharedDataPointer<QCborContainerPrivate>) == sizeof(void *)); |
112 | static_assert(sizeof(QCborValue::Type) == sizeof(QJsonValue::Type)); |
113 | }; |
114 | |
115 | Q_DECLARE_SHARED(QJsonValue)template<> class QTypeInfo<QJsonValue > { public: enum { isComplex = (((Q_RELOCATABLE_TYPE) & Q_PRIMITIVE_TYPE ) == 0) && !std::is_trivial_v<QJsonValue>, isRelocatable = !isComplex || ((Q_RELOCATABLE_TYPE) & Q_RELOCATABLE_TYPE ) || qIsRelocatable<QJsonValue>, isPointer = false, isIntegral = std::is_integral< QJsonValue >::value, }; }; inline void swap(QJsonValue &value1, QJsonValue &value2) noexcept (noexcept(value1.swap(value2))) { value1.swap(value2); } |
116 | |
117 | class QJsonValueConstRef |
118 | { |
119 | public: |
120 | QJsonValueConstRef(const QJsonValueConstRef &) = default; |
121 | QJsonValueConstRef &operator=(const QJsonValueConstRef &) = delete; |
122 | inline operator QJsonValue() const { return concrete(*this); } |
123 | |
124 | Q_CORE_EXPORT__attribute__((visibility("default"))) QVariant toVariant() const; |
125 | QJsonValue::Type type() const { return concreteType(*this); } |
126 | bool isNull() const { return type() == QJsonValue::Null; } |
127 | bool isBool() const { return type() == QJsonValue::Bool; } |
128 | bool isDouble() const { return type() == QJsonValue::Double; } |
129 | bool isString() const { return type() == QJsonValue::String; } |
130 | bool isArray() const { return type() == QJsonValue::Array; } |
131 | bool isObject() const { return type() == QJsonValue::Object; } |
132 | bool isUndefined() const { return type() == QJsonValue::Undefined; } |
133 | |
134 | bool toBool(bool defaultValue = false) const |
135 | { return concreteBool(*this, defaultValue); } |
136 | int toInt(int defaultValue = 0) const |
137 | { return concreteInt(*this, defaultValue, true); } |
138 | qint64 toInteger(qint64 defaultValue = 0) const |
139 | { return concreteInt(*this, defaultValue, false); } |
140 | double toDouble(double defaultValue = 0) const |
141 | { return concreteDouble(*this, defaultValue); } |
142 | QString toString(const QString &defaultValue = {}) const |
143 | { return concreteString(*this, defaultValue); } |
144 | Q_CORE_EXPORT__attribute__((visibility("default"))) QJsonArray toArray() const; |
145 | Q_CORE_EXPORT__attribute__((visibility("default"))) QJsonObject toObject() const; |
146 | |
147 | const QJsonValue operator[](QStringView key) const { return concrete(*this)[key]; } |
148 | const QJsonValue operator[](QLatin1StringView key) const { return concrete(*this)[key]; } |
149 | const QJsonValue operator[](qsizetype i) const { return concrete(*this)[i]; } |
150 | |
151 | inline bool operator==(const QJsonValue &other) const { return concrete(*this) == other; } |
152 | inline bool operator!=(const QJsonValue &other) const { return concrete(*this) != other; } |
153 | |
154 | protected: |
155 | Q_CORE_EXPORT__attribute__((visibility("default"))) static QJsonValue::Type |
156 | concreteType(QJsonValueConstRef self) noexcept Q_DECL_PURE_FUNCTION__attribute__((pure)); |
157 | Q_CORE_EXPORT__attribute__((visibility("default"))) static bool |
158 | concreteBool(QJsonValueConstRef self, bool defaultValue) noexcept Q_DECL_PURE_FUNCTION__attribute__((pure)); |
159 | Q_CORE_EXPORT__attribute__((visibility("default"))) static qint64 |
160 | concreteInt(QJsonValueConstRef self, qint64 defaultValue, bool clamp) noexcept Q_DECL_PURE_FUNCTION__attribute__((pure)); |
161 | Q_CORE_EXPORT__attribute__((visibility("default"))) static double |
162 | concreteDouble(QJsonValueConstRef self, double defaultValue) noexcept Q_DECL_PURE_FUNCTION__attribute__((pure)); |
163 | Q_CORE_EXPORT__attribute__((visibility("default"))) static QString concreteString(QJsonValueConstRef self, const QString &defaultValue); |
164 | Q_CORE_EXPORT__attribute__((visibility("default"))) static QJsonValue concrete(QJsonValueConstRef self) noexcept; |
165 | |
166 | // for iterators |
167 | Q_CORE_EXPORT__attribute__((visibility("default"))) static QString objectKey(QJsonValueConstRef self); |
168 | QString objectKey() const { return objectKey(*this); } |
169 | |
170 | #if QT_VERSION((6<<16)|(4<<8)|(2)) < QT_VERSION_CHECK(7, 0, 0)((7<<16)|(0<<8)|(0)) && !defined(QT_BOOTSTRAPPED) |
171 | QJsonValueConstRef(QJsonArray *array, qsizetype idx) |
172 | : a(array), is_object(false), index(static_cast<quint64>(idx)) {} |
173 | QJsonValueConstRef(QJsonObject *object, qsizetype idx) |
174 | : o(object), is_object(true), index(static_cast<quint64>(idx)) {} |
175 | |
176 | void rebind(QJsonValueConstRef other) |
177 | { |
178 | Q_ASSERT(is_object == other.is_object)((is_object == other.is_object) ? static_cast<void>(0) : qt_assert("is_object == other.is_object", "/usr/include/x86_64-linux-gnu/qt6/QtCore/qjsonvalue.h" , 178)); |
179 | if (is_object) |
180 | o = other.o; |
181 | else |
182 | a = other.a; |
183 | index = other.index; |
184 | } |
185 | |
186 | union { |
187 | QJsonArray *a; |
188 | QJsonObject *o; |
189 | void *d; |
190 | }; |
191 | quint64 is_object : 1; |
192 | quint64 index : 63; |
193 | #else |
194 | constexpr QJsonValueConstRef(QCborContainerPrivate *d, size_t index, bool is_object) |
195 | : d(d), is_object(is_object), index(index) |
196 | {} |
197 | |
198 | // implemented in qjsonarray.h & qjsonobject.h, to get their d |
199 | QJsonValueConstRef(QJsonArray *array, qsizetype idx); |
200 | QJsonValueConstRef(QJsonObject *object, qsizetype idx); |
201 | |
202 | void rebind(QJsonValueConstRef other) |
203 | { |
204 | d = other.d; |
205 | index = other.index; |
206 | } |
207 | |
208 | QCborContainerPrivate *d = nullptr; |
209 | size_t is_object : 1; |
210 | size_t index : std::numeric_limits<size_t>::digits - 1; |
211 | #endif |
212 | |
213 | friend class QJsonArray; |
214 | friend class QJsonObject; |
215 | friend class QJsonPrivate::Value; |
216 | }; |
217 | |
218 | class QT6_ONLY(Q_CORE_EXPORT)__attribute__((visibility("default"))) QJsonValueRef : public QJsonValueConstRef |
219 | { |
220 | public: |
221 | QJsonValueRef(const QJsonValueRef &) = default; |
222 | QT7_ONLY(Q_CORE_EXPORT) QJsonValueRef &operator = (const QJsonValue &val); |
223 | QT7_ONLY(Q_CORE_EXPORT) QJsonValueRef &operator = (const QJsonValueRef &val); |
224 | |
225 | #if QT_VERSION((6<<16)|(4<<8)|(2)) < QT_VERSION_CHECK(7, 0, 0)((7<<16)|(0<<8)|(0)) && !defined(QT_BOOTSTRAPPED) |
226 | // retained for binary compatibility (due to the Q_CORE_EXPORT) because at |
227 | // least one compiler emits and exports all inlines in an exported class |
228 | |
229 | QJsonValueRef(QJsonArray *array, qsizetype idx) |
230 | : QJsonValueConstRef(array, idx) {} |
231 | QJsonValueRef(QJsonObject *object, qsizetype idx) |
232 | : QJsonValueConstRef(object, idx) {} |
233 | |
234 | operator QJsonValue() const { return toValue(); } |
235 | |
236 | QVariant toVariant() const; |
237 | inline QJsonValue::Type type() const { return QJsonValueConstRef::type(); } |
238 | inline bool isNull() const { return type() == QJsonValue::Null; } |
239 | inline bool isBool() const { return type() == QJsonValue::Bool; } |
240 | inline bool isDouble() const { return type() == QJsonValue::Double; } |
241 | inline bool isString() const { return type() == QJsonValue::String; } |
242 | inline bool isArray() const { return type() == QJsonValue::Array; } |
243 | inline bool isObject() const { return type() == QJsonValue::Object; } |
244 | inline bool isUndefined() const { return type() == QJsonValue::Undefined; } |
245 | |
246 | inline bool toBool(bool defaultValue = false) const { return QJsonValueConstRef::toBool(defaultValue); } |
247 | inline int toInt(int defaultValue = 0) const { return QJsonValueConstRef::toInt(defaultValue); } |
248 | inline qint64 toInteger(qint64 defaultValue = 0) const { return QJsonValueConstRef::toInteger(defaultValue); } |
249 | inline double toDouble(double defaultValue = 0) const { return QJsonValueConstRef::toDouble(defaultValue); } |
250 | inline QString toString(const QString &defaultValue = {}) const { return QJsonValueConstRef::toString(defaultValue); } |
251 | QJsonArray toArray() const; |
252 | QJsonObject toObject() const; |
253 | |
254 | const QJsonValue operator[](QStringView key) const { return QJsonValueConstRef::operator[](key); } |
255 | const QJsonValue operator[](QLatin1StringView key) const { return QJsonValueConstRef::operator[](key); } |
256 | const QJsonValue operator[](qsizetype i) const { return QJsonValueConstRef::operator[](i); } |
257 | |
258 | inline bool operator==(const QJsonValue &other) const { return QJsonValueConstRef::operator==(other); } |
259 | inline bool operator!=(const QJsonValue &other) const { return QJsonValueConstRef::operator!=(other); } |
260 | |
261 | private: |
262 | QJsonValue toValue() const; |
263 | #else |
264 | using QJsonValueConstRef::operator[]; |
265 | Q_CORE_EXPORT__attribute__((visibility("default"))) QJsonValueRef operator[](QAnyStringView key); |
266 | Q_CORE_EXPORT__attribute__((visibility("default"))) QJsonValueRef operator[](qsizetype i); |
267 | |
268 | private: |
269 | using QJsonValueConstRef::QJsonValueConstRef; |
270 | #endif // < Qt 7 |
271 | |
272 | QT7_ONLY(Q_CORE_EXPORT) void detach(); |
273 | friend class QJsonArray; |
274 | friend class QJsonObject; |
275 | }; |
276 | |
277 | inline QJsonValue QCborValueConstRef::toJsonValue() const |
278 | { |
279 | return concrete().toJsonValue(); |
280 | } |
281 | |
282 | inline bool operator==(const QJsonValueConstRef &lhs, const QJsonValueRef &rhs) |
283 | { return QJsonValue(lhs) == QJsonValue(rhs); } |
284 | inline bool operator!=(const QJsonValueConstRef &lhs, const QJsonValueRef &rhs) |
285 | { return !(lhs == rhs); } |
286 | |
287 | inline bool operator==(const QJsonValueRef &lhs, const QJsonValueConstRef &rhs) |
288 | { return QJsonValue(lhs) == QJsonValue(rhs); } |
289 | inline bool operator!=(const QJsonValueRef &lhs, const QJsonValueConstRef &rhs) |
290 | { return !(lhs == rhs); } |
291 | |
292 | inline bool operator==(const QJsonValueRef &lhs, const QJsonValueRef &rhs) |
293 | { return QJsonValue(lhs) == QJsonValue(rhs); } |
294 | inline bool operator!=(const QJsonValueRef &lhs, const QJsonValueRef &rhs) |
295 | { return !(lhs == rhs); } |
296 | |
297 | Q_CORE_EXPORT__attribute__((visibility("default"))) size_t qHash(const QJsonValue &value, size_t seed = 0); |
298 | |
299 | #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) |
300 | Q_CORE_EXPORT__attribute__((visibility("default"))) QDebug operator<<(QDebug, const QJsonValue &); |
301 | #endif |
302 | |
303 | #ifndef QT_NO_DATASTREAM |
304 | Q_CORE_EXPORT__attribute__((visibility("default"))) QDataStream &operator<<(QDataStream &, const QJsonValue &); |
305 | Q_CORE_EXPORT__attribute__((visibility("default"))) QDataStream &operator>>(QDataStream &, QJsonValue &); |
306 | #endif |
307 | |
308 | QT_END_NAMESPACE |
309 | |
310 | #endif // QJSONVALUE_H |