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