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