Files
qt-creator/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate_56.cpp
Antti Määttä 3c2c8b97a1 Use Repeater3D instead of Object3D in component complete check
Do not use QQuick3DObject when disallowing recursive component complete
check so that the animations get added to the instance server.

Fixes: QDS-5731
Change-Id: Iff8e39f74d68b312b66d68adaf6ab79d625f88f8
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
2022-01-10 09:03:53 +00:00

636 lines
22 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 "qmlprivategate.h"
#include "designercustomobjectdata.h"
#include <objectnodeinstance.h>
#include <nodeinstanceserver.h>
#include <QQuickItem>
#include <QQmlComponent>
#include <QFileInfo>
#include <QProcessEnvironment>
#include <private/qabstractfileengine_p.h>
#include <private/qfsfileengine_p.h>
#include <private/qquickdesignersupport_p.h>
#include <private/qquickdesignersupportmetainfo_p.h>
#include <private/qquickdesignersupportitems_p.h>
#include <private/qquickdesignersupportproperties_p.h>
#include <private/qquickdesignersupportpropertychanges_p.h>
#include <private/qquickdesignersupportstates_p.h>
#include <private/qqmldata_p.h>
#include <private/qqmlcomponentattached_p.h>
#include <private/qabstractanimation_p.h>
#include <private/qobject_p.h>
#include <private/qquickbehavior_p.h>
#include <private/qquicktext_p.h>
#include <private/qquicktextinput_p.h>
#include <private/qquicktextedit_p.h>
#include <private/qquicktransition_p.h>
#include <private/qquickloader_p.h>
#include <private/qquickanimation_p.h>
#include <private/qqmlmetatype_p.h>
#include <private/qqmltimer_p.h>
#ifdef QUICK3D_MODULE
#include <private/qquick3dobject_p.h>
#include <private/qquick3drepeater_p.h>
#endif
namespace QmlDesigner {
namespace Internal {
namespace QmlPrivateGate {
bool isPropertyBlackListed(const QmlDesigner::PropertyName &propertyName)
{
return QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName);
}
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
static void addToPropertyNameListIfNotBlackListed(
PropertyNameList *propertyNameList, const QQuickDesignerSupport::PropertyName &propertyName)
{
if (!QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName))
propertyNameList->append(propertyName);
}
PropertyNameList allPropertyNamesInline(QObject *object,
const PropertyName &baseName = {},
QObjectList *inspectedObjects = nullptr,
int depth = 0)
{
QQuickDesignerSupport::PropertyNameList propertyNameList;
QObjectList localObjectList;
if (inspectedObjects == nullptr)
inspectedObjects = &localObjectList;
if (depth > 2)
return propertyNameList;
if (!inspectedObjects->contains(object))
inspectedObjects->append(object);
const QMetaObject *metaObject = object->metaObject();
QStringList deferredPropertyNames;
const int namesIndex = metaObject->indexOfClassInfo("DeferredPropertyNames");
if (namesIndex != -1) {
QMetaClassInfo classInfo = metaObject->classInfo(namesIndex);
deferredPropertyNames = QString::fromUtf8(classInfo.value()).split(QLatin1Char(','));
}
for (int index = 0; index < metaObject->propertyCount(); ++index) {
QMetaProperty metaProperty = metaObject->property(index);
QQmlProperty declarativeProperty(object, QString::fromUtf8(metaProperty.name()));
if (declarativeProperty.isValid()
&& declarativeProperty.propertyTypeCategory() == QQmlProperty::Object) {
if (declarativeProperty.name() != QLatin1String("parent")
&& !deferredPropertyNames.contains(declarativeProperty.name())) {
QObject *childObject = QQmlMetaType::toQObject(declarativeProperty.read());
if (childObject)
propertyNameList.append(
allPropertyNamesInline(childObject,
baseName
+ QQuickDesignerSupport::PropertyName(
metaProperty.name())
+ '.',
inspectedObjects,
depth + 1));
}
} else if (QQmlGadgetPtrWrapper *valueType
= QQmlGadgetPtrWrapper::instance(qmlEngine(object), metaProperty.userType())) {
valueType->setValue(metaProperty.read(object));
propertyNameList.append(baseName
+ QQuickDesignerSupport::PropertyName(metaProperty.name()));
propertyNameList.append(
allPropertyNamesInline(valueType,
baseName
+ QQuickDesignerSupport::PropertyName(metaProperty.name())
+ '.',
inspectedObjects,
depth + 1));
} else {
addToPropertyNameListIfNotBlackListed(&propertyNameList,
baseName
+ QQuickDesignerSupport::PropertyName(
metaProperty.name()));
}
}
return propertyNameList;
}
#endif
PropertyNameList allPropertyNames(QObject *object)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
return QQuickDesignerSupportProperties::allPropertyNames(object);
#elif QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
return allPropertyNamesInline(object);
#else
return QQuickDesignerSupportProperties::allPropertyNames(object);
#endif
}
PropertyNameList propertyNameListForWritableProperties(QObject *object)
{
return QQuickDesignerSupportProperties::propertyNameListForWritableProperties(object);
}
void tweakObjects(QObject *object)
{
QQuickDesignerSupportItems::tweakObjects(object);
}
void createNewDynamicProperty(QObject *object, QQmlEngine *engine, const QString &name)
{
QQuickDesignerSupportProperties::createNewDynamicProperty(object, engine, name);
}
void registerNodeInstanceMetaObject(QObject *object, QQmlEngine *engine)
{
QQuickDesignerSupportProperties::registerNodeInstanceMetaObject(object, engine);
}
static bool isQuickStyleItemMetaObject(const QMetaObject *metaObject)
{
if (metaObject) {
if (metaObject->className() == QByteArrayLiteral("QQuickStyleItem"))
return true;
return isQuickStyleItemMetaObject(metaObject->superClass());
}
return false;
}
static bool isQuickStyleItem(QObject *object)
{
if (object)
return isQuickStyleItemMetaObject(object->metaObject());
return false;
}
// This is used in share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp
QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QTypeRevision revision = QTypeRevision::zero();
if (majorNumber > 0)
revision = QTypeRevision::fromVersion(majorNumber, minorNumber);
return QQuickDesignerSupportItems::createPrimitive(typeName, revision, context);
#else
return QQuickDesignerSupportItems::createPrimitive(typeName, majorNumber, minorNumber, context);
#endif
}
static QString qmlDesignerRCPath()
{
static const QString qmlDesignerRcPathsString = QString::fromLocal8Bit(
qgetenv("QMLDESIGNER_RC_PATHS"));
return qmlDesignerRcPathsString;
}
QVariant fixResourcePaths(const QVariant &value)
{
if (value.type() == QVariant::Url)
{
const QUrl url = value.toUrl();
if (url.scheme() == QLatin1String("qrc")) {
const QString path = QLatin1String("qrc:") + url.path();
if (!qmlDesignerRCPath().isEmpty()) {
const QStringList searchPaths = qmlDesignerRCPath().split(QLatin1Char(';'));
foreach (const QString &qrcPath, searchPaths) {
const QStringList qrcDefintion = qrcPath.split(QLatin1Char('='));
if (qrcDefintion.count() == 2) {
QString fixedPath = path;
fixedPath.replace(QLatin1String("qrc:") + qrcDefintion.first(), qrcDefintion.last() + QLatin1Char('/'));
if (QFileInfo::exists(fixedPath)) {
fixedPath.replace(QLatin1String("//"), QLatin1String("/"));
fixedPath.replace(QLatin1Char('\\'), QLatin1Char('/'));
return QUrl::fromLocalFile(fixedPath);
}
}
}
}
}
}
if (value.type() == QVariant::String) {
const QString str = value.toString();
if (str.contains(QLatin1String("qrc:"))) {
if (!qmlDesignerRCPath().isEmpty()) {
const QStringList searchPaths = qmlDesignerRCPath().split(QLatin1Char(';'));
foreach (const QString &qrcPath, searchPaths) {
const QStringList qrcDefintion = qrcPath.split(QLatin1Char('='));
if (qrcDefintion.count() == 2) {
QString fixedPath = str;
fixedPath.replace(QLatin1String("qrc:") + qrcDefintion.first(), qrcDefintion.last() + QLatin1Char('/'));
if (QFileInfo::exists(fixedPath)) {
fixedPath.replace(QLatin1String("//"), QLatin1String("/"));
fixedPath.replace(QLatin1Char('\\'), QLatin1Char('/'));
return QUrl::fromLocalFile(fixedPath);
}
}
}
}
}
}
return value;
}
QObject *createComponent(const QUrl &componentUrl, QQmlContext *context)
{
return QQuickDesignerSupportItems::createComponent(componentUrl, context);
}
bool hasFullImplementedListInterface(const QQmlListReference &list)
{
return list.isValid() && list.canCount() && list.canAt() && list.canAppend() && list.canClear();
}
void registerCustomData(QObject *object)
{
QQuickDesignerSupportProperties::registerCustomData(object);
}
QVariant getResetValue(QObject *object, const PropertyName &propertyName)
{
if (propertyName == "Layout.rowSpan")
return 1;
else if (propertyName == "Layout.columnSpan")
return 1;
else if (propertyName == "Layout.fillHeight")
return false;
else if (propertyName == "Layout.fillWidth")
return false;
else
return QQuickDesignerSupportProperties::getResetValue(object, propertyName);
}
static void setProperty(QObject *object, QQmlContext *context, const PropertyName &propertyName, const QVariant &value)
{
QQmlProperty property(object, QString::fromUtf8(propertyName), context);
property.write(value);
}
void doResetProperty(QObject *object, QQmlContext *context, const PropertyName &propertyName)
{
if (propertyName == "Layout.rowSpan")
setProperty(object, context, propertyName, getResetValue(object, propertyName));
else if (propertyName == "Layout.columnSpan")
setProperty(object, context, propertyName, getResetValue(object, propertyName));
else if (propertyName == "Layout.fillHeight")
setProperty(object, context, propertyName, getResetValue(object, propertyName));
else if (propertyName == "Layout.fillWidth")
setProperty(object, context, propertyName, getResetValue(object, propertyName));
else
QQuickDesignerSupportProperties::doResetProperty(object, context, propertyName);
}
bool hasValidResetBinding(QObject *object, const PropertyName &propertyName)
{
if (propertyName == "Layout.rowSpan")
return true;
else if (propertyName == "Layout.columnSpan")
return true;
else if (propertyName == "Layout.fillHeight")
return true;
else if (propertyName == "Layout.fillWidth")
return true;
return QQuickDesignerSupportProperties::hasValidResetBinding(object, propertyName);
}
bool hasBindingForProperty(QObject *object, QQmlContext *context, const PropertyName &propertyName, bool *hasChanged)
{
return QQuickDesignerSupportProperties::hasBindingForProperty(object, context, propertyName, hasChanged);
}
void setPropertyBinding(QObject *object, QQmlContext *context, const PropertyName &propertyName, const QString &expression)
{
QQuickDesignerSupportProperties::setPropertyBinding(object, context, propertyName, expression);
}
void emitComponentComplete(QObject *item)
{
if (!item)
return;
QQmlData *data = QQmlData::get(item);
if (data && data->context) {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QQmlComponentAttached *componentAttached = data->context->componentAttached;
#else
QQmlComponentAttached *componentAttached = data->context->componentAttacheds();
#endif
while (componentAttached) {
if (componentAttached->parent())
if (componentAttached->parent() == item)
emit componentAttached->completed();
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
componentAttached = componentAttached->next;
#else
componentAttached = componentAttached->next();
#endif
}
}
}
void doComponentCompleteRecursive(QObject *object, NodeInstanceServer *nodeInstanceServer)
{
if (object) {
QQuickItem *item = qobject_cast<QQuickItem*>(object);
if (item && DesignerSupport::isComponentComplete(item))
return;
#ifdef QUICK3D_MODULE
auto obj3d = qobject_cast<QQuick3DRepeater *>(object);
if (obj3d && QQuick3DObjectPrivate::get(obj3d)->componentComplete)
return;
#endif
if (!nodeInstanceServer->hasInstanceForObject(item))
emitComponentComplete(object);
QList<QObject*> childList = object->children();
if (item) {
foreach (QQuickItem *childItem, item->childItems()) {
if (!childList.contains(childItem))
childList.append(childItem);
}
}
foreach (QObject *child, childList) {
if (!nodeInstanceServer->hasInstanceForObject(child))
doComponentCompleteRecursive(child, nodeInstanceServer);
}
if (!isQuickStyleItem(item)) {
if (item) {
static_cast<QQmlParserStatus *>(item)->componentComplete();
} else {
QQmlParserStatus *qmlParserStatus = dynamic_cast<QQmlParserStatus *>(object);
if (qmlParserStatus) {
qmlParserStatus->componentComplete();
auto *anim = dynamic_cast<QQuickAbstractAnimation *>(object);
if (anim && ViewConfig::isParticleViewMode()) {
nodeInstanceServer->addAnimation(anim);
anim->setEnableUserControl();
anim->stop();
}
}
}
}
}
}
void keepBindingFromGettingDeleted(QObject *object, QQmlContext *context, const PropertyName &propertyName)
{
QQuickDesignerSupportProperties::keepBindingFromGettingDeleted(object, context, propertyName);
}
bool objectWasDeleted(QObject *object)
{
return QQuickDesignerSupportItems::objectWasDeleted(object);
}
void disableNativeTextRendering(QQuickItem *item)
{
QQuickDesignerSupportItems::disableNativeTextRendering(item);
}
void disableTextCursor(QQuickItem *item)
{
QQuickDesignerSupportItems::disableTextCursor(item);
}
void disableTransition(QObject *object)
{
QQuickDesignerSupportItems::disableTransition(object);
}
void disableBehaivour(QObject *object)
{
QQuickDesignerSupportItems::disableBehaivour(object);
}
void stopUnifiedTimer()
{
QQuickDesignerSupportItems::stopUnifiedTimer();
}
bool isPropertyQObject(const QMetaProperty &metaProperty)
{
return QQuickDesignerSupportProperties::isPropertyQObject(metaProperty);
}
QObject *readQObjectProperty(const QMetaProperty &metaProperty, QObject *object)
{
return QQuickDesignerSupportProperties::readQObjectProperty(metaProperty, object);
}
namespace States {
bool isStateActive(QObject *object, QQmlContext *context)
{
return QQuickDesignerSupportStates::isStateActive(object, context);
}
void activateState(QObject *object, QQmlContext *context)
{
QQuickDesignerSupportStates::activateState(object, context);
}
void deactivateState(QObject *object)
{
QQuickDesignerSupportStates::deactivateState(object);
}
bool changeValueInRevertList(QObject *state, QObject *target, const PropertyName &propertyName, const QVariant &value)
{
return QQuickDesignerSupportStates::changeValueInRevertList(state, target, propertyName, value);
}
bool updateStateBinding(QObject *state, QObject *target, const PropertyName &propertyName, const QString &expression)
{
return QQuickDesignerSupportStates::updateStateBinding(state, target, propertyName, expression);
}
bool resetStateProperty(QObject *state, QObject *target, const PropertyName &propertyName, const QVariant &value)
{
return QQuickDesignerSupportStates::resetStateProperty(state, target, propertyName, value);
}
} //namespace States
namespace PropertyChanges {
void detachFromState(QObject *propertyChanges)
{
return QQuickDesignerSupportPropertyChanges::detachFromState(propertyChanges);
}
void attachToState(QObject *propertyChanges)
{
return QQuickDesignerSupportPropertyChanges::attachToState(propertyChanges);
}
QObject *targetObject(QObject *propertyChanges)
{
return QQuickDesignerSupportPropertyChanges::targetObject(propertyChanges);
}
void removeProperty(QObject *propertyChanges, const PropertyName &propertyName)
{
QQuickDesignerSupportPropertyChanges::removeProperty(propertyChanges, propertyName);
}
QVariant getProperty(QObject *propertyChanges, const PropertyName &propertyName)
{
return QQuickDesignerSupportPropertyChanges::getProperty(propertyChanges, propertyName);
}
void changeValue(QObject *propertyChanges, const PropertyName &propertyName, const QVariant &value)
{
QQuickDesignerSupportPropertyChanges::changeValue(propertyChanges, propertyName, value);
}
void changeExpression(QObject *propertyChanges, const PropertyName &propertyName, const QString &expression)
{
QQuickDesignerSupportPropertyChanges::changeExpression(propertyChanges, propertyName, expression);
}
QObject *stateObject(QObject *propertyChanges)
{
return QQuickDesignerSupportPropertyChanges::stateObject(propertyChanges);
}
bool isNormalProperty(const PropertyName &propertyName)
{
return QQuickDesignerSupportPropertyChanges::isNormalProperty(propertyName);
}
} // namespace PropertyChanges
bool isSubclassOf(QObject *object, const QByteArray &superTypeName)
{
return QQuickDesignerSupportMetaInfo::isSubclassOf(object, superTypeName);
}
void getPropertyCache(QObject *object, QQmlEngine *engine)
{
QQuickDesignerSupportProperties::getPropertyCache(object, engine);
}
void registerNotifyPropertyChangeCallBack(void (*callback)(QObject *, const PropertyName &))
{
QQuickDesignerSupportMetaInfo::registerNotifyPropertyChangeCallBack(callback);
}
ComponentCompleteDisabler::ComponentCompleteDisabler()
{
DesignerSupport::disableComponentComplete();
}
ComponentCompleteDisabler::~ComponentCompleteDisabler()
{
DesignerSupport::enableComponentComplete();
}
class QrcEngineHandler : public QAbstractFileEngineHandler
{
public:
QAbstractFileEngine *create(const QString &fileName) const final;
};
QAbstractFileEngine *QrcEngineHandler::create(const QString &fileName) const
{
if (fileName.startsWith(":/qt-project.org"))
return nullptr;
if (fileName.startsWith(":/qtquickplugin"))
return nullptr;
if (fileName.startsWith(":/")) {
const QStringList searchPaths = qmlDesignerRCPath().split(';');
foreach (const QString &qrcPath, searchPaths) {
const QStringList qrcDefintion = qrcPath.split('=');
if (qrcDefintion.count() == 2) {
QString fixedPath = fileName;
fixedPath.replace(":" + qrcDefintion.first(), qrcDefintion.last() + '/');
if (fileName == fixedPath)
return nullptr;
if (QFileInfo::exists(fixedPath)) {
fixedPath.replace("//", "/");
fixedPath.replace('\\', '/');
return new QFSFileEngine(fixedPath);
}
}
}
}
return nullptr;
}
static QrcEngineHandler* s_qrcEngineHandler = nullptr;
class EngineHandlerDeleter
{
public:
EngineHandlerDeleter()
{}
~EngineHandlerDeleter()
{ delete s_qrcEngineHandler; }
};
void registerFixResourcePathsForObjectCallBack()
{
static EngineHandlerDeleter deleter;
if (!s_qrcEngineHandler)
s_qrcEngineHandler = new QrcEngineHandler();
}
} // namespace QmlPrivateGate
} // namespace Internal
} // namespace QmlDesigner