Files
qt-creator/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp
Miikka Heikkinen f146b846cd QmlDesigner: Implement proper preview for pure 3D scenes
Refactored the existing 3D node preview generation to be done
synchronously, which enables their use also for creating state
and item library previews for 3D nodes with ease.

Fixes: QDS-5785
Change-Id: Ib493eccbc239f33bcad3301673a865494616a901
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
2022-02-10 14:47:26 +00:00

1055 lines
29 KiB
C++

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "objectnodeinstance.h"
#include <enumeration.h>
#include <qmlprivategate.h>
#include <QDebug>
#include <QEvent>
#include <QQmlContext>
#include <QQmlError>
#include <QQmlEngine>
#include <QQmlProperty>
#include <QQmlComponent>
#include <QSharedPointer>
#include <QFileInfo>
#include <QFileSystemWatcher>
#include <QPixmapCache>
#include <QQuickItem>
#include <QQmlExpression>
#include <QQmlParserStatus>
#include <QTextDocument>
#include <QLibraryInfo>
#include <QJSValue>
static bool isSimpleExpression(const QString &expression)
{
if (expression.startsWith(QStringLiteral("{")))
return false;
return true;
}
namespace QmlDesigner {
namespace Internal {
ObjectNodeInstance::ObjectNodeInstance(QObject *object)
: m_object(object),
m_instanceId(-1),
m_deleteHeldInstance(true),
m_isInLayoutable(false)
{
if (object)
QObject::connect(m_object.data(), &QObject::destroyed, [=] {
handleObjectDeletion(object);
});
}
ObjectNodeInstance::~ObjectNodeInstance()
{
destroy();
}
void ObjectNodeInstance::destroy()
{
if (deleteHeldInstance()) {
// Remove from old property
if (object()) {
setId(QString());
if (m_instanceId >= 0) {
reparent(parentInstance(), m_parentProperty, ObjectNodeInstance::Pointer(), PropertyName());
}
}
if (object()) {
QObject *obj = object();
m_object.clear();
delete obj;
}
}
m_instanceId = -1;
}
void ObjectNodeInstance::handleObjectDeletion(QObject *object)
{
// We must pass the m_instanceId here, because this instance is no longer
// valid, so the wrapper ServerNodeInstance will report -1 for id.
if (m_nodeInstanceServer)
m_nodeInstanceServer->removeInstanceRelationsipForDeletedObject(object, m_instanceId);
}
void ObjectNodeInstance::setInstanceId(qint32 id)
{
m_instanceId = id;
}
qint32 ObjectNodeInstance::instanceId() const
{
return m_instanceId;
}
NodeInstanceServer *ObjectNodeInstance::nodeInstanceServer() const
{
return m_nodeInstanceServer.data();
}
void ObjectNodeInstance::setNodeInstanceServer(NodeInstanceServer *server)
{
Q_ASSERT(!m_nodeInstanceServer.data());
m_nodeInstanceServer = server;
}
void ObjectNodeInstance::initializePropertyWatcher(const ObjectNodeInstance::Pointer &objectNodeInstance)
{
m_signalSpy.setObjectNodeInstance(objectNodeInstance);
}
void ObjectNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance,
InstanceContainer::NodeFlags /*flags*/)
{
initializePropertyWatcher(objectNodeInstance);
QmlPrivateGate::registerNodeInstanceMetaObject(objectNodeInstance->object(), objectNodeInstance->nodeInstanceServer()->engine());
}
void ObjectNodeInstance::setId(const QString &id)
{
if (!m_id.isEmpty() && context()) {
context()->engine()->rootContext()->setContextProperty(m_id, nullptr);
}
if (!id.isEmpty() && context()) {
context()->engine()->rootContext()->setContextProperty(id, object()); // will also force refresh of all bindings
}
m_id = id;
}
QString ObjectNodeInstance::id() const
{
return m_id;
}
bool ObjectNodeInstance::isTransition() const
{
return false;
}
bool ObjectNodeInstance::isPositioner() const
{
return false;
}
bool ObjectNodeInstance::isQuickItem() const
{
return false;
}
bool ObjectNodeInstance::isQuickWindow() const
{
return false;
}
bool ObjectNodeInstance::isLayoutable() const
{
return false;
}
bool ObjectNodeInstance::isRenderable() const
{
return false;
}
bool ObjectNodeInstance::equalGraphicsItem(QGraphicsItem * /*item*/) const
{
return false;
}
QTransform ObjectNodeInstance::transform() const
{
return QTransform();
}
QTransform ObjectNodeInstance::contentTransform() const
{
return QTransform();
}
QTransform ObjectNodeInstance::customTransform() const
{
return QTransform();
}
QTransform ObjectNodeInstance::contentItemTransform() const
{
return QTransform();
}
QTransform ObjectNodeInstance::sceneTransform() const
{
return QTransform();
}
double ObjectNodeInstance::rotation() const
{
return 0.0;
}
double ObjectNodeInstance::scale() const
{
return 1.0;
}
QList<QGraphicsTransform *> ObjectNodeInstance::transformations() const
{
QList<QGraphicsTransform *> transformationsList;
return transformationsList;
}
QPointF ObjectNodeInstance::transformOriginPoint() const
{
return QPoint();
}
double ObjectNodeInstance::zValue() const
{
return 0.0;
}
double ObjectNodeInstance::opacity() const
{
return 1.0;
}
bool ObjectNodeInstance::hasAnchor(const PropertyName &/*name*/) const
{
return false;
}
bool ObjectNodeInstance::isAnchoredBySibling() const
{
return false;
}
bool ObjectNodeInstance::isAnchoredByChildren() const
{
return false;
}
QPair<PropertyName, ServerNodeInstance> ObjectNodeInstance::anchor(const PropertyName &/*name*/) const
{
return {PropertyName(), ServerNodeInstance()};
}
static bool isList(const QQmlProperty &property)
{
return property.propertyTypeCategory() == QQmlProperty::List;
}
static bool isQJSValue(const QQmlProperty &property)
{
return property.isValid() && !strcmp(property.propertyTypeName(), "QJSValue");
}
static bool isObject(const QQmlProperty &property)
{
/* QVariant and QJSValue can also store QObjects. Lets trust our model. */
return property.isValid() && (property.propertyTypeCategory() == QQmlProperty::Object
|| !strcmp(property.propertyTypeName(), "QVariant")
|| isQJSValue(property));
}
static QVariant objectToVariant(QObject *object)
{
return QVariant::fromValue(object);
}
static void removeObjectFromList(const QQmlProperty &property, QObject *objectToBeRemoved, QQmlEngine * engine)
{
QQmlListReference listReference(property.object(), property.name().toUtf8(), engine);
if (!QmlPrivateGate::hasFullImplementedListInterface(listReference)) {
qWarning() << "Property list interface not fully implemented for Class " << property.property().typeName() << " in property " << property.name() << "!";
return;
}
int count = listReference.count();
QObjectList objectList;
for (int i = 0; i < count; i ++) {
QObject *listItem = listReference.at(i);
if (listItem && listItem != objectToBeRemoved)
objectList.append(listItem);
}
listReference.clear();
foreach (QObject *object, objectList)
listReference.append(object);
}
void ObjectNodeInstance::removeFromOldProperty(QObject *object, QObject *oldParent, const PropertyName &oldParentProperty)
{
QQmlProperty property(oldParent, QString::fromUtf8(oldParentProperty), context());
if (!property.isValid())
return;
if (isList(property)) {
removeObjectFromList(property, object, nodeInstanceServer()->engine());
} else if (isObject(property)) {
if (nodeInstanceServer()->hasInstanceForObject(oldParent)) {
nodeInstanceServer()->instanceForObject(oldParent).resetProperty(oldParentProperty);
}
}
if (object && object->parent())
object->setParent(nullptr);
}
void ObjectNodeInstance::addToNewProperty(QObject *object, QObject *newParent, const PropertyName &newParentProperty)
{
QQmlProperty property(newParent, QString::fromUtf8(newParentProperty), context());
if (object)
object->setParent(newParent);
if (isList(property)) {
QQmlListReference list = qvariant_cast<QQmlListReference>(property.read());
if (!QmlPrivateGate::hasFullImplementedListInterface(list)) {
qWarning() << "Property list interface not fully implemented for Class " << property.property().typeName() << " in property " << property.name() << "!";
return;
}
list.append(object);
} else if (isObject(property)) {
if (isQJSValue(property)) /* In this case we have to explcitly generate and convert a QJSValue */
property.write(QVariant::fromValue(engine()->newQObject(object)));
else
property.write(objectToVariant(object));
if (QQuickItem *item = qobject_cast<QQuickItem *>(object))
if (QQuickItem *newParentItem = qobject_cast<QQuickItem *>(newParent))
item->setParentItem(newParentItem);
}
Q_ASSERT(objectToVariant(object).isValid());
}
void ObjectNodeInstance::reparent(const ObjectNodeInstance::Pointer &oldParentInstance, const PropertyName &oldParentProperty, const ObjectNodeInstance::Pointer &newParentInstance, const PropertyName &newParentProperty)
{
if (oldParentInstance && !oldParentInstance->ignoredProperties().contains(oldParentProperty)) {
removeFromOldProperty(object(), oldParentInstance->object(), oldParentProperty);
m_parentProperty.clear();
}
if (newParentInstance && !newParentInstance->ignoredProperties().contains(newParentProperty)) {
m_parentProperty = newParentProperty;
addToNewProperty(object(), newParentInstance->object(), newParentProperty);
}
}
QVariant ObjectNodeInstance::convertSpecialCharacter(const QVariant& value) const
{
QVariant specialCharacterConvertedValue = value;
if (value.type() == QVariant::String) {
QString string = value.toString();
string.replace(QLatin1String("\\n"), QLatin1String("\n"));
string.replace(QLatin1String("\\t"), QLatin1String("\t"));
specialCharacterConvertedValue = string;
}
return specialCharacterConvertedValue;
}
void ObjectNodeInstance::updateAllDirtyNodesRecursive()
{
}
PropertyNameList ObjectNodeInstance::ignoredProperties() const
{
return PropertyNameList();
}
void ObjectNodeInstance::setHiddenInEditor(bool b)
{
m_isHiddenInEditor = b;
}
bool ObjectNodeInstance::isHiddenInEditor() const
{
return m_isHiddenInEditor;
}
void ObjectNodeInstance::setLockedInEditor(bool b)
{
m_isLockedInEditor = b;
}
bool ObjectNodeInstance::isLockedInEditor() const
{
return m_isLockedInEditor;
}
bool ObjectNodeInstance::isComponentWrap() const
{
return m_isComponentWrap;
}
void ObjectNodeInstance::setComponentWrap(bool wrap)
{
m_isComponentWrap = wrap;
}
void ObjectNodeInstance::setModifiedFlag(bool b)
{
m_isModified = b;
}
QVariant ObjectNodeInstance::convertEnumToValue(const QVariant &value, const PropertyName &name)
{
Q_ASSERT(value.canConvert<Enumeration>());
int propertyIndex = object()->metaObject()->indexOfProperty(name);
QMetaProperty metaProperty = object()->metaObject()->property(propertyIndex);
QVariant adjustedValue;
Enumeration enumeration = value.value<Enumeration>();
if (metaProperty.isValid() && metaProperty.isEnumType()) {
adjustedValue = metaProperty.enumerator().keyToValue(enumeration.name());
} else {
QQmlExpression expression(context(), object(), enumeration.toString());
adjustedValue = expression.evaluate();
if (expression.hasError())
qDebug() << "Enumeration cannot be evaluated:" << object() << name << enumeration;
}
return adjustedValue;
}
void ObjectNodeInstance::setPropertyVariant(const PropertyName &name, const QVariant &value)
{
if (ignoredProperties().contains(name))
return;
if (m_isModified)
return;
QQmlProperty property(object(), QString::fromUtf8(name), context());
if (!property.isValid())
return;
QVariant adjustedValue;
if (value.canConvert<Enumeration>())
adjustedValue = convertEnumToValue(value, name);
else
adjustedValue = QmlPrivateGate::fixResourcePaths(value);
QVariant oldValue = property.read();
if (oldValue.type() == QVariant::Url) {
QUrl url = oldValue.toUrl();
QString path = url.toLocalFile();
if (QFileInfo::exists(path) && nodeInstanceServer() && !path.isEmpty())
nodeInstanceServer()->removeFilePropertyFromFileSystemWatcher(object(), name, path);
}
if (hasValidResetBinding(name)) {
QmlPrivateGate::keepBindingFromGettingDeleted(object(), context(), name);
}
bool isWritten = property.write(convertSpecialCharacter(adjustedValue));
if (!isWritten)
qDebug() << "ObjectNodeInstance.setPropertyVariant: Cannot be written: " << object() << name << adjustedValue;
QVariant newValue = property.read();
if (newValue.type() == QVariant::Url) {
QUrl url = newValue.toUrl();
QString path = url.toLocalFile();
if (QFileInfo::exists(path) && nodeInstanceServer() && !path.isEmpty())
nodeInstanceServer()->addFilePropertyToFileSystemWatcher(object(), name, path);
}
}
void ObjectNodeInstance::setPropertyBinding(const PropertyName &name, const QString &expression)
{
if (ignoredProperties().contains(name))
return;
if (!isSimpleExpression(expression))
return;
QmlPrivateGate::setPropertyBinding(object(), context(), name, expression);
}
void ObjectNodeInstance::deleteObjectsInList(const QQmlProperty &property)
{
QObjectList objectList;
QQmlListReference list = qvariant_cast<QQmlListReference>(property.read());
if (!QmlPrivateGate::hasFullImplementedListInterface(list)) {
qWarning() << "Property list interface not fully implemented for Class " << property.property().typeName() << " in property " << property.name() << "!";
return;
}
for (int i = 0; i < list.count(); i++) {
objectList += list.at(i);
}
list.clear();
}
void ObjectNodeInstance::resetProperty(const PropertyName &name)
{
if (ignoredProperties().contains(name))
return;
doResetProperty(name);
if (name == "font.pixelSize")
doResetProperty("font.pointSize");
if (name == "font.pointSize")
doResetProperty("font.pixelSize");
}
void ObjectNodeInstance::refreshProperty(const PropertyName &name)
{
QQmlProperty property(object(), QString::fromUtf8(name), context());
if (!property.isValid())
return;
QVariant oldValue(property.read());
if (property.isResettable())
property.reset();
else
property.write(resetValue(name));
if (oldValue.type() == QVariant::Url) {
QByteArray key = oldValue.toUrl().toEncoded(QUrl::UrlFormattingOption(0x100));
QString pixmapKey = QString::fromUtf8(key.constData(), key.count());
QPixmapCache::remove(pixmapKey);
}
property.write(oldValue);
}
bool ObjectNodeInstance::hasBindingForProperty(const PropertyName &propertyName, bool *hasChanged) const
{
return QmlPrivateGate::hasBindingForProperty(object(), context(), propertyName, hasChanged);
}
void ObjectNodeInstance::doResetProperty(const PropertyName &propertyName)
{
QmlPrivateGate::doResetProperty(object(), context(), propertyName);
}
QVariant ObjectNodeInstance::property(const PropertyName &name) const
{
if (ignoredProperties().contains(name))
return QVariant();
// TODO: handle model nodes
if (QmlPrivateGate::isPropertyBlackListed(name))
return QVariant();
QQmlProperty property(object(), QString::fromUtf8(name), context());
if (property.property().isEnumType()) {
QVariant value = property.read();
return property.property().enumerator().valueToKey(value.toInt());
}
if (property.propertyType() == QVariant::Url) {
QUrl url = property.read().toUrl();
if (url.isEmpty())
return QVariant();
if (url.scheme() == "file") {
int basePathLength = nodeInstanceServer()->fileUrl().toLocalFile().lastIndexOf('/');
return QUrl(url.toLocalFile().mid(basePathLength + 1));
}
}
return property.read();
}
void ObjectNodeInstance::ensureVector3DDotProperties(PropertyNameList &list) const
{
const PropertyNameList properties = { "rotation", "scale", "pivot" };
for (const auto &property : properties) {
if (list.contains(property) && instanceType(property) == "QVector3D") {
const PropertyNameList dotProperties = { "x", "y", "z" };
for (const auto &dotProperty : dotProperties) {
const PropertyName dotPropertyName = property + "." + dotProperty;
if (!list.contains(dotPropertyName))
list.append(dotPropertyName);
}
}
}
}
PropertyNameList ObjectNodeInstance::propertyNames() const
{
PropertyNameList list;
if (isValid())
list = QmlPrivateGate::allPropertyNames(object());
ensureVector3DDotProperties(list);
return list;
}
QString ObjectNodeInstance::instanceType(const PropertyName &name) const
{
if (QmlPrivateGate::isPropertyBlackListed(name))
return QLatin1String("undefined");
QQmlProperty property(object(), QString::fromUtf8(name), context());
if (!property.isValid())
return QLatin1String("undefined");
return QString::fromUtf8(property.propertyTypeName());
}
QList<ServerNodeInstance> ObjectNodeInstance::childItems() const
{
return QList<ServerNodeInstance>();
}
QList<QQuickItem *> ObjectNodeInstance::allItemsRecursive() const
{
return QList<QQuickItem *>();
}
QList<ServerNodeInstance> ObjectNodeInstance::stateInstances() const
{
return QList<ServerNodeInstance>();
}
void ObjectNodeInstance::setNodeSource(const QString & /*source*/)
{
}
void ObjectNodeInstance::setDeleteHeldInstance(bool deleteInstance)
{
m_deleteHeldInstance = deleteInstance;
}
bool ObjectNodeInstance::deleteHeldInstance() const
{
return m_deleteHeldInstance;
}
ObjectNodeInstance::Pointer ObjectNodeInstance::create(QObject *object)
{
Pointer instance(new ObjectNodeInstance(object));
instance->populateResetHashes();
return instance;
}
QObject *ObjectNodeInstance::createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context)
{
QString polishTypeName = typeName;
if (typeName == "QtQuick.Controls/Popup" || typeName == "QtQuick.Controls/Drawer"
|| typeName == "QtQuick.Controls/Dialog" || typeName == "QtQuick.Controls/Menu"
|| typeName == "QtQuick.Controls/ToolTip"
|| typeName == "QtQuick.Controls/ApplicationWindow")
polishTypeName = "QtQuick/Item";
const QHash<QString, QString> mockHash = {{"QtQuick.Controls/SwipeView","qrc:/qtquickplugin/mockfiles/SwipeView.qml"},
{"QtQuick.Dialogs/Dialog","qrc:/qtquickplugin/mockfiles/Dialog.qml"}};
QObject *object = nullptr;
if (mockHash.contains(typeName))
object = QmlPrivateGate::createComponent(mockHash.value(typeName), context);
else if (majorNumber != -1 && minorNumber != -1)
object = QmlPrivateGate::createPrimitive(polishTypeName, majorNumber, minorNumber, context);
else
object = QmlPrivateGate::createPrimitive(polishTypeName, 0, 0, context);
/* Let's try to create the primitive from source, since with incomplete meta info this might be a pure
* QML type. This is the case for example if a C++ type is mocked up with a QML file.
*/
if (!object && majorNumber == 6 && minorNumber == 0) {
object = QmlPrivateGate::createPrimitive(polishTypeName, 2, 15, context);
if (!object)
object = QmlPrivateGate::createPrimitive(polishTypeName, 1, 0, context);
}
if (!object)
object = createPrimitiveFromSource(polishTypeName, majorNumber, minorNumber, context);
return object;
}
QObject *ObjectNodeInstance::createPrimitiveFromSource(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context)
{
if (typeName.isEmpty())
return nullptr;
QStringList parts = typeName.split("/");
const QString unqualifiedTypeName = parts.last();
parts.removeLast();
if (parts.isEmpty())
return nullptr;
QString importString = parts.join(".");
if (majorNumber >= 0)
importString = importString + " " + QString::number(majorNumber) + "."
+ QString::number(minorNumber);
if (importString == "QtQuick 1.0") /* Workaround for implicit QQml import */
importString = "QtQuick 2.0";
QString source = "import " + importString + "\n" + unqualifiedTypeName + " {\n" + "}\n";
return createCustomParserObject(source, "", context);
}
QObject *ObjectNodeInstance::createComponentWrap(const QString &nodeSource, const QByteArray &importCode, QQmlContext *context)
{
QmlPrivateGate::ComponentCompleteDisabler disableComponentComplete;
Q_UNUSED(disableComponentComplete)
QQmlComponent *component = new QQmlComponent(context->engine());
QByteArray data(nodeSource.toUtf8());
if (data.isEmpty()) {
// Add a fake root element as an empty component is not valid and crashes in some cases
data.append("QtObject{}");
}
data.prepend(importCode);
component->setData(data, context->baseUrl().resolved(QUrl("createComponent.qml")));
QObject *object = component;
QmlPrivateGate::tweakObjects(object);
QQmlEngine::setContextForObject(object, context);
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
if (component->isError()) {
qWarning() << "Error in:" << Q_FUNC_INFO << component->url().toString();
foreach (const QQmlError &error, component->errors())
qWarning() << error;
qWarning() << "file data:\n" << data;
}
return object;
}
//The component might also be shipped with Creator.
//To avoid trouble with import "." we use the component shipped with Creator.
static inline QString fixComponentPathForIncompatibleQt(const QString &componentPath)
{
QString result = componentPath;
const QLatin1String importString("/imports/");
if (componentPath.contains(importString)) {
int index = componentPath.indexOf(importString) + 8;
const QString relativeImportPath = componentPath.right(componentPath.length() - index);
QString fixedComponentPath = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath) + relativeImportPath;
fixedComponentPath.replace(QLatin1Char('\\'), QLatin1Char('/'));
if (QFileInfo::exists(fixedComponentPath))
return fixedComponentPath;
QString fixedPath = QFileInfo(fixedComponentPath).path();
if (fixedPath.endsWith(QLatin1String(".1.0"))) {
//plugin directories might contain the version number
fixedPath.chop(4);
fixedPath += QLatin1Char('/') + QFileInfo(componentPath).fileName();
if (QFileInfo::exists(fixedPath))
return fixedPath;
}
}
return result;
}
QObject *ObjectNodeInstance::createComponent(const QString &componentPath, QQmlContext *context)
{
QmlPrivateGate::ComponentCompleteDisabler disableComponentComplete;
Q_UNUSED(disableComponentComplete)
QQmlComponent component(context->engine(), fixComponentPathForIncompatibleQt(componentPath));
QObject *object = nullptr;
if (!component.isError()) {
object = component.beginCreate(context);
QmlPrivateGate::tweakObjects(object);
component.completeCreate();
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
}
if (component.isError()) {
qDebug() << componentPath;
foreach (const QQmlError &error, component.errors())
qWarning() << error;
}
if (object)
object->setProperty("__designer_url__", QUrl::fromLocalFile(componentPath));
return object;
}
QObject *ObjectNodeInstance::createComponent(const QUrl &componentUrl, QQmlContext *context)
{
return QmlPrivateGate::createComponent(componentUrl, context);
}
QObject *ObjectNodeInstance::createCustomParserObject(const QString &nodeSource,
const QByteArray &importCode,
QQmlContext *context)
{
QmlPrivateGate::ComponentCompleteDisabler disableComponentComplete;
Q_UNUSED(disableComponentComplete)
QQmlComponent component(context->engine());
QByteArray data(nodeSource.toUtf8());
data.prepend(importCode);
component.setData(data, context->baseUrl().resolved(QUrl("createCustomParserObject.qml")));
QObject *object = component.beginCreate(context);
if (object) {
QmlPrivateGate::tweakObjects(object);
component.completeCreate();
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
}
if (component.isError()) {
qWarning() << "Error in:" << Q_FUNC_INFO << component.url().toString();
foreach (const QQmlError &error, component.errors())
qWarning() << error;
qWarning() << "file data:\n" << data;
}
return object;
}
QObject *ObjectNodeInstance::object() const
{
if (!m_object.isNull() && !QmlPrivateGate::objectWasDeleted(m_object.data()))
return m_object.data();
return nullptr;
}
QQuickItem *ObjectNodeInstance::contentItem() const
{
return nullptr;
}
bool ObjectNodeInstance::hasContent() const
{
return false;
}
bool ObjectNodeInstance::isResizable() const
{
return false;
}
bool ObjectNodeInstance::isMovable() const
{
return false;
}
bool ObjectNodeInstance::isInLayoutable() const
{
return m_isInLayoutable;
}
void ObjectNodeInstance::setInLayoutable(bool isInLayoutable)
{
m_isInLayoutable = isInLayoutable;
}
void ObjectNodeInstance::refreshLayoutable()
{
}
void ObjectNodeInstance::updateAnchors()
{
}
QQmlContext *ObjectNodeInstance::context() const
{
if (nodeInstanceServer())
return nodeInstanceServer()->context();
qWarning() << "Error: No NodeInstanceServer";
return nullptr;
}
QQmlEngine *ObjectNodeInstance::engine() const
{
return nodeInstanceServer()->engine();
}
void ObjectNodeInstance::paintUpdate()
{
}
void ObjectNodeInstance::activateState()
{
}
void ObjectNodeInstance::deactivateState()
{
}
QStringList ObjectNodeInstance::allStates() const
{
return {};
}
void ObjectNodeInstance::populateResetHashes()
{
QmlPrivateGate::registerCustomData(object());
}
bool ObjectNodeInstance::hasValidResetBinding(const PropertyName &propertyName) const
{
return QmlPrivateGate::hasValidResetBinding(object(), propertyName);
}
QVariant ObjectNodeInstance::resetValue(const PropertyName &propertyName) const
{
return QmlPrivateGate::getResetValue(object(), propertyName);
}
QImage ObjectNodeInstance::renderImage() const
{
return QImage();
}
QImage ObjectNodeInstance::renderPreviewImage(const QSize & /*previewImageSize*/) const
{
return QImage();
}
QSharedPointer<QQuickItemGrabResult> ObjectNodeInstance::createGrabResult() const
{
return {};
}
QObject *ObjectNodeInstance::parent() const
{
if (!object())
return nullptr;
return object()->parent();
}
QObject *ObjectNodeInstance::parentObject(QObject *object)
{
QQuickItem *quickItem = qobject_cast<QQuickItem*>(object);
if (quickItem && quickItem->parentItem())
return quickItem->parentItem();
return object->parent();
}
ObjectNodeInstance::Pointer ObjectNodeInstance::parentInstance() const
{
QObject *parentHolder = parent();
if (!nodeInstanceServer())
return Pointer();
while (parentHolder) {
if (nodeInstanceServer()->hasInstanceForObject(parentHolder))
return nodeInstanceServer()->instanceForObject(parentHolder).internalInstance();
parentHolder = parentObject(parentHolder);
}
return Pointer();
}
QRectF ObjectNodeInstance::boundingRect() const
{
return QRectF();
}
QRectF ObjectNodeInstance::contentItemBoundingBox() const
{
return QRectF();
}
QPointF ObjectNodeInstance::position() const
{
return QPointF();
}
QSizeF ObjectNodeInstance::size() const
{
return QSizeF();
}
int ObjectNodeInstance::penWidth() const
{
return 0;
}
bool ObjectNodeInstance::updateStateVariant(const ObjectNodeInstance::Pointer &/*target*/, const PropertyName &/*propertyName*/, const QVariant &/*value*/)
{
return false;
}
bool ObjectNodeInstance::updateStateBinding(const ObjectNodeInstance::Pointer &/*target*/, const PropertyName &/*propertyName*/, const QString &/*expression*/)
{
return false;
}
bool ObjectNodeInstance::resetStateProperty(const ObjectNodeInstance::Pointer &/*target*/, const PropertyName &/*propertyName*/, const QVariant &/*resetValue*/)
{
return false;
}
void ObjectNodeInstance::doComponentComplete()
{
QmlPrivateGate::doComponentCompleteRecursive(object(), nodeInstanceServer());
}
bool ObjectNodeInstance::isRootNodeInstance() const
{
return nodeInstanceServer()->rootNodeInstance().isWrappingThisObject(object());
}
bool ObjectNodeInstance::isValid() const
{
return instanceId() >= 0 && object();
}
}
}