QGIS API Documentation 3.43.0-Master (a93bf8b6462)
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#include "qgslogger.h"
19
20#include <QDate>
21#include <QTime>
22#include <QDateTime>
23#include <QBitArray>
24#include <QRect>
25#include <QLine>
26#include <QUuid>
27#include <QImage>
28#include <QPixmap>
29#include <QBrush>
30#include <QColor>
31#include <QBitmap>
32#include <QIcon>
33#include <QVector2D>
34#include <QVector3D>
35#include <QVector4D>
36#include <QQuaternion>
37
38QString QgsVariantUtils::typeToDisplayString( QMetaType::Type type, QMetaType::Type subType )
39{
40 switch ( type )
41 {
42 case QMetaType::Type::UnknownType:
43 break;
44 case QMetaType::Type::Bool:
45 return QObject::tr( "Boolean" );
46 case QMetaType::Type::Int:
47 return QObject::tr( "Integer (32 bit)" );
48 case QMetaType::Type::UInt:
49 return QObject::tr( "Integer (unsigned 32 bit)" );
50 case QMetaType::Type::LongLong:
51 return QObject::tr( "Integer (64 bit)" );
52 case QMetaType::Type::ULongLong:
53 return QObject::tr( "Integer (unsigned 64 bit)" );
54 case QMetaType::Type::Double:
55 return QObject::tr( "Decimal (double)" );
56 case QMetaType::Type::QChar:
57 return QObject::tr( "Character" );
58 case QMetaType::Type::QVariantMap:
59 return QObject::tr( "Map" );
60 case QMetaType::Type::QVariantList:
61 {
62 switch ( subType )
63 {
64 case QMetaType::Type::Int:
65 return QObject::tr( "Integer List" );
66 case QMetaType::Type::LongLong:
67 return QObject::tr( "Integer (64 bit) List" );
68 case QMetaType::Type::Double:
69 return QObject::tr( "Decimal (double) List" );
70 default:
71 return QObject::tr( "List" );
72 }
73 }
74 case QMetaType::Type::QString:
75 return QObject::tr( "Text (string)" );
76 case QMetaType::Type::QStringList:
77 return QObject::tr( "String List" );
78 case QMetaType::Type::QByteArray:
79 return QObject::tr( "Binary Object (BLOB)" );
80 case QMetaType::Type::QBitArray:
81 return QObject::tr( "Bit Array" );
82 case QMetaType::Type::QDate:
83 return QObject::tr( "Date" );
84 case QMetaType::Type::QTime:
85 return QObject::tr( "Time" );
86 case QMetaType::Type::QDateTime:
87 return QObject::tr( "Date & Time" );
88 case QMetaType::Type::QUrl:
89 return QObject::tr( "URL" );
90 case QMetaType::Type::QLocale:
91 return QObject::tr( "Locale" );
92 case QMetaType::Type::QRect:
93 case QMetaType::Type::QRectF:
94 return QObject::tr( "Rectangle" );
95 case QMetaType::Type::QSize:
96 case QMetaType::Type::QSizeF:
97 return QObject::tr( "Size" );
98 case QMetaType::Type::QLine:
99 case QMetaType::Type::QLineF:
100 return QObject::tr( "Line" );
101 case QMetaType::Type::QPoint:
102 case QMetaType::Type::QPointF:
103 return QObject::tr( "Point" );
104 case QMetaType::Type::QRegularExpression:
105 return QObject::tr( "Regular Expression" );
106 case QMetaType::Type::QVariantHash:
107 return QObject::tr( "Hash" );
108 case QMetaType::Type::QEasingCurve:
109 return QObject::tr( "Easing Curve" );
110 case QMetaType::Type::QUuid:
111 return QObject::tr( "UUID" );
112 case QMetaType::Type::QModelIndex:
113 case QMetaType::Type::QPersistentModelIndex:
114 return QObject::tr( "Model Index" );
115 case QMetaType::Type::QFont:
116 return QObject::tr( "Font" );
117 case QMetaType::Type::QPixmap:
118 return QObject::tr( "Pixmap" );
119 case QMetaType::Type::QBrush:
120 return QObject::tr( "Brush" );
121 case QMetaType::Type::QColor:
122 return QObject::tr( "Color" );
123 case QMetaType::Type::QPalette:
124 return QObject::tr( "Palette" );
125 case QMetaType::Type::QImage:
126 return QObject::tr( "Image" );
127 case QMetaType::Type::QPolygon:
128 case QMetaType::Type::QPolygonF:
129 return QObject::tr( "Polygon" );
130 case QMetaType::Type::QRegion:
131 return QObject::tr( "Region" );
132 case QMetaType::Type::QBitmap:
133 return QObject::tr( "Bitmap" );
134 case QMetaType::Type::QCursor:
135 return QObject::tr( "Cursor" );
136 case QMetaType::Type::QKeySequence:
137 return QObject::tr( "Key Sequence" );
138 case QMetaType::Type::QPen:
139 return QObject::tr( "Pen" );
140 case QMetaType::Type::QTextLength:
141 return QObject::tr( "Text Length" );
142 case QMetaType::Type::QTextFormat:
143 return QObject::tr( "Text Format" );
144 case QMetaType::Type::QMatrix4x4:
145 return QObject::tr( "Matrix" );
146 case QMetaType::Type::QTransform:
147 return QObject::tr( "Transform" );
148 case QMetaType::Type::QVector2D:
149 case QMetaType::Type::QVector3D:
150 case QMetaType::Type::QVector4D:
151 return QObject::tr( "Vector" );
152 case QMetaType::Type::QQuaternion:
153 return QObject::tr( "Quaternion" );
154 case QMetaType::Type::QIcon:
155 return QObject::tr( "Icon" );
156 case QMetaType::Type::QSizePolicy:
157 return QObject::tr( "Size Policy" );
158
159 default:
160 break;
161 }
162 return QString();
163}
164
165QString QgsVariantUtils::typeToDisplayString( QVariant::Type type, QVariant::Type subType )
166{
168}
169
170bool QgsVariantUtils::isNull( const QVariant &variant, bool silenceNullWarnings )
171{
172#ifndef QGISDEBUG
173 ( void )silenceNullWarnings;
174#endif
175
176 if ( variant.isNull() || !variant.isValid() )
177 return true;
178
179 switch ( variant.userType() )
180 {
181 case QMetaType::Type::UnknownType:
182 case QMetaType::Type::Bool:
183 case QMetaType::Type::Int:
184 case QMetaType::Type::UInt:
185 case QMetaType::Type::LongLong:
186 case QMetaType::Type::ULongLong:
187 case QMetaType::Type::Double:
188 case QMetaType::Type::QVariantMap:
189 case QMetaType::Type::QVariantList:
190 case QMetaType::Type::QStringList:
191 case QMetaType::Type::QUrl:
192 case QMetaType::Type::QLocale:
193 case QMetaType::Type::QRegularExpression:
194 case QMetaType::Type::QVariantHash:
195 case QMetaType::Type::QEasingCurve:
196 case QMetaType::Type::QModelIndex:
197 case QMetaType::Type::QPersistentModelIndex:
198
199 return false;
200
201 case QMetaType::Type::QDate:
202 if ( variant.toDate().isNull() )
203 {
204 if ( !silenceNullWarnings )
205 {
206 QgsDebugError( QStringLiteral( "NULL QDateTime was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
207 }
208 return true;
209 }
210 return false;
211 case QMetaType::Type::QTime:
212 if ( variant.toTime().isNull() )
213 {
214 if ( !silenceNullWarnings )
215 {
216 QgsDebugError( QStringLiteral( "NULL QTime was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
217 }
218 return true;
219 }
220 return false;
221 case QMetaType::Type::QDateTime:
222 if ( variant.toDate().isNull() )
223 {
224 if ( !silenceNullWarnings )
225 {
226 QgsDebugError( QStringLiteral( "NULL QDate was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
227 }
228 return true;
229 }
230 return false;
231 case QMetaType::Type::QChar:
232 if ( variant.toChar().isNull() )
233 {
234 if ( !silenceNullWarnings )
235 {
236 QgsDebugError( QStringLiteral( "NULL QChar was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
237 }
238 return true;
239 }
240 return false;
241 case QMetaType::Type::QString:
242 if ( variant.toString().isNull() )
243 {
244 if ( !silenceNullWarnings )
245 {
246 QgsDebugError( QStringLiteral( "NULL QString was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
247 }
248 return true;
249 }
250 return false;
251 case QMetaType::Type::QByteArray:
252 if ( variant.toByteArray().isNull() )
253 {
254 if ( !silenceNullWarnings )
255 {
256 QgsDebugError( QStringLiteral( "NULL QByteArray was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
257 }
258 return true;
259 }
260 return false;
261 case QMetaType::Type::QBitArray:
262 if ( variant.toBitArray().isNull() )
263 {
264 if ( !silenceNullWarnings )
265 {
266 QgsDebugError( QStringLiteral( "NULL QBitArray was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
267 }
268 return true;
269 }
270 return false;
271 case QMetaType::Type::QRect:
272 if ( variant.toRect().isNull() )
273 {
274 if ( !silenceNullWarnings )
275 {
276 QgsDebugError( QStringLiteral( "NULL QRect was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
277 }
278 return true;
279 }
280 return false;
281 case QMetaType::Type::QRectF:
282 if ( variant.toRectF().isNull() )
283 {
284 if ( !silenceNullWarnings )
285 {
286 QgsDebugError( QStringLiteral( "NULL QRectF was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
287 }
288 return true;
289 }
290 return false;
291 case QMetaType::Type::QSize:
292 if ( variant.toSize().isNull() )
293 {
294 if ( !silenceNullWarnings )
295 {
296 QgsDebugError( QStringLiteral( "NULL QSize was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
297 }
298 return true;
299 }
300 return false;
301 case QMetaType::Type::QSizeF:
302 if ( variant.toSizeF().isNull() )
303 {
304 if ( !silenceNullWarnings )
305 {
306 QgsDebugError( QStringLiteral( "NULL QSizeF was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
307 }
308 return true;
309 }
310 return false;
311 case QMetaType::Type::QLine:
312 if ( variant.toLine().isNull() )
313 {
314 if ( !silenceNullWarnings )
315 {
316 QgsDebugError( QStringLiteral( "NULL QLine was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
317 }
318 return true;
319 }
320 return false;
321 case QMetaType::Type::QLineF:
322 if ( variant.toLineF().isNull() )
323 {
324 if ( !silenceNullWarnings )
325 {
326 QgsDebugError( QStringLiteral( "NULL QLineF was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
327 }
328 return true;
329 }
330 return false;
331 case QMetaType::Type::QPoint:
332 if ( variant.toPoint().isNull() )
333 {
334 if ( !silenceNullWarnings )
335 {
336 QgsDebugError( QStringLiteral( "NULL QPoint was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
337 }
338 return true;
339 }
340 return false;
341 case QMetaType::Type::QPointF:
342 if ( variant.toPointF().isNull() )
343 {
344 if ( !silenceNullWarnings )
345 {
346 QgsDebugError( QStringLiteral( "NULL QPointF was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
347 }
348 return true;
349 }
350 return false;
351 case QMetaType::Type::QUuid:
352 if ( variant.toUuid().isNull() )
353 {
354 if ( !silenceNullWarnings )
355 {
356 QgsDebugError( QStringLiteral( "NULL QUuid was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
357 }
358 return true;
359 }
360 return false;
361 case QMetaType::Type::QPixmap:
362 if ( variant.value< QPixmap >().isNull() )
363 {
364 if ( !silenceNullWarnings )
365 {
366 QgsDebugError( QStringLiteral( "NULL QPixmap was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
367 }
368 return true;
369 }
370 return false;
371 case QMetaType::Type::QImage:
372 if ( variant.value< QImage >().isNull() )
373 {
374 if ( !silenceNullWarnings )
375 {
376 QgsDebugError( QStringLiteral( "NULL QImage was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
377 }
378 return true;
379 }
380 return false;
381 case QMetaType::Type::QRegion:
382 if ( variant.value< QRegion >().isNull() )
383 {
384 if ( !silenceNullWarnings )
385 {
386 QgsDebugError( QStringLiteral( "NULL QRegion was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
387 }
388 return true;
389 }
390 return false;
391 case QMetaType::Type::QBitmap:
392 if ( variant.value< QBitmap >().isNull() )
393 {
394 if ( !silenceNullWarnings )
395 {
396 QgsDebugError( QStringLiteral( "NULL QBitmap was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
397 }
398 return true;
399 }
400 return false;
401 case QMetaType::Type::QIcon:
402 if ( variant.value< QIcon >().isNull() )
403 {
404 if ( !silenceNullWarnings )
405 {
406 QgsDebugError( QStringLiteral( "NULL QIcon was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
407 }
408 return true;
409 }
410 return false;
411 case QMetaType::Type::QVector2D:
412 if ( variant.value< QVector2D >().isNull() )
413 {
414 if ( !silenceNullWarnings )
415 {
416 QgsDebugError( QStringLiteral( "NULL QVector2D was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
417 }
418 return true;
419 }
420 return false;
421 case QMetaType::Type::QVector3D:
422 if ( variant.value< QVector3D >().isNull() )
423 {
424 if ( !silenceNullWarnings )
425 {
426 QgsDebugError( QStringLiteral( "NULL QVector3D was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
427 }
428 return true;
429 }
430 return false;
431 case QMetaType::Type::QVector4D:
432 if ( variant.value< QVector4D >().isNull() )
433 {
434 if ( !silenceNullWarnings )
435 {
436 QgsDebugError( QStringLiteral( "NULL QVector4D was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
437 }
438 return true;
439 }
440 return false;
441 case QMetaType::Type::QQuaternion:
442 if ( variant.value< QQuaternion >().isNull() )
443 {
444 if ( !silenceNullWarnings )
445 {
446 QgsDebugError( QStringLiteral( "NULL QQuaternion was stored in a QVariant -- stop it! Always use an invalid QVariant() instead." ) );
447 }
448 return true;
449 }
450 return false;
451
452 case QMetaType::Type::QColor:
453 case QMetaType::Type::QFont:
454 case QMetaType::Type::QBrush:
455 case QMetaType::Type::QPolygon:
456 case QMetaType::Type::QPalette:
457 case QMetaType::Type::QCursor:
458 case QMetaType::Type::QKeySequence:
459 case QMetaType::Type::QPen:
460 case QMetaType::Type::QTextLength:
461 case QMetaType::Type::QPolygonF:
462 case QMetaType::Type::QTextFormat:
463 case QMetaType::Type::QTransform:
464 case QMetaType::Type::QMatrix4x4:
465 case QMetaType::Type::QSizePolicy:
466 case QMetaType::Type::User:
467 default:
468 break;
469 }
470
471 return false;
472}
473
474bool QgsVariantUtils::isNumericType( QMetaType::Type metaType )
475{
476 switch ( metaType )
477 {
478 case QMetaType::Type::Int:
479 case QMetaType::Type::UInt:
480 case QMetaType::Type::LongLong:
481 case QMetaType::Type::ULongLong:
482 case QMetaType::Type::Double:
483 case QMetaType::Type::Float:
484 case QMetaType::Type::Short:
485 case QMetaType::Type::UShort:
486 case QMetaType::Type::Char:
487 case QMetaType::Type::UChar:
488 case QMetaType::Type::SChar:
489 return true;
490 default:
491 return false;
492 }
493}
494
495QMetaType::Type QgsVariantUtils::variantTypeToMetaType( QVariant::Type variantType )
496{
497 // variant types can be directly mapped to meta types
498 return static_cast< QMetaType::Type >( variantType );
499}
500
501QVariant::Type QgsVariantUtils::metaTypeToVariantType( QMetaType::Type metaType )
502{
503 // NOLINTBEGIN(bugprone-branch-clone)
504 switch ( metaType )
505 {
506 // exact mapping, these are identical:
507 case QMetaType::Bool:
508 case QMetaType::Int:
509 case QMetaType::UInt:
510 case QMetaType::LongLong:
511 case QMetaType::ULongLong:
512 case QMetaType::Double:
513 case QMetaType::QChar:
514 case QMetaType::QVariantMap:
515 case QMetaType::QVariantList:
516 case QMetaType::QString:
517 case QMetaType::QStringList:
518 case QMetaType::QByteArray:
519 case QMetaType::QBitArray:
520 case QMetaType::QDate:
521 case QMetaType::QTime:
522 case QMetaType::QDateTime:
523 case QMetaType::QUrl:
524 case QMetaType::QLocale:
525 case QMetaType::QRect:
526 case QMetaType::QRectF:
527 case QMetaType::QSize:
528 case QMetaType::QSizeF:
529 case QMetaType::QLine:
530 case QMetaType::QLineF:
531 case QMetaType::QPoint:
532 case QMetaType::QPointF:
533 case QMetaType::QRegularExpression:
534 case QMetaType::QVariantHash:
535 case QMetaType::QEasingCurve:
536 case QMetaType::QUuid:
537 case QMetaType::QModelIndex:
538 case QMetaType::QPersistentModelIndex:
539 case QMetaType::QFont:
540 case QMetaType::QPixmap:
541 case QMetaType::QBrush:
542 case QMetaType::QColor:
543 case QMetaType::QPalette:
544 case QMetaType::QImage:
545 case QMetaType::QPolygon:
546 case QMetaType::QRegion:
547 case QMetaType::QBitmap:
548 case QMetaType::QCursor:
549 case QMetaType::QKeySequence:
550 case QMetaType::QPen:
551 case QMetaType::QTextLength:
552 case QMetaType::QTextFormat:
553 case QMetaType::QTransform:
554 case QMetaType::QMatrix4x4:
555 case QMetaType::QVector2D:
556 case QMetaType::QVector3D:
557 case QMetaType::QVector4D:
558 case QMetaType::QQuaternion:
559 case QMetaType::QPolygonF:
560 case QMetaType::QIcon:
561 case QMetaType::QSizePolicy:
562 case QMetaType::UnknownType:
563 case QMetaType::User:
564 return static_cast< QVariant::Type >( metaType );
565
566 // lossy, not exact mappings. We prefer to "expand" types
567 // to avoid truncation
568 case QMetaType::Long:
569 return QVariant::Type::LongLong;
570
571 case QMetaType::ULong:
572 return QVariant::Type::ULongLong;
573
574 case QMetaType::Char:
575#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
576 case QMetaType::Char16:
577 case QMetaType::Char32:
578#endif
579 case QMetaType::Short:
580 case QMetaType::SChar:
581 return QVariant::Type::Int;
582
583 case QMetaType::UShort:
584 case QMetaType::UChar:
585 return QVariant::Type::UInt;
586
587 case QMetaType::Float:
588#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
589 case QMetaType::Float16:
590#endif
591 return QVariant::Type::Double;
592
593 // no mapping possible:
594 case QMetaType::Nullptr:
595 case QMetaType::QCborSimpleType:
596 case QMetaType::Void:
597 case QMetaType::VoidStar:
598 case QMetaType::QVariant:
599 case QMetaType::QJsonValue:
600 case QMetaType::QJsonObject:
601 case QMetaType::QJsonArray:
602 case QMetaType::QJsonDocument:
603 case QMetaType::QCborValue:
604 case QMetaType::QCborArray:
605 case QMetaType::QCborMap:
606 case QMetaType::QObjectStar:
607#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
608 case QMetaType::QVariantPair:
609#endif
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#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
629 return QVariant( QgsVariantUtils::metaTypeToVariantType( metaType ) );
630#else
631 return QVariant( QMetaType( metaType ) );
632#endif
633
634}
static QMetaType::Type variantTypeToMetaType(QVariant::Type variantType)
Converts a QVariant::Type to a QMetaType::Type.
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.
#define QgsDebugError(str)
Definition qgslogger.h:40