Files
qt-creator/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate_56.cpp
Tomi Korpipaa 69c8be67ae Add particle editor support
Add a way to edit and view particles visually, as editing
only the properties in property editor does not help visualize
how the particle effect is going to look. Support toggling the
effects on/off, pausing, resuming, and scrubbing the time back
and forth. Only the selected particle system is animated to allow
concentrating on that particular system without being confused
by other possible particle systems.

Fixes: QDS-4623
Change-Id: I2677c56a73279d451d77df1d131bd7294e6b23bb
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
2021-11-05 11:31:31 +00:00

627 lines
21 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 "metaobject.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>
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;
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