1 // QT_MODULES: core 2 module testcore1; 3 4 import qt.config; 5 import qt.core.coreapplication; 6 import qt.core.list; 7 import qt.core.object; 8 import qt.core.string; 9 import qt.core.typeinfo; 10 import qt.core.variant; 11 import qt.core.vector; 12 import qt.helpers; 13 import std.stdio; 14 15 QCoreApplication app; 16 shared static this() 17 { 18 import core.runtime; 19 app = new QCoreApplication(Runtime.cArgs.argc, Runtime.cArgs.argv); 20 assert(QCoreApplication.instance() is app); 21 } 22 23 class TestObject : QObject 24 { 25 mixin(Q_OBJECT_D); 26 public: 27 /+ explicit +/@QInvokable this(QObject parent = null) 28 { 29 super(parent); 30 lastStr = QString.create; 31 } 32 33 QString lastStr; 34 35 @QInvokable final void emitSignalVoid() 36 { 37 /+ emit +/ signalVoid(); 38 } 39 @QInvokable final void emitSignalInt(int i) 40 { 41 /+ emit +/ signalInt(i); 42 } 43 @QInvokable final void emitSignalInt3(int x, int y, int z) 44 { 45 /+ emit +/ signalInt3(x, y, z); 46 } 47 @QInvokable final void emitSignalDouble(double d) 48 { 49 /+ emit +/ signalDouble(d); 50 } 51 @QInvokable final void emitSignalString(ref const(QString) s) 52 { 53 /+ emit +/ signalString(s); 54 } 55 @QInvokable final void emitSignalListInt(ref const(QList!(int)) l) 56 { 57 /+ emit +/ signalListInt(l); 58 } 59 @QInvokable final void emitSignalVectorInt(ref const(QVector!(int)) v) 60 { 61 /+ emit +/ signalVectorInt(v); 62 } 63 @QInvokable final void emitSignalPointerInt(int* p) 64 { 65 /+ emit +/ signalPointerInt(p); 66 } 67 68 /+ signals +/public: 69 @QSignal final void signalVoid(){mixin(Q_SIGNAL_IMPL_D);} 70 @QSignal final void signalInt(int i){mixin(Q_SIGNAL_IMPL_D);} 71 @QSignal final void signalInt3(int x, int y, int z){mixin(Q_SIGNAL_IMPL_D);} 72 @QSignal final void signalDouble(double d){mixin(Q_SIGNAL_IMPL_D);} 73 @QSignal final void signalString(ref const(QString) s){mixin(Q_SIGNAL_IMPL_D);} 74 @QSignal final void signalListInt(ref const(QList!(int)) l){mixin(Q_SIGNAL_IMPL_D);} 75 @QSignal final void signalVectorInt(ref const(QVector!(int)) v){mixin(Q_SIGNAL_IMPL_D);} 76 @QSignal final void signalPointerInt(int* p){mixin(Q_SIGNAL_IMPL_D);} 77 78 public /+ slots +/: 79 @QSlot final void onSignalVoid() 80 { 81 lastStr = QString("void"); 82 } 83 @QSlot final void onSignalInt(int i) 84 { 85 lastStr = "int " ~ QString.number(i); 86 } 87 @QSlot final void onSignalInt3(int x, int y, int z) 88 { 89 lastStr = "int3 " ~ QString.number(x) ~ " " ~ QString.number(y) ~ " " ~ QString.number(z); 90 } 91 @QSlot final void onSignalDouble(double d) 92 { 93 lastStr = "double " ~ QString.number(d); 94 } 95 @QSlot final void onSignalString(ref const(QString) s) 96 { 97 lastStr = "QString " ~ s; 98 } 99 @QSlot final void onSignalListInt(ref const(QList!(int)) l) 100 { 101 lastStr = QString("QList<int>"); 102 for(int i=0; i<l.size(); i++) 103 lastStr ~= " " ~ QString.number(l[i]); 104 } 105 @QSlot final void onSignalVectorInt(ref const(QVector!(int)) v) 106 { 107 lastStr = QString("QVector<int>"); 108 for(int i=0; i<v.size(); i++) 109 lastStr ~= " " ~ QString.number(v[i]); 110 } 111 @QSlot final void onSignalPointerInt(int* p) 112 { 113 lastStr = "int* " ~ QString.number(*p); 114 } 115 116 } 117 118 unittest 119 { 120 QString s = QString.create; 121 s = QString("QString(Utf8): abc äöüÄÖÜßẞ αβ ∃∀ ∨∧⊥¬ ≤≥≠ 𝕆🎵🎶"); 122 assert(s.toConstWString == "QString(Utf8): abc äöüÄÖÜßẞ αβ ∃∀ ∨∧⊥¬ ≤≥≠ 𝕆🎵🎶"w); 123 124 s = QString.fromUtf8("QString::fromUtf8: abc äöüÄÖÜßẞ αβ ∃∀ ∨∧⊥¬ ≤≥≠ 𝕆🎵🎶".ptr); 125 assert(s.toConstWString == "QString::fromUtf8: abc äöüÄÖÜßẞ αβ ∃∀ ∨∧⊥¬ ≤≥≠ 𝕆🎵🎶"w); 126 127 s = QString("QString(Utf16): abc äöüÄÖÜßẞ αβ ∃∀ ∨∧⊥¬ ≤≥≠ 𝕆🎵🎶"w); 128 assert(s.toConstWString == "QString(Utf16): abc äöüÄÖÜßẞ αβ ∃∀ ∨∧⊥¬ ≤≥≠ 𝕆🎵🎶"w); 129 130 s = QString.fromUtf16("QString::fromUtf16: abc äöüÄÖÜßẞ αβ ∃∀ ∨∧⊥¬ ≤≥≠ 𝕆🎵🎶"w.ptr); 131 assert(s.toConstWString == "QString::fromUtf16: abc äöüÄÖÜßẞ αβ ∃∀ ∨∧⊥¬ ≤≥≠ 𝕆🎵🎶"w); 132 133 s = QString("QString(Utf32): abc äöüÄÖÜßẞ αβ ∃∀ ∨∧⊥¬ ≤≥≠ 𝕆🎵🎶"d); 134 assert(s.toConstWString == "QString(Utf32): abc äöüÄÖÜßẞ αβ ∃∀ ∨∧⊥¬ ≤≥≠ 𝕆🎵🎶"w); 135 136 s = QString.fromUcs4("QString::fromUcs4: abc äöüÄÖÜßẞ αβ ∃∀ ∨∧⊥¬ ≤≥≠ 𝕆🎵🎶"d.ptr); 137 assert(s.toConstWString == "QString::fromUcs4: abc äöüÄÖÜßẞ αβ ∃∀ ∨∧⊥¬ ≤≥≠ 𝕆🎵🎶"w); 138 } 139 140 void checkType(T, bool relocatable, bool complex)() 141 { 142 //writefln("checkType!(%s, %d, %d)();\n", T.stringof, QTypeInfo!T.isRelocatable, QTypeInfo!T.isComplex); 143 static assert(QTypeInfo!(T).isRelocatable == relocatable); 144 static assert(QTypeInfo!(T).isComplex == complex); 145 } 146 147 unittest 148 { 149 import core.stdc.wchar_; 150 import qt.core.abstractitemmodel; 151 import qt.core.bytearray; 152 import qt.core.itemselectionmodel; 153 import qt.core.line; 154 import qt.core.locale; 155 import qt.core.namespace; 156 import qt.core.pair; 157 import qt.core.point; 158 import qt.core.size; 159 import qt.core.stringview; 160 import qt.core.timezone; 161 import qt.core.url; 162 163 checkType!(double, 1, 0)(); 164 checkType!(int, 1, 0)(); 165 checkType!(uint, 1, 0)(); 166 checkType!(int*, 1, 0)(); 167 checkType!(void*, 1, 0)(); 168 checkType!(void, 0, 0)(); 169 checkType!(ubyte, 1, 0)(); 170 checkType!(char, 1, 0)(); 171 checkType!(wchar, 1, 0)(); 172 checkType!(wchar_t, 1, 0)(); 173 checkType!(QLocale.Country, 1, 0)(); 174 checkType!(/+ Qt:: +/qt.core.namespace.DayOfWeek, 1, 0)(); 175 checkType!(QTimeZone.OffsetData, 1, 1)(); 176 checkType!(QByteArray, 1, 1)(); 177 checkType!(QItemSelectionRange, 1, 1)(); 178 checkType!(QLine, 1, 1)(); 179 checkType!(QLineF, 1, 1)(); 180 checkType!(QLocale, 1, 1)(); 181 checkType!(QModelIndex, 1, 1)(); 182 checkType!(QObject, 1, 0)(); 183 checkType!(qt.core.pair.QPair!(double, QSize), 1, 1)(); 184 checkType!(QPersistentModelIndex, 1, 1)(); 185 checkType!(QPoint, 1, 0)(); 186 checkType!(QPointF, 1, 0)(); 187 checkType!(QSize, 1, 1)(); 188 checkType!(QString, 1, 1)(); 189 checkType!(QStringView, 1, 0)(); 190 checkType!(QUrl, 1, 1)(); 191 checkType!(QVariant, 1, 1)(); 192 checkType!(QAbstractItemModel, 1, 0)(); 193 checkType!(QTimeZone.OffsetData, 1, 1)(); 194 checkType!(QList!(int), 1, 1)(); 195 checkType!(QList!(void*), 1, 1)(); 196 checkType!(QList!(QSize), 1, 1)(); 197 checkType!(QVector!(int), 1, 1)(); 198 checkType!(QVector!(void*), 1, 1)(); 199 checkType!(QVector!(QSize), 1, 1)(); 200 checkType!(/+ Qt:: +/qt.core.namespace.Edge, 1, 0)(); 201 checkType!(/+ Qt:: +/qt.core.namespace.Edges, 1, 0)(); 202 } 203 204 unittest 205 { 206 import core.stdc.string; 207 import core.stdcpp.new_; 208 import qt.core.metaobject; 209 import qt.core.metatype; 210 import qt.core.objectdefs; 211 212 const(QMetaObject)* mo = &TestObject.staticMetaObject; 213 assert(strcmp(mo.className(), "TestObject") == 0); 214 //assert(mo->constructorCount() == 2); 215 assert(mo.methodCount() - mo.methodOffset() == 8 + 8 + 8); 216 217 TestObject a = cpp_new!TestObject(); 218 assert(a.metaObject() == mo); 219 220 QMetaMethod method = mo.method(mo.methodOffset() + 0); 221 assert(method.name().toConstCharArray() == "signalVoid"); 222 assert(method.methodSignature().toConstCharArray() == "signalVoid()"); 223 assert(method.parameterCount() == 0); 224 225 method = mo.method(mo.methodOffset() + 1); 226 assert(method.name().toConstCharArray() == "signalInt"); 227 assert(method.methodSignature().toConstCharArray() == "signalInt(int)"); 228 assert(method.parameterCount() == 1); 229 assert(method.parameterType(0) == QMetaType.Type.Int); 230 231 method = mo.method(mo.methodOffset() + 2); 232 assert(method.name().toConstCharArray() == "signalInt3"); 233 assert(method.methodSignature().toConstCharArray() == "signalInt3(int,int,int)"); 234 assert(method.parameterCount() == 3); 235 assert(method.parameterType(0) == QMetaType.Type.Int); 236 assert(method.parameterType(1) == QMetaType.Type.Int); 237 assert(method.parameterType(2) == QMetaType.Type.Int); 238 239 method = mo.method(mo.methodOffset() + 3); 240 assert(method.name().toConstCharArray() == "signalDouble"); 241 assert(method.methodSignature().toConstCharArray() == "signalDouble(double)"); 242 assert(method.parameterCount() == 1); 243 assert(method.parameterType(0) == QMetaType.Type.Double); 244 245 method = mo.method(mo.methodOffset() + 4); 246 assert(method.name().toConstCharArray() == "signalString"); 247 assert(method.methodSignature().toConstCharArray() == "signalString(QString)"); 248 assert(method.parameterCount() == 1); 249 assert(method.parameterType(0) == QMetaType.Type.QString); 250 251 method = mo.method(mo.methodOffset() + 5); 252 assert(method.name().toConstCharArray() == "signalListInt"); 253 assert(method.methodSignature().toConstCharArray() == "signalListInt(QList<int>)"); 254 assert(method.parameterCount() == 1); 255 256 method = mo.method(mo.methodOffset() + 6); 257 assert(method.name().toConstCharArray() == "signalVectorInt"); 258 assert(method.methodSignature().toConstCharArray() == "signalVectorInt(QList<int>)"); 259 assert(method.parameterCount() == 1); 260 261 method = mo.method(mo.methodOffset() + 7); 262 assert(method.name().toConstCharArray() == "signalPointerInt"); 263 assert(method.methodSignature().toConstCharArray() == "signalPointerInt(int*)"); 264 assert(method.parameterCount() == 1); 265 } 266 267 void connectByString(TestObject a, TestObject b) 268 { 269 import qt.core.object; 270 import qt.core.objectdefs; 271 272 QObject.connect(a, (mixin(SIGNAL(q{signalVoid()}))).ptr, b, (mixin(SLOT(q{onSignalVoid()}))).ptr); 273 QObject.connect(a, (mixin(SIGNAL(q{signalInt(int)}))).ptr, b, (mixin(SLOT(q{onSignalInt(int)}))).ptr); 274 QObject.connect(a, (mixin(SIGNAL(q{signalInt3(int,int,int)}))).ptr, b, (mixin(SLOT(q{onSignalInt3(int,int,int)}))).ptr); 275 QObject.connect(a, (mixin(SIGNAL(q{signalDouble(double)}))).ptr, b, (mixin(SLOT(q{onSignalDouble(double)}))).ptr); 276 QObject.connect(a, (mixin(SIGNAL(q{signalString(const QString&)}))).ptr, b, (mixin(SLOT(q{onSignalString(const QString&)}))).ptr); 277 QObject.connect(a, (mixin(SIGNAL(q{signalListInt(const QList<int>&)}))).ptr, b, (mixin(SLOT(q{onSignalListInt(const QList<int>&)}))).ptr); 278 QObject.connect(a, (mixin(SIGNAL(q{signalVectorInt(const QVector<int>&)}))).ptr, b, (mixin(SLOT(q{onSignalVectorInt(const QVector<int>&)}))).ptr); 279 QObject.connect(a, (mixin(SIGNAL(q{signalPointerInt(int*)}))).ptr, b, (mixin(SLOT(q{onSignalPointerInt(int*)}))).ptr); 280 } 281 282 void connectByPointer(TestObject a, TestObject b) 283 { 284 import qt.core.list; 285 import qt.core.object; 286 import qt.core.vector; 287 288 QObject.connect(a.signal!"signalVoid", b.slot!"onSignalVoid"); 289 QObject.connect(a.signal!"signalInt", b.slot!"onSignalInt"); 290 QObject.connect(a.signal!"signalInt3", b.slot!"onSignalInt3"); 291 QObject.connect(a.signal!"signalDouble", b.slot!"onSignalDouble"); 292 QObject.connect(a.signal!"signalString", b.slot!"onSignalString"); 293 QObject.connect(a.signal!"signalListInt", b.slot!"onSignalListInt"); 294 QObject.connect(a.signal!"signalVectorInt", b.slot!"onSignalVectorInt"); 295 QObject.connect(a.signal!"signalPointerInt", b.slot!"onSignalPointerInt"); 296 } 297 298 void testSignals(TestObject a, TestObject b) 299 { 300 import qt.core.list; 301 import qt.core.vector; 302 303 a.emitSignalVoid(); 304 assert(b.lastStr == "void"); 305 a.emitSignalInt(5); 306 assert(b.lastStr == "int 5"); 307 a.emitSignalInt3(1, 2, 3); 308 assert(b.lastStr == "int3 1 2 3"); 309 a.emitSignalDouble(16.5); 310 assert(b.lastStr == "double 16.5"); 311 auto tmp = QString("test"); a.emitSignalString(tmp); 312 assert(b.lastStr == "QString test"); 313 QList!(int) l = QList!(int).create(); 314 l ~= 10; 315 l ~= 11; 316 l ~= 12; 317 a.emitSignalListInt(l); 318 assert(b.lastStr == "QList<int> 10 11 12"); 319 QVector!(int) v = QVector!(int).create(); 320 v ~= 20; 321 v ~= 21; 322 v ~= 22; 323 a.emitSignalVectorInt(v); 324 assert(b.lastStr == "QVector<int> 20 21 22"); 325 int x = 30; 326 a.emitSignalPointerInt(&x); 327 assert(b.lastStr == "int* 30"); 328 } 329 330 unittest 331 { 332 import core.stdcpp.new_; 333 334 TestObject a = cpp_new!TestObject(); 335 TestObject b = cpp_new!TestObject(); 336 connectByString(a, b); 337 testSignals(a, b); 338 } 339 340 unittest 341 { 342 import core.stdcpp.new_; 343 344 TestObject a = cpp_new!TestObject(); 345 TestObject b = cpp_new!TestObject(); 346 connectByPointer(a, b); 347 testSignals(a, b); 348 } 349 350 void compareVariant(ref const(QVariant) v, const(char)* expected) 351 { 352 import core.stdc.stdio; 353 354 char[(v). sizeof * 3 + 1] buffer; 355 size_t pos = 0; 356 for(size_t i=0; i<(v). sizeof; i++) 357 { 358 snprintf(&buffer[pos], 3, "%02X", (cast(ubyte*)&v)[i]); 359 pos += 2; 360 if(i % 4 == 3 && i + 1 < (v). sizeof) 361 { 362 buffer[pos] = ' '; 363 pos++; 364 } 365 } 366 buffer[pos] = 0; 367 bool different = false; 368 for(size_t i=0; i<pos; i++) 369 { 370 if(!expected[i]) 371 break; 372 if(expected[i] == '?') 373 continue; 374 if(buffer[i] != expected[i]) 375 different = true; 376 } 377 if(different) 378 { 379 printf("expected: %s\n", expected); 380 printf("got: %s\n", buffer.ptr); 381 assert(false); 382 } 383 } 384 385 unittest 386 { 387 QVariant v; 388 static if((void*).sizeof == 8) 389 compareVariant(v, "00000000 00000000 00000000 00000000 00000000 00000000 02000000 00000000"); 390 else 391 compareVariant(v, "00000000 00000000 00000000 02000000"); 392 v = QVariant(5); 393 static if((void*).sizeof == 8) 394 compareVariant(v, "05000000 00000000 00000000 00000000 00000000 00000000 ???????? ????????"); 395 else 396 compareVariant(v, "05000000 00000000 00000000 ????????"); 397 v = QVariant(100.0f); 398 static if((void*).sizeof == 8) 399 compareVariant(v, "0000C842 00000000 00000000 00000000 00000000 00000000 ???????? ????????"); 400 else 401 compareVariant(v, "0000C842 00000000 00000000 ????????"); 402 v = QVariant(100.0); 403 static if((void*).sizeof == 8) 404 compareVariant(v, "00000000 00005940 00000000 00000000 00000000 00000000 ???????? ????????"); 405 else 406 compareVariant(v, "00000000 00005940 00000000 ????????"); 407 v = QVariant(cast(int)'A'); 408 static if((void*).sizeof == 8) 409 compareVariant(v, "41000000 00000000 00000000 00000000 00000000 00000000 ???????? ????????"); 410 else 411 compareVariant(v, "41000000 00000000 00000000 ????????"); 412 } 413 414 unittest 415 { 416 import qt.core.objectdefs; 417 418 size_t changeCount = 0; 419 { 420 scope QObject dummy = new QObject; 421 QObject.connect(QCoreApplication.instance().signal!"applicationNameChanged", dummy, (){ 422 changeCount++; 423 }); 424 assert(changeCount == 0); 425 QCoreApplication.setApplicationName(QString("ApplicationName1")); 426 assert(changeCount == 1); 427 } 428 QCoreApplication.setApplicationName(QString("ApplicationName2")); 429 // Slot was not called again, because dummy is out of scope. 430 assert(changeCount == 1); 431 432 scope QObject dummy = new QObject; 433 QMetaObject.Connection connection = QObject.connect(QCoreApplication.instance().signal!"applicationNameChanged", dummy, (){ 434 changeCount++; 435 }); 436 assert(changeCount == 1); 437 438 QCoreApplication.setApplicationName(QString("ApplicationName3")); 439 assert(changeCount == 2); 440 441 QObject.disconnect(connection); 442 QCoreApplication.setApplicationName(QString("ApplicationName4")); 443 assert(changeCount == 2); 444 } 445 446 unittest 447 { 448 import core.stdcpp.new_; 449 import qt.core.timer; 450 451 QObject obj = cpp_new!QObject(); 452 assert(qobject_cast!(QObject)(obj) is obj); 453 assert(qobject_cast!(TestObject)(obj) is null); 454 assert(qobject_cast!(QTimer)(obj) is null); 455 456 TestObject testObject = cpp_new!TestObject(); 457 assert(qobject_cast!(QObject)(testObject) is testObject); 458 assert(qobject_cast!(TestObject)(testObject) is testObject); 459 assert(qobject_cast!(QTimer)(testObject) is null); 460 461 QTimer timer = cpp_new!QTimer(); 462 assert(qobject_cast!(QObject)(timer) is timer); 463 assert(qobject_cast!(TestObject)(timer) is null); 464 assert(qobject_cast!(QTimer)(timer) is timer); 465 } 466 467 unittest 468 { 469 import qt.core.algorithms; 470 471 assert(qPopulationCount(0U) == 0); 472 assert(qPopulationCount(0xffffU) == 16); 473 assert(qPopulationCount(0xffffffffU) == 32); 474 assert(qPopulationCount(0xffffffffffffffffU) == 64); 475 assert(qPopulationCount(0x8000000000000000U) == 1); 476 477 assert(qCountTrailingZeroBits(cast(ubyte)0U) == 8); 478 assert(qCountTrailingZeroBits(cast(ushort)0U) == 16); 479 assert(qCountTrailingZeroBits(0U) == 32); 480 assert(qCountTrailingZeroBits(cast(ulong)0U) == 64); 481 assert(qCountTrailingZeroBits(0x10U) == 4); 482 assert(qCountTrailingZeroBits(0x1000U) == 12); 483 assert(qCountTrailingZeroBits(0x80000000U) == 31); 484 assert(qCountTrailingZeroBits(0x8000000000000000U) == 63); 485 assert(qCountTrailingZeroBits(0xffffffff80000000U) == 31); 486 487 assert(qCountLeadingZeroBits(cast(ubyte)0U) == 8); 488 assert(qCountLeadingZeroBits(cast(ushort)0U) == 16); 489 assert(qCountLeadingZeroBits(0U) == 32); 490 assert(qCountLeadingZeroBits(cast(ulong)0U) == 64); 491 assert(qCountLeadingZeroBits(0x10U) == 27); 492 assert(qCountLeadingZeroBits(0x1000U) == 19); 493 assert(qCountLeadingZeroBits(0x80000000U) == 0); 494 assert(qCountLeadingZeroBits(0x8000000000000000U) == 0); 495 assert(qCountLeadingZeroBits(0xffffffff80000000U) == 0); 496 }