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 }