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.objectdefs;
13 extern(C++):
14 
15 import qt.config;
16 import qt.core.bytearray;
17 import qt.core.metaobject;
18 import qt.core.metatype;
19 import qt.core.namespace;
20 import qt.core.object;
21 import qt.core.objectdefs_impl;
22 import qt.helpers;
23 import std.traits;
24 import std.meta;
25 version(QT_NO_TRANSLATION){}else
26     import qt.core.string;
27 
28 /+ #if defined(__OBJC__) && !defined(__cplusplus)
29 #  warning "File built in Objective-C mode (.m), but using Qt requires Objective-C++ (.mm)"
30 #endif
31 
32 
33 
34 
35 
36 #ifndef QT_NO_META_MACROS
37 // macro for onaming members
38 #ifdef METHOD
39 #undef METHOD
40 #endif
41 #ifdef SLOT
42 #undef SLOT
43 #endif
44 #ifdef SIGNAL
45 #undef SIGNAL
46 #endif
47 #endif +/ // QT_NO_META_MACROS
48 
49 /+ Q_CORE_EXPORT +/ const(char)* qFlagLocation(const(char)* method);
50 
51 /+ #ifndef QT_NO_META_MACROS +/
52 /+ #ifndef QT_NO_DEBUG
53 # define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__)
54 # ifndef QT_NO_KEYWORDS
55 #  define METHOD(a)   qFlagLocation("0"#a QLOCATION)
56 # endif
57 # define SLOT(a)     qFlagLocation("1"#a QLOCATION)
58 # define SIGNAL(a)   qFlagLocation("2"#a QLOCATION)
59 #else +/
60 /+ # ifndef QT_NO_KEYWORDS
61 #  define METHOD(a)   "0"#a
62 # endif +/
63 /+ # define SLOT(a)     "1"#a +/
64 extern(D) alias SLOT = function string(string a)
65 {
66     return     mixin(interpolateMixin(q{"1" ~$(stringifyMacroParameter(a))}));
67 };
68 /+ # define SIGNAL(a)   "2"#a +/
69 extern(D) alias SIGNAL = function string(string a)
70 {
71     return   mixin(interpolateMixin(q{"2" ~$(stringifyMacroParameter(a))}));
72 };
73 /+ #endif
74 
75 #define QMETHOD_CODE  0                        // member type codes
76 #define QSLOT_CODE    1
77 #define QSIGNAL_CODE  2 +/
78 /+ #endif // QT_NO_META_MACROS
79 
80 #define Q_ARG(type, data) QArgument<type >(#type, data)
81 #define Q_RETURN_ARG(type, data) QReturnArgument<type >(#type, data)
82 
83 
84 namespace QtPrivate {
85 class QMetaTypeInterface} +/
86 
87 struct QMethodRawArguments
88 {
89     void** arguments;
90 }
91 
92 /// Binding for C++ class [QGenericArgument](https://doc.qt.io/qt-6/qgenericargument.html).
93 extern(C++, class) struct /+ Q_CORE_EXPORT +/ QGenericArgument
94 {
95 public:
96     pragma(inline, true) this(const(char)* aName/+ = null+/, const(void)* aData = null)
97     {
98         this._data = aData;
99         this._name = aName;
100     }
101     pragma(inline, true) void* data() const { return const_cast!(void*)(_data); }
102     pragma(inline, true) const(char)* name() const { return _name; }
103 
104 private:
105     const(void)* _data = null;
106     const(char)* _name = null;
107     mixin(CREATE_CONVENIENCE_WRAPPERS);
108 }
109 
110 /// Binding for C++ class [QGenericReturnArgument](https://doc.qt.io/qt-6/qgenericreturnargument.html).
111 extern(C++, class) struct /+ Q_CORE_EXPORT +/ QGenericReturnArgument
112 {
113     public QGenericArgument base0;
114     alias base0 this;
115 public:
116     pragma(inline, true) this(const(char)* aName/+ = null+/, void* aData = null)
117     {
118         this.base0 = QGenericArgument(aName, aData);
119     }
120     mixin(CREATE_CONVENIENCE_WRAPPERS);
121 }
122 
123 class QArgument(T): QGenericArgument
124 {
125 public:
126     pragma(inline, true) this(const(char)* aName, ref const(T) aData)
127     {
128         super(aName, static_cast!(const(void)*)(&aData));
129     }
130 }
131 /+ template <class T>
132 class QArgument<T &>: public QGenericArgument
133 {
134 public:
135     inline QArgument(const char *aName, T &aData)
136         : QGenericArgument(aName, static_cast<const void *>(&aData))
137         {}
138 }; +/
139 
140 
141 class QReturnArgument(T): QGenericReturnArgument
142 {
143 public:
144     pragma(inline, true) this(const(char)* aName, ref T aData)
145     {
146         super(aName, static_cast!(void*)(&aData));
147     }
148 }
149 
150 struct /+ Q_CORE_EXPORT +/ QMetaObject
151 {
152     /+
153     extern(C++, class) struct Connection;
154     +/
155     /// Binding for C++ class [Connection](https://doc.qt.io/qt-6/qmetaobject-connection.html).
156     extern(C++, class) struct /+ Q_CORE_EXPORT +/ Connection {
157     private:
158         void* d_ptr; //QObjectPrivate::Connection*
159         /+ explicit +/this(void* data)
160         {
161             this.d_ptr = data;
162         }
163         /+ friend class QObject; +/
164         /+ friend class QObjectPrivate; +/
165         /+ friend struct QMetaObject; +/
166         bool isConnected_helper() const;
167     public:
168         ~this();
169 
170         this(ref const(Connection) other);
171         /+ref Connection operator =(ref const(Connection) other);+/
172     /+ #ifdef Q_QDOC
173         operator bool() const;
174     #else +/
175         // still using the restricted bool trick here, in order to support
176         // code using copy-init (e.g. `bool ok = connect(...)`)
177         alias RestrictedBool = void*/+ Connection::* +/*;
178         /+auto opCast(T : RestrictedBool)() const { return d_ptr && isConnected_helper() ? &Connection.d_ptr : null; }+/
179     /+ #endif +/
180 
181         /+ Connection(Connection &&other) noexcept : d_ptr(qExchange(other.d_ptr, nullptr)) {} +/
182         /+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Connection) +/
183         /+ void swap(Connection &other) noexcept { qSwap(d_ptr, other.d_ptr); } +/
184         mixin(CREATE_CONVENIENCE_WRAPPERS);
185     }
186 
187     const(char)* className() const;
188 /+    pragma(inline, true) const(QMetaObject)* superClass() const
189     { return cast(const(QMetaObject)*)(d.superdata); }+/
190 
191     bool inherits(const(QMetaObject)* metaObject) const/+ noexcept+/;
192     QObject cast_(QObject obj) const
193     { return const_cast!(QObject)(cast_(const_cast!(const(QObject))(obj))); }
194     mixin(mangleWindows("?cast@QMetaObject@@QEBAPEBVQObject@@PEBV2@@Z", q{
195     mixin(mangleItanium("_ZNK11QMetaObject4castEPK7QObject", q{
196     const(QObject) cast_(const(QObject) obj) const;
197     }));
198     }));
199 
200     version(QT_NO_TRANSLATION){}else
201     {
202         QString tr(const(char)* s, const(char)* c, int n = -1) const;
203     }
204 
205     QMetaType metaType() const;
206 
207     int methodOffset() const;
208     int enumeratorOffset() const;
209     int propertyOffset() const;
210     int classInfoOffset() const;
211 
212     int constructorCount() const;
213     int methodCount() const;
214     int enumeratorCount() const;
215     int propertyCount() const;
216     int classInfoCount() const;
217 
218     int indexOfConstructor(const(char)* constructor) const;
219     int indexOfMethod(const(char)* method) const;
220     int indexOfSignal(const(char)* signal) const;
221     int indexOfSlot(const(char)* slot) const;
222     int indexOfEnumerator(const(char)* name) const;
223     int indexOfProperty(const(char)* name) const;
224     int indexOfClassInfo(const(char)* name) const;
225 
226     QMetaMethod constructor(int index) const;
227     QMetaMethod method(int index) const;
228     QMetaEnum enumerator(int index) const;
229     QMetaProperty property(int index) const;
230     QMetaClassInfo classInfo(int index) const;
231     QMetaProperty userProperty() const;
232 
233     static bool checkConnectArgs(const(char)* signal, const(char)* method);
234     static bool checkConnectArgs(ref const(QMetaMethod) signal,
235                                      ref const(QMetaMethod) method);
236     static QByteArray normalizedSignature(const(char)* method);
237     static QByteArray normalizedType(const(char)* type);
238 
239     // internal index-based connect
240     /+ static Connection connect(const QObject *sender, int signal_index,
241                         const QObject *receiver, int method_index,
242                         int type = 0, int *types = nullptr); +/
243     // internal index-based disconnect
244     /+ static bool disconnect(const QObject *sender, int signal_index,
245                            const QObject *receiver, int method_index); +/
246     mixin(changeWindowsMangling(q{mangleClassesTailConst}, q{
247     static bool disconnectOne(const(QObject) sender, int signal_index,
248                                   const(QObject) receiver, int method_index);
249     }));
250     // internal slot-name based connect
251     static void connectSlotsByName(QObject o);
252 
253     // internal index-based signal activation
254     static void activate(QObject sender, int signal_index, void** argv);
255     static void activate(QObject sender, const(QMetaObject)* , int local_signal_index, void** argv);
256     static void activate(QObject sender, int signal_offset, int local_signal_index, void** argv);
257 
258     static bool invokeMethod(QObject obj, const(char)* member,
259                                  /+ Qt:: +/qt.core.namespace.ConnectionType,
260                                  QGenericReturnArgument ret,
261                                  QGenericArgument val0 = QGenericArgument(null),
262                                  QGenericArgument val1 = QGenericArgument(),
263                                  QGenericArgument val2 = QGenericArgument(),
264                                  QGenericArgument val3 = QGenericArgument(),
265                                  QGenericArgument val4 = QGenericArgument(),
266                                  QGenericArgument val5 = QGenericArgument(),
267                                  QGenericArgument val6 = QGenericArgument(),
268                                  QGenericArgument val7 = QGenericArgument(),
269                                  QGenericArgument val8 = QGenericArgument(),
270                                  QGenericArgument val9 = QGenericArgument());
271 
272 /+    pragma(inline, true) static bool invokeMethod(QObject obj, const(char)* member,
273                                  QGenericReturnArgument ret,
274                                  QGenericArgument val0 = QGenericArgument(null),
275                                  QGenericArgument val1 = QGenericArgument(),
276                                  QGenericArgument val2 = QGenericArgument(),
277                                  QGenericArgument val3 = QGenericArgument(),
278                                  QGenericArgument val4 = QGenericArgument(),
279                                  QGenericArgument val5 = QGenericArgument(),
280                                  QGenericArgument val6 = QGenericArgument(),
281                                  QGenericArgument val7 = QGenericArgument(),
282                                  QGenericArgument val8 = QGenericArgument(),
283                                  QGenericArgument val9 = QGenericArgument())
284     {
285         return invokeMethod(obj, member, /+ Qt:: +/qt.core.namespace.ConnectionType.AutoConnection, ret, val0, val1, val2, val3,
286                 val4, val5, val6, val7, val8, val9);
287     }+/
288 
289 /+    pragma(inline, true) static bool invokeMethod(QObject obj, const(char)* member,
290                                  /+ Qt:: +/qt.core.namespace.ConnectionType type,
291                                  QGenericArgument val0 = QGenericArgument(null),
292                                  QGenericArgument val1 = QGenericArgument(),
293                                  QGenericArgument val2 = QGenericArgument(),
294                                  QGenericArgument val3 = QGenericArgument(),
295                                  QGenericArgument val4 = QGenericArgument(),
296                                  QGenericArgument val5 = QGenericArgument(),
297                                  QGenericArgument val6 = QGenericArgument(),
298                                  QGenericArgument val7 = QGenericArgument(),
299                                  QGenericArgument val8 = QGenericArgument(),
300                                  QGenericArgument val9 = QGenericArgument())
301     {
302         return invokeMethod(obj, member, type, QGenericReturnArgument(), val0, val1, val2,
303                                  val3, val4, val5, val6, val7, val8, val9);
304     }+/
305 
306 /+    pragma(inline, true) static bool invokeMethod(QObject obj, const(char)* member,
307                                  QGenericArgument val0 = QGenericArgument(null),
308                                  QGenericArgument val1 = QGenericArgument(),
309                                  QGenericArgument val2 = QGenericArgument(),
310                                  QGenericArgument val3 = QGenericArgument(),
311                                  QGenericArgument val4 = QGenericArgument(),
312                                  QGenericArgument val5 = QGenericArgument(),
313                                  QGenericArgument val6 = QGenericArgument(),
314                                  QGenericArgument val7 = QGenericArgument(),
315                                  QGenericArgument val8 = QGenericArgument(),
316                                  QGenericArgument val9 = QGenericArgument())
317     {
318         return invokeMethod(obj, member, /+ Qt:: +/qt.core.namespace.ConnectionType.AutoConnection, QGenericReturnArgument(), val0,
319                 val1, val2, val3, val4, val5, val6, val7, val8, val9);
320     }+/
321 
322 /+ #ifdef Q_CLANG_QDOC
323     template<typename Functor, typename FunctorReturnType>
324     static bool invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr);
325     template<typename Functor, typename FunctorReturnType>
326     static bool invokeMethod(QObject *context, Functor function, FunctorReturnType *ret);
327 #else +/
328 
329     // invokeMethod() for member function pointer
330     /+ template <typename Func> +/
331     /+ static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
332                                    && !std::is_convertible<Func, const char*>::value
333                                    && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type
334     invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object,
335                  Func function,
336                  Qt::ConnectionType type = Qt::AutoConnection,
337                  typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr)
338     {
339         return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), type, ret);
340     } +/
341 
342     /+ template <typename Func> +/
343     /+ static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
344                                    && !std::is_convertible<Func, const char*>::value
345                                    && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type
346     invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object,
347                  Func function,
348                  typename QtPrivate::FunctionPointer<Func>::ReturnType *ret)
349     {
350         return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), Qt::AutoConnection, ret);
351     } +/
352 
353     // invokeMethod() for function pointer (not member)
354     /+ template <typename Func> +/
355     /+ static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
356                                    && !std::is_convertible<Func, const char*>::value
357                                    && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type
358     invokeMethod(QObject *context, Func function,
359                  Qt::ConnectionType type = Qt::AutoConnection,
360                  typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr)
361     {
362         return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), type, ret);
363     } +/
364 
365     /+ template <typename Func> +/
366     /+ static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
367                                    && !std::is_convertible<Func, const char*>::value
368                                    && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type
369     invokeMethod(QObject *context, Func function,
370                  typename QtPrivate::FunctionPointer<Func>::ReturnType *ret)
371     {
372         return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), Qt::AutoConnection, ret);
373     } +/
374 
375     // invokeMethod() for Functor
376     /+ template <typename Func> +/
377     /+ static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
378                                    && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1
379                                    && !std::is_convertible<Func, const char*>::value, bool>::type
380     invokeMethod(QObject *context, Func function,
381                  Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr)
382     {
383         return invokeMethodImpl(context,
384                                 new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
385                                 type,
386                                 ret);
387     } +/
388 
389     /+ template <typename Func> +/
390     /+ static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
391                                    && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1
392                                    && !std::is_convertible<Func, const char*>::value, bool>::type
393     invokeMethod(QObject *context, Func function, decltype(function()) *ret)
394     {
395         return invokeMethodImpl(context,
396                                 new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
397                                 Qt::AutoConnection,
398                                 ret);
399     } +/
400 
401 /+ #endif +/
402 
403     QObject newInstance(QGenericArgument val0 = QGenericArgument(null),
404                              QGenericArgument val1 = QGenericArgument(),
405                              QGenericArgument val2 = QGenericArgument(),
406                              QGenericArgument val3 = QGenericArgument(),
407                              QGenericArgument val4 = QGenericArgument(),
408                              QGenericArgument val5 = QGenericArgument(),
409                              QGenericArgument val6 = QGenericArgument(),
410                              QGenericArgument val7 = QGenericArgument(),
411                              QGenericArgument val8 = QGenericArgument(),
412                              QGenericArgument val9 = QGenericArgument()) const;
413 
414     enum Call {
415         InvokeMetaMethod,
416         ReadProperty,
417         WriteProperty,
418         ResetProperty,
419         CreateInstance,
420         IndexOfMethod,
421         RegisterPropertyMetaType,
422         RegisterMethodArgumentMetaType,
423         BindableProperty
424     }
425 
426     int static_metacall(Call, int, void** ) const;
427     static int metacall(QObject , Call, int, void** );
428 
429     static const(QMetaObject*) staticMetaObject(alias MO)()
430     {
431         return &MO;
432     }
433 
434     struct SuperData {
435         const(QMetaObject)* direct;
436         /+ SuperData() = default; +/
437         this(typeof(null))
438         {
439             this.direct = null;
440         }
441         this(const(QMetaObject)* mo)
442         {
443             this.direct = mo;
444         }
445 
446         /+const(QMetaObject)* operator ->() const { return operator const QMetaObject *(); }+/
447 
448         static if((versionIsSet!("QT_NO_DATA_RELOCATION") || (versionIsSet!("Windows") && !versionIsSet!("Cygwin"))))
449         {
450             alias Getter = ExternCPPFunc!(const(QMetaObject)* function());
451             Getter indirect = null;
452             this(Getter g)
453             {
454                 this.direct = null;
455                 this.indirect = g;
456             }
457             /+auto opCast(T : const(QMetaObject))() const
458             { return indirect ? indirect() : cast(const(QMetaObject))(direct); }+/
459             /+ template <const QMetaObject &MO> +/ /+ static constexpr SuperData link()
460             { return SuperData(QMetaObject::staticMetaObject<MO>); } +/
461         }
462         else
463         {
464             /+auto opCast(T : const(QMetaObject))() const
465             { return cast(const(QMetaObject))(direct); }+/
466             static SuperData link(alias MO)()
467             { return SuperData(QMetaObject.staticMetaObject!(MO)()); }
468         }
469     }
470 
471     struct Data { // private data
472         SuperData superdata;
473         const(void)* stringdata;
474         const(uint)* data;
475         alias StaticMetacallFunction = ExternCPPFunc!(void function(QObject , QMetaObject.Call, int, void** ));
476         StaticMetacallFunction static_metacall;
477         const(SuperData)* relatedMetaObjects;
478         const(/+ QtPrivate:: +/qt.core.metatype.QMetaTypeInterface)*/+ const +/ * metaTypes;
479         void* extradata; //reserved for future use
480     }Data d;
481 
482 private:
483     static bool invokeMethodImpl(QObject object, /+ QtPrivate:: +/qt.core.objectdefs_impl.QSlotObjectBase* slot, /+ Qt:: +/qt.core.namespace.ConnectionType type, void* ret);
484     /+ friend class QTimer; +/
485     mixin(CREATE_CONVENIENCE_WRAPPERS);
486 }
487 
488 /+ inline void swap(QMetaObject::Connection &lhs, QMetaObject::Connection &rhs) noexcept
489 {
490     lhs.swap(rhs);
491 } +/
492 
493 extern(C++, "QtPrivate") {
494     /* Trait that tells is a the Object has a Q_OBJECT macro */
495     struct HasQ_OBJECT_Macro(Object) {
496         /+ template <typename T> +/
497         static char test(T)(ExternCPPFunc!(int function(QMetaObject.Call, int, void** ))/+ T::* +/ );
498         static int test(ExternCPPFunc!(int function(QMetaObject.Call, int, void** ))/+ Object::* +/ );
499         enum { Value =  (test(&Object.qt_metacall)). sizeof == int.sizeof }
500     }
501 }
502