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.property;
13 extern(C++):
14 
15 import qt.config;
16 import qt.core.anystringview;
17 import qt.core.global;
18 import qt.core.metatype;
19 import qt.core.propertyprivate;
20 import qt.core.shareddata;
21 import qt.core.string;
22 import qt.core.taggedpointer;
23 import qt.core.typeinfo;
24 import qt.helpers;
25 
26 /+ #if __has_include(<source_location>) && __cplusplus >= 202002L && !defined(Q_CLANG_QDOC)
27 #if defined(__cpp_lib_source_location)
28 #define QT_SOURCE_LOCATION_NAMESPACE std
29 #define QT_PROPERTY_COLLECT_BINDING_LOCATION
30 #define QT_PROPERTY_DEFAULT_BINDING_LOCATION QPropertyBindingSourceLocation(std::source_location::current())
31 #endif
32 #endif +/
33 
34 static if(!defined!"QT_PROPERTY_COLLECT_BINDING_LOCATION")
35 {
36 /+ #if defined(__cpp_lib_experimental_source_location) +/
37 /+ #define QT_SOURCE_LOCATION_NAMESPACE std::experimental
38 #define QT_PROPERTY_COLLECT_BINDING_LOCATION +/
39 /+ #define QT_PROPERTY_DEFAULT_BINDING_LOCATION QPropertyBindingSourceLocation(std::experimental::source_location::current()) +/
40 enum QT_PROPERTY_DEFAULT_BINDING_LOCATION = q{QPropertyBindingSourceLocation(current())};
41 /+ #endif +/
42 }
43 
44 /+ #if !defined(QT_PROPERTY_COLLECT_BINDING_LOCATION)
45 #define QT_PROPERTY_DEFAULT_BINDING_LOCATION QPropertyBindingSourceLocation()
46 #endif +/
47 
48 
49 extern(C++, "Qt") {
50 /+ Q_CORE_EXPORT +/ void beginPropertyUpdateGroup();
51 /+ Q_CORE_EXPORT +/ void endPropertyUpdateGroup();
52 }
53 
54 /// Binding for C++ class [QPropertyData](https://doc.qt.io/qt-6/qpropertydata.html).
55 class QPropertyData(T) : QUntypedPropertyData
56 {
57 protected:
58     /+ mutable +/ T val = T();
59 private:
60     extern(C++, class) struct DisableRValueRefs {}
61 protected:
62     extern(D) static immutable bool UseReferences = !(/+ std:: +/is_arithmetic_v!(T) || /+ std:: +/is_enum_v!(T) || /+ std:: +/is_pointer_v!(T));
63 public:
64 /*    alias value_type = T;
65     alias parameter_type = /+ std:: +/conditional_t!(UseReferences, ref const(T), T);
66     /+ using rvalue_ref = typename std::conditional_t<UseReferences, T &&, DisableRValueRefs>; +/
67     alias arrow_operator_result = /+ std:: +/conditional_t!(bool, ref const(T),
68                                             /+ std:: +/conditional_t!(bool, ref const(T), void));
69 
70     /+ QPropertyData() = default; +/
71     this(parameter_type t)
72     {
73         this.val = t;
74     }
75     this(rvalue_ref t)
76     {
77         this.val = /+ std:: +/move(t);
78     }
79     /+ ~QPropertyData() = default; +/
80 
81     final parameter_type valueBypassingBindings() const { return val; }
82     final void setValueBypassingBindings(parameter_type v) { val = v; }
83     final void setValueBypassingBindings(rvalue_ref v) { val = /+ std:: +/move(v); }*/
84 }
85 
86 struct /+ Q_CORE_EXPORT +/ QPropertyBindingSourceLocation
87 {
88     const(char)* fileName = null;
89     const(char)* functionName = null;
90     quint32 line = 0;
91     quint32 column = 0;
92     /+ QPropertyBindingSourceLocation() = default; +/
93 /+ #ifdef QT_PROPERTY_COLLECT_BINDING_LOCATION +/
94 /+    this(ref UnknownType!q{/+ QT_SOURCE_LOCATION_NAMESPACE:: +/source_location source_location} cppLocation)
95     {
96         fileName = cppLocation.file_name();
97         functionName = cppLocation.function_name();
98         line = cppLocation.line();
99         column = cppLocation.column();
100     }+/
101 /+ #endif +/
102     mixin(CREATE_CONVENIENCE_WRAPPERS);
103 }
104 
105 extern(C++, class) struct QPropertyBindingErrorPrivate;
106 
107 /// Binding for C++ class [QPropertyBindingError](https://doc.qt.io/qt-6/qpropertybindingerror.html).
108 extern(C++, class) struct /+ Q_CORE_EXPORT +/ QPropertyBindingError
109 {
110 public:
111     enum Type {
112         NoError,
113         BindingLoop,
114         EvaluationError,
115         UnknownError
116     }
117 
118     @disable this();
119     pragma(mangle, defaultConstructorMangling(__traits(identifier, typeof(this))))
120     ref typeof(this) rawConstructor();
121     static typeof(this) create()
122     {
123         typeof(this) r = typeof(this).init;
124         r.rawConstructor();
125         return r;
126     }
127 
128     this(Type type, ref const(QString) description = globalInitVar!QString);
129 
130     @disable this(this);
131     this(ref const(QPropertyBindingError) other);
132     /+ref QPropertyBindingError operator =(ref const(QPropertyBindingError) other);+/
133     /+ QPropertyBindingError(QPropertyBindingError &&other); +/
134     /+ QPropertyBindingError &operator=(QPropertyBindingError &&other); +/
135     ~this();
136 
137     bool hasError() const { return d.get() !is null; }
138     Type type() const;
139     QString description() const;
140 
141 private:
142     QSharedDataPointer!(QPropertyBindingErrorPrivate) d;
143     mixin(CREATE_CONVENIENCE_WRAPPERS);
144 }
145 
146 extern(C++, class) struct /+ Q_CORE_EXPORT +/ QUntypedPropertyBinding
147 {
148 public:
149     // writes binding result into dataPtr
150     alias BindingFunctionVTable = /+ QtPrivate:: +/qt.core.propertyprivate.BindingFunctionVTable;
151 
152     @disable this();
153     pragma(mangle, defaultConstructorMangling(__traits(identifier, typeof(this))))
154     ref typeof(this) rawConstructor();
155     static typeof(this) create()
156     {
157         typeof(this) r = typeof(this).init;
158         r.rawConstructor();
159         return r;
160     }
161 
162     this(QMetaType metaType, const(BindingFunctionVTable)* vtable, void* function_, ref const(QPropertyBindingSourceLocation) location);
163 
164     /+ template<typename Functor> +/
165     /+ QUntypedPropertyBinding(QMetaType metaType, Functor &&f, const QPropertyBindingSourceLocation &location)
166         : QUntypedPropertyBinding(metaType, &QtPrivate::bindingFunctionVTable<std::remove_reference_t<Functor>>, &f, location)
167     {} +/
168 
169     /+ QUntypedPropertyBinding(QUntypedPropertyBinding &&other); +/
170     @disable this(this);
171     this(ref const(QUntypedPropertyBinding) other);
172     /+ref QUntypedPropertyBinding operator =(ref const(QUntypedPropertyBinding) other);+/
173     /+ QUntypedPropertyBinding &operator=(QUntypedPropertyBinding &&other); +/
174     ~this();
175 
176     bool isNull() const;
177 
178     QPropertyBindingError error() const;
179 
180     QMetaType valueMetaType() const;
181 
182     /+ explicit +/this(QPropertyBindingPrivate* priv);
183 private:
184     /+ friend class QtPrivate::QPropertyBindingData; +/
185     /+ friend class QPropertyBindingPrivate; +/
186     /+ template <typename> +/ /+ friend class QPropertyBinding; +/
187     QPropertyBindingPrivatePtr d;
188     mixin(CREATE_CONVENIENCE_WRAPPERS);
189 }
190 
191 extern(C++, class) struct QPropertyBinding(PropertyType)
192 {
193     public QUntypedPropertyBinding base0;
194     alias base0 this;
195 
196 public:
197     /+ QPropertyBinding() = default; +/
198 
199     /+ template<typename Functor> +/
200     /+ QPropertyBinding(Functor &&f, const QPropertyBindingSourceLocation &location)
201         : QUntypedPropertyBinding(QMetaType::fromType<PropertyType>(), &QtPrivate::bindingFunctionVTable<std::remove_reference_t<Functor>, PropertyType>, &f, location)
202     {} +/
203 
204 
205     // Internal
206     /+ explicit +/this(ref const(QUntypedPropertyBinding) binding)
207     {
208         this.base0 = QUntypedPropertyBinding(binding);
209     }
210 }
211 
212 /+ namespace Qt {
213     template <typename Functor>
214     auto makePropertyBinding(Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
215                              std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr)
216     {
217         return QPropertyBinding<std::invoke_result_t<Functor>>(std::forward<Functor>(f), location);
218     }
219 } +/
220 
221 struct QPropertyObserverPrivate;
222 struct QPropertyObserverPointer;
223 
224 extern(C++, class) struct QPropertyObserverBase
225 {
226 public:
227     // Internal
228     enum ObserverTag {
229         ObserverNotifiesBinding, // observer was installed to notify bindings that obsverved property changed
230         ObserverNotifiesChangeHandler, // observer is a change handler, which runs on every change
231         ObserverIsPlaceholder,  // the observer before this one is currently evaluated in QPropertyObserver::notifyObservers.
232         ObserverIsAlias
233     }
234 protected:
235     alias ChangeHandler = ExternCPPFunc!(void function(QPropertyObserver*, QUntypedPropertyData* ));
236 
237 private:
238     /+ friend struct QPropertyDelayedNotifications; +/
239     /+ friend struct QPropertyObserverNodeProtector; +/
240     /+ friend class QPropertyObserver; +/
241     /+ friend struct QPropertyObserverPointer; +/
242     /+ friend struct QPropertyBindingDataPointer; +/
243     /+ friend class QPropertyBindingPrivate; +/
244 
245     QTaggedPointer!(QPropertyObserver, ObserverTag) next;
246     // prev is a pointer to the "next" element within the previous node, or to the "firstObserverPtr" if it is the
247     // first node.
248     /+ QtPrivate:: +/qt.core.propertyprivate.QTagPreservingPointerToPointer!(QPropertyObserver, ObserverTag) prev;
249 
250     union {
251         QPropertyBindingPrivate* binding = null;
252         ChangeHandler changeHandler;
253         QUntypedPropertyData* aliasData;
254     }
255 }
256 
257 extern(C++, class) struct /+ Q_CORE_EXPORT +/ QPropertyObserver
258 {
259     public QPropertyObserverBase base0;
260     alias base0 this;
261 protected:
262     alias ChangeHandler = QPropertyObserverBase.ChangeHandler;
263 public:
264     /+ constexpr QPropertyObserver() = default; +/
265     /+ QPropertyObserver(QPropertyObserver &&other) noexcept; +/
266     /+ QPropertyObserver &operator=(QPropertyObserver &&other) noexcept; +/
267     ~this();
268 
269     /+ template<typename Property, typename = typename Property::InheritsQUntypedPropertyData> +/
270     void setSource(Property,)(ref const(Property) property)
271     { setSource(property.bindingData()); }
272     void setSource(ref const(/+ QtPrivate:: +/qt.core.propertyprivate.QPropertyBindingData) property);
273 
274 protected:
275     this(ChangeHandler changeHandler);
276     this(QUntypedPropertyData* aliasedPropertyPtr);
277 
278     QUntypedPropertyData* aliasedProperty() /*const*/
279     {
280         return aliasData;
281     }
282 
283 private:
284 
285     @disable this(this);
286     /+this(ref const(QPropertyObserver) ) /+ = delete +/;+/
287     /+ref QPropertyObserver operator =(ref const(QPropertyObserver) ) /+ = delete +/;+/
288 
289     mixin(CREATE_CONVENIENCE_WRAPPERS);
290 }
291 
292 /// Binding for C++ class [QPropertyChangeHandler](https://doc.qt.io/qt-6/qpropertychangehandler.html).
293 class /+ [[nodiscard]] +/ QPropertyChangeHandler(Functor) : QPropertyObserver
294 {
295 private:
296     Functor m_handler;
297 public:
298 /*    this(Functor handler)
299     {
300         super([](QPropertyObserver *self, QUntypedPropertyData *) {
301                       auto This = static_cast!(QPropertyChangeHandler!(Functor))(self);
302                       This.m_handler();
303                   });
304         this.m_handler = handler;
305     }*/
306 
307     /+ template<typename Property, typename = typename Property::InheritsQUntypedPropertyData> +/
308     /+ this(Property,)(ref const(Property) property, Functor handler)
309     {
310         super([](QPropertyObserver *self, QUntypedPropertyData *) {
311                       auto This = static_cast!(QPropertyChangeHandler!(Functor))(self);
312                       This.m_handler();
313                   });
314         this.m_handler = handler;
315 
316         setSource(property);
317     } +/
318 }
319 
320 /// Binding for C++ class [QPropertyNotifier](https://doc.qt.io/qt-6/qpropertynotifier.html).
321 /+extern(C++, class) struct /+ [[nodiscard]] +/ QPropertyNotifier
322 {
323     public QPropertyObserver base0;
324     alias base0 this;
325 private:
326     /+ std:: +/function_!(UnresolvedMergeConflict!(q{UnknownType!q{void}},q{void()})) m_handler;
327 public:
328     /+ QPropertyNotifier() = default; +/
329     /+ template<typename Functor> +/
330     this(Functor)(Functor handler)
331     {
332         this.base0 = QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) {
333                     auto This = static_cast!(QPropertyNotifier*)(self);
334                     This.m_handler();
335                 });
336         this.m_handler = handler;
337     }
338 
339     /+ template<typename Functor, typename Property, typename = typename Property::InheritsQUntypedPropertyData> +/
340     this(Functor,Property,)(ref const(Property) property, Functor handler)
341     {
342         this.base0 = QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) {
343                     auto This = static_cast!(QPropertyNotifier*)(self);
344                     This.m_handler();
345                 });
346         this.m_handler = handler;
347 
348         setSource(property);
349     }
350     mixin(CREATE_CONVENIENCE_WRAPPERS);
351 }+/
352 
353 /// Binding for C++ class [QProperty](https://doc.qt.io/qt-6/qproperty.html).
354 extern(C++, class) struct QProperty(T)
355 {
356     public QPropertyData!(T) base0;
357     alias base0 this;
358 private:
359     /+ QtPrivate:: +/qt.core.propertyprivate.QPropertyBindingData d;
360     bool is_equal(ref const(T) v)
361     {
362         static if (/+ QTypeTraits:: +/qt.core.typeinfo.has_operator_equal_v!(T)) {
363             if (v == this.val)
364                 return true;
365         }
366         return false;
367     }
368 
369 public:
370     alias value_type = QPropertyData!(T).value_type;
371     alias parameter_type = QPropertyData!(T).parameter_type;
372     /+ using rvalue_ref = typename QPropertyData<T>::rvalue_ref; +/
373     alias arrow_operator_result = QPropertyData!(T).arrow_operator_result;
374 
375     /+ QProperty() = default; +/
376     /+ explicit +/this(parameter_type initialValue)
377     {
378         this.QPropertyData!(T) = initialValue;
379     }
380     /+ explicit +/this(rvalue_ref initialValue)
381     {
382         this.QPropertyData!(T) = /+ std:: +/move(initialValue);
383     }
384     /+ explicit +/this(ref const(QPropertyBinding!(T)) binding)
385     {
386         setBinding(binding);
387     }
388 /+ #ifndef Q_CLANG_QDOC +/
389     /+ template <typename Functor> +/
390     /+ explicit QProperty(Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
391                        typename std::enable_if_t<std::is_invocable_r_v<T, Functor&>> * = nullptr)
392         : QProperty(QPropertyBinding<T>(std::forward<Functor>(f), location))
393     {} +/
394 /+ #else
395     template <typename Functor>
396     explicit QProperty(Functor &&f);
397 #endif +/
398     /+ ~QProperty() = default; +/
399 
400     parameter_type value() const
401     {
402         d.registerWithCurrentlyEvaluatingBinding();
403         return this.val;
404     }
405 
406     /+arrow_operator_result operator ->() const
407     {
408         static if (/+ QTypeTraits:: +/qt.core.typeinfo.is_dereferenceable_v!(T)) {
409             return value();
410         } else static if (/+ std:: +/is_pointer_v!(T)) {
411             value();
412             return this.val;
413         } else {
414             return;
415         }
416     }+/
417 
418     parameter_type opUnary(string op)() const if(op == "*")
419     {
420         return value();
421     }
422 
423     /+auto opCast(T : parameter_type)() const
424     {
425         return value();
426     }+/
427 
428     void setValue(rvalue_ref newValue)
429     {
430         d.removeBinding();
431         if (is_equal(newValue))
432             return;
433         this.val = /+ std:: +/move(newValue);
434         notify();
435     }
436 
437     void setValue(parameter_type newValue)
438     {
439         d.removeBinding();
440         if (is_equal(newValue))
441             return;
442         this.val = newValue;
443         notify();
444     }
445 
446     /+ref QProperty!(T) operator =(rvalue_ref newValue)
447     {
448         setValue(/+ std:: +/move(newValue));
449         return this;
450     }+/
451 
452     /+ref QProperty!(T) operator =(parameter_type newValue)
453     {
454         setValue(newValue);
455         return this;
456     }+/
457 
458     QPropertyBinding!(T) setBinding(ref const(QPropertyBinding!(T)) newBinding)
459     {
460         return QPropertyBinding!(T)(d.setBinding(newBinding, &this));
461     }
462 
463 /+    bool setBinding(ref const(QUntypedPropertyBinding) newBinding)
464     {
465         if (!newBinding.isNull() && newBinding.valueMetaType().id() != qMetaTypeId!(T)())
466             return false;
467         setBinding(static_cast!(ref const(QPropertyBinding!(T)))(newBinding));
468         return true;
469     }+/
470 
471 /+ #ifndef Q_CLANG_QDOC +/
472     /+ template <typename Functor> +/
473     /+ QPropertyBinding<T> setBinding(Functor &&f,
474                                    const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
475                                    std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr)
476     {
477         return setBinding(Qt::makePropertyBinding(std::forward<Functor>(f), location));
478     } +/
479 /+ #else
480     template <typename Functor>
481     QPropertyBinding<T> setBinding(Functor f);
482 #endif +/
483 
484     bool hasBinding() const { return d.hasBinding(); }
485 
486     QPropertyBinding!(T) binding() const
487     {
488         return QPropertyBinding!(T)(QUntypedPropertyBinding(d.binding()));
489     }
490 
491     QPropertyBinding!(T) takeBinding()
492     {
493         return QPropertyBinding!(T)(d.setBinding(QUntypedPropertyBinding(), &this));
494     }
495 
496     /+ template<typename Functor> +/
497     ValueClass!(QPropertyChangeHandler!(Functor)) onValueChanged(Functor)(Functor f)
498     {
499         static assert(/+ std:: +/is_invocable_v!(Functor), "Functor callback must be callable without any parameters");
500         return QPropertyChangeHandler!(Functor)(this, f);
501     }
502 
503     /+ template<typename Functor> +/
504     ValueClass!(QPropertyChangeHandler!(Functor)) subscribe(Functor)(Functor f)
505     {
506         static assert(/+ std:: +/is_invocable_v!(Functor), "Functor callback must be callable without any parameters");
507         f();
508         return onValueChanged(f);
509     }
510 
511     /+ template<typename Functor> +/
512     QPropertyNotifier addNotifier(Functor)(Functor f)
513     {
514         static assert(/+ std:: +/is_invocable_v!(Functor), "Functor callback must be callable without any parameters");
515         return QPropertyNotifier(this, f);
516     }
517 
518     ref const(/+ QtPrivate:: +/qt.core.propertyprivate.QPropertyBindingData) bindingData() const { return d; }
519 private:
520     void notify()
521     {
522         d.notifyObservers(&this);
523     }
524 
525     /+ Q_DISABLE_COPY_MOVE(QProperty) +/
526 @disable this(this);
527 /+this(ref const(QProperty));+//+ref QProperty operator =(ref const(QProperty));+/}
528 
529 extern(C++, "Qt") {
530 /+    QPropertyBinding!(PropertyType) makePropertyBinding(PropertyType)(ref const(QProperty!(PropertyType)) otherProperty,
531                                                            ref const(QPropertyBindingSourceLocation) location /+ =
532                                                            QT_PROPERTY_DEFAULT_BINDING_LOCATION +/)
533     {
534         return makePropertyBinding([&otherProperty]() -> PropertyType { return otherProperty; }, location);
535     }+/
536 }
537 
538 
539 extern(C++, "QtPrivate")
540 {
541 
542 
543 struct QBindableInterface
544 {
545     alias Getter = ExternCPPFunc!(void function(const(QUntypedPropertyData)* d, void* value));
546     alias Setter = ExternCPPFunc!(void function(QUntypedPropertyData* d, const(void)* value));
547     alias BindingGetter = ExternCPPFunc!(QUntypedPropertyBinding function(const(QUntypedPropertyData)* d));
548     alias BindingSetter = ExternCPPFunc!(QUntypedPropertyBinding function(QUntypedPropertyData* d, ref const(QUntypedPropertyBinding) binding));
549     alias MakeBinding = ExternCPPFunc!(QUntypedPropertyBinding function(const(QUntypedPropertyData)* d, ref const(QPropertyBindingSourceLocation) location));
550     alias SetObserver = ExternCPPFunc!(void function(const(QUntypedPropertyData)* d, QPropertyObserver* observer));
551     alias GetMetaType = ExternCPPFunc!(QMetaType function());
552     Getter getter;
553     Setter setter;
554     BindingGetter getBinding;
555     BindingSetter setBinding;
556     MakeBinding makeBinding;
557     SetObserver setObserver;
558     GetMetaType metaType;
559 
560     extern(D) static immutable quintptr MetaTypeAccessorFlag = 0x1;
561 }
562 
563 class QBindableInterfaceForProperty(Property, )
564 {
565 private:
566     alias T = UnknownType!q{Property.value_type};
567 public:
568     // interface for computed properties. Those do not have a binding()/setBinding() method, but one can
569     // install observers on them.
570 /+    extern(D) static immutable QBindableInterface iface = {
571         [](const QUntypedPropertyData *d, void *value) -> void
572         { *static_cast!(T*)(value) = static_cast!(const(Property)*)(d).value(); },
573         null,
574         null,
575         null,
576         [](const QUntypedPropertyData *d, const QPropertyBindingSourceLocation &location) -> QUntypedPropertyBinding
577         { return /+ Qt:: +/makePropertyBinding([d]() -> T { return static_cast!(const(Property)*)(d).value(); }, location); },
578         [](const QUntypedPropertyData *d, QPropertyObserver *observer) -> void
579         { observer.setSource(static_cast!(const(Property)*)(d).bindingData()); },
580         []() { return QMetaType.fromType!(T)(); }}
581     ;+/
582 }
583 
584 /+ template<typename Property>
585 class QBindableInterfaceForProperty<const Property, std::void_t<decltype(std::declval<Property>().binding())>>
586 {
587     using T = typename Property::value_type;
588 public:
589     // A bindable created from a const property results in a read-only interface, too.
590     static constexpr QBindableInterface iface = {
591 
592         [](const QUntypedPropertyData *d, void *value) -> void
593         { *static_cast<T*>(value) = static_cast<const Property *>(d)->value(); },
594         /*setter=*/nullptr,
595         [](const QUntypedPropertyData *d) -> QUntypedPropertyBinding
596         { return static_cast<const Property *>(d)->binding(); },
597         /*setBinding=*/nullptr,
598         [](const QUntypedPropertyData *d, const QPropertyBindingSourceLocation &location) -> QUntypedPropertyBinding
599         { return Qt::makePropertyBinding([d]() -> T { return static_cast<const Property *>(d)->value(); }, location); },
600         [](const QUntypedPropertyData *d, QPropertyObserver *observer) -> void
601         { observer->setSource(static_cast<const Property *>(d)->bindingData()); },
602         []() { return QMetaType::fromType<T>(); }
603     };
604 };
605 
606 template<typename Property>
607 class QBindableInterfaceForProperty<Property, std::void_t<decltype(std::declval<Property>().binding())>>
608 {
609     using T = typename Property::value_type;
610 public:
611     static constexpr QBindableInterface iface = {
612         [](const QUntypedPropertyData *d, void *value) -> void
613         { *static_cast<T*>(value) = static_cast<const Property *>(d)->value(); },
614         [](QUntypedPropertyData *d, const void *value) -> void
615         { static_cast<Property *>(d)->setValue(*static_cast<const T*>(value)); },
616         [](const QUntypedPropertyData *d) -> QUntypedPropertyBinding
617         { return static_cast<const Property *>(d)->binding(); },
618         [](QUntypedPropertyData *d, const QUntypedPropertyBinding &binding) -> QUntypedPropertyBinding
619         { return static_cast<Property *>(d)->setBinding(static_cast<const QPropertyBinding<T> &>(binding)); },
620         [](const QUntypedPropertyData *d, const QPropertyBindingSourceLocation &location) -> QUntypedPropertyBinding
621         { return Qt::makePropertyBinding([d]() -> T { return static_cast<const Property *>(d)->value(); }, location); },
622         [](const QUntypedPropertyData *d, QPropertyObserver *observer) -> void
623         { observer->setSource(static_cast<const Property *>(d)->bindingData()); },
624         []() { return QMetaType::fromType<T>(); }
625     };
626 }; +/
627 
628 }
629 
630 extern(C++, "QtPrivate") {
631 // used in Q(Untyped)Bindable to print warnings about various binding errors
632 extern(C++, "BindableWarnings") {
633 enum Reason { InvalidInterface, NonBindableInterface, ReadOnlyInterface }
634 /+ Q_CORE_EXPORT +/ void printUnsuitableBindableWarning(QAnyStringView prefix, Reason reason);
635 /+ Q_CORE_EXPORT +/ void printMetaTypeMismatch(QMetaType actual, QMetaType expected);
636 }
637 }
638 
639 /// Binding for C++ class [QUntypedBindable](https://doc.qt.io/qt-6/quntypedbindable.html).
640 extern(C++, class) struct QUntypedBindable
641 {
642 private:
643     /+ friend struct QUntypedBindablePrivate; +/ // allows access to internal data
644 protected:
645     QUntypedPropertyData* data = null;
646     const(/+ QtPrivate:: +/QBindableInterface)* iface = null;
647     this(QUntypedPropertyData* d, const(/+ QtPrivate:: +/QBindableInterface)* i)
648     {
649         this.data = d;
650         this.iface = i;
651     }
652 
653 public:
654     /+ constexpr QUntypedBindable() = default; +/
655     /+ template<typename Property> +/
656     this(Property)(Property* p)
657     {
658         this.data = const_cast!(/+ std:: +/remove_cv_t!(Property)*)(p);
659         this.iface = &/+ QtPrivate:: +/QBindableInterfaceForProperty!(Property).iface;
660         (mixin(Q_ASSERT(q{QUntypedBindable.data && QUntypedBindable.iface})));
661     }
662 
663     bool isValid() const { return data !is null; }
664     bool isBindable() const { return iface && iface.getBinding; }
665     bool isReadOnly() const { return !(iface && iface.setBinding && iface.setObserver); }
666 
667     QUntypedPropertyBinding makeBinding(ref const(QPropertyBindingSourceLocation) location /+ = QT_PROPERTY_DEFAULT_BINDING_LOCATION +/) const
668     {
669         return iface ? iface.makeBinding(data, location) : QUntypedPropertyBinding.create();
670     }
671 
672     QUntypedPropertyBinding takeBinding()
673     {
674         if (!iface)
675             return QUntypedPropertyBinding.create();
676         // We do not have a dedicated takeBinding function pointer in the interface
677         // therefore we synthesize takeBinding by retrieving the binding with binding
678         // and calling setBinding with a default constructed QUntypedPropertyBinding
679         // afterwards.
680         if (!(iface.getBinding && iface.setBinding))
681             return QUntypedPropertyBinding.create();
682         QUntypedPropertyBinding binding = iface.getBinding(data);
683         QUntypedPropertyBinding tmp = QUntypedPropertyBinding.create();
684         iface.setBinding(data, tmp);
685         return binding;
686     }
687 
688     void observe(QPropertyObserver* observer) const
689     {
690         if (iface)
691             iface.setObserver(data, observer);
692 /+ #ifndef QT_NO_DEBUG
693         else
694             QtPrivate::BindableWarnings::printUnsuitableBindableWarning("observe:",
695                                                                         QtPrivate::BindableWarnings::InvalidInterface);
696 #endif +/
697     }
698 
699     /+ template<typename Functor> +/
700     /+ ValueClass!(QPropertyChangeHandler!(Functor)) onValueChanged(Functor)(Functor f) const
701     {
702         auto handler = ValueClass!(QPropertyChangeHandler!(Functor))(f);
703         observe(&handler);
704         return handler;
705     } +/
706 
707     /+ template<typename Functor> +/
708     /+ ValueClass!(QPropertyChangeHandler!(Functor)) subscribe(Functor)(Functor f) const
709     {
710         f();
711         return onValueChanged(f);
712     } +/
713 
714     /+ template<typename Functor> +/
715     QPropertyNotifier addNotifier(Functor)(Functor f)
716     {
717         auto handler = QPropertyNotifier(f);
718         observe(&handler);
719         return handler;
720     }
721 
722     QUntypedPropertyBinding binding() const
723     {
724         if (!isBindable()) {
725 /+ #ifndef QT_NO_DEBUG
726             QtPrivate::BindableWarnings::printUnsuitableBindableWarning("binding: ",
727                                                                         QtPrivate::BindableWarnings::NonBindableInterface);
728 #endif +/
729             return QUntypedPropertyBinding.create();
730         }
731         return iface.getBinding(data);
732     }
733     bool setBinding(ref const(QUntypedPropertyBinding) binding)
734     {
735         if (isReadOnly()) {
736 /+ #ifndef QT_NO_DEBUG
737             const auto errorType = iface ? QtPrivate::BindableWarnings::ReadOnlyInterface :
738                                            QtPrivate::BindableWarnings::InvalidInterface;
739             QtPrivate::BindableWarnings::printUnsuitableBindableWarning("setBinding: Could not set binding via bindable interface.", errorType);
740 #endif +/
741             return false;
742         }
743         if (!binding.isNull() && binding.valueMetaType() != metaType()) {
744 /+ #ifndef QT_NO_DEBUG
745             QtPrivate::BindableWarnings::printMetaTypeMismatch(metaType(), binding.valueMetaType());
746 #endif +/
747             return false;
748         }
749         iface.setBinding(data, binding);
750         return true;
751     }
752     bool hasBinding() const
753     {
754         return !binding().isNull();
755     }
756 
757     QMetaType metaType() const
758     {
759         if (!(iface && data))
760             return QMetaType();
761         if (iface.metaType)
762             return iface.metaType();
763         // ### Qt 7: Change the metatype function to take data as its argument
764         // special casing for QML's proxy bindable: allow multiplexing in the getter
765         // function to retrieve the metatype from data
766         (mixin(Q_ASSERT(q{QUntypedBindable.iface.getter})));
767         QMetaType result;
768         iface.getter(data, reinterpret_cast!(void*)(cast(quintptr)(&result) | /+ QtPrivate:: +/QBindableInterface.MetaTypeAccessorFlag));
769         return result;
770     }
771 
772     mixin(CREATE_CONVENIENCE_WRAPPERS);
773 }
774 
775 /// Binding for C++ class [QBindable](https://doc.qt.io/qt-6/qbindable.html).
776 extern(C++, class) struct QBindable(T)
777 {
778     public QUntypedBindable base0;
779     alias base0 this;
780 private:
781     /+ template<typename U> +/
782     /+ friend class QPropertyAlias; +/
783     this(QUntypedPropertyData* d, const(/+ QtPrivate:: +/QBindableInterface)* i)
784     {
785         this.base0 = QUntypedBindable(d, i);
786     }
787 public:
788     /+ using QUntypedBindable::QUntypedBindable; +/
789     /*/+ explicit +/this(ref const(QUntypedBindable) b)
790     {
791         this.base0 = QUntypedBindable(b);
792 
793         if (iface && metaType() != QMetaType.fromType!(T)()) {
794             data = null;
795             iface = null;
796         }
797     }*/
798 
799 /+    QPropertyBinding!(T) makeBinding(ref const(QPropertyBindingSourceLocation) location /+ = QT_PROPERTY_DEFAULT_BINDING_LOCATION +/) const
800     {
801         return static_cast!(QPropertyBinding!(T) && /+ && +/)(QUntypedBindable.makeBinding(location));
802     }
803     QPropertyBinding!(T) binding() const
804     {
805         return static_cast!(QPropertyBinding!(T) && /+ && +/)(QUntypedBindable.binding());
806     }
807 
808     QPropertyBinding!(T) takeBinding()
809     {
810         return static_cast!(QPropertyBinding!(T) && /+ && +/)(QUntypedBindable.takeBinding());
811     }
812 
813     /+ using QUntypedBindable::setBinding; +/
814     QPropertyBinding!(T) setBinding(ref const(QPropertyBinding!(T)) binding)
815     {
816         (mixin(Q_ASSERT(q{!QUntypedBindable.iface || binding.isNull() || binding.valueMetaType() == QUntypedBindable.metaType()})));
817 
818         if (iface && iface.setBinding)
819             return static_cast!(QPropertyBinding!(T) && /+ && +/)(iface.setBinding(data, binding));
820 /+ #ifndef QT_NO_DEBUG
821         if (!iface)
822             QtPrivate::BindableWarnings::printUnsuitableBindableWarning("setBinding", QtPrivate::BindableWarnings::InvalidInterface);
823         else
824             QtPrivate::BindableWarnings::printUnsuitableBindableWarning("setBinding: Could not set binding via bindable interface.", QtPrivate::BindableWarnings::ReadOnlyInterface);
825 #endif +/
826         return QPropertyBinding!(T)();
827     }+/
828 /+ #ifndef Q_CLANG_QDOC +/
829     /+ template <typename Functor> +/
830     /+ QPropertyBinding<T> setBinding(Functor &&f,
831                                    const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
832                                    std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr)
833     {
834         return setBinding(Qt::makePropertyBinding(std::forward<Functor>(f), location));
835     } +/
836 /+ #else
837     template <typename Functor>
838     QPropertyBinding<T> setBinding(Functor f);
839 #endif +/
840 
841     T value() const
842     {
843         if (iface) {
844             T result;
845             iface.getter(data, &result);
846             return result;
847         }
848         return T.init;
849     }
850 
851     void setValue(ref const(T) value)
852     {
853         if (iface && iface.setter)
854             iface.setter(data, &value);
855     }
856 }
857 
858 extern(C++, class) struct QPropertyAlias(T)
859 {
860     public QPropertyObserver base0;
861     alias base0 this;
862 private:
863     /+ Q_DISABLE_COPY_MOVE(QPropertyAlias) +/
864 @disable this(this);
865 /+this(ref const(QPropertyAlias));+//+ref QPropertyAlias operator =(ref const(QPropertyAlias));+/    const(/+ QtPrivate:: +/QBindableInterface)* iface = null;
866 
867 public:
868 /+    this(QProperty!(T)* property)
869     {
870         this.base0 = QPropertyObserver(property);
871         this.iface = &/+ QtPrivate:: +/QBindableInterfaceForProperty!(QProperty!(T)).iface;
872 
873         if (iface)
874             iface.setObserver(aliasedProperty(), &this);
875     }+/
876 
877     /+ template<typename Property, typename = typename Property::InheritsQUntypedPropertyData> +/
878     this(Property,)(Property* property)
879     {
880         this.base0 = QPropertyObserver(property);
881         this.iface = &/+ QtPrivate:: +/QBindableInterfaceForProperty!(Property).iface;
882 
883         if (iface)
884             iface.setObserver(aliasedProperty(), &this);
885     }
886 
887     this(QPropertyAlias!(T)* alias_)
888     {
889         this.base0 = QPropertyObserver(alias_.aliasedProperty());
890         this.iface = alias_.iface;
891 
892         if (iface)
893             iface.setObserver(aliasedProperty(), &this);
894     }
895 
896     this(ref const(QBindable!(T)) property)
897     {
898         this.base0 = QPropertyObserver(property.data);
899         this.iface = property.iface;
900 
901         if (iface)
902             iface.setObserver(aliasedProperty(), &this);
903     }
904 
905     /+T value() const
906     {
907         T t = T();
908         if (auto* p = aliasedProperty())
909             iface.getter(p, &t);
910         return t;
911     }+/
912 
913     /+auto opCast(T : T)() const { return value(); }+/
914 
915     /+void setValue(ref const(T) newValue)
916     {
917         if (auto* p = aliasedProperty())
918             iface.setter(p, &newValue);
919     }+/
920 
921     /+ref QPropertyAlias!(T) operator =(ref const(T) newValue)
922     {
923         setValue(newValue);
924         return this;
925     }+/
926 
927     /+QPropertyBinding!(T) setBinding(ref const(QPropertyBinding!(T)) newBinding)
928     {
929         return QBindable!(T)(aliasedProperty(), iface).setBinding(cast(Functor && )(newBinding));
930     }+/
931 
932     bool setBinding(ref const(QUntypedPropertyBinding) newBinding)
933     {
934         return cast(bool)(QBindable!(T)(aliasedProperty(), iface).setBinding(newBinding));
935     }
936 
937 /+ #ifndef Q_CLANG_QDOC +/
938     /+ template <typename Functor> +/
939     /+ QPropertyBinding<T> setBinding(Functor &&f,
940                                    const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
941                                    std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr)
942     {
943         return setBinding(Qt::makePropertyBinding(std::forward<Functor>(f), location));
944     } +/
945 /+ #else
946     template <typename Functor>
947     QPropertyBinding<T> setBinding(Functor f);
948 #endif +/
949 
950     bool hasBinding() const
951     {
952         return QBindable!(T)(aliasedProperty(), iface).hasBinding();
953     }
954 
955     QPropertyBinding!(T) binding() const
956     {
957         return QBindable!(T)(aliasedProperty(), iface).binding();
958     }
959 
960     QPropertyBinding!(T) takeBinding()
961     {
962         return QBindable!(T)(aliasedProperty(), iface).takeBinding();
963     }
964 
965     /+ template<typename Functor> +/
966     ValueClass!(QPropertyChangeHandler!(Functor)) onValueChanged(Functor)(Functor f)
967     {
968         return QBindable!(T)(aliasedProperty(), iface).onValueChanged(f);
969     }
970 
971     /+ template<typename Functor> +/
972     ValueClass!(QPropertyChangeHandler!(Functor)) subscribe(Functor)(Functor f)
973     {
974         return QBindable!(T)(aliasedProperty(), iface).subscribe(f);
975     }
976 
977     /+ template<typename Functor> +/
978     QPropertyNotifier addNotifier(Functor)(Functor f)
979     {
980         return QBindable!(T)(aliasedProperty(), iface).notify(f);
981     }
982 
983     bool isValid() const
984     {
985         return aliasedProperty() !is null;
986     }
987 }
988 
989 /+
990 /// Binding for C++ class [QObjectBindableProperty](https://doc.qt.io/qt-6/qobjectbindableproperty.html).
991 extern(C++, class) struct QObjectBindableProperty(Class, T, auto Offset, auto Signal=null)
992 {
993     public QPropertyData!(T) base0;
994     alias base0 this;
995 private:
996     alias ThisType = QObjectBindableProperty!(Class, T, Offset, Signal);
997     extern(D) static immutable bool HasSignal = !/+ std:: +/is_same_v!(/+ decltype(Signal) +/auto, /+ std:: +/nullptr_t);
998     alias SignalTakesValue = /+ std:: +/is_invocable!(/+ decltype(Signal) +/auto, Class, T);
999     Class* owner()
1000     {
1001         char* that = reinterpret_cast!(char*)(&this);
1002         return reinterpret_cast!(Class*)(that - /+ QtPrivate:: +//+ detail:: +/qt.core.propertyprivate.getOffset(Offset));
1003     }
1004     const(Class)* owner() const
1005     {
1006         char* that = const_cast!(char*)(reinterpret_cast!(const(char)*)(&this));
1007         return reinterpret_cast!(Class*)(that - /+ QtPrivate:: +//+ detail:: +/qt.core.propertyprivate.getOffset(Offset));
1008     }
1009     static void signalCallBack(QUntypedPropertyData* o)
1010     {
1011         QObjectBindableProperty* that = static_cast!(QObjectBindableProperty*)(o);
1012         static if (HasSignal) {
1013             static if (SignalTakesValue.value)
1014                 (that.owner()->*Signal)(that.valueBypassingBindings());
1015             else
1016                 (that.owner()->*Signal)();
1017         }
1018     }
1019 public:
1020     alias value_type = QPropertyData!(T).value_type;
1021     alias parameter_type = QPropertyData!(T).parameter_type;
1022     /+ using rvalue_ref = typename QPropertyData<T>::rvalue_ref; +/
1023     alias arrow_operator_result = QPropertyData!(T).arrow_operator_result;
1024 
1025     /+ QObjectBindableProperty() = default; +/
1026     /+ explicit +/this(ref const(T) initialValue)
1027     {
1028         this.QPropertyData!(T) = initialValue;
1029     }
1030     /+ explicit QObjectBindableProperty(T &&initialValue) : QPropertyData<T>(std::move(initialValue)) {} +/
1031     /+ explicit +/this(ref const(QPropertyBinding!(T)) binding)
1032     {
1033         this();
1034         setBinding(binding);
1035     }
1036 /+ #ifndef Q_CLANG_QDOC +/
1037     /+ template <typename Functor> +/
1038     /+ explicit QObjectBindableProperty(Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
1039                        typename std::enable_if_t<std::is_invocable_r_v<T, Functor&>> * = nullptr)
1040         : QObjectBindableProperty(QPropertyBinding<T>(std::forward<Functor>(f), location))
1041     {} +/
1042 /+ #else
1043     template <typename Functor>
1044     explicit QObjectBindableProperty(Functor &&f);
1045 #endif +/
1046 
1047     parameter_type value() const
1048     {
1049         import qt.core.object;
1050 
1051         qGetBindingStorage(owner()).registerDependency(&this);
1052         return this.val;
1053     }
1054 
1055     /+arrow_operator_result operator ->() const
1056     {
1057         static if (/+ QTypeTraits:: +/qt.core.typeinfo.is_dereferenceable_v!(T)) {
1058             return value();
1059         } else static if (/+ std:: +/is_pointer_v!(T)) {
1060             value();
1061             return this.val;
1062         } else {
1063             return;
1064         }
1065     }+/
1066 
1067     parameter_type opUnary(string op)() const if(op == "*")
1068     {
1069         return value();
1070     }
1071 
1072     /+auto opCast(T : parameter_type)() const
1073     {
1074         return value();
1075     }+/
1076 
1077     void setValue(parameter_type t)
1078     {
1079         import qt.core.object;
1080 
1081         auto* bd = cast(auto*)(qGetBindingStorage(owner()).bindingData(&this));
1082         if (bd)
1083             bd.removeBinding();
1084         if (this.val == t)
1085             return;
1086         this.val = t;
1087         notify(cast(const(qt.core.propertyprivate.QPropertyBindingData)*)(bd));
1088     }
1089 
1090     void notify() {
1091         import qt.core.object;
1092 
1093         auto* bd = cast(auto*)(qGetBindingStorage(owner()).bindingData(&this));
1094         notify(cast(const(qt.core.propertyprivate.QPropertyBindingData)*)(bd));
1095     }
1096 
1097     void setValue(rvalue_ref t)
1098     {
1099         import qt.core.object;
1100 
1101         auto* bd = cast(auto*)(qGetBindingStorage(owner()).bindingData(&this));
1102         if (bd)
1103             bd.removeBinding();
1104         if (this.val == t)
1105             return;
1106         this.val = /+ std:: +/move(t);
1107         notify(cast(const(qt.core.propertyprivate.QPropertyBindingData)*)(bd));
1108     }
1109 
1110     /+ref QObjectBindableProperty operator =(rvalue_ref newValue)
1111     {
1112         setValue(/+ std:: +/move(newValue));
1113         return this;
1114     }+/
1115 
1116     /+ref QObjectBindableProperty operator =(parameter_type newValue)
1117     {
1118         setValue(newValue);
1119         return this;
1120     }+/
1121 
1122     QPropertyBinding!(T) setBinding(ref const(QPropertyBinding!(T)) newBinding)
1123     {
1124         import qt.core.object;
1125 
1126         /+ QtPrivate:: +/qt.core.propertyprivate.QPropertyBindingData* bd = qGetBindingStorage(owner()).bindingData(&this, true);
1127         auto oldBinding = QUntypedPropertyBinding(bd.setBinding(newBinding, &this, HasSignal ? &signalCallBack : null));
1128         return static_cast!(ref QPropertyBinding!(T))(oldBinding);
1129     }
1130 
1131     bool setBinding(ref const(QUntypedPropertyBinding) newBinding)
1132     {
1133         if (!newBinding.isNull() && newBinding.valueMetaType().id() != qMetaTypeId!(T)())
1134             return false;
1135         setBinding(static_cast!(ref const(QPropertyBinding!(T)))(newBinding));
1136         return true;
1137     }
1138 
1139 /+ #ifndef Q_CLANG_QDOC +/
1140     /+ template <typename Functor> +/
1141     /+ QPropertyBinding<T> setBinding(Functor &&f,
1142                                    const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION,
1143                                    std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr)
1144     {
1145         return setBinding(Qt::makePropertyBinding(std::forward<Functor>(f), location));
1146     } +/
1147 /+ #else
1148     template <typename Functor>
1149     QPropertyBinding<T> setBinding(Functor f);
1150 #endif +/
1151 
1152     bool hasBinding() const
1153     {
1154         import qt.core.object;
1155 
1156         auto* bd = cast(auto*)(qGetBindingStorage(owner()).bindingData(&this));
1157         return bd && bd.binding() !is null;
1158     }
1159 
1160     QPropertyBinding!(T) binding() const
1161     {
1162         import qt.core.object;
1163 
1164         auto* bd = cast(auto*)(qGetBindingStorage(owner()).bindingData(&this));
1165         return static_cast!(QPropertyBinding!(T) && /+ && +/)(QUntypedPropertyBinding(bd ? bd.binding() : null));
1166     }
1167 
1168     QPropertyBinding!(T) takeBinding()
1169     {
1170         return setBinding(cast(Functor && )(QPropertyBinding!(T)()));
1171     }
1172 
1173     /+ template<typename Functor> +/
1174     ValueClass!(QPropertyChangeHandler!(Functor)) onValueChanged(Functor)(Functor f)
1175     {
1176         static assert(/+ std:: +/is_invocable_v!(Functor), "Functor callback must be callable without any parameters");
1177         return QPropertyChangeHandler!(Functor)(this, f);
1178     }
1179 
1180     /+ template<typename Functor> +/
1181     ValueClass!(QPropertyChangeHandler!(Functor)) subscribe(Functor)(Functor f)
1182     {
1183         static assert(/+ std:: +/is_invocable_v!(Functor), "Functor callback must be callable without any parameters");
1184         f();
1185         return onValueChanged(f);
1186     }
1187 
1188     /+ template<typename Functor> +/
1189     QPropertyNotifier addNotifier(Functor)(Functor f)
1190     {
1191         static assert(/+ std:: +/is_invocable_v!(Functor), "Functor callback must be callable without any parameters");
1192         return QPropertyNotifier(this, f);
1193     }
1194 
1195     ref const(/+ QtPrivate:: +/qt.core.propertyprivate.QPropertyBindingData) bindingData() const
1196     {
1197         import qt.core.bindingstorage;
1198         import qt.core.object;
1199 
1200         auto* storage = const_cast!(QBindingStorage*)(qGetBindingStorage(owner()));
1201         return *storage.bindingData(const_cast!(ThisType*)(&this), true);
1202     }
1203 private:
1204     void notify(const(/+ QtPrivate:: +/qt.core.propertyprivate.QPropertyBindingData)* binding)
1205     {
1206         import qt.core.object;
1207 
1208         if (binding)
1209             binding.notifyObservers(&this, qGetBindingStorage(owner()));
1210         static if (HasSignal) {
1211             static if (SignalTakesValue.value)
1212                 (owner()->*Signal)(this.valueBypassingBindings());
1213             else
1214                 (owner()->*Signal)();
1215         }
1216     }
1217 }+/
1218 
1219 /+ #define QT_OBJECT_BINDABLE_PROPERTY_3(Class, Type, name) \
1220     static constexpr size_t _qt_property_##name##_offset() { \
1221         QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
1222         return offsetof(Class, name); \
1223         QT_WARNING_POP \
1224     } \
1225     QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, nullptr> name;
1226 
1227 #define QT_OBJECT_BINDABLE_PROPERTY_4(Class, Type, name, Signal) \
1228     static constexpr size_t _qt_property_##name##_offset() { \
1229         QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
1230         return offsetof(Class, name); \
1231         QT_WARNING_POP \
1232     } \
1233     QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, Signal> name;
1234 
1235 #define Q_OBJECT_BINDABLE_PROPERTY(...) \
1236     QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
1237     QT_OVERLOADED_MACRO(QT_OBJECT_BINDABLE_PROPERTY, __VA_ARGS__) \
1238     QT_WARNING_POP
1239 
1240 #define QT_OBJECT_BINDABLE_PROPERTY_WITH_ARGS_4(Class, Type, name, value)                          \
1241     static constexpr size_t _qt_property_##name##_offset()                                         \
1242     {                                                                                              \
1243         QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF                                        \
1244         return offsetof(Class, name);                                                              \
1245         QT_WARNING_POP                                                                             \
1246     }                                                                                              \
1247     QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, nullptr> name =      \
1248             QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, nullptr>(    \
1249                     value);
1250 
1251 #define QT_OBJECT_BINDABLE_PROPERTY_WITH_ARGS_5(Class, Type, name, value, Signal)                  \
1252     static constexpr size_t _qt_property_##name##_offset()                                         \
1253     {                                                                                              \
1254         QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF                                        \
1255         return offsetof(Class, name);                                                              \
1256         QT_WARNING_POP                                                                             \
1257     }                                                                                              \
1258     QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, Signal> name =       \
1259             QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, Signal>(     \
1260                     value);
1261 
1262 #define Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(...)                                                  \
1263     QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
1264     QT_OVERLOADED_MACRO(QT_OBJECT_BINDABLE_PROPERTY_WITH_ARGS, __VA_ARGS__) \
1265     QT_WARNING_POP +/
1266 
1267 /// Binding for C++ class [QObjectComputedProperty](https://doc.qt.io/qt-6/qobjectcomputedproperty.html).
1268 /+class QObjectComputedProperty(Class, T, auto Offset, auto Getter) : QUntypedPropertyData
1269 {
1270 private:
1271     final Class* owner()
1272     {
1273         char* that = reinterpret_cast!(char*)(this);
1274         return reinterpret_cast!(Class*)(that - /+ QtPrivate:: +//+ detail:: +/qt.core.propertyprivate.getOffset(Offset));
1275     }
1276     final const(Class)* owner() const
1277     {
1278         char* that = const_cast!(char*)(reinterpret_cast!(const(char)*)(this));
1279         return reinterpret_cast!(Class*)(that - /+ QtPrivate:: +//+ detail:: +/qt.core.propertyprivate.getOffset(Offset));
1280     }
1281 
1282 public:
1283     alias value_type = T;
1284     alias parameter_type = T;
1285 
1286     /+ QObjectComputedProperty() = default; +/
1287 
1288     final parameter_type value() const
1289     {
1290         import qt.core.object;
1291 
1292         qGetBindingStorage(owner()).registerDependency(this);
1293         return (owner()->*Getter)();
1294     }
1295 
1296     /+ std::conditional_t<QTypeTraits::is_dereferenceable_v<T>, parameter_type, void>
1297     operator->() const
1298     {
1299         static if (QTypeTraits::is_dereferenceable_v<T>)
1300             return value();
1301         else
1302             return;
1303     } +/
1304 
1305     final parameter_type opUnary(string op)() const if(op == "*")
1306     {
1307         return value();
1308     }
1309 
1310     /+final auto opCast(T : parameter_type)() const
1311     {
1312         return value();
1313     }+/
1314 
1315     final bool hasBinding() const { return false; }
1316 
1317     /+ template<typename Functor> +/
1318     final ValueClass!(QPropertyChangeHandler!(Functor)) onValueChanged(Functor)(Functor f)
1319     {
1320         static assert(/+ std:: +/is_invocable_v!(Functor), "Functor callback must be callable without any parameters");
1321         return QPropertyChangeHandler!(Functor)(*this, f);
1322     }
1323 
1324     /+ template<typename Functor> +/
1325     final ValueClass!(QPropertyChangeHandler!(Functor)) subscribe(Functor)(Functor f)
1326     {
1327         static assert(/+ std:: +/is_invocable_v!(Functor), "Functor callback must be callable without any parameters");
1328         f();
1329         return onValueChanged(f);
1330     }
1331 
1332     /+ template<typename Functor> +/
1333     final QPropertyNotifier addNotifier(Functor)(Functor f)
1334     {
1335         static assert(/+ std:: +/is_invocable_v!(Functor), "Functor callback must be callable without any parameters");
1336         return QPropertyNotifier(*this, f);
1337     }
1338 
1339     final ref /+ QtPrivate:: +/qt.core.propertyprivate.QPropertyBindingData bindingData() const
1340     {
1341         import qt.core.bindingstorage;
1342         import qt.core.object;
1343 
1344         auto* storage = const_cast!(QBindingStorage*)(qGetBindingStorage(owner()));
1345         return *storage.bindingData(const_cast!(QObjectComputedProperty)(this), true);
1346     }
1347 
1348     final void notify() {
1349         import qt.core.bindingstorage;
1350         import qt.core.object;
1351 
1352         // computed property can't store a binding, so there's nothing to mark
1353         auto* storage = const_cast!(QBindingStorage*)(qGetBindingStorage(owner()));
1354         auto bd = storage.bindingData(const_cast!(QObjectComputedProperty)(this), false);
1355         if (bd)
1356             bd.notifyObservers(this, qGetBindingStorage(owner()));
1357     }
1358 }+/
1359 
1360 /+ #define Q_OBJECT_COMPUTED_PROPERTY(Class, Type, name,  ...) \
1361     static constexpr size_t _qt_property_##name##_offset() { \
1362         QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
1363         return offsetof(Class, name); \
1364         QT_WARNING_POP \
1365     } \
1366     QObjectComputedProperty<Class, Type, Class::_qt_property_##name##_offset, __VA_ARGS__> name;
1367 
1368 #undef QT_SOURCE_LOCATION_NAMESPACE +/
1369 
1370