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