1 /****************************************************************************
2 **
3 ** DQt - D bindings for the Qt Toolkit
4 **
5 ** GNU Lesser General Public License Usage
6 ** This file may be used under the terms of the GNU Lesser
7 ** General Public License version 3 as published by the Free Software
8 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 ** packaging of this file. Please review the following information to
10 ** ensure the GNU Lesser General Public License version 3 requirements
11 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 **
13 ****************************************************************************/
14 module qt.core.object;
15 extern(C++):
16 
17 import qt.config;
18 import qt.core.coreevent;
19 import qt.core.list;
20 import qt.core.metaobject;
21 import qt.core.metatype;
22 import qt.core.namespace;
23 import qt.core.objectdefs;
24 import qt.core.objectdefs_impl;
25 import qt.core.regexp;
26 import qt.core.regularexpression;
27 import qt.core.scopedpointer;
28 import qt.core.string;
29 import qt.core.thread;
30 import qt.helpers;
31 import std.traits;
32 import std.meta;
33 version(QT_NO_PROPERTIES){}else
34 {
35     import qt.core.bytearray;
36     import qt.core.variant;
37 }
38 
39 /+ #ifndef QT_NO_QOBJECT +/
40 
41 /+ #ifdef QT_INCLUDE_COMPAT
42 #endif
43 #if __has_include(<chrono>)
44 #endif
45 
46 
47 
48 class QEvent;
49 class QTimerEvent;
50 class QChildEvent;
51 struct QMetaObject;
52 class QVariant; +/
53 extern(C++, class) struct QObjectPrivate;
54 /+ class QObject;
55 class QThread;
56 class QWidget; +/
57 extern(C++, class) struct QAccessibleWidget;
58 /+ #ifndef QT_NO_REGEXP
59 class QRegExp;
60 #endif
61 #if QT_CONFIG(regularexpression)
62 class QRegularExpression;
63 #endif
64 #if !QT_DEPRECATED_SINCE(5, 14) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
65 # define QT_NO_USERDATA
66 #endif
67 #ifndef QT_NO_USERDATA
68 class QObjectUserData;
69 #endif +/
70 struct QDynamicMetaObjectData;
71 
72 alias QObjectList = QList!(QObject);
73 
74 /+ Q_CORE_EXPORT +/ void qt_qFindChildren_helper(const(QObject) parent, ref const(QString) name,
75                                            ref const(QMetaObject) mo, QList!(void*)* list, /+ Qt:: +/qt.core.namespace.FindChildOptions options);
76 /+ Q_CORE_EXPORT +/ void qt_qFindChildren_helper(const(QObject) parent, ref const(QRegExp) re,
77                                            ref const(QMetaObject) mo, QList!(void*)* list, /+ Qt:: +/qt.core.namespace.FindChildOptions options);
78 /+ Q_CORE_EXPORT +/ void qt_qFindChildren_helper(const(QObject) parent, ref const(QRegularExpression) re,
79                                            ref const(QMetaObject) mo, QList!(void*)* list, /+ Qt:: +/qt.core.namespace.FindChildOptions options);
80 /+ Q_CORE_EXPORT +/ QObject qt_qFindChild_helper(const(QObject) parent, ref const(QString) name, ref const(QMetaObject) mo, /+ Qt:: +/qt.core.namespace.FindChildOptions options);
81 
82 class /+ Q_CORE_EXPORT +/ QObjectData {
83 private:
84     /+ Q_DISABLE_COPY(QObjectData) +/
85 public:
86     /+ QObjectData() = default; +/
87     this()
88     {
89         children = QObjectList.create();
90     }
91     /+ virtual +/ /*abstract*/ ~this();
92     QObject q_ptr;
93     QObject parent;
94     QObjectList children;
95 
96     /+ uint isWidget : 1; +/
97     uint bitfieldData_isWidget;
98     final bool isWidget() const
99     {
100         return (bitfieldData_isWidget >> 0) & 0x1;
101     }
102     final bool isWidget(bool value)
103     {
104         bitfieldData_isWidget = (bitfieldData_isWidget & ~0x1) | ((value & 0x1) << 0);
105         return value;
106     }
107     /+ uint blockSig : 1; +/
108     final bool blockSig() const
109     {
110         return (bitfieldData_isWidget >> 1) & 0x1;
111     }
112     final bool blockSig(bool value)
113     {
114         bitfieldData_isWidget = (bitfieldData_isWidget & ~0x2) | ((value & 0x1) << 1);
115         return value;
116     }
117     /+ uint wasDeleted : 1; +/
118     final uint wasDeleted() const
119     {
120         return (bitfieldData_isWidget >> 2) & 0x1;
121     }
122     final uint wasDeleted(uint value)
123     {
124         bitfieldData_isWidget = (bitfieldData_isWidget & ~0x4) | ((value & 0x1) << 2);
125         return value;
126     }
127     /+ uint isDeletingChildren : 1; +/
128     final uint isDeletingChildren() const
129     {
130         return (bitfieldData_isWidget >> 3) & 0x1;
131     }
132     final uint isDeletingChildren(uint value)
133     {
134         bitfieldData_isWidget = (bitfieldData_isWidget & ~0x8) | ((value & 0x1) << 3);
135         return value;
136     }
137     /+ uint sendChildEvents : 1; +/
138     final uint sendChildEvents() const
139     {
140         return (bitfieldData_isWidget >> 4) & 0x1;
141     }
142     final uint sendChildEvents(uint value)
143     {
144         bitfieldData_isWidget = (bitfieldData_isWidget & ~0x10) | ((value & 0x1) << 4);
145         return value;
146     }
147     /+ uint receiveChildEvents : 1; +/
148     final uint receiveChildEvents() const
149     {
150         return (bitfieldData_isWidget >> 5) & 0x1;
151     }
152     final uint receiveChildEvents(uint value)
153     {
154         bitfieldData_isWidget = (bitfieldData_isWidget & ~0x20) | ((value & 0x1) << 5);
155         return value;
156     }
157     /+ uint isWindow : 1; +/ //for QWindow
158     final bool isWindow() const
159     {
160         return (bitfieldData_isWidget >> 6) & 0x1;
161     }
162     final bool isWindow(bool value)
163     {
164         bitfieldData_isWidget = (bitfieldData_isWidget & ~0x40) | ((value & 0x1) << 6);
165         return value;
166     }
167     /+ uint deleteLaterCalled : 1; +/
168     final uint deleteLaterCalled() const
169     {
170         return (bitfieldData_isWidget >> 7) & 0x1;
171     }
172     final uint deleteLaterCalled(uint value)
173     {
174         bitfieldData_isWidget = (bitfieldData_isWidget & ~0x80) | ((value & 0x1) << 7);
175         return value;
176     }
177     /+ uint unused : 24; +/
178     final uint unused() const
179     {
180         return (bitfieldData_isWidget >> 8) & 0xffffff;
181     }
182     final uint unused(uint value)
183     {
184         bitfieldData_isWidget = (bitfieldData_isWidget & ~0xffffff00) | ((value & 0xffffff) << 8);
185         return value;
186     }
187     int postedEvents;
188     QDynamicMetaObjectData* metaObject;
189     final QMetaObject* dynamicMetaObject() const;
190 
191     version(QT_DEBUG)
192     {
193         enum { CheckForParentChildLoopsWarnDepth = 4096 }
194     }
195 }
196 
197 extern(D) struct DQtMember(T, Members_...) if(is(T: QObject))
198 {
199     alias Type = T;
200     alias Members = Members_;
201     T obj;
202 }
203 
204 template parametersSame(Params...)
205 {
206     template parametersSame(alias O)
207     {
208         enum parametersSame = is(Parameters!O == Params);
209     }
210 }
211 
212 @(QMetaType.Type.QObjectStar) class /+ Q_CORE_EXPORT +/ QObject
213 {
214     mixin((){import std.array; return Q_OBJECT.replace("override", "");}());
215 
216     /+ Q_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged)
217     Q_DECLARE_PRIVATE(QObject) +/
218 
219 public:
220     /+ explicit +/@QInvokable this(QObject parent=null);
221     /+ virtual +/~this();
222 
223 protected:
224     struct QSignal{}
225     struct QSlot{}
226     struct QInvokable{}
227     struct QScriptable{}
228     enum Q_OBJECT = qt.core.objectdefs.Q_OBJECT;
229     enum Q_OBJECT_D = qt.core.objectdefs.Q_OBJECT_D;
230     enum Q_SIGNAL_IMPL_D = qt.core.objectdefs.Q_SIGNAL_IMPL_D;
231 
232 public:
233 
234     /+ virtual +/ bool event(QEvent event);
235     /+ virtual +/ bool eventFilter(QObject watched, QEvent event);
236 
237 /+ #if defined(QT_NO_TRANSLATION) || defined(Q_CLANG_QDOC) +/
238     version(QT_NO_TRANSLATION)
239     {
240         static QString tr(const(char)* sourceText, const(char)*  /+ = nullptr +/, int /+ = -1 +/)
241             { return QString.fromUtf8(sourceText); }
242     }
243 /+ #if QT_DEPRECATED_SINCE(5, 0)
244     QT_DEPRECATED static QString trUtf8(const char *sourceText, const char * = nullptr, int = -1)
245         { return QString::fromUtf8(sourceText); }
246 #endif
247 #endif +/ //QT_NO_TRANSLATION
248 
249     final QString objectName() const;
250     final void setObjectName(ref const(QString) name);
251     extern(D) final void setObjectName(const(char)[] name)
252     {
253         QString s = QString.fromUtf8(name.ptr, cast(int)name.length);
254         setObjectName(s);
255     }
256 
257     pragma(inline, true) final bool isWidgetType() const { return d_ptr.isWidget; }
258     pragma(inline, true) final bool isWindowType() const { return d_ptr.isWindow; }
259 
260     pragma(inline, true) final bool signalsBlocked() const/+ noexcept+/ { return d_ptr.blockSig; }
261     final bool blockSignals(bool b)/+ noexcept+/;
262 
263     final QThread thread() const;
264     final void moveToThread(QThread thread);
265 
266     final int startTimer(int interval, /+ Qt:: +/qt.core.namespace.TimerType timerType = /+ Qt:: +/qt.core.namespace.TimerType.CoarseTimer);
267 /+ #if __has_include(<chrono>) +/
268     /+ Q_ALWAYS_INLINE +/
269 /+        pragma(inline, true) final int startTimer(/+ std::chrono:: +/milliseconds time, /+ Qt:: +/qt.core.namespace.TimerType timerType = /+ Qt:: +/qt.core.namespace.TimerType.CoarseTimer)
270     {
271         return startTimer(int(time.count()), timerType);
272     }+/
273 /+ #endif +/
274     final void killTimer(int id);
275 
276     /+ template<typename T> +/
277     /+ inline T findChild(const QString &aName = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
278     {
279         typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
280         return static_cast<T>(qt_qFindChild_helper(this, aName, ObjType::staticMetaObject, options));
281     } +/
282 
283     /+ template<typename T> +/
284     /+ inline QList<T> findChildren(const QString &aName = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
285     {
286         typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
287         QList<T> list;
288         qt_qFindChildren_helper(this, aName, ObjType::staticMetaObject,
289                                 reinterpret_cast<QList<void *> *>(&list), options);
290         return list;
291     } +/
292 
293 /+ #ifndef QT_NO_REGEXP
294 #if QT_DEPRECATED_SINCE(5, 13) +/
295     version(QT_NO_REGEXP){}else
296     {
297         /+ template<typename T> +/
298         /+ QT_DEPRECATED_X("Use findChildren(const QRegularExpression &, ...) instead.")
299         inline QList<T> findChildren(const QRegExp &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
300         {
301             typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
302             QList<T> list;
303             qt_qFindChildren_helper(this, re, ObjType::staticMetaObject,
304                                     reinterpret_cast<QList<void *> *>(&list), options);
305             return list;
306         } +/
307     }
308 /+ #endif
309 #endif
310 
311 #if QT_CONFIG(regularexpression) +/
312     /+ template<typename T> +/
313     /+ inline QList<T> findChildren(const QRegularExpression &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
314     {
315         typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
316         QList<T> list;
317         qt_qFindChildren_helper(this, re, ObjType::staticMetaObject,
318                                 reinterpret_cast<QList<void *> *>(&list), options);
319         return list;
320     } +/
321 /+ #endif +/ // QT_CONFIG(regularexpression)
322 
323     pragma(inline, true) final ref const(QObjectList) children() const { return d_ptr.children; }
324 
325     final void setParent(QObject parent);
326     final void installEventFilter(QObject filterObj);
327     final void removeEventFilter(QObject obj);
328 
329     static QMetaObject.Connection connect(const QObject sender, const char *signal,
330                         const QObject receiver, const char *member, ConnectionType = ConnectionType.AutoConnection);
331 
332     /+ static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,
333                         const QObject *receiver, const QMetaMethod &method,
334                         Qt::ConnectionType type = Qt::AutoConnection); +/
335 
336     /+ inline QMetaObject::Connection connect(const QObject *sender, const char *signal,
337                         const char *member, Qt::ConnectionType type = Qt::AutoConnection) const; +/
338 
339 /+ #ifdef Q_CLANG_QDOC
340     template<typename PointerToMemberFunction>
341     static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection);
342     template<typename PointerToMemberFunction, typename Functor>
343     static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor);
344     template<typename PointerToMemberFunction, typename Functor>
345     static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection);
346 #else +/
347     //Connect a signal to a pointer to qobject member function
348     /+ template <typename Func1, typename Func2> +/
349     /+ static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
350                                      const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot,
351                                      Qt::ConnectionType type = Qt::AutoConnection)
352     {
353         typedef QtPrivate::FunctionPointer<Func1> SignalType;
354         typedef QtPrivate::FunctionPointer<Func2> SlotType;
355 
356         Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
357                           "No Q_OBJECT in the class with the signal");
358 
359         //compilation error if the arguments does not match.
360         Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
361                           "The slot requires more arguments than the signal provides.");
362         Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
363                           "Signal and slot arguments are not compatible.");
364         Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
365                           "Return type of the slot is not compatible with the return type of the signal.");
366 
367         const int *types = nullptr;
368         if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
369             types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
370 
371         return connectImpl(sender, reinterpret_cast<void **>(&signal),
372                            receiver, reinterpret_cast<void **>(&slot),
373                            new QtPrivate::QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
374                                            typename SignalType::ReturnType>(slot),
375                             type, types, &SignalType::Object::staticMetaObject);
376     } +/
377 
378     //connect to a function pointer  (not a member)
379     /+ template <typename Func1, typename Func2> +/
380     /+ static inline typename std::enable_if<int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0, QMetaObject::Connection>::type
381             connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
382     {
383         return connect(sender, signal, sender, slot, Qt::DirectConnection);
384     } +/
385 
386     //connect to a function pointer  (not a member)
387     /+ template <typename Func1, typename Func2> +/
388     /+ static inline typename std::enable_if<int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0 &&
389                                           !QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction, QMetaObject::Connection>::type
390             connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
391                     Qt::ConnectionType type = Qt::AutoConnection)
392     {
393         typedef QtPrivate::FunctionPointer<Func1> SignalType;
394         typedef QtPrivate::FunctionPointer<Func2> SlotType;
395 
396         Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
397                           "No Q_OBJECT in the class with the signal");
398 
399         //compilation error if the arguments does not match.
400         Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
401                           "The slot requires more arguments than the signal provides.");
402         Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
403                           "Signal and slot arguments are not compatible.");
404         Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
405                           "Return type of the slot is not compatible with the return type of the signal.");
406 
407         const int *types = nullptr;
408         if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
409             types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
410 
411         return connectImpl(sender, reinterpret_cast<void **>(&signal), context, nullptr,
412                            new QtPrivate::QStaticSlotObject<Func2,
413                                                  typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
414                                                  typename SignalType::ReturnType>(slot),
415                            type, types, &SignalType::Object::staticMetaObject);
416     } +/
417 
418     //connect to a functor
419     /+ template <typename Func1, typename Func2> +/
420     /+ static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type
421             connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
422     {
423         return connect(sender, signal, sender, std::move(slot), Qt::DirectConnection);
424     } +/
425 
426     //connect to a functor, with a "context" object defining in which event loop is going to be executed
427     /+ template <typename Func1, typename Func2> +/
428     /+ static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type
429             connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
430                     Qt::ConnectionType type = Qt::AutoConnection)
431     {
432         typedef QtPrivate::FunctionPointer<Func1> SignalType;
433         const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<Func2 , typename SignalType::Arguments>::Value;
434 
435         Q_STATIC_ASSERT_X((FunctorArgumentCount >= 0),
436                           "Signal and slot arguments are not compatible.");
437         const int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0;
438         typedef typename QtPrivate::FunctorReturnType<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value>::Value SlotReturnType;
439 
440         Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<SlotReturnType, typename SignalType::ReturnType>::value),
441                           "Return type of the slot is not compatible with the return type of the signal.");
442 
443         Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
444                           "No Q_OBJECT in the class with the signal");
445 
446         const int *types = nullptr;
447         if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
448             types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
449 
450         return connectImpl(sender, reinterpret_cast<void **>(&signal), context, nullptr,
451                            new QtPrivate::QFunctorSlotObject<Func2, SlotArgumentCount,
452                                 typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value,
453                                 typename SignalType::ReturnType>(std::move(slot)),
454                            type, types, &SignalType::Object::staticMetaObject);
455     } +/
456 /+ #endif +/ //Q_CLANG_QDOC
457 
458     /+ static bool disconnect(const QObject *sender, const char *signal,
459                            const QObject *receiver, const char *member); +/
460     /+ static bool disconnect(const QObject *sender, const QMetaMethod &signal,
461                            const QObject *receiver, const QMetaMethod &member); +/
462     /+ inline bool disconnect(const char *signal = nullptr,
463                            const QObject *receiver = nullptr, const char *member = nullptr) const
464         { return disconnect(this, signal, receiver, member); } +/
465     /+ inline bool disconnect(const QObject *receiver, const char *member = nullptr) const
466         { return disconnect(this, nullptr, receiver, member); } +/
467     /+ static bool disconnect(const QMetaObject::Connection &); +/
468 
469 /+ #ifdef Q_CLANG_QDOC
470     template<typename PointerToMemberFunction>
471     static bool disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method);
472 #else +/
473     /+ template <typename Func1, typename Func2> +/
474     /+ static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
475                                   const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot)
476     {
477         typedef QtPrivate::FunctionPointer<Func1> SignalType;
478         typedef QtPrivate::FunctionPointer<Func2> SlotType;
479 
480         Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
481                           "No Q_OBJECT in the class with the signal");
482 
483         //compilation error if the arguments does not match.
484         Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
485                           "Signal and slot arguments are not compatible.");
486 
487         return disconnectImpl(sender, reinterpret_cast<void **>(&signal), receiver, reinterpret_cast<void **>(&slot),
488                               &SignalType::Object::staticMetaObject);
489     } +/
490     /+ template <typename Func1> +/
491     /+ static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
492                                   const QObject *receiver, void **zero)
493     {
494         // This is the overload for when one wish to disconnect a signal from any slot. (slot=nullptr)
495         // Since the function template parameter cannot be deduced from '0', we use a
496         // dummy void ** parameter that must be equal to 0
497         Q_ASSERT(!zero);
498         typedef QtPrivate::FunctionPointer<Func1> SignalType;
499         return disconnectImpl(sender, reinterpret_cast<void **>(&signal), receiver, zero,
500                               &SignalType::Object::staticMetaObject);
501     } +/
502 /+ #endif +/ //Q_CLANG_QDOC
503 
504     template signal(string name, Params...)
505     {
506         extern(D) auto signal(this T)()
507         {
508             import std.meta;
509             static if(Params.length)
510                 return DQtMember!(T, Filter!(parametersSame!Params, __traits(getOverloads, T, name)))(cast(T)this);
511             else
512                 return DQtMember!(T, __traits(getOverloads, T, name))(cast(T)this);
513         }
514     }
515     template slot(string name, Params...)
516     {
517         extern(D) auto slot(this T)()
518         {
519             import std.meta;
520             static if(Params.length)
521                 return DQtMember!(T, Filter!(parametersSame!Params, __traits(getOverloads, T, name)))(cast(T)this);
522             else
523                 return DQtMember!(T, __traits(getOverloads, T, name))(cast(T)this);
524         }
525     }
526 
527         /+ template <typename Func1, typename Func2>
528      +//+ static inline typename std::enable_if<int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0 &&
529                                           !QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction, QMetaObject::Connection>::type
530             connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
531                     Qt::ConnectionType type = Qt::AutoConnection)
532 +/
533     static extern(D) QMetaObject.Connection connect(Signal, Dg)(Signal sender, Dg dg, ConnectionType type = ConnectionType.AutoConnection) if(is(Signal: DQtMember!P, P...) && !is(Dg: DQtMember!P2, P2...))
534     {
535         return connect(sender, sender.obj, dg, type);
536     }
537     static extern(D) QMetaObject.Connection connect(Signal, Dg)(Signal sender, QObject context, Dg dg, ConnectionType type = ConnectionType.AutoConnection) if(is(Signal: DQtMember!P, P...) && !is(Dg: DQtMember!P2, P2...))
538     {
539         import core.stdcpp.new_;
540 
541         /*typedef QtPrivate::FunctionPointer<Func1> SignalType;
542         typedef QtPrivate::FunctionPointer<Func2> SlotType;
543 
544         Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
545                           "No Q_OBJECT in the class with the signal");*/
546 
547         //compilation error if the arguments does not match.
548         /*Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
549                           "The slot requires more arguments than the signal provides.");
550         Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
551                           "Signal and slot arguments are not compatible.");
552         Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
553                           "Return type of the slot is not compatible with the return type of the signal.");*/
554 
555         const int *types = null;
556         if (type == ConnectionType.QueuedConnection || type == ConnectionType.BlockingQueuedConnection)
557         {
558             assert(false);
559             //types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
560         }
561 
562         static assert(Signal.Members.length == 1);
563 
564         auto signal = &memberFunctionExternDeclaration!(Signal.Members[0]);
565 
566         auto slotObj = cpp_new!(DQtStaticSlotObject!(Parameters!Dg))(dg);
567 
568         //pragma(msg, __traits(parent, Signal.Type.staticMetaObject));
569 
570         auto mo = &Signal.Type.staticMetaObject;
571 
572         // TODO: ABI for virtual functions is different.
573         CPPMemberFunctionPointer!(Signal.Type) memberFunction = CPPMemberFunctionPointer!(Signal.Type)(signal);
574 
575         return connectImpl(sender.obj, cast(void**)&memberFunction, context, null,
576                            &slotObj.base,
577                            type, types, mo);
578     }
579 
580     static extern(D) QMetaObject.Connection connect(Signal, Slot)(Signal sender, Slot receiver, ConnectionType type = ConnectionType.AutoConnection) if(is(Signal: DQtMember!P, P...) && is(Slot: DQtMember!P2, P2...))
581     {
582        import core.stdcpp.new_;
583 
584        /+ typedef QtPrivate::FunctionPointer<Func1> SignalType;
585         typedef QtPrivate::FunctionPointer<Func2> SlotType;
586 
587         Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
588                           "No Q_OBJECT in the class with the signal");
589 
590         //compilation error if the arguments does not match.
591         Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
592                           "The slot requires more arguments than the signal provides.");
593         Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
594                           "Signal and slot arguments are not compatible.");
595         Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
596                           "Return type of the slot is not compatible with the return type of the signal.");+/
597 
598         const int *types = null;
599         if (type == ConnectionType.QueuedConnection || type == ConnectionType.BlockingQueuedConnection)
600         {
601             assert(false); // TODO
602             //types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
603         }
604 
605         enum size_t[2] overloadIndices = delegate size_t[2](){
606             size_t[2] r = [size_t.max, size_t.max];
607             size_t numPossible;
608             static foreach(i, signal; Signal.Members)
609             static foreach(j, slot; Slot.Members)
610             {
611                 //pragma(msg, i, " ", j, " ", __traits(identifier, signal), " ", __traits(identifier, slot));
612                 static if(Parameters!(signal).length >= Parameters!(slot).length) // TODO: allow default arguments
613                 {{
614                     bool possible = true;
615                     static foreach(k; 0..Parameters!(slot).length)
616                     {
617                         static if(!__traits(compiles, {Parameters!(slot)[k] p = Parameters!(signal)[k].init;}))
618                         {
619                             //pragma(msg, " param ", k, " not compatible ", Parameters!(signal)[k], " ", Parameters!(slot)[k]);
620                             possible = false;
621                         }
622                         else
623                         {
624                             //pragma(msg, " param ", k, " compatible ", Parameters!(signal)[k], " ", Parameters!(slot)[k]);
625                         }
626                     }
627                     if(possible)
628                     {
629                         r = [i, j];
630                         numPossible++;
631                     }
632                 }}
633             }
634             if(numPossible == 1)
635                 return r;
636             return [size_t.max, size_t.max];
637         }();
638 
639         static if(overloadIndices[0] == size_t.max || overloadIndices[1] == size_t.max)
640         {
641             pragma(msg, "Signals:");
642             static foreach(signal; Signal.Members)
643                 pragma(msg, __traits(identifier, signal), " ", Parameters!(signal));
644             pragma(msg, "Slots:");
645             static foreach(slot; Slot.Members)
646                 pragma(msg, __traits(identifier, slot), " ", Parameters!(slot));
647         }
648         static assert(overloadIndices[0] != size_t.max);
649         static assert(overloadIndices[1] != size_t.max);
650 
651         auto signal = &memberFunctionExternDeclaration!(Signal.Members[overloadIndices[0]]);
652 
653         auto slot = &memberFunctionExternDeclaration!(Slot.Members[overloadIndices[1]]);
654 
655         alias UsedParams = Parameters!(Signal.Members[overloadIndices[0]])[0..Parameters!(Slot.Members[overloadIndices[1]]).length];
656 
657         auto slotObj = cpp_new!(DQtMemberSlotObject!(typeof(Slot.obj), Slot.Members[overloadIndices[1]], UsedParams))(0);
658 
659         auto mo = &Signal.Type.staticMetaObject;
660 
661         // TODO: ABI for virtual functions is different.
662         CPPMemberFunctionPointer!(Signal.Type) memberFunction = CPPMemberFunctionPointer!(Signal.Type)(signal);
663         CPPMemberFunctionPointer!(Slot.Type) memberFunction2 = CPPMemberFunctionPointer!(Slot.Type)(slot);
664 
665         return connectImpl(sender.obj, cast(void**)&memberFunction,
666                            receiver.obj, cast(void**)&memberFunction2,
667                            &slotObj.base,
668                             type, types, mo);
669     }
670 
671 /+ #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +/
672     final void dumpObjectTree(); // ### Qt 6: remove
673     final void dumpObjectInfo(); // ### Qt 6: remove
674 /+ #endif +/
675     final void dumpObjectTree() const;
676     final void dumpObjectInfo() const;
677 
678 /+ #ifndef QT_NO_PROPERTIES +/
679     version(QT_NO_PROPERTIES){}else
680     {
681         final bool setProperty(const(char)* name, ref const(QVariant) value);
682         final bool setProperty(T)(const(char)* name, auto ref T value)
683         {
684             QVariant v = QVariant(value);
685             return setProperty(name, v);
686         }
687         final QVariant property(const(char)* name) const;
688         final QList!(QByteArray) dynamicPropertyNames() const;
689     }
690 /+ #endif // QT_NO_PROPERTIES
691 
692 #ifndef QT_NO_USERDATA +/
693     version(QT_NO_USERDATA){}else
694     {
695         /+ QT_DEPRECATED_VERSION_5_14 +/
696             static uint registerUserData();
697         /+ QT_DEPRECATED_VERSION_X_5_14("Use setProperty()") +/
698             final void setUserData(uint id, QObjectUserData data);
699         /+ QT_DEPRECATED_VERSION_X_5_14("Use property()") +/
700             final QObjectUserData userData(uint id) const;
701     }
702 /+ #endif +/ // QT_NO_USERDATA
703 
704 /+ Q_SIGNALS +/public:
705     @QSignal final void destroyed(QObject  /+ = nullptr +/);
706     @QSignal final void objectNameChanged(ref const(QString) objectName, QPrivateSignal);
707 
708 public:
709     pragma(inline, true) final QObject parent() const { return d_ptr.data.parent; }
710 
711     pragma(inline, true) final bool inherits(const(char)* classname) const
712         { return const_cast!(QObject)(this).qt_metacast(classname) !is null; }
713 
714 public /+ Q_SLOTS +/:
715     @QSlot final void deleteLater();
716 
717 protected:
718     final QObject sender() const;
719     final int senderSignalIndex() const;
720     final int receivers(const(char)* signal) const;
721     final bool isSignalConnected(ref const(QMetaMethod) signal) const;
722 
723     /+ virtual +/ void timerEvent(QTimerEvent event);
724     /+ virtual +/ void childEvent(QChildEvent event);
725     /+ virtual +/ void customEvent(QEvent event);
726 
727     /+ virtual +/ void connectNotify(ref const(QMetaMethod) signal);
728     /+ virtual +/ void disconnectNotify(ref const(QMetaMethod) signal);
729 
730 protected:
731     this(ref QObjectPrivate dd, QObject parent = null);
732 
733 protected:
734     QScopedPointer!(QObjectData) d_ptr;
735 
736     mixin(mangleWindows("?staticQtMetaObject@QObject@@1UQMetaObject@@B", exportOnWindows ~ q{
737     extern static __gshared const(QMetaObject) staticQtMetaObject;
738     }));
739     /+ friend inline const QMetaObject *qt_getQtMetaObject() noexcept; +/
740 
741     /+ friend struct QMetaObject; +/
742     /+ friend struct QMetaObjectPrivate; +/
743     /+ friend class QMetaCallEvent; +/
744     /+ friend class QApplication; +/
745     /+ friend class QApplicationPrivate; +/
746     /+ friend class QCoreApplication; +/
747     /+ friend class QCoreApplicationPrivate; +/
748     /+ friend class QWidget; +/
749     /+ friend class QAccessibleWidget; +/
750     /+ friend class QThreadData; +/
751 
752 private:
753     /+ Q_DISABLE_COPY(QObject) +/
754     /+ Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *)) +/
755 
756 private:
757     mixin(mangleWindows("?connectImpl@QObject@@CA?AVConnection@QMetaObject@@PEBV1@PEAPEAX01PEAVQSlotObjectBase@QtPrivate@@W4ConnectionType@Qt@@PEBHPEBU3@@Z", q{
758     static QMetaObject.Connection connectImpl(const(QObject) sender, void** signal,
759                                                    const(QObject) receiver, void** slotPtr,
760                                                    /+ QtPrivate:: +/qt.core.objectdefs_impl.QSlotObjectBase* slot, /+ Qt:: +/qt.core.namespace.ConnectionType type,
761                                                    const(int)* types, const(QMetaObject)* senderMetaObject);
762     }));
763 
764     static bool disconnectImpl(const(QObject) sender, void** signal, const(QObject) receiver, void** slot,
765                                    const(QMetaObject)* senderMetaObject);
766 
767 }
768 
769 /+ inline QMetaObject::Connection QObject::connect(const QObject *asender, const char *asignal,
770                                             const char *amember, Qt::ConnectionType atype) const
771 { return connect(asender, asignal, this, amember, atype); } +/
772 
773 pragma(inline, true) const(QMetaObject)* qt_getQtMetaObject()/+ noexcept+/
774 { return &QObject.staticQtMetaObject; }
775 
776 version(QT_NO_USERDATA){}else
777 {
778 class /+ Q_CORE_EXPORT +/ QObjectUserData {
779 private:
780     /+ Q_DISABLE_COPY(QObjectUserData) +/
781 public:
782     /+ QObjectUserData() = default; +/
783     /+ virtual +/~this();
784 }
785 }
786 
787 /+ #if QT_DEPRECATED_SINCE(5, 0)
788 template<typename T>
789 inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QString())
790 { return o->findChild<T>(name); }
791 
792 template<typename T>
793 inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QString &name = QString())
794 {
795     return o->findChildren<T>(name);
796 }
797 
798 #if !defined(QT_NO_REGEXP) || defined(Q_CLANG_QDOC)
799 template<typename T>
800 inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QRegExp &re)
801 {
802     return o->findChildren<T>(re);
803 }
804 #endif
805 
806 #endif //QT_DEPRECATED
807 
808 template <class T>
809 inline T qobject_cast(QObject *object)
810 {
811     typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
812     Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
813                     "qobject_cast requires the type to have a Q_OBJECT macro");
814     return static_cast<T>(ObjType::staticMetaObject.cast(object));
815 }
816 
817 template <class T>
818 inline T qobject_cast(const QObject *object)
819 {
820     typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
821     Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
822                       "qobject_cast requires the type to have a Q_OBJECT macro");
823     return static_cast<T>(ObjType::staticMetaObject.cast(object));
824 }
825 
826 
827 template <class T> inline const char * qobject_interface_iid()
828 { return nullptr; }
829 
830 
831 #if defined(Q_CLANG_QDOC)
832 #  define Q_DECLARE_INTERFACE(IFace, IId)
833 #elif !defined(Q_MOC_RUN)
834 #  define Q_DECLARE_INTERFACE(IFace, IId) \
835     template <> inline const char *qobject_interface_iid<IFace *>() \
836     { return IId; } \
837     template <> inline IFace *qobject_cast<IFace *>(QObject *object) \
838     { return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : nullptr)); } \
839     template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
840     { return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : nullptr)); }
841 #endif // Q_MOC_RUN
842 
843 #ifndef QT_NO_DEBUG_STREAM
844 Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
845 #endif
846 
847 class QSignalBlocker
848 {
849 public:
850     inline explicit QSignalBlocker(QObject *o) noexcept;
851     inline explicit QSignalBlocker(QObject &o) noexcept;
852     inline ~QSignalBlocker();
853 
854     inline QSignalBlocker(QSignalBlocker &&other) noexcept;
855     inline QSignalBlocker &operator=(QSignalBlocker &&other) noexcept;
856 
857     inline void reblock() noexcept;
858     inline void unblock() noexcept;
859 private:
860     Q_DISABLE_COPY(QSignalBlocker)
861     QObject * m_o;
862     bool m_blocked;
863     bool m_inhibited;
864 };
865 
866 QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) noexcept
867     : m_o(other.m_o),
868       m_blocked(other.m_blocked),
869       m_inhibited(other.m_inhibited)
870 {
871     other.m_o = nullptr;
872 }
873 
874 QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) noexcept
875 {
876     if (this != &other) {
877         // if both *this and other block the same object's signals:
878         // unblock *this iff our dtor would unblock, but other's wouldn't
879         if (m_o != other.m_o || (!m_inhibited && other.m_inhibited))
880             unblock();
881         m_o = other.m_o;
882         m_blocked = other.m_blocked;
883         m_inhibited = other.m_inhibited;
884         // disable other:
885         other.m_o = nullptr;
886     }
887     return *this;
888 }
889 
890 namespace QtPrivate {
891     inline QObject & deref_for_methodcall(QObject &o) { return  o; }
892     inline QObject & deref_for_methodcall(QObject *o) { return *o; }
893 }
894 #define Q_SET_OBJECT_NAME(obj) QT_PREPEND_NAMESPACE(QtPrivate)::deref_for_methodcall(obj).setObjectName(QLatin1String(#obj)) +/
895 
896 
897 /+ #endif +/
898 
899 template IsQSignal(alias F)
900 {
901     enum IsQSignal = getUDAs!(F, QObject.QSignal).length > 0;
902 }
903 template IsQSlot(alias F)
904 {
905     enum IsQSlot = getUDAs!(F, QObject.QSlot).length > 0;
906 }
907 template IsQInvokable(alias F)
908 {
909     enum IsQInvokable = getUDAs!(F, QObject.QInvokable).length > 0;
910 }
911 template IsQScriptable(alias F)
912 {
913     enum IsQScriptable = getUDAs!(F, QObject.Scriptable).length > 0;
914 }