1 /* 2 * DQt - D bindings for the Qt Toolkit 3 * 4 * GNU Lesser General Public License Usage 5 * This file may be used under the terms of the GNU Lesser 6 * General Public License version 3 as published by the Free Software 7 * Foundation and appearing in the file LICENSE.LGPL3 included in the 8 * packaging of this file. Please review the following information to 9 * ensure the GNU Lesser General Public License version 3 requirements 10 * will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 11 */ 12 module qt.core.variant; 13 extern(C++): 14 15 import qt.config; 16 import qt.core.abstractitemmodel; 17 import qt.core.atomic; 18 import qt.core.bitarray; 19 import qt.core.bytearray; 20 import qt.core.compare; 21 import qt.core.datetime; 22 import qt.core.easingcurve; 23 import qt.core.global; 24 import qt.core.hash; 25 import qt.core.list; 26 import qt.core.locale; 27 import qt.core.map; 28 import qt.core.metatype; 29 import qt.core.namespace; 30 import qt.core.qchar; 31 import qt.core.regularexpression; 32 import qt.core.string; 33 import qt.core.stringlist; 34 import qt.core.typeinfo; 35 import qt.core.url; 36 import qt.core.uuid; 37 import qt.helpers; 38 version(QT_NO_DATASTREAM){}else 39 import qt.core.datastream; 40 version(QT_NO_GEOM_VARIANT){}else 41 { 42 import qt.core.line; 43 import qt.core.point; 44 import qt.core.rect; 45 import qt.core.size; 46 } 47 48 /+ #ifndef QT_NO_DEBUG_STREAM 49 #endif 50 #ifndef QT_BOOTSTRAPPED 51 #endif 52 #if __has_include(<variant>) && __cplusplus >= 201703L 53 #elif defined(Q_CLANG_QDOC) 54 namespace std { template<typename...> struct variant; } 55 #endif 56 57 58 59 #if QT_CONFIG(easingcurve) 60 class QEasingCurve; 61 #endif 62 #if QT_CONFIG(regularexpression) 63 class QRegularExpression; 64 #endif +/ // QT_CONFIG(regularexpression) 65 66 /// Binding for C++ class [QVariant](https://doc.qt.io/qt-6/qvariant.html). 67 @Q_RELOCATABLE_TYPE extern(C++, class) struct /+ Q_CORE_EXPORT +/ QVariant 68 { 69 public: 70 /+ #if QT_DEPRECATED_SINCE(6, 0) +/ 71 enum /+ QT_DEPRECATED_VERSION_X_6_0("Use QMetaType::Type instead.") +/ Type 72 { 73 Invalid = QMetaType.Type.UnknownType, 74 Bool = QMetaType.Type.Bool, 75 Int = QMetaType.Type.Int, 76 UInt = QMetaType.Type.UInt, 77 LongLong = QMetaType.Type.LongLong, 78 ULongLong = QMetaType.Type.ULongLong, 79 Double = QMetaType.Type.Double, 80 Char = QMetaType.Type.QChar, 81 Map = QMetaType.Type.QVariantMap, 82 List = QMetaType.Type.QVariantList, 83 String = QMetaType.Type.QString, 84 StringList = QMetaType.Type.QStringList, 85 ByteArray = QMetaType.Type.QByteArray, 86 BitArray = QMetaType.Type.QBitArray, 87 Date = QMetaType.Type.QDate, 88 Time = QMetaType.Type.QTime, 89 DateTime = QMetaType.Type.QDateTime, 90 Url = QMetaType.Type.QUrl, 91 Locale = QMetaType.Type.QLocale, 92 Rect = QMetaType.Type.QRect, 93 RectF = QMetaType.Type.QRectF, 94 Size = QMetaType.Type.QSize, 95 SizeF = QMetaType.Type.QSizeF, 96 Line = QMetaType.Type.QLine, 97 LineF = QMetaType.Type.QLineF, 98 Point = QMetaType.Type.QPoint, 99 PointF = QMetaType.Type.QPointF, 100 /+ #if QT_CONFIG(regularexpression) +/ 101 RegularExpression = QMetaType.Type.QRegularExpression, 102 /+ #endif +/ 103 Hash = QMetaType.Type.QVariantHash, 104 /+ #if QT_CONFIG(easingcurve) +/ 105 EasingCurve = QMetaType.Type.QEasingCurve, 106 /+ #endif +/ 107 Uuid = QMetaType.Type.QUuid, 108 /+ #if QT_CONFIG(itemmodel) +/ 109 ModelIndex = QMetaType.Type.QModelIndex, 110 PersistentModelIndex = QMetaType.Type.QPersistentModelIndex, 111 /+ #endif +/ 112 LastCoreType = QMetaType.Type.LastCoreType, 113 114 Font = QMetaType.Type.QFont, 115 Pixmap = QMetaType.Type.QPixmap, 116 Brush = QMetaType.Type.QBrush, 117 Color = QMetaType.Type.QColor, 118 Palette = QMetaType.Type.QPalette, 119 Image = QMetaType.Type.QImage, 120 Polygon = QMetaType.Type.QPolygon, 121 Region = QMetaType.Type.QRegion, 122 Bitmap = QMetaType.Type.QBitmap, 123 Cursor = QMetaType.Type.QCursor, 124 /+ #if QT_CONFIG(shortcut) +/ 125 KeySequence = QMetaType.Type.QKeySequence, 126 /+ #endif +/ 127 Pen = QMetaType.Type.QPen, 128 TextLength = QMetaType.Type.QTextLength, 129 TextFormat = QMetaType.Type.QTextFormat, 130 Transform = QMetaType.Type.QTransform, 131 Matrix4x4 = QMetaType.Type.QMatrix4x4, 132 Vector2D = QMetaType.Type.QVector2D, 133 Vector3D = QMetaType.Type.QVector3D, 134 Vector4D = QMetaType.Type.QVector4D, 135 Quaternion = QMetaType.Type.QQuaternion, 136 PolygonF = QMetaType.Type.QPolygonF, 137 Icon = QMetaType.Type.QIcon, 138 LastGuiType = QMetaType.Type.LastGuiType, 139 140 SizePolicy = QMetaType.Type.QSizePolicy, 141 142 UserType = QMetaType.Type.User, 143 // LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type 144 } 145 /+ #endif +/ 146 /+this()/+ noexcept+/ 147 { 148 this.d = typeof(this.d)(); 149 }+/ 150 ~this(); 151 /+ explicit +/this(QMetaType type, const(void)* copy = null); 152 @disable this(this); 153 this(ref const(QVariant) other); 154 155 this(int i); 156 this(uint ui); 157 this(qlonglong ll); 158 this(qulonglong ull); 159 this(bool b); 160 this(double d); 161 this(float f); 162 /+ #ifndef QT_NO_CAST_FROM_ASCII 163 QT_ASCII_CAST_WARN QVariant(const char *str) 164 : QVariant(QString::fromUtf8(str)) 165 {} 166 #endif +/ 167 168 this(ref const(QByteArray) bytearray); 169 this(ref const(QBitArray) bitarray); 170 this(ref const(QString) string); 171 this(QLatin1String string); 172 this(ref const(QStringList) stringlist); 173 this(QChar qchar); 174 this(QDate date); 175 this(QTime time); 176 this(ref const(QDateTime) datetime); 177 this(ref const(QList!(QVariant)) list); 178 // this(ref const(QMap!(QString, QVariant)) map); 179 // this(ref const(QHash!(QString, QVariant)) hash); 180 version(QT_NO_GEOM_VARIANT){}else 181 { 182 this(ref const(QSize) size); 183 this(ref const(QSizeF) size); 184 this(ref const(QPoint) pt); 185 this(ref const(QPointF) pt); 186 this(ref const(QLine) line); 187 this(ref const(QLineF) line); 188 this(ref const(QRect) rect); 189 this(ref const(QRectF) rect); 190 } 191 this(ref const(QLocale) locale); 192 /+ #if QT_CONFIG(regularexpression) +/ 193 this(ref const(QRegularExpression) re); 194 /+ #endif // QT_CONFIG(regularexpression) 195 #if QT_CONFIG(easingcurve) +/ 196 this(ref const(QEasingCurve) easing); 197 /+ #endif +/ 198 this(ref const(QUuid) uuid); 199 /+ #ifndef QT_BOOTSTRAPPED +/ 200 this(ref const(QUrl) url); 201 // this(ref const(QJsonValue) jsonValue); 202 // this(ref const(QJsonObject) jsonObject); 203 // this(ref const(QJsonArray) jsonArray); 204 // this(ref const(QJsonDocument) jsonDocument); 205 /+ #endif // QT_BOOTSTRAPPED 206 #if QT_CONFIG(itemmodel) +/ 207 this(ref const(QModelIndex) modelIndex); 208 this(ref const(QPersistentModelIndex) modelIndex); 209 /+ #endif +/ 210 211 /+ref QVariant operator =(ref const(QVariant) other);+/ 212 /+ inline QVariant(QVariant &&other) noexcept : d(other.d) 213 { other.d = Private(); } +/ 214 /+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QVariant) +/ 215 216 /+ inline void swap(QVariant &other) noexcept { qSwap(d, other.d); } +/ 217 218 int userType() const { return typeId(); } 219 int typeId() const { return metaType().id(); } 220 221 const(char)* typeName() const; 222 QMetaType metaType() const; 223 224 bool canConvert(QMetaType targetType) const 225 { return QMetaType.canConvert(d.type(), targetType); } 226 bool convert(QMetaType type); 227 228 bool canView(QMetaType targetType) const 229 { return QMetaType.canView(d.type(), targetType); } 230 231 /+ #if QT_DEPRECATED_SINCE(6, 0) +/ 232 /+ QT_DEPRECATED_VERSION_6_0 +/ 233 bool canConvert(int targetTypeId) const 234 { return QMetaType.canConvert(d.type(), QMetaType(targetTypeId)); } 235 /+ QT_DEPRECATED_VERSION_6_0 +/ 236 bool convert(int targetTypeId) 237 { return convert(QMetaType(targetTypeId)); } 238 /+ #endif +/ 239 240 pragma(inline, true) bool isValid() const 241 { 242 return d.type().isValid(); 243 } 244 bool isNull() const; 245 246 void clear(); 247 248 void detach(); 249 pragma(inline, true) bool isDetached() const 250 { return !d.is_shared || d.data.shared_.ref_.loadRelaxed() == 1; } 251 252 int toInt(bool* ok = null) const; 253 uint toUInt(bool* ok = null) const; 254 qlonglong toLongLong(bool* ok = null) const; 255 qulonglong toULongLong(bool* ok = null) const; 256 bool toBool() const; 257 double toDouble(bool* ok = null) const; 258 float toFloat(bool* ok = null) const; 259 qreal toReal(bool* ok = null) const; 260 QByteArray toByteArray() const; 261 QBitArray toBitArray() const; 262 QString toString() const; 263 QStringList toStringList() const; 264 QChar toChar() const; 265 QDate toDate() const; 266 QTime toTime() const; 267 QDateTime toDateTime() const; 268 QList!(QVariant) toList() const; 269 // QMap!(QString, QVariant) toMap() const; 270 // QHash!(QString, QVariant) toHash() const; 271 272 version(QT_NO_GEOM_VARIANT){}else 273 { 274 QPoint toPoint() const; 275 QPointF toPointF() const; 276 QRect toRect() const; 277 QSize toSize() const; 278 QSizeF toSizeF() const; 279 QLine toLine() const; 280 QLineF toLineF() const; 281 QRectF toRectF() const; 282 } 283 QLocale toLocale() const; 284 /+ #if QT_CONFIG(regularexpression) +/ 285 QRegularExpression toRegularExpression() const; 286 /+ #endif // QT_CONFIG(regularexpression) 287 #if QT_CONFIG(easingcurve) +/ 288 QEasingCurve toEasingCurve() const; 289 /+ #endif +/ 290 QUuid toUuid() const; 291 /+ #ifndef QT_BOOTSTRAPPED +/ 292 QUrl toUrl() const; 293 /+ QJsonValue toJsonValue() const; +/ 294 /+ QJsonObject toJsonObject() const; +/ 295 /+ QJsonArray toJsonArray() const; +/ 296 /+ QJsonDocument toJsonDocument() const; +/ 297 /+ #endif // QT_BOOTSTRAPPED 298 #if QT_CONFIG(itemmodel) +/ 299 QModelIndex toModelIndex() const; 300 QPersistentModelIndex toPersistentModelIndex() const; 301 /+ #endif 302 303 #ifndef QT_NO_DATASTREAM +/ 304 version(QT_NO_DATASTREAM){}else 305 { 306 void load(ref QDataStream ds); 307 void save(ref QDataStream ds) const; 308 } 309 /+ #endif 310 #if QT_DEPRECATED_SINCE(6, 0) 311 QT_WARNING_PUSH 312 QT_WARNING_DISABLE_DEPRECATED +/ 313 /+ QT_DEPRECATED_VERSION_X_6_0("Use the constructor taking a QMetaType instead.") +/ 314 /+ explicit +/this(Type type) 315 { 316 this(QMetaType(int(type))); 317 } 318 /+ QT_DEPRECATED_VERSION_X_6_0("Use typeId() or metaType().") +/ 319 Type type() const 320 { 321 int type = d.typeId(); 322 return type >= QMetaType.Type.User ? Type.UserType : static_cast!(Type)(type); 323 } 324 /+ QT_DEPRECATED_VERSION_6_0 +/ 325 static const(char)* typeToName(int typeId) 326 { return QMetaType(typeId).name(); } 327 /+ QT_DEPRECATED_VERSION_6_0 +/ 328 static Type nameToType(const(char)* name) 329 { 330 import qt.core.bytearrayview; 331 332 int metaType = QMetaType.fromName(cast(QByteArrayView)(name)).id(); 333 return metaType <= int(Type.UserType) ? cast(QVariant.Type)(metaType) : Type.UserType; 334 } 335 /+ QT_WARNING_POP 336 #endif +/ 337 338 void* data(); 339 const(void)* constData() const 340 { return d.storage(); } 341 pragma(inline, true) const(void)* data() const { return constData(); } 342 343 /+ template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>> +/ 344 /+ void setValue(T &&avalue) 345 { 346 using VT = std::decay_t<T>; 347 QMetaType metaType = QMetaType::fromType<VT>(); 348 // If possible we reuse the current QVariant private. 349 if (isDetached() && d.type() == metaType) { 350 *reinterpret_cast<VT *>(const_cast<void *>(constData())) = std::forward<T>(avalue); 351 } else { 352 *this = QVariant::fromValue<VT>(std::forward<T>(avalue)); 353 } 354 } +/ 355 356 void setValue(ref const(QVariant) avalue) 357 { 358 this = avalue; 359 } 360 361 /+ void setValue(QVariant &&avalue) 362 { 363 *this = std::move(avalue); 364 } +/ 365 366 pragma(inline, true) T value(T)() const 367 { return qvariant_cast!(T)(this); } 368 369 /+ template<typename T> +/ 370 /+ pragma(inline, true) T view(T)() 371 { 372 T t T(); 373 QMetaType.view(metaType(), data(), QMetaType.fromType!(T)(), &t); 374 return t; 375 } +/ 376 377 /+ template<typename T> 378 #ifndef Q_CLANG_QDOC +/ 379 pragma(inline, true) static QVariant fromValue(T)(ref const T value)/+ -> 380 std::enable_if_t<std::is_copy_constructible_v<T>, QVariant> +/ 381 /+ #else 382 static inline QVariant fromValue(const T &value) 383 #endif +/ 384 { 385 return QVariant(QMetaType.fromType!(T)(), &value); 386 } 387 388 /+ #if (__has_include(<variant>) && __cplusplus >= 201703L) || defined(Q_CLANG_QDOC) +/ 389 /+ template<typename... Types> +/ 390 /+ static inline QVariant fromStdVariant(const std::variant<Types...> &value) 391 { 392 if (value.valueless_by_exception()) 393 return QVariant(); 394 return std::visit([](const auto &arg) { return fromValue(arg); }, value); 395 } +/ 396 /+ #endif +/ 397 398 /+ template<typename T> +/ 399 bool canConvert(T)() const 400 { return canConvert(QMetaType.fromType!(T)()); } 401 402 /+ template<typename T> +/ 403 bool canView(T)() const 404 { return canView(QMetaType.fromType!(T)()); } 405 406 public: 407 struct PrivateShared 408 { 409 private: 410 @disable this(); 411 /+pragma(inline, true) this() 412 { 413 this.ref_ = 1; 414 }+/ 415 public: 416 /+ static PrivateShared *create(const QtPrivate::QMetaTypeInterface *type) 417 { 418 Q_ASSERT(type); 419 size_t size = type->size; 420 size_t align = type->alignment; 421 422 size += sizeof(PrivateShared); 423 if (align > sizeof(PrivateShared)) { 424 // The alignment is larger than the alignment we can guarantee for the pointer 425 // directly following PrivateShared, so we need to allocate some additional 426 // memory to be able to fit the object into the available memory with suitable 427 // alignment. 428 size += align - sizeof(PrivateShared); 429 } 430 void *data = operator new(size); 431 auto *ps = new (data) QVariant::PrivateShared(); 432 ps->offset = int(((quintptr(ps) + sizeof(PrivateShared) + align - 1) & ~(align - 1)) - quintptr(ps)); 433 return ps; 434 } +/ 435 static void free(PrivateShared* p) 436 { 437 destroy!false(p); 438 // operator delete(p); 439 } 440 441 /+ alignas(8) +/ QAtomicInt ref_ = QAtomicInt(1); 442 int offset; 443 444 const(void)* data() const 445 { return reinterpret_cast!(const(ubyte)*)(&this) + offset; } 446 void* data() 447 { return reinterpret_cast!(ubyte*)(&this) + offset; } 448 } 449 struct Private 450 { 451 extern(D) static immutable size_t MaxInternalSize = 3*(void*).sizeof; 452 /+ template<typename T> +/ 453 /+ static constexpr bool CanUseInternalSpace = (QTypeInfo<T>::isRelocatable && sizeof(T) <= MaxInternalSize && alignof(T) <= alignof(double)); +/ 454 static bool canUseInternalSpace(/+ QtPrivate:: +/qt.core.metatype.QMetaTypeInterface* type) 455 { 456 import qt.core.flags; 457 458 (mixin(Q_ASSERT(q{type}))); 459 return QMetaType.TypeFlags(cast(QFlag)(type.flags)) & QMetaType.TypeFlag.RelocatableType && 460 size_t(type.size) <= MaxInternalSize && size_t(type.alignment) <= double.alignof; 461 } 462 463 union generated_qvariant_0 464 { 465 uchar[MaxInternalSize] data = [0]; 466 PrivateShared* shared_; 467 double _forAlignment; // we want an 8byte alignment on 32bit systems as well 468 }generated_qvariant_0 data; 469 quintptr bitfield = 1 << 1; 470 /+ quintptr is_shared : 1; +/ 471 final quintptr is_shared() const 472 { 473 return (bitfield >> 0) & 0x1; 474 } 475 final quintptr is_shared(quintptr value) 476 { 477 bitfield = (bitfield & ~0x1) | ((value & 0x1) << 0); 478 return value; 479 } 480 /+ quintptr is_null : 1; +/ 481 final quintptr is_null() const 482 { 483 return (bitfield >> 1) & 0x1; 484 } 485 final quintptr is_null(quintptr value) 486 { 487 bitfield = (bitfield & ~0x2) | ((value & 0x1) << 1); 488 return value; 489 } 490 /+ quintptr packedType : sizeof(QMetaType) * 8 - 2; +/ 491 final quintptr packedType() const 492 { 493 return (bitfield >> 2) & 0x1; 494 } 495 final quintptr packedType(quintptr value) 496 { 497 bitfield = (bitfield & ~0x4) | ((value & 0x1) << 2); 498 return value; 499 } 500 501 //@disable this(); 502 /+this()/+ noexcept+/ 503 { 504 this.is_shared = false; 505 this.is_null = true; 506 this.packedType = 0; 507 }+/ 508 /+ explicit +/this(QMetaType type)/+ noexcept+/ 509 { 510 this.is_shared = false; 511 this.is_null = false; 512 513 quintptr mt = cast(quintptr)(type.d_ptr); 514 (mixin(Q_ASSERT(q{(mt & 0x3) == 0}))); 515 packedType = mt >> 2; 516 } 517 /+ explicit +/this(int type)/+ noexcept+/ 518 { 519 this(QMetaType(type)); 520 } 521 522 const(void)* storage() const return 523 { return is_shared ? data.shared_.data() : &data.data; } 524 525 const(void)* internalStorage() const return 526 { (mixin(Q_ASSERT(q{QVariant.Private.is_shared}))); return &data.data; } 527 528 // determine internal storage at compile time 529 /+ template<typename T> +/ 530 ref const(T) get(T)() const 531 { return *static_cast!(const(T)*)(storage()); } 532 /+ template<typename T> +/ 533 void set(T)(ref const(T) t) 534 { *static_cast!(T*)(CanUseInternalSpace!(T) ? &data.data : data.shared_.data()) = t; } 535 536 pragma(inline, true) QMetaType type() const 537 { 538 return QMetaType(reinterpret_cast!(/+ QtPrivate:: +/qt.core.metatype.QMetaTypeInterface*)(packedType << 2)); 539 } 540 541 pragma(inline, true) /+ QtPrivate:: +/qt.core.metatype.QMetaTypeInterface* typeInterface() const 542 { 543 return reinterpret_cast!(/+ QtPrivate:: +/qt.core.metatype.QMetaTypeInterface*)(packedType << 2); 544 } 545 546 pragma(inline, true) int typeId() const 547 { 548 return type().id(); 549 } 550 } 551 public: 552 static QPartialOrdering compare(ref const(QVariant) lhs, ref const(QVariant) rhs); 553 554 private: 555 /+ friend inline bool operator==(const QVariant &a, const QVariant &b) 556 { return a.equals(b); } +/ 557 /+ friend inline bool operator!=(const QVariant &a, const QVariant &b) 558 { return !a.equals(b); } +/ 559 /+ #ifndef QT_NO_DEBUG_STREAM 560 template <typename T> 561 friend auto operator<<(const QDebug &debug, const T &variant) -> std::enable_if_t<std::is_same_v<T, QVariant>, QDebug> { 562 return variant.qdebugHelper(debug); 563 } 564 QDebug qdebugHelper(QDebug) const; 565 #endif +/ 566 /+ template<typename T> +/ 567 /+ friend inline T qvariant_cast(const QVariant &); +/ 568 protected: 569 Private d; 570 /+ void create(int type, const void *copy); +/ 571 /+ void create(QMetaType type, const void *copy); +/ 572 bool equals(ref const(QVariant) other) const; 573 bool convert(int type, void* ptr) const; 574 bool view(int type, void* ptr); 575 576 private: 577 // force compile error, prevent QVariant(bool) to be called 578 pragma(inline, true) @disable this(void* ) /+ = delete +/; 579 // QVariant::Type is marked as \obsolete, but we don't want to 580 // provide a constructor from its intended replacement, 581 // QMetaType::Type, instead, because the idea behind these 582 // constructors is flawed in the first place. But we also don't 583 // want QVariant(QMetaType::String) to compile and falsely be an 584 // int variant, so delete this constructor: 585 @disable this(QMetaType.Type) /+ = delete +/; 586 587 // These constructors don't create QVariants of the type associated 588 // with the enum, as expected, but they would create a QVariant of 589 // type int with the value of the enum value. 590 // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for 591 // example. 592 @disable this(/+ Qt:: +/qt.core.namespace.GlobalColor) /+ = delete +/; 593 @disable this(/+ Qt:: +/qt.core.namespace.BrushStyle) /+ = delete +/; 594 @disable this(/+ Qt:: +/qt.core.namespace.PenStyle) /+ = delete +/; 595 @disable this(/+ Qt:: +/qt.core.namespace.CursorShape) /+ = delete +/; 596 /+ #ifdef QT_NO_CAST_FROM_ASCII +/ 597 // force compile error when implicit conversion is not wanted 598 pragma(inline, true) @disable this(const(char)* ) /+ = delete +/; 599 /+ #endif +/ 600 public: 601 alias DataPtr = Private; 602 pragma(inline, true) ref DataPtr data_ptr() return { return d; } 603 pragma(inline, true) ref const(DataPtr) data_ptr() const return { return d; } 604 mixin(CREATE_CONVENIENCE_WRAPPERS); 605 } 606 607 /+ template<> 608 #if __has_include(<variant>) && __cplusplus >= 201703L 609 template<> 610 inline QVariant QVariant::fromValue(const std::monostate &) 611 { 612 return QVariant(); 613 } 614 #endif 615 616 #ifndef QT_NO_DATASTREAM 617 Q_CORE_EXPORT QDataStream &operator>>(QDataStream &s, QVariant &p); 618 Q_CORE_EXPORT QDataStream &operator<<(QDataStream &s, const QVariant &p); 619 620 #if QT_DEPRECATED_SINCE(6, 0) 621 QT_WARNING_PUSH 622 QT_WARNING_DISABLE_DEPRECATED 623 QT_DEPRECATED_VERSION_6_0 624 inline QDataStream &operator>>(QDataStream &s, QVariant::Type &p) 625 { 626 quint32 u; 627 s >> u; 628 p = static_cast<QVariant::Type>(u); 629 return s; 630 } 631 QT_DEPRECATED_VERSION_6_0 632 inline QDataStream &operator<<(QDataStream &s, const QVariant::Type p) 633 { 634 s << static_cast<quint32>(p); 635 return s; 636 } 637 QT_WARNING_POP 638 #endif 639 640 #endif 641 642 Q_DECLARE_SHARED(QVariant) +/ 643 644 version(QT_MOC){}else 645 { 646 647 /+pragma(inline, true) T qvariant_cast(T)(ref const(QVariant) v) 648 { 649 QMetaType targetType = QMetaType.fromType!(T)(); 650 if (v.d.type() == targetType) 651 return v.d.get<TT>(); 652 static if (/+ std:: +/is_same_v!(T,const(/+ std:: +/remove_const_t!(/+ std:: +/remove_pointer_t!(T)))*)) { 653 alias nonConstT = /+ std:: +/remove_const_t!(/+ std:: +/remove_pointer_t!(T))*; 654 QMetaType nonConstTargetType = QMetaType.fromType!(nonConstT)(); 655 if (v.d.type() == nonConstTargetType) 656 return v.d.get<nonConstTnonConstT>(); 657 } 658 659 T t T(); 660 QMetaType.convert(v.metaType(), v.constData(), targetType, &t); 661 return t; 662 } 663 664 /+ template<> +/ 665 pragma(inline, true) QVariant qvariant_cast(ref const(QVariant) v) 666 { 667 if (v.metaType().id() == QMetaType.Type.QVariant) 668 return *reinterpret_cast!(const(QVariant)*)(v.constData()); 669 return v; 670 }+/ 671 672 } 673 674 /+ #ifndef QT_NO_DEBUG_STREAM 675 #if QT_DEPRECATED_SINCE(6, 0) 676 QT_WARNING_PUSH 677 QT_WARNING_DISABLE_DEPRECATED 678 QT_DEPRECATED_VERSION_6_0 679 Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type); 680 QT_WARNING_POP 681 #endif 682 #endif +/ 683 684 extern(C++, "QtPrivate") { 685 extern(C++, class) struct /+ Q_CORE_EXPORT +/ QVariantTypeCoercer 686 { 687 public: 688 const(void)* convert(ref const(QVariant) value, ref const(QMetaType) type); 689 const(void)* coerce(ref const(QVariant) value, ref const(QMetaType) type); 690 691 private: 692 QVariant converted; 693 } 694 } 695 696 /// Binding for C++ class [QVariantRef](https://doc.qt.io/qt-6/qvariantref.html). 697 extern(C++, class) struct QVariantRef(Pointer) 698 { 699 private: 700 const(Pointer)* m_pointer = null; 701 702 public: 703 /+ explicit +/this(const(Pointer)* reference) 704 { 705 this.m_pointer = reference; 706 } 707 /+ QVariantRef(const QVariantRef &) = default; +/ 708 /+ QVariantRef(QVariantRef &&) = default; +/ 709 /+ ~QVariantRef() = default; +/ 710 711 /+auto opCast(T : QVariant)() const;+/ 712 /+ref QVariantRef operator =(ref const(QVariant) value);+/ 713 /+ref QVariantRef operator =(ref const(QVariantRef) value) { return operator=(QVariant(value)); }+/ 714 /+ QVariantRef &operator=(QVariantRef &&value) { return operator=(QVariant(value)); } +/ 715 716 /+ friend void swap(QVariantRef a, QVariantRef b) 717 { 718 QVariant tmp = a; 719 a = b; 720 b = std::move(tmp); 721 } +/ 722 } 723 724 /// Binding for C++ class [QVariantConstPointer](https://doc.qt.io/qt-6/qvariantconstpointer.html). 725 extern(C++, class) struct /+ Q_CORE_EXPORT +/ QVariantConstPointer 726 { 727 private: 728 QVariant m_variant; 729 730 public: 731 /+ explicit +/this(QVariant variant); 732 733 QVariant opUnary(string op)() const if(op == "*"); 734 /+const(QVariant)* operator ->() const;+/ 735 mixin(CREATE_CONVENIENCE_WRAPPERS); 736 } 737 738 /// Binding for C++ class [QVariantPointer](https://doc.qt.io/qt-6/qvariantpointer.html). 739 class QVariantPointer(Pointer) 740 { 741 private: 742 const(Pointer)* m_pointer = null; 743 744 public: 745 /+ explicit +/this(const(Pointer)* pointer) 746 { 747 this.m_pointer = pointer; 748 } 749 //final QVariantRef!(Pointer) opUnary(string op)() const if(op == "*") { return QVariantRef!(Pointer)(cast(QVariantRef && )(m_pointer)); } 750 /+final Pointer operator ->() const { return *m_pointer; }+/ 751 } 752 753 pragma(inline, true) T qvariant_cast(T)(ref const(QVariant) v) 754 { 755 // TODO: special cases of qvariant_cast 756 static if(is(T == class)) 757 static assert(false); 758 else 759 { 760 const(int) vid = qMetaTypeId!(T)(); 761 if (vid == v.userType()) 762 return *reinterpret_cast!(T*)(v.constData()); 763 static if(__traits(hasMember, T, "rawConstructor")) 764 mixin("T t = T.init; t.rawConstructor();"); 765 else 766 mixin("T t;"); 767 if (v.convert(vid, &t)) 768 return t; 769 static if(__traits(hasMember, T, "rawConstructor")) 770 mixin("T r = T.init; r.rawConstructor(); return r;"); 771 else 772 mixin("return T();"); 773 } 774 } 775 pragma(inline, true) T qvariant_cast(T)(const(QVariant) v) 776 { 777 return qvariant_cast!T(v); 778 } 779