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, bool static_)() 141 { 142 //writefln("checkType!(%s, %d, %d, %d, %d)();", T.stringof, QTypeInfo!T.isRelocatable, QTypeInfo!T.isComplex, QTypeInfo!T.isStatic); 143 static assert(QTypeInfo!(T).isRelocatable == relocatable); 144 static assert(QTypeInfo!(T).isComplex == complex); 145 static assert(QTypeInfo!(T).isStatic == static_); 146 static assert(QTypeInfoQuery!(T).isRelocatable == relocatable); 147 static assert(QTypeInfoQuery!(T).isComplex == complex); 148 static assert(QTypeInfoQuery!(T).isStatic == static_); 149 } 150 151 unittest 152 { 153 import core.stdc.wchar_; 154 import qt.core.abstractitemmodel; 155 import qt.core.bytearray; 156 import qt.core.itemselectionmodel; 157 import qt.core.line; 158 import qt.core.locale; 159 import qt.core.namespace; 160 import qt.core.pair; 161 import qt.core.point; 162 import qt.core.size; 163 import qt.core.stringview; 164 import qt.core.timezone; 165 import qt.core.url; 166 167 checkType!(double, 1, 0, 0)(); 168 checkType!(int, 1, 0, 0)(); 169 checkType!(uint, 1, 0, 0)(); 170 checkType!(int*, 1, 0, 0)(); 171 checkType!(void*, 1, 0, 0)(); 172 checkType!(void, 0, 0, 0)(); 173 checkType!(char, 1, 0, 0)(); 174 checkType!(wchar, 1, 0, 1)(); 175 checkType!(wchar_t, 1, 0, 1)(); 176 checkType!(QLocale.Country, 1, 0, 1)(); 177 checkType!(/+ Qt:: +/qt.core.namespace.DayOfWeek, 1, 0, 1)(); 178 checkType!(QTimeZone.OffsetData, 1, 1, 0)(); 179 checkType!(QByteArray, 1, 1, 0)(); 180 checkType!(QItemSelectionRange, 1, 1, 0)(); 181 checkType!(QLine, 1, 1, 0)(); 182 checkType!(QLineF, 1, 1, 0)(); 183 checkType!(QLocale, 1, 1, 0)(); 184 checkType!(QModelIndex, 1, 1, 0)(); 185 checkType!(QObject, 1, 0, 0)(); 186 checkType!(QPair!(double, QSize), 1, 1, 0)(); 187 checkType!(QPersistentModelIndex, 1, 1, 0)(); 188 checkType!(QPoint, 1, 1, 0)(); 189 checkType!(QPointF, 1, 1, 0)(); 190 checkType!(QSize, 1, 1, 0)(); 191 checkType!(QString, 1, 1, 0)(); 192 checkType!(QStringRef, 1, 0, 0)(); 193 checkType!(QStringView, 1, 0, 0)(); 194 checkType!(QUrl, 1, 1, 0)(); 195 checkType!(QVariant, 1, 1, 0)(); 196 checkType!(QAbstractItemModel, 1, 0, 0)(); 197 checkType!(QTimeZone.OffsetData, 1, 1, 0)(); 198 checkType!(QList!(int), 1, 1, 0)(); 199 checkType!(QList!(void*), 1, 1, 0)(); 200 checkType!(QList!(QSize), 1, 1, 0)(); 201 checkType!(QVector!(int), 1, 1, 0)(); 202 checkType!(QVector!(void*), 1, 1, 0)(); 203 checkType!(QVector!(QSize), 1, 1, 0)(); 204 checkType!(/+ Qt:: +/qt.core.namespace.Edge, 1, 0, 1)(); 205 checkType!(/+ Qt:: +/qt.core.namespace.Edges, 1, 0, 0)(); 206 } 207 208 unittest 209 { 210 import core.stdc.string; 211 import qt.core.objectdefs; 212 213 const(QMetaObject)* mo = &TestObject.staticMetaObject; 214 assert(strcmp(mo.className(), "TestObject") == 0); 215 //assert(mo->constructorCount() == 2); 216 assert(mo.methodCount() - mo.methodOffset() == 8 + 8 + 8); 217 } 218 219 void connectByString(TestObject a, TestObject b) 220 { 221 import qt.core.object; 222 import qt.core.objectdefs; 223 224 QObject.connect(a, (mixin(SIGNAL(q{signalVoid()}))).ptr, b, (mixin(SLOT(q{onSignalVoid()}))).ptr); 225 QObject.connect(a, (mixin(SIGNAL(q{signalInt(int)}))).ptr, b, (mixin(SLOT(q{onSignalInt(int)}))).ptr); 226 QObject.connect(a, (mixin(SIGNAL(q{signalInt3(int,int,int)}))).ptr, b, (mixin(SLOT(q{onSignalInt3(int,int,int)}))).ptr); 227 QObject.connect(a, (mixin(SIGNAL(q{signalDouble(double)}))).ptr, b, (mixin(SLOT(q{onSignalDouble(double)}))).ptr); 228 QObject.connect(a, (mixin(SIGNAL(q{signalString(const QString&)}))).ptr, b, (mixin(SLOT(q{onSignalString(const QString&)}))).ptr); 229 QObject.connect(a, (mixin(SIGNAL(q{signalListInt(const QList<int>&)}))).ptr, b, (mixin(SLOT(q{onSignalListInt(const QList<int>&)}))).ptr); 230 QObject.connect(a, (mixin(SIGNAL(q{signalVectorInt(const QVector<int>&)}))).ptr, b, (mixin(SLOT(q{onSignalVectorInt(const QVector<int>&)}))).ptr); 231 QObject.connect(a, (mixin(SIGNAL(q{signalPointerInt(int*)}))).ptr, b, (mixin(SLOT(q{onSignalPointerInt(int*)}))).ptr); 232 } 233 234 void connectByPointer(TestObject a, TestObject b) 235 { 236 import qt.core.list; 237 import qt.core.object; 238 import qt.core.vector; 239 240 QObject.connect(a.signal!"signalVoid", b.slot!"onSignalVoid"); 241 QObject.connect(a.signal!"signalInt", b.slot!"onSignalInt"); 242 QObject.connect(a.signal!"signalInt3", b.slot!"onSignalInt3"); 243 QObject.connect(a.signal!"signalDouble", b.slot!"onSignalDouble"); 244 QObject.connect(a.signal!"signalString", b.slot!"onSignalString"); 245 QObject.connect(a.signal!"signalListInt", b.slot!"onSignalListInt"); 246 QObject.connect(a.signal!"signalVectorInt", b.slot!"onSignalVectorInt"); 247 QObject.connect(a.signal!"signalPointerInt", b.slot!"onSignalPointerInt"); 248 } 249 250 void testSignals(TestObject a, TestObject b) 251 { 252 import qt.core.list; 253 import qt.core.vector; 254 255 a.emitSignalVoid(); 256 assert(b.lastStr == "void"); 257 a.emitSignalInt(5); 258 assert(b.lastStr == "int 5"); 259 a.emitSignalInt3(1, 2, 3); 260 assert(b.lastStr == "int3 1 2 3"); 261 a.emitSignalDouble(16.5); 262 assert(b.lastStr == "double 16.5"); 263 auto tmp = QString("test"); a.emitSignalString(tmp); 264 assert(b.lastStr == "QString test"); 265 QList!(int) l = QList!(int).create(); 266 l ~= 10; 267 l ~= 11; 268 l ~= 12; 269 a.emitSignalListInt(l); 270 assert(b.lastStr == "QList<int> 10 11 12"); 271 QVector!(int) v = QVector!(int).create(); 272 v ~= 20; 273 v ~= 21; 274 v ~= 22; 275 a.emitSignalVectorInt(v); 276 assert(b.lastStr == "QVector<int> 20 21 22"); 277 int x = 30; 278 a.emitSignalPointerInt(&x); 279 assert(b.lastStr == "int* 30"); 280 } 281 282 unittest 283 { 284 import core.stdcpp.new_; 285 286 TestObject a = cpp_new!TestObject(); 287 TestObject b = cpp_new!TestObject(); 288 connectByString(a, b); 289 testSignals(a, b); 290 } 291 292 unittest 293 { 294 import core.stdcpp.new_; 295 296 TestObject a = cpp_new!TestObject(); 297 TestObject b = cpp_new!TestObject(); 298 connectByPointer(a, b); 299 testSignals(a, b); 300 } 301 302 void compareVariant(ref const(QVariant) v, const(char)* expected) 303 { 304 import core.stdc.stdio; 305 306 char[(v). sizeof * 3 + 1] buffer; 307 size_t pos = 0; 308 for(size_t i=0; i<(v). sizeof; i++) 309 { 310 snprintf(&buffer[pos], 3, "%02X", (cast(ubyte*)&v)[i]); 311 pos += 2; 312 if(i % 4 == 3 && i + 1 < (v). sizeof) 313 { 314 buffer[pos] = ' '; 315 pos++; 316 } 317 } 318 buffer[pos] = 0; 319 bool different = false; 320 for(size_t i=0; i<pos; i++) 321 { 322 if(!expected[i]) 323 break; 324 if(expected[i] == '?') 325 continue; 326 if(buffer[i] != expected[i]) 327 different = true; 328 } 329 if(different) 330 { 331 printf("expected: %s\n", expected); 332 printf("got: %s\n", buffer.ptr); 333 assert(false); 334 } 335 } 336 337 unittest 338 { 339 QVariant v; 340 compareVariant(v, "00000000 ???????? 00000080"); 341 v = QVariant(5); 342 compareVariant(v, "05000000 ???????? 02000000"); 343 v = QVariant(100.0f); 344 compareVariant(v, "0000C842 ???????? 26000000"); 345 v = QVariant(100.0); 346 compareVariant(v, "00000000 00005940 06000000"); 347 v = QVariant(cast(int)'A'); 348 compareVariant(v, "41000000 ???????? 02000000"); 349 } 350 351 unittest 352 { 353 import qt.core.objectdefs; 354 355 size_t changeCount = 0; 356 { 357 scope QObject dummy = new QObject; 358 QObject.connect(QCoreApplication.instance().signal!"applicationNameChanged", dummy, (){ 359 changeCount++; 360 }); 361 assert(changeCount == 0); 362 QCoreApplication.setApplicationName(QString("ApplicationName1")); 363 assert(changeCount == 1); 364 } 365 QCoreApplication.setApplicationName(QString("ApplicationName2")); 366 // Slot was not called again, because dummy is out of scope. 367 assert(changeCount == 1); 368 369 scope QObject dummy = new QObject; 370 QMetaObject.Connection connection = QObject.connect(QCoreApplication.instance().signal!"applicationNameChanged", dummy, (){ 371 changeCount++; 372 }); 373 assert(changeCount == 1); 374 375 QCoreApplication.setApplicationName(QString("ApplicationName3")); 376 assert(changeCount == 2); 377 378 QObject.disconnect(connection); 379 QCoreApplication.setApplicationName(QString("ApplicationName4")); 380 assert(changeCount == 2); 381 } 382 383 unittest 384 { 385 import core.stdcpp.new_; 386 import qt.core.timer; 387 388 QObject obj = cpp_new!QObject(); 389 assert(qobject_cast!(QObject)(obj) is obj); 390 assert(qobject_cast!(TestObject)(obj) is null); 391 assert(qobject_cast!(QTimer)(obj) is null); 392 393 TestObject testObject = cpp_new!TestObject(); 394 assert(qobject_cast!(QObject)(testObject) is testObject); 395 assert(qobject_cast!(TestObject)(testObject) is testObject); 396 assert(qobject_cast!(QTimer)(testObject) is null); 397 398 QTimer timer = cpp_new!QTimer(); 399 assert(qobject_cast!(QObject)(timer) is timer); 400 assert(qobject_cast!(TestObject)(timer) is null); 401 assert(qobject_cast!(QTimer)(timer) is timer); 402 }