QGIS API Documentation 4.1.0-Master (3b8ef1f72a3)
Loading...
Searching...
No Matches
qgsvariantutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsvariantutils.h
3 ------------------
4 Date : January 2022
5 Copyright : (C) 2022 Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsvariantutils.h"
17
18#include "qgsapplication.h"
19#include "qgslogger.h"
20#include "qgsstringutils.h"
22
23#include <QBitArray>
24#include <QBitmap>
25#include <QBrush>
26#include <QColor>
27#include <QDate>
28#include <QDateTime>
29#include <QIcon>
30#include <QImage>
31#include <QLine>
32#include <QPixmap>
33#include <QQuaternion>
34#include <QRect>
35#include <QString>
36#include <QTime>
37#include <QUuid>
38#include <QVector2D>
39#include <QVector3D>
40#include <QVector4D>
41
42using namespace Qt::StringLiterals;
43
44QString QgsVariantUtils::typeToDisplayString( QMetaType::Type type, QMetaType::Type subType )
45{
46 switch ( type )
47 {
48 case QMetaType::Type::UnknownType:
49 break;
50 case QMetaType::Type::Bool:
51 return QObject::tr( "Boolean" );
52 case QMetaType::Type::Int:
53 return QObject::tr( "Integer (32 bit)" );
54 case QMetaType::Type::UInt:
55 return QObject::tr( "Integer (unsigned 32 bit)" );
56 case QMetaType::Type::LongLong:
57 return QObject::tr( "Integer (64 bit)" );
58 case QMetaType::Type::ULongLong:
59 return QObject::tr( "Integer (unsigned 64 bit)" );
60 case QMetaType::Type::Double:
61 return QObject::tr( "Decimal (double)" );
62 case QMetaType::Type::QChar:
63 return QObject::tr( "Character" );
64 case QMetaType::Type::QVariantMap:
65 return QObject::tr( "Map" );
66 case QMetaType::Type::QVariantList:
67 {
68 switch ( subType )
69 {
70 case QMetaType::Type::Int:
71 return QObject::tr( "Integer List" );
72 case QMetaType::Type::LongLong:
73 return QObject::tr( "Integer (64 bit) List" );
74 case QMetaType::Type::Double:
75 return QObject::tr( "Decimal (double) List" );
76 default:
77 return QObject::tr( "List" );
78 }
79 }
80 case QMetaType::Type::QString:
81 return QObject::tr( "Text (string)" );
82 case QMetaType::Type::QStringList:
83 return QObject::tr( "String List" );
84 case QMetaType::Type::QByteArray:
85 return QObject::tr( "Binary Object (BLOB)" );
86 case QMetaType::Type::QBitArray:
87 return QObject::tr( "Bit Array" );
88 case QMetaType::Type::QDate:
89 return QObject::tr( "Date" );
90 case QMetaType::Type::QTime:
91 return QObject::tr( "Time" );
92 case QMetaType::Type::QDateTime:
93 return QObject::tr( "Date & Time" );
94 case QMetaType::Type::QUrl:
95 return QObject::tr( "URL" );
96 case QMetaType::Type::QLocale:
97 return QObject::tr( "Locale" );
98 case QMetaType::Type::QRect:
99 case QMetaType::Type::QRectF:
100 return QObject::tr( "Rectangle" );
101 case QMetaType::Type::QSize:
102 case QMetaType::Type::QSizeF:
103 return QObject::tr( "Size" );
104 case QMetaType::Type::QLine:
105 case QMetaType::Type::QLineF:
106 return QObject::tr( "Line" );
107 case QMetaType::Type::QPoint:
108 case QMetaType::Type::QPointF:
109 return QObject::tr( "Point" );
110 case QMetaType::Type::QRegularExpression:
111 return QObject::tr( "Regular Expression" );
112 case QMetaType::Type::QVariantHash:
113 return QObject::tr( "Hash" );
114 case QMetaType::Type::QEasingCurve:
115 return QObject::tr( "Easing Curve" );
116 case QMetaType::Type::QUuid:
117 return QObject::tr( "UUID" );
118 case QMetaType::Type::QModelIndex:
119 case QMetaType::Type::QPersistentModelIndex:
120 return QObject::tr( "Model Index" );
121 case QMetaType::Type::QFont:
122 return QObject::tr( "Font" );
123 case QMetaType::Type::QPixmap:
124 return QObject::tr( "Pixmap" );
125 case QMetaType::Type::QBrush:
126 return QObject::tr( "Brush" );
127 case QMetaType::Type::QColor:
128 return QObject::tr( "Color" );
129 case QMetaType::Type::QPalette:
130 return QObject::tr( "Palette" );
131 case QMetaType::Type::QImage:
132 return QObject::tr( "Image" );
133 case QMetaType::Type::QPolygon:
134 case QMetaType::Type::QPolygonF:
135 return QObject::tr( "Polygon" );
136 case QMetaType::Type::QRegion:
137 return QObject::tr( "Region" );
138 case QMetaType::Type::QBitmap:
139 return QObject::tr( "Bitmap" );
140 case QMetaType::Type::QCursor:
141 return QObject::tr( "Cursor" );
142 case QMetaType::Type::QKeySequence:
143 return QObject::tr( "Key Sequence" );
144 case QMetaType::Type::QPen:
145 return QObject::tr( "Pen" );
146 case QMetaType::Type::QTextLength:
147 return QObject::tr( "Text Length" );
148 case QMetaType::Type::QTextFormat:
149 return QObject::tr( "Text Format" );
150 case QMetaType::Type::QMatrix4x4:
151 return QObject::tr( "Matrix" );
152 case QMetaType::Type::QTransform:
153 return QObject::tr( "Transform" );
154 case QMetaType::Type::QVector2D:
155 case QMetaType::Type::QVector3D:
156 case QMetaType::Type::QVector4D:
157 return QObject::tr( "Vector" );
158 case QMetaType::Type::QQuaternion:
159 return QObject::tr( "Quaternion" );
160 case QMetaType::Type::QIcon:
161 return QObject::tr( "Icon" );
162 case QMetaType::Type::QSizePolicy:
163 return QObject::tr( "Size Policy" );
164
165 default:
166 break;
167 }
168 return QString();
169}
170
171QString QgsVariantUtils::typeToDisplayString( QVariant::Type type, QVariant::Type subType )
172{
174}
175
176bool QgsVariantUtils::isNull( const QVariant &variant, bool silenceNullWarnings )
177{
178#ifndef QGISDEBUG
179 ( void ) silenceNullWarnings;
180#endif
181
182 if ( variant.isNull() || !variant.isValid() )
183 return true;
184
185 switch ( variant.userType() )
186 {
187 case QMetaType::Type::UnknownType:
188 case QMetaType::Type::Bool:
189 case QMetaType::Type::Int:
190 case QMetaType::Type::UInt:
191 case QMetaType::Type::LongLong:
192 case QMetaType::Type::ULongLong:
193 case QMetaType::Type::Double:
194 case QMetaType::Type::QVariantMap:
195 case QMetaType::Type::QVariantList:
196 case QMetaType::Type::QStringList:
197 case QMetaType::Type::QUrl:
198 case QMetaType::Type::QLocale:
199 case QMetaType::Type::QRegularExpression:
200 case QMetaType::Type::QVariantHash:
201 case QMetaType::Type::QEasingCurve:
202 case QMetaType::Type::QModelIndex:
203 case QMetaType::Type::QPersistentModelIndex:
204
205 return false;
206
207 case QMetaType::Type::QDate:
208 if ( variant.toDate().isNull() )
209 {
210 if ( !silenceNullWarnings )
211 {
212 QgsDebugError( u"NULL QDateTime was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
213 }
214 return true;
215 }
216 return false;
217 case QMetaType::Type::QTime:
218 if ( variant.toTime().isNull() )
219 {
220 if ( !silenceNullWarnings )
221 {
222 QgsDebugError( u"NULL QTime was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
223 }
224 return true;
225 }
226 return false;
227 case QMetaType::Type::QDateTime:
228 if ( variant.toDate().isNull() )
229 {
230 if ( !silenceNullWarnings )
231 {
232 QgsDebugError( u"NULL QDate was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
233 }
234 return true;
235 }
236 return false;
237 case QMetaType::Type::QChar:
238 if ( variant.toChar().isNull() )
239 {
240 if ( !silenceNullWarnings )
241 {
242 QgsDebugError( u"NULL QChar was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
243 }
244 return true;
245 }
246 return false;
247 case QMetaType::Type::QString:
248 if ( variant.toString().isNull() )
249 {
250 if ( !silenceNullWarnings )
251 {
252 QgsDebugError( u"NULL QString was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
253 }
254 return true;
255 }
256 return false;
257 case QMetaType::Type::QByteArray:
258 if ( variant.toByteArray().isNull() )
259 {
260 if ( !silenceNullWarnings )
261 {
262 QgsDebugError( u"NULL QByteArray was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
263 }
264 return true;
265 }
266 return false;
267 case QMetaType::Type::QBitArray:
268 if ( variant.toBitArray().isNull() )
269 {
270 if ( !silenceNullWarnings )
271 {
272 QgsDebugError( u"NULL QBitArray was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
273 }
274 return true;
275 }
276 return false;
277 case QMetaType::Type::QRect:
278 if ( variant.toRect().isNull() )
279 {
280 if ( !silenceNullWarnings )
281 {
282 QgsDebugError( u"NULL QRect was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
283 }
284 return true;
285 }
286 return false;
287 case QMetaType::Type::QRectF:
288 if ( variant.toRectF().isNull() )
289 {
290 if ( !silenceNullWarnings )
291 {
292 QgsDebugError( u"NULL QRectF was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
293 }
294 return true;
295 }
296 return false;
297 case QMetaType::Type::QSize:
298 if ( variant.toSize().isNull() )
299 {
300 if ( !silenceNullWarnings )
301 {
302 QgsDebugError( u"NULL QSize was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
303 }
304 return true;
305 }
306 return false;
307 case QMetaType::Type::QSizeF:
308 if ( variant.toSizeF().isNull() )
309 {
310 if ( !silenceNullWarnings )
311 {
312 QgsDebugError( u"NULL QSizeF was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
313 }
314 return true;
315 }
316 return false;
317 case QMetaType::Type::QLine:
318 if ( variant.toLine().isNull() )
319 {
320 if ( !silenceNullWarnings )
321 {
322 QgsDebugError( u"NULL QLine was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
323 }
324 return true;
325 }
326 return false;
327 case QMetaType::Type::QLineF:
328 if ( variant.toLineF().isNull() )
329 {
330 if ( !silenceNullWarnings )
331 {
332 QgsDebugError( u"NULL QLineF was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
333 }
334 return true;
335 }
336 return false;
337 case QMetaType::Type::QPoint:
338 if ( variant.toPoint().isNull() )
339 {
340 if ( !silenceNullWarnings )
341 {
342 QgsDebugError( u"NULL QPoint was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
343 }
344 return true;
345 }
346 return false;
347 case QMetaType::Type::QPointF:
348 if ( variant.toPointF().isNull() )
349 {
350 if ( !silenceNullWarnings )
351 {
352 QgsDebugError( u"NULL QPointF was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
353 }
354 return true;
355 }
356 return false;
357 case QMetaType::Type::QUuid:
358 if ( variant.toUuid().isNull() )
359 {
360 if ( !silenceNullWarnings )
361 {
362 QgsDebugError( u"NULL QUuid was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
363 }
364 return true;
365 }
366 return false;
367 case QMetaType::Type::QPixmap:
368 if ( variant.value< QPixmap >().isNull() )
369 {
370 if ( !silenceNullWarnings )
371 {
372 QgsDebugError( u"NULL QPixmap was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
373 }
374 return true;
375 }
376 return false;
377 case QMetaType::Type::QImage:
378 if ( variant.value< QImage >().isNull() )
379 {
380 if ( !silenceNullWarnings )
381 {
382 QgsDebugError( u"NULL QImage was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
383 }
384 return true;
385 }
386 return false;
387 case QMetaType::Type::QRegion:
388 if ( variant.value< QRegion >().isNull() )
389 {
390 if ( !silenceNullWarnings )
391 {
392 QgsDebugError( u"NULL QRegion was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
393 }
394 return true;
395 }
396 return false;
397 case QMetaType::Type::QBitmap:
398 if ( variant.value< QBitmap >().isNull() )
399 {
400 if ( !silenceNullWarnings )
401 {
402 QgsDebugError( u"NULL QBitmap was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
403 }
404 return true;
405 }
406 return false;
407 case QMetaType::Type::QIcon:
408 if ( variant.value< QIcon >().isNull() )
409 {
410 if ( !silenceNullWarnings )
411 {
412 QgsDebugError( u"NULL QIcon was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
413 }
414 return true;
415 }
416 return false;
417 case QMetaType::Type::QVector2D:
418 if ( variant.value< QVector2D >().isNull() )
419 {
420 if ( !silenceNullWarnings )
421 {
422 QgsDebugError( u"NULL QVector2D was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
423 }
424 return true;
425 }
426 return false;
427 case QMetaType::Type::QVector3D:
428 if ( variant.value< QVector3D >().isNull() )
429 {
430 if ( !silenceNullWarnings )
431 {
432 QgsDebugError( u"NULL QVector3D was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
433 }
434 return true;
435 }
436 return false;
437 case QMetaType::Type::QVector4D:
438 if ( variant.value< QVector4D >().isNull() )
439 {
440 if ( !silenceNullWarnings )
441 {
442 QgsDebugError( u"NULL QVector4D was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
443 }
444 return true;
445 }
446 return false;
447 case QMetaType::Type::QQuaternion:
448 if ( variant.value< QQuaternion >().isNull() )
449 {
450 if ( !silenceNullWarnings )
451 {
452 QgsDebugError( u"NULL QQuaternion was stored in a QVariant -- stop it! Always use an invalid QVariant() instead."_s );
453 }
454 return true;
455 }
456 return false;
457
458 case QMetaType::Type::QColor:
459 case QMetaType::Type::QFont:
460 case QMetaType::Type::QBrush:
461 case QMetaType::Type::QPolygon:
462 case QMetaType::Type::QPalette:
463 case QMetaType::Type::QCursor:
464 case QMetaType::Type::QKeySequence:
465 case QMetaType::Type::QPen:
466 case QMetaType::Type::QTextLength:
467 case QMetaType::Type::QPolygonF:
468 case QMetaType::Type::QTextFormat:
469 case QMetaType::Type::QTransform:
470 case QMetaType::Type::QMatrix4x4:
471 case QMetaType::Type::QSizePolicy:
472 case QMetaType::Type::User:
473 default:
474 break;
475 }
476
477 return false;
478}
479
480bool QgsVariantUtils::isNumericType( QMetaType::Type metaType )
481{
482 switch ( metaType )
483 {
484 case QMetaType::Type::Int:
485 case QMetaType::Type::UInt:
486 case QMetaType::Type::LongLong:
487 case QMetaType::Type::ULongLong:
488 case QMetaType::Type::Double:
489 case QMetaType::Type::Float:
490 case QMetaType::Type::Short:
491 case QMetaType::Type::UShort:
492 case QMetaType::Type::Char:
493 case QMetaType::Type::UChar:
494 case QMetaType::Type::SChar:
495 return true;
496 default:
497 return false;
498 }
499}
500
501QMetaType::Type QgsVariantUtils::variantTypeToMetaType( QVariant::Type variantType )
502{
503 // variant types can be directly mapped to meta types
504 return static_cast< QMetaType::Type >( variantType );
505}
506
507QVariant::Type QgsVariantUtils::metaTypeToVariantType( QMetaType::Type metaType )
508{
509 // NOLINTBEGIN(bugprone-branch-clone)
510 switch ( metaType )
511 {
512 // exact mapping, these are identical:
513 case QMetaType::Bool:
514 case QMetaType::Int:
515 case QMetaType::UInt:
516 case QMetaType::LongLong:
517 case QMetaType::ULongLong:
518 case QMetaType::Double:
519 case QMetaType::QChar:
520 case QMetaType::QVariantMap:
521 case QMetaType::QVariantList:
522 case QMetaType::QString:
523 case QMetaType::QStringList:
524 case QMetaType::QByteArray:
525 case QMetaType::QBitArray:
526 case QMetaType::QDate:
527 case QMetaType::QTime:
528 case QMetaType::QDateTime:
529 case QMetaType::QUrl:
530 case QMetaType::QLocale:
531 case QMetaType::QRect:
532 case QMetaType::QRectF:
533 case QMetaType::QSize:
534 case QMetaType::QSizeF:
535 case QMetaType::QLine:
536 case QMetaType::QLineF:
537 case QMetaType::QPoint:
538 case QMetaType::QPointF:
539 case QMetaType::QRegularExpression:
540 case QMetaType::QVariantHash:
541 case QMetaType::QEasingCurve:
542 case QMetaType::QUuid:
543 case QMetaType::QModelIndex:
544 case QMetaType::QPersistentModelIndex:
545 case QMetaType::QFont:
546 case QMetaType::QPixmap:
547 case QMetaType::QBrush:
548 case QMetaType::QColor:
549 case QMetaType::QPalette:
550 case QMetaType::QImage:
551 case QMetaType::QPolygon:
552 case QMetaType::QRegion:
553 case QMetaType::QBitmap:
554 case QMetaType::QCursor:
555 case QMetaType::QKeySequence:
556 case QMetaType::QPen:
557 case QMetaType::QTextLength:
558 case QMetaType::QTextFormat:
559 case QMetaType::QTransform:
560 case QMetaType::QMatrix4x4:
561 case QMetaType::QVector2D:
562 case QMetaType::QVector3D:
563 case QMetaType::QVector4D:
564 case QMetaType::QQuaternion:
565 case QMetaType::QPolygonF:
566 case QMetaType::QIcon:
567 case QMetaType::QSizePolicy:
568 case QMetaType::UnknownType:
569 case QMetaType::User:
570 return static_cast< QVariant::Type >( metaType );
571
572 // lossy, not exact mappings. We prefer to "expand" types
573 // to avoid truncation
574 case QMetaType::Long:
575 return QVariant::Type::LongLong;
576
577 case QMetaType::ULong:
578 return QVariant::Type::ULongLong;
579
580 case QMetaType::Char:
581 case QMetaType::Char16:
582 case QMetaType::Char32:
583 case QMetaType::Short:
584 case QMetaType::SChar:
585 return QVariant::Type::Int;
586
587 case QMetaType::UShort:
588 case QMetaType::UChar:
589 return QVariant::Type::UInt;
590
591 case QMetaType::Float:
592 case QMetaType::Float16:
593 return QVariant::Type::Double;
594
595 // no mapping possible:
596 case QMetaType::Nullptr:
597 case QMetaType::QCborSimpleType:
598 case QMetaType::Void:
599 case QMetaType::VoidStar:
600 case QMetaType::QVariant:
601 case QMetaType::QJsonValue:
602 case QMetaType::QJsonObject:
603 case QMetaType::QJsonArray:
604 case QMetaType::QJsonDocument:
605 case QMetaType::QCborValue:
606 case QMetaType::QCborArray:
607 case QMetaType::QCborMap:
608 case QMetaType::QObjectStar:
609 case QMetaType::QVariantPair:
610 case QMetaType::QByteArrayList:
611 case QMetaType::QColorSpace:
612 break;
613
614 default:
615 break;
616 }
617 // NOLINTEND(bugprone-branch-clone)
618 return QVariant::Type::UserType;
619}
620
621bool QgsVariantUtils::isUnsetAttributeValue( const QVariant &variant )
622{
623 return variant.userType() == qMetaTypeId< QgsUnsetAttributeValue >();
624}
625
626QVariant QgsVariantUtils::createNullVariant( QMetaType::Type metaType )
627{
628 return QVariant( QMetaType( metaType ) );
629}
630
631QString QgsVariantUtils::displayString( const QVariant &variant, int precision )
632{
633 auto _displayString = []( const QVariant &variant, int precision ) -> QString {
634 if ( QgsVariantUtils::isNull( variant ) )
635 {
637 }
638
639 // Special treatment for numeric types if group separator is set or decimalPoint is not a dot
640 if ( variant.userType() == QMetaType::Type::Double )
641 {
642 // Locales with decimal point != '.' or that require group separator: use QLocale
643 if ( QLocale().decimalPoint() != '.' || !( QLocale().numberOptions() & QLocale::NumberOption::OmitGroupSeparator ) )
644 {
645 if ( precision > 0 )
646 {
647 if ( -1 < variant.toDouble() && variant.toDouble() < 1 )
648 {
649 return QLocale().toString( variant.toDouble(), 'g', precision );
650 }
651 else
652 {
653 return QLocale().toString( variant.toDouble(), 'f', precision );
654 }
655 }
656 else
657 {
658 // Precision is not set, let's guess it from the
659 // standard conversion to string
660 const QString str( variant.toString() );
661 const int dotPosition( static_cast<int>( str.indexOf( '.' ) ) );
662 int precision;
663 if ( dotPosition < 0 && str.indexOf( 'e', 0, Qt::CaseInsensitive ) < 0 )
664 {
665 precision = 0;
666 return QLocale().toString( variant.toDouble(), 'f', precision );
667 }
668 else
669 {
670 if ( dotPosition < 0 )
671 precision = 0;
672 else
673 precision = static_cast<int>( str.length() ) - dotPosition - 1;
674
675 if ( -1 < variant.toDouble() && variant.toDouble() < 1 )
676 {
677 return QLocale().toString( variant.toDouble(), 'g', precision );
678 }
679 else
680 {
681 return QLocale().toString( variant.toDouble(), 'f', precision );
682 }
683 }
684 }
685 }
686 // Default for doubles with precision
687 else if ( precision > 0 )
688 {
689 if ( -1 < variant.toDouble() && variant.toDouble() < 1 )
690 {
691 return QString::number( variant.toDouble(), 'g', precision );
692 }
693 else
694 {
695 return QString::number( variant.toDouble(), 'f', precision );
696 }
697 }
698 }
699 // Other numeric types than doubles
700 else if ( QgsVariantUtils::isNumericType( static_cast< QMetaType::Type >( variant.userType() ) ) && !( QLocale().numberOptions() & QLocale::NumberOption::OmitGroupSeparator ) )
701 {
702 bool ok;
703 const qlonglong converted( variant.toLongLong( &ok ) );
704 if ( ok )
705 return QLocale().toString( converted );
706 }
707 else if ( variant.userType() == QMetaType::Type::QByteArray )
708 {
709 return QObject::tr( "BLOB" );
710 }
711
712 // Fallback if special rules do not apply
713 return variant.toString();
714 };
715
716 if ( variant.userType() == QMetaType::Type::QStringList || variant.userType() == QMetaType::Type::QVariantList )
717 {
718 QString result;
719 const QVariantList list = variant.toList();
720 for ( const QVariant &var : list )
721 {
722 if ( !result.isEmpty() )
723 {
724 result.append( ';' );
725 }
726 result.append( _displayString( var, precision ) );
727 }
728 return result;
729 }
730 else
731 {
732 return _displayString( variant, precision );
733 }
734}
735
736QString QgsVariantUtils::variantToHtml( const QVariantMap &variantMap, const QString &title = QString() )
737{
738 QString result;
739 if ( !title.isEmpty() )
740 {
741 result += u"<tr><td class=\"highlight\">%1</td><td></td></tr>"_s.arg( title );
742 }
743 for ( auto it = variantMap.constBegin(); it != variantMap.constEnd(); ++it )
744 {
745 if ( ( it.value().type() == QVariant::List || it.value().type() == QVariant::StringList ) )
746 {
747 const QVariantList childList = it.value().toList();
748 result += u"<tr><td class=\"highlight\">%1</td><td><ul>"_s.arg( it.key() );
749 for ( const QVariant &v : childList )
750 {
751 if ( v.type() == QVariant::Map )
752 {
753 const QVariantMap grandChildMap = v.toMap();
754 result += u"<li><table>%1</table></li>"_s.arg( variantToHtml( grandChildMap ) );
755 }
756 else
757 {
758 result += u"<li>%1</li>"_s.arg( QgsStringUtils::insertLinks( v.toString() ) );
759 }
760 }
761 result += "</ul></td></tr>"_L1;
762 }
763 else if ( it.value().type() == QVariant::Map )
764 {
765 const QVariantMap childMap = it.value().toMap();
766 result += u"<tr><td class=\"highlight\">%1</td><td><table>%2</table></td></tr>"_s.arg( it.key(), variantToHtml( childMap ) );
767 }
768 else
769 {
770 result += u"<tr><td class=\"highlight\">%1</td><td>%2</td></tr>"_s.arg( it.key(), QgsStringUtils::insertLinks( it.value().toString() ) );
771 }
772 }
773 return result;
774}
static QString nullRepresentation()
Returns the string used to represent the value NULL throughout QGIS.
static QString insertLinks(const QString &string, bool *foundLinks=nullptr)
Returns a string with any URL (e.g., http(s)/ftp) and mailto: text converted to valid HTML <a ....
static QMetaType::Type variantTypeToMetaType(QVariant::Type variantType)
Converts a QVariant::Type to a QMetaType::Type.
static QString displayString(const QVariant &variant, int precision=-1)
Returns a localized representation of value with the given precision, if precision is -1 then precisi...
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static QString typeToDisplayString(QMetaType::Type type, QMetaType::Type subType=QMetaType::Type::UnknownType)
Returns a user-friendly translated string representing a QVariant type.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
static bool isNumericType(QMetaType::Type metaType)
Returns true if the specified metaType is a numeric type.
static bool isUnsetAttributeValue(const QVariant &variant)
Check if the variant is a QgsUnsetAttributeValue.
static QVariant::Type metaTypeToVariantType(QMetaType::Type metaType)
Converts a QMetaType::Type to a QVariant::Type.
static QString variantToHtml(const QVariantMap &variant, const QString &title)
Exports a variant map to a HTML formatted representation.
#define QgsDebugError(str)
Definition qgslogger.h:59