forked from quickshell/quickshell
		
	core/boundcomponent: add BoundComponent
This commit is contained in:
		
							parent
							
								
									d64bf59bb0
								
							
						
					
					
						commit
						3c0456a3c0
					
				
					 4 changed files with 385 additions and 0 deletions
				
			
		| 
						 | 
					@ -25,6 +25,7 @@ qt_add_library(quickshell-core STATIC
 | 
				
			||||||
	iconimageprovider.cpp
 | 
						iconimageprovider.cpp
 | 
				
			||||||
	imageprovider.cpp
 | 
						imageprovider.cpp
 | 
				
			||||||
	transformwatcher.cpp
 | 
						transformwatcher.cpp
 | 
				
			||||||
 | 
						boundcomponent.cpp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set_source_files_properties(main.cpp PROPERTIES COMPILE_DEFINITIONS GIT_REVISION="${GIT_REVISION}")
 | 
					set_source_files_properties(main.cpp PROPERTIES COMPILE_DEFINITIONS GIT_REVISION="${GIT_REVISION}")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										258
									
								
								src/core/boundcomponent.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								src/core/boundcomponent.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,258 @@
 | 
				
			||||||
 | 
					#include "boundcomponent.hpp"
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qcontainerfwd.h>
 | 
				
			||||||
 | 
					#include <qlogging.h>
 | 
				
			||||||
 | 
					#include <qmetaobject.h>
 | 
				
			||||||
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qobjectdefs.h>
 | 
				
			||||||
 | 
					#include <qqmlcomponent.h>
 | 
				
			||||||
 | 
					#include <qqmlcontext.h>
 | 
				
			||||||
 | 
					#include <qqmlengine.h>
 | 
				
			||||||
 | 
					#include <qqmlerror.h>
 | 
				
			||||||
 | 
					#include <qquickitem.h>
 | 
				
			||||||
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "incubator.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QObject* BoundComponent::item() const { return this->object; }
 | 
				
			||||||
 | 
					QQmlComponent* BoundComponent::sourceComponent() const { return this->mComponent; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BoundComponent::setSourceComponent(QQmlComponent* component) {
 | 
				
			||||||
 | 
						if (component == this->mComponent) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->componentCompleted) {
 | 
				
			||||||
 | 
							qWarning() << "BoundComponent.component cannot be set after creation";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this->disconnectComponent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->ownsComponent = false;
 | 
				
			||||||
 | 
						this->mComponent = component;
 | 
				
			||||||
 | 
						if (component != nullptr) {
 | 
				
			||||||
 | 
							QObject::connect(component, &QObject::destroyed, this, &BoundComponent::onComponentDestroyed);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						emit this->sourceComponentChanged();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BoundComponent::disconnectComponent() {
 | 
				
			||||||
 | 
						if (this->mComponent == nullptr) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->ownsComponent) {
 | 
				
			||||||
 | 
							delete this->mComponent;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							QObject::disconnect(this->mComponent, nullptr, this, nullptr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->mComponent = nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BoundComponent::onComponentDestroyed() { this->mComponent = nullptr; }
 | 
				
			||||||
 | 
					QString BoundComponent::source() const { return this->mSource; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BoundComponent::setSource(QString source) {
 | 
				
			||||||
 | 
						if (source == this->mSource) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->componentCompleted) {
 | 
				
			||||||
 | 
							qWarning() << "BoundComponent.url cannot be set after creation";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto* context = QQmlEngine::contextForObject(this);
 | 
				
			||||||
 | 
						auto* component = new QQmlComponent(context->engine(), context->resolvedUrl(source), this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (component->isError()) {
 | 
				
			||||||
 | 
							qWarning() << component->errorString().toStdString().c_str();
 | 
				
			||||||
 | 
							delete component;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							this->disconnectComponent();
 | 
				
			||||||
 | 
							this->ownsComponent = true;
 | 
				
			||||||
 | 
							this->mSource = std::move(source);
 | 
				
			||||||
 | 
							this->mComponent = component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							emit this->sourceChanged();
 | 
				
			||||||
 | 
							emit this->sourceComponentChanged();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool BoundComponent::bindValues() const { return this->mBindValues; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BoundComponent::setBindValues(bool bindValues) {
 | 
				
			||||||
 | 
						if (this->componentCompleted) {
 | 
				
			||||||
 | 
							qWarning() << "BoundComponent.bindValues cannot be set after creation";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->mBindValues = bindValues;
 | 
				
			||||||
 | 
						emit this->bindValuesChanged();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BoundComponent::componentComplete() {
 | 
				
			||||||
 | 
						this->QQuickItem::componentComplete();
 | 
				
			||||||
 | 
						this->componentCompleted = true;
 | 
				
			||||||
 | 
						this->tryCreate();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BoundComponent::tryCreate() {
 | 
				
			||||||
 | 
						if (this->mComponent == nullptr) {
 | 
				
			||||||
 | 
							qWarning() << "BoundComponent has no component";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto initialProperties = QVariantMap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto* metaObject = this->metaObject();
 | 
				
			||||||
 | 
						for (auto i = metaObject->propertyOffset(); i < metaObject->propertyCount(); i++) {
 | 
				
			||||||
 | 
							const auto prop = metaObject->property(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (prop.isReadable()) {
 | 
				
			||||||
 | 
								initialProperties.insert(prop.name(), prop.read(this));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->incubator = new QsQmlIncubator(QsQmlIncubator::AsynchronousIfNested, this);
 | 
				
			||||||
 | 
						this->incubator->setInitialProperties(initialProperties);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// clang-format off
 | 
				
			||||||
 | 
						QObject::connect(this->incubator, &QsQmlIncubator::completed, this, &BoundComponent::onIncubationCompleted);
 | 
				
			||||||
 | 
						QObject::connect(this->incubator, &QsQmlIncubator::failed, this, &BoundComponent::onIncubationFailed);
 | 
				
			||||||
 | 
						// clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->mComponent->create(*this->incubator, QQmlEngine::contextForObject(this));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BoundComponent::onIncubationCompleted() {
 | 
				
			||||||
 | 
						this->object = this->incubator->object();
 | 
				
			||||||
 | 
						delete this->incubator;
 | 
				
			||||||
 | 
						this->disconnectComponent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->object->setParent(this);
 | 
				
			||||||
 | 
						this->mItem = qobject_cast<QQuickItem*>(this->object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto* metaObject = this->metaObject();
 | 
				
			||||||
 | 
						const auto* objectMetaObject = this->object->metaObject();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->mBindValues) {
 | 
				
			||||||
 | 
							for (auto i = metaObject->propertyOffset(); i < metaObject->propertyCount(); i++) {
 | 
				
			||||||
 | 
								const auto prop = metaObject->property(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (prop.isReadable() && prop.hasNotifySignal()) {
 | 
				
			||||||
 | 
									const auto objectPropIndex = objectMetaObject->indexOfProperty(prop.name());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (objectPropIndex == -1) {
 | 
				
			||||||
 | 
										qWarning() << "property" << prop.name()
 | 
				
			||||||
 | 
										           << "defined on BoundComponent but not on its contained object.";
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									const auto objectProp = objectMetaObject->property(objectPropIndex);
 | 
				
			||||||
 | 
									if (objectProp.isWritable()) {
 | 
				
			||||||
 | 
										auto* proxy = new BoundComponentPropertyProxy(this, this->object, prop, objectProp);
 | 
				
			||||||
 | 
										proxy->onNotified(); // any changes that might've happened before connection
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										qWarning() << "property" << prop.name()
 | 
				
			||||||
 | 
										           << "defined on BoundComponent is not writable for its contained object.";
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto i = metaObject->methodOffset(); i < metaObject->methodCount(); i++) {
 | 
				
			||||||
 | 
							const auto method = metaObject->method(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (method.name().startsWith("on") && method.name().length() > 2) {
 | 
				
			||||||
 | 
								auto sig = QString(method.methodSignature()).sliced(2);
 | 
				
			||||||
 | 
								if (!sig[0].isUpper()) continue;
 | 
				
			||||||
 | 
								sig[0] = sig[0].toLower();
 | 
				
			||||||
 | 
								auto name = sig.sliced(0, sig.indexOf('('));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto mostViableSignal = QMetaMethod();
 | 
				
			||||||
 | 
								for (auto i = 0; i < objectMetaObject->methodCount(); i++) {
 | 
				
			||||||
 | 
									const auto method = objectMetaObject->method(i);
 | 
				
			||||||
 | 
									if (method.methodSignature() == sig) {
 | 
				
			||||||
 | 
										mostViableSignal = method;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (method.name() == name) {
 | 
				
			||||||
 | 
										if (mostViableSignal.isValid()) {
 | 
				
			||||||
 | 
											qWarning() << "Multiple candidates, so none will be attached for signal" << name;
 | 
				
			||||||
 | 
											goto next;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										mostViableSignal = method;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!mostViableSignal.isValid()) {
 | 
				
			||||||
 | 
									qWarning() << "Function" << method.name() << "appears to be a signal handler for" << name
 | 
				
			||||||
 | 
									           << "but it does not match any signals on the target object";
 | 
				
			||||||
 | 
									goto next;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								QMetaObject::connect(
 | 
				
			||||||
 | 
								    this->object,
 | 
				
			||||||
 | 
								    mostViableSignal.methodIndex(),
 | 
				
			||||||
 | 
								    this,
 | 
				
			||||||
 | 
								    method.methodIndex()
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						next:;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->mItem != nullptr) {
 | 
				
			||||||
 | 
							this->mItem->setParentItem(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// clang-format off
 | 
				
			||||||
 | 
							QObject::connect(this, &QQuickItem::widthChanged, this, &BoundComponent::updateSize);
 | 
				
			||||||
 | 
							QObject::connect(this, &QQuickItem::heightChanged, this, &BoundComponent::updateSize);
 | 
				
			||||||
 | 
							QObject::connect(this->mItem, &QQuickItem::implicitWidthChanged, this, &BoundComponent::updateImplicitSize);
 | 
				
			||||||
 | 
							QObject::connect(this->mItem, &QQuickItem::implicitHeightChanged, this, &BoundComponent::updateImplicitSize);
 | 
				
			||||||
 | 
							// clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this->updateImplicitSize();
 | 
				
			||||||
 | 
							this->updateSize();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						emit this->loaded();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BoundComponent::onIncubationFailed() {
 | 
				
			||||||
 | 
						qWarning() << "Failed to create BoundComponent";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto& error: this->incubator->errors()) {
 | 
				
			||||||
 | 
							qWarning() << error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						delete this->incubator;
 | 
				
			||||||
 | 
						this->disconnectComponent();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BoundComponent::updateSize() { this->mItem->setSize(this->size()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BoundComponent::updateImplicitSize() {
 | 
				
			||||||
 | 
						this->setImplicitWidth(this->mItem->implicitWidth());
 | 
				
			||||||
 | 
						this->setImplicitHeight(this->mItem->implicitHeight());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BoundComponentPropertyProxy::BoundComponentPropertyProxy(
 | 
				
			||||||
 | 
					    QObject* from,
 | 
				
			||||||
 | 
					    QObject* to,
 | 
				
			||||||
 | 
					    QMetaProperty fromProperty,
 | 
				
			||||||
 | 
					    QMetaProperty toProperty
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					    : QObject(from)
 | 
				
			||||||
 | 
					    , from(from)
 | 
				
			||||||
 | 
					    , to(to)
 | 
				
			||||||
 | 
					    , fromProperty(fromProperty)
 | 
				
			||||||
 | 
					    , toProperty(toProperty) {
 | 
				
			||||||
 | 
						const auto* metaObject = this->metaObject();
 | 
				
			||||||
 | 
						auto method = metaObject->indexOfSlot("onNotified()");
 | 
				
			||||||
 | 
						QMetaObject::connect(from, fromProperty.notifySignal().methodIndex(), this, method);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BoundComponentPropertyProxy::onNotified() {
 | 
				
			||||||
 | 
						this->toProperty.write(this->to, this->fromProperty.read(this->from));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										125
									
								
								src/core/boundcomponent.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								src/core/boundcomponent.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,125 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qmetaobject.h>
 | 
				
			||||||
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qqmlcomponent.h>
 | 
				
			||||||
 | 
					#include <qqmlparserstatus.h>
 | 
				
			||||||
 | 
					#include <qquickitem.h>
 | 
				
			||||||
 | 
					#include <qsignalmapper.h>
 | 
				
			||||||
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "incubator.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					///! Component loader that allows setting initial properties.
 | 
				
			||||||
 | 
					/// Component loader that allows setting initial properties, primarily useful for
 | 
				
			||||||
 | 
					/// escaping cyclic dependency errors.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Properties defined on the BoundComponent will be applied to its loaded component,
 | 
				
			||||||
 | 
					/// including required properties, and will remain reactive. Functions created with
 | 
				
			||||||
 | 
					/// the names of signal handlers will also be attached to signals of the loaded component.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// ```qml {filename="MyComponent.qml"}
 | 
				
			||||||
 | 
					/// MouseArea {
 | 
				
			||||||
 | 
					///   required property color color;
 | 
				
			||||||
 | 
					///   width: 100
 | 
				
			||||||
 | 
					///   height: 100
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					///   Rectangle {
 | 
				
			||||||
 | 
					///     anchors.fill: parent
 | 
				
			||||||
 | 
					///     color: parent.color
 | 
				
			||||||
 | 
					///   }
 | 
				
			||||||
 | 
					/// }
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// ```qml
 | 
				
			||||||
 | 
					/// BoundComponent {
 | 
				
			||||||
 | 
					///   source: "MyComponent.qml"
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					///   // this is the same as assigning to `color` on MyComponent if loaded normally.
 | 
				
			||||||
 | 
					///   property color color: "red";
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					///   // this will be triggered when the `clicked` signal from the MouseArea is sent.
 | 
				
			||||||
 | 
					///   function onClicked() {
 | 
				
			||||||
 | 
					///     color = "blue";
 | 
				
			||||||
 | 
					///   }
 | 
				
			||||||
 | 
					/// }
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					class BoundComponent: public QQuickItem {
 | 
				
			||||||
 | 
						Q_OBJECT;
 | 
				
			||||||
 | 
						// clang-format off
 | 
				
			||||||
 | 
						/// The loaded component. Will be null until it has finished loading.
 | 
				
			||||||
 | 
						Q_PROPERTY(QObject* item READ item NOTIFY loaded);
 | 
				
			||||||
 | 
						/// The source to load, as a Component.
 | 
				
			||||||
 | 
						Q_PROPERTY(QQmlComponent* sourceComponent READ sourceComponent WRITE setSourceComponent NOTIFY sourceComponentChanged);
 | 
				
			||||||
 | 
						/// The source to load, as a Url.
 | 
				
			||||||
 | 
						Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged);
 | 
				
			||||||
 | 
						/// If property values should be bound after they are initially set. Defaults to `true`.
 | 
				
			||||||
 | 
						Q_PROPERTY(bool bindValues READ bindValues WRITE setBindValues NOTIFY bindValuesChanged);
 | 
				
			||||||
 | 
						Q_PROPERTY(qreal implicitWidth READ implicitWidth NOTIFY implicitWidthChanged);
 | 
				
			||||||
 | 
						Q_PROPERTY(qreal implicitHeight READ implicitHeight NOTIFY implicitHeightChanged);
 | 
				
			||||||
 | 
						// clang-format on
 | 
				
			||||||
 | 
						QML_ELEMENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						explicit BoundComponent(QQuickItem* parent = nullptr): QQuickItem(parent) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void componentComplete() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] QObject* item() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] QQmlComponent* sourceComponent() const;
 | 
				
			||||||
 | 
						void setSourceComponent(QQmlComponent* sourceComponent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] QString source() const;
 | 
				
			||||||
 | 
						void setSource(QString source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] bool bindValues() const;
 | 
				
			||||||
 | 
						void setBindValues(bool bindValues);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					signals:
 | 
				
			||||||
 | 
						void loaded();
 | 
				
			||||||
 | 
						void sourceComponentChanged();
 | 
				
			||||||
 | 
						void sourceChanged();
 | 
				
			||||||
 | 
						void bindValuesChanged();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private slots:
 | 
				
			||||||
 | 
						void onComponentDestroyed();
 | 
				
			||||||
 | 
						void onIncubationCompleted();
 | 
				
			||||||
 | 
						void onIncubationFailed();
 | 
				
			||||||
 | 
						void updateSize();
 | 
				
			||||||
 | 
						void updateImplicitSize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						void disconnectComponent();
 | 
				
			||||||
 | 
						void tryCreate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QString mSource;
 | 
				
			||||||
 | 
						bool mBindValues = true;
 | 
				
			||||||
 | 
						QQmlComponent* mComponent = nullptr;
 | 
				
			||||||
 | 
						bool ownsComponent = false;
 | 
				
			||||||
 | 
						QsQmlIncubator* incubator = nullptr;
 | 
				
			||||||
 | 
						QObject* object = nullptr;
 | 
				
			||||||
 | 
						QQuickItem* mItem = nullptr;
 | 
				
			||||||
 | 
						bool componentCompleted = false;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BoundComponentPropertyProxy: public QObject {
 | 
				
			||||||
 | 
						Q_OBJECT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						BoundComponentPropertyProxy(
 | 
				
			||||||
 | 
						    QObject* from,
 | 
				
			||||||
 | 
						    QObject* to,
 | 
				
			||||||
 | 
						    QMetaProperty fromProperty,
 | 
				
			||||||
 | 
						    QMetaProperty toProperty
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public slots:
 | 
				
			||||||
 | 
						void onNotified();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						QObject* from;
 | 
				
			||||||
 | 
						QObject* to;
 | 
				
			||||||
 | 
						QMetaProperty fromProperty;
 | 
				
			||||||
 | 
						QMetaProperty toProperty;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -17,5 +17,6 @@ headers = [
 | 
				
			||||||
	"lazyloader.hpp",
 | 
						"lazyloader.hpp",
 | 
				
			||||||
	"easingcurve.hpp",
 | 
						"easingcurve.hpp",
 | 
				
			||||||
	"transformwatcher.hpp",
 | 
						"transformwatcher.hpp",
 | 
				
			||||||
 | 
						"boundcomponent.hpp",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
-----
 | 
					-----
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue