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 }