diff options
Diffstat (limited to 'src/quick/designer')
19 files changed, 2195 insertions, 68 deletions
diff --git a/src/quick/designer/designer.pri b/src/quick/designer/designer.pri index 9f3f7e8be6..eb2141134d 100644 --- a/src/quick/designer/designer.pri +++ b/src/quick/designer/designer.pri @@ -1,4 +1,21 @@ -HEADERS += designer/designersupport.h \ - designer/designerwindowmanager_p.h -SOURCES += designer/designersupport.cpp \ - designer/designerwindowmanager.cpp +HEADERS += \ + designer/qquickdesignercustomobjectdata_p.h \ + designer/qquickdesignersupportitems_p.h \ + designer/qquickdesignerwindowmanager_p.h \ + designer/qquickdesignersupportstates_p.h \ + designer/qquickdesignersupportpropertychanges_p.h \ + designer/qquickdesignersupportproperties_p.h \ + designer/qquickdesignersupportmetainfo_p.h \ + designer/qqmldesignermetaobject_p.h \ + designer/qquickdesignersupport_p.h + +SOURCES += \ + designer/qquickdesignercustomobjectdata.cpp \ + designer/qquickdesignersupport.cpp \ + designer/qquickdesignersupportitems.cpp \ + designer/qquickdesignersupportmetainfo.cpp \ + designer/qquickdesignersupportproperties.cpp \ + designer/qquickdesignersupportpropertychanges.cpp \ + designer/qquickdesignersupportstates.cpp \ + designer/qquickdesignerwindowmanager.cpp \ + designer/qqmldesignermetaobject.cpp diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp new file mode 100644 index 0000000000..76c94b242d --- /dev/null +++ b/src/quick/designer/qqmldesignermetaobject.cpp @@ -0,0 +1,340 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmldesignermetaobject_p.h" + +#include <QSharedPointer> +#include <QMetaProperty> +#include <qnumeric.h> +#include <QDebug> + +#include <private/qqmlengine_p.h> +#include <private/qqmlpropertycache_p.h> + +QT_BEGIN_NAMESPACE + +static QHash<QDynamicMetaObjectData *, bool> nodeInstanceMetaObjectList; +static void (*notifyPropertyChangeCallBack)(QObject*, const QQuickDesignerSupport::PropertyName &propertyName) = 0; + +struct MetaPropertyData { + inline QPair<QVariant, bool> &getDataRef(int idx) { + while (m_data.count() <= idx) + m_data << QPair<QVariant, bool>(QVariant(), false); + return m_data[idx]; + } + + inline QVariant &getData(int idx) { + QPair<QVariant, bool> &prop = getDataRef(idx); + if (!prop.second) { + prop.first = QVariant(); + prop.second = true; + } + return prop.first; + } + + inline bool hasData(int idx) const { + if (idx >= m_data.count()) + return false; + return m_data[idx].second; + } + + inline int count() { return m_data.count(); } + + QVector<QPair<QVariant, bool> > m_data; +}; + +static bool constructedMetaData(const QQmlVMEMetaData* data) +{ + return data->propertyCount == 0 + && data->aliasCount == 0 + && data->signalCount == 0 + && data->methodCount == 0; +} + +static QQmlVMEMetaData* fakeMetaData() +{ + QQmlVMEMetaData* data = new QQmlVMEMetaData; + data->propertyCount = 0; + data->aliasCount = 0; + data->signalCount = 0; + data->methodCount = 0; + + return data; +} + +static const QQmlVMEMetaData* vMEMetaDataForObject(QObject *object) +{ + QQmlVMEMetaObject *metaObject = QQmlVMEMetaObject::get(object); + if (metaObject) + return metaObject->metaData; + + return fakeMetaData(); +} + +static QQmlPropertyCache *cacheForObject(QObject *object, QQmlEngine *engine) +{ + QQmlVMEMetaObject *metaObject = QQmlVMEMetaObject::get(object); + if (metaObject) + return metaObject->cache; + + return QQmlEnginePrivate::get(engine)->cache(object); +} + +QQmlDesignerMetaObject* QQmlDesignerMetaObject::getNodeInstanceMetaObject(QObject *object, QQmlEngine *engine) +{ + //Avoid setting up multiple MetaObjects on the same QObject + QObjectPrivate *op = QObjectPrivate::get(object); + QDynamicMetaObjectData *parent = op->metaObject; + if (nodeInstanceMetaObjectList.contains(parent)) + return static_cast<QQmlDesignerMetaObject *>(parent); + + // we just create one and the ownership goes automatically to the object in nodeinstance see init method + return new QQmlDesignerMetaObject(object, engine); +} + +void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine) +{ + //Creating QQmlOpenMetaObjectType + m_type = new QQmlOpenMetaObjectType(metaObjectParent(), engine); + m_type->addref(); + //Assigning type to this + copyTypeMetaObject(); + + //Assign this to object + QObjectPrivate *op = QObjectPrivate::get(object); + op->metaObject = this; + + //create cache + cache = m_cache = QQmlEnginePrivate::get(engine)->cache(this); + cache->addref(); + + //If our parent is not a VMEMetaObject we just se the flag to false again + if (constructedMetaData(metaData)) + QQmlData::get(object)->hasVMEMetaObject = false; + + nodeInstanceMetaObjectList.insert(this, true); + hasAssignedMetaObjectData = true; +} + +QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine) + : QQmlVMEMetaObject(object, cacheForObject(object, engine), vMEMetaDataForObject(object)), + m_context(engine->contextForObject(object)), + m_data(new MetaPropertyData), + m_cache(0) +{ + init(object, engine); + + QQmlData *ddata = QQmlData::get(object, false); + + //Assign cache to object + if (ddata && ddata->propertyCache) { + cache->setParent(ddata->propertyCache); + cache->invalidate(engine, this); + ddata->propertyCache = m_cache; + } + +} + +QQmlDesignerMetaObject::~QQmlDesignerMetaObject() +{ + if (cache->count() > 1) // qml is crashing because the property cache is not removed from the engine + cache->release(); + else + m_type->release(); + + nodeInstanceMetaObjectList.remove(this); +} + +void QQmlDesignerMetaObject::createNewDynamicProperty(const QString &name) +{ + int id = m_type->createProperty(name.toUtf8()); + copyTypeMetaObject(); + setValue(id, QVariant()); + Q_ASSERT(id >= 0); + Q_UNUSED(id); + + //Updating cache + QQmlPropertyCache *oldParent = m_cache->parent(); + QQmlEnginePrivate::get(m_context->engine())->cache(this)->invalidate(m_context->engine(), this); + m_cache->setParent(oldParent); + + QQmlProperty property(myObject(), name, m_context); + Q_ASSERT(property.isValid()); +} + +void QQmlDesignerMetaObject::setValue(int id, const QVariant &value) +{ + QPair<QVariant, bool> &prop = m_data->getDataRef(id); + prop.first = propertyWriteValue(id, value); + prop.second = true; + QMetaObject::activate(myObject(), id + m_type->signalOffset(), 0); +} + +QVariant QQmlDesignerMetaObject::propertyWriteValue(int, const QVariant &value) +{ + return value; +} + +const QAbstractDynamicMetaObject *QQmlDesignerMetaObject::dynamicMetaObjectParent() const +{ + if (QQmlVMEMetaObject::parent.isT1()) + return QQmlVMEMetaObject::parent.asT1()->toDynamicMetaObject(QQmlVMEMetaObject::object); + else + return 0; +} + +const QMetaObject *QQmlDesignerMetaObject::metaObjectParent() const +{ + if (QQmlVMEMetaObject::parent.isT1()) + return QQmlVMEMetaObject::parent.asT1()->toDynamicMetaObject(QQmlVMEMetaObject::object); + + return QQmlVMEMetaObject::parent.asT2(); +} + +int QQmlDesignerMetaObject::propertyOffset() const +{ + return cache->propertyOffset(); +} + +int QQmlDesignerMetaObject::openMetaCall(QObject *o, QMetaObject::Call call, int id, void **a) +{ + if ((call == QMetaObject::ReadProperty || call == QMetaObject::WriteProperty) + && id >= m_type->propertyOffset()) { + int propId = id - m_type->propertyOffset(); + if (call == QMetaObject::ReadProperty) { + //propertyRead(propId); + *reinterpret_cast<QVariant *>(a[0]) = m_data->getData(propId); + } else if (call == QMetaObject::WriteProperty) { + if (propId <= m_data->count() || m_data->m_data[propId].first != *reinterpret_cast<QVariant *>(a[0])) { + //propertyWrite(propId); + QPair<QVariant, bool> &prop = m_data->getDataRef(propId); + prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0])); + prop.second = true; + //propertyWritten(propId); + activate(myObject(), m_type->signalOffset() + propId, 0); + } + } + return -1; + } else { + QAbstractDynamicMetaObject *directParent = parent(); + if (directParent) + return directParent->metaCall(o, call, id, a); + else + return myObject()->qt_metacall(call, id, a); + } +} + +int QQmlDesignerMetaObject::metaCall(QObject *o, QMetaObject::Call call, int id, void **a) +{ + Q_ASSERT(myObject() == o); + + int metaCallReturnValue = -1; + + const QMetaProperty propertyById = QQmlVMEMetaObject::property(id); + + if (call == QMetaObject::WriteProperty + && propertyById.userType() == QMetaType::QVariant + && reinterpret_cast<QVariant *>(a[0])->type() == QVariant::Double + && qIsNaN(reinterpret_cast<QVariant *>(a[0])->toDouble())) { + return -1; + } + + if (call == QMetaObject::WriteProperty + && propertyById.userType() == QMetaType::Double + && qIsNaN(*reinterpret_cast<double*>(a[0]))) { + return -1; + } + + if (call == QMetaObject::WriteProperty + && propertyById.userType() == QMetaType::Float + && qIsNaN(*reinterpret_cast<float*>(a[0]))) { + return -1; + } + + QVariant oldValue; + + if (call == QMetaObject::WriteProperty && !propertyById.hasNotifySignal()) + { + oldValue = propertyById.read(myObject()); + } + + QAbstractDynamicMetaObject *directParent = parent(); + if (directParent && id < directParent->propertyOffset()) { + metaCallReturnValue = directParent->metaCall(o, call, id, a); + } else { + openMetaCall(o, call, id, a); + } + + + if (call == QMetaObject::WriteProperty + && !propertyById.hasNotifySignal() + && oldValue != propertyById.read(myObject())) + notifyPropertyChange(id); + + return metaCallReturnValue; +} + +void QQmlDesignerMetaObject::notifyPropertyChange(int id) +{ + const QMetaProperty propertyById = property(id); + + if (id < propertyOffset()) { + if (notifyPropertyChangeCallBack) + notifyPropertyChangeCallBack(myObject(), propertyById.name()); + } else { + if (notifyPropertyChangeCallBack) + notifyPropertyChangeCallBack(myObject(), name(id - propertyOffset())); + } +} + +int QQmlDesignerMetaObject::count() const +{ + return m_type->propertyCount(); +} + +QByteArray QQmlDesignerMetaObject::name(int idx) const +{ + return m_type->propertyName(idx); +} + +void QQmlDesignerMetaObject::copyTypeMetaObject() +{ + *static_cast<QMetaObject *>(this) = *m_type->metaObject(); +} + +void QQmlDesignerMetaObject::registerNotifyPropertyChangeCallBack(void (*callback)(QObject *, const QQuickDesignerSupport::PropertyName &)) +{ + notifyPropertyChangeCallBack = callback; +} + +QT_END_NAMESPACE diff --git a/src/quick/designer/qqmldesignermetaobject_p.h b/src/quick/designer/qqmldesignermetaobject_p.h new file mode 100644 index 0000000000..47f4baad2b --- /dev/null +++ b/src/quick/designer/qqmldesignermetaobject_p.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NODEINSTANCEMETAOBJECT_H +#define NODEINSTANCEMETAOBJECT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickdesignersupport_p.h" + +#include <QQmlContext> +#include <QScopedPointer> +#include <private/qqmlopenmetaobject_p.h> +#include <private/qqmlvmemetaobject_p.h> + +QT_BEGIN_NAMESPACE + +struct MetaPropertyData; + +class QQmlDesignerMetaObject : public QQmlVMEMetaObject +{ +public: + ~QQmlDesignerMetaObject(); + + static void registerNotifyPropertyChangeCallBack(void (*callback)(QObject*, const QQuickDesignerSupport::PropertyName &propertyName)); + +protected: + QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine); + static QQmlDesignerMetaObject* getNodeInstanceMetaObject(QObject *object, QQmlEngine *engine); + + void createNewDynamicProperty(const QString &name); + int openMetaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a); + int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a); + void notifyPropertyChange(int id); + void setValue(int id, const QVariant &value); + QVariant propertyWriteValue(int, const QVariant &); + + QObject *myObject() const { return QQmlVMEMetaObject::object; } + QAbstractDynamicMetaObject *parent() const { return const_cast<QAbstractDynamicMetaObject *>(dynamicMetaObjectParent()); } + + const QAbstractDynamicMetaObject *dynamicMetaObjectParent() const; + + const QMetaObject *metaObjectParent() const; + + int propertyOffset() const; + + int count() const; + QByteArray name(int) const; + + void copyTypeMetaObject(); + +private: + void init(QObject *, QQmlEngine *engine); + + QPointer<QQmlContext> m_context; + QQmlOpenMetaObjectType *m_type; + QScopedPointer<MetaPropertyData> m_data; + //QAbstractDynamicMetaObject *m_parent; + QQmlPropertyCache *m_cache; + + friend class QQuickDesignerSupportProperties; +}; + +QT_END_NAMESPACE + +#endif // NODEINSTANCEMETAOBJECT_H diff --git a/src/quick/designer/qquickdesignercustomobjectdata.cpp b/src/quick/designer/qquickdesignercustomobjectdata.cpp new file mode 100644 index 0000000000..7f074d8341 --- /dev/null +++ b/src/quick/designer/qquickdesignercustomobjectdata.cpp @@ -0,0 +1,286 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickdesignersupportmetainfo_p.h" +#include "qquickdesignersupportproperties_p.h" + +#include "qquickdesignercustomobjectdata_p.h" + +#include <QGlobalStatic> +#include <QQmlContext> +#include <QQmlEngine> + +#include <private/qqmlbinding_p.h> + +QT_BEGIN_NAMESPACE + +typedef QHash<QObject*, QQuickDesignerCustomObjectData*> CustomObjectDataHash; +Q_GLOBAL_STATIC(CustomObjectDataHash, s_designerObjectToDataHash) + +struct HandleDestroyedFunctor { + QQuickDesignerCustomObjectData *data; + void operator()() { data->handleDestroyed(); } +}; + +QQuickDesignerCustomObjectData::QQuickDesignerCustomObjectData(QObject *object) + : m_object(object) +{ + if (object) { + populateResetHashes(); + s_designerObjectToDataHash()->insert(object, this); + + HandleDestroyedFunctor functor; + functor.data = this; + QObject::connect(object, &QObject::destroyed, functor); + } +} + +void QQuickDesignerCustomObjectData::registerData(QObject *object) +{ + new QQuickDesignerCustomObjectData(object); +} + +QQuickDesignerCustomObjectData *QQuickDesignerCustomObjectData::get(QObject *object) +{ + return s_designerObjectToDataHash()->value(object); +} + +QVariant QQuickDesignerCustomObjectData::getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName) +{ + QQuickDesignerCustomObjectData* data = get(object); + + if (data) + return data->getResetValue(propertyName); + + return QVariant(); +} + +void QQuickDesignerCustomObjectData::doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName) +{ + QQuickDesignerCustomObjectData* data = get(object); + + if (data) + data->doResetProperty(context, propertyName); +} + +bool QQuickDesignerCustomObjectData::hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName) +{ + QQuickDesignerCustomObjectData* data = get(object); + + if (data) + return data->hasValidResetBinding(propertyName); + + return false; +} + +bool QQuickDesignerCustomObjectData::hasBindingForProperty(QObject *object, + QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName, + bool *hasChanged) +{ + QQuickDesignerCustomObjectData* data = get(object); + + if (data) + return data->hasBindingForProperty(context, propertyName, hasChanged); + + return false; +} + +void QQuickDesignerCustomObjectData::setPropertyBinding(QObject *object, + QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName, + const QString &expression) +{ + QQuickDesignerCustomObjectData* data = get(object); + + if (data) + data->setPropertyBinding(context, propertyName, expression); +} + +void QQuickDesignerCustomObjectData::keepBindingFromGettingDeleted(QObject *object, + QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName) +{ + QQuickDesignerCustomObjectData* data = get(object); + + if (data) + data->keepBindingFromGettingDeleted(context, propertyName); +} + +void QQuickDesignerCustomObjectData::populateResetHashes() +{ + QQuickDesignerSupport::PropertyNameList propertyNameList = + QQuickDesignerSupportProperties::propertyNameListForWritableProperties(object()); + + Q_FOREACH (const QQuickDesignerSupport::PropertyName &propertyName, propertyNameList) { + QQmlProperty property(object(), QString::fromUtf8(propertyName), QQmlEngine::contextForObject(object())); + + QQmlAbstractBinding::Ptr binding = QQmlAbstractBinding::Ptr(QQmlPropertyPrivate::binding(property)); + + if (binding) { + m_resetBindingHash.insert(propertyName, binding); + } else if (property.isWritable()) { + m_resetValueHash.insert(propertyName, property.read()); + } + } +} + +QObject *QQuickDesignerCustomObjectData::object() const +{ + return m_object; +} + +QVariant QQuickDesignerCustomObjectData::getResetValue(const QQuickDesignerSupport::PropertyName &propertyName) const +{ + return m_resetValueHash.value(propertyName); +} + +void QQuickDesignerCustomObjectData::doResetProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName) +{ + QQmlProperty property(object(), QString::fromUtf8(propertyName), context); + + if (!property.isValid()) + return; + + QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(property); + if (binding && !(hasValidResetBinding(propertyName) && getResetBinding(propertyName) == binding)) { + binding->setEnabled(false, 0); + } + + + if (hasValidResetBinding(propertyName)) { + QQmlAbstractBinding *binding = getResetBinding(propertyName); + +#if defined(QT_NO_DYNAMIC_CAST) + QQmlBinding *qmlBinding = static_cast<QQmlBinding*>(binding); +#else + QQmlBinding *qmlBinding = dynamic_cast<QQmlBinding*>(binding); +#endif + if (qmlBinding) + qmlBinding->setTarget(property); + QQmlPropertyPrivate::setBinding(binding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding); + if (qmlBinding) + qmlBinding->update(); + + } else if (property.isResettable()) { + property.reset(); + } else if (property.propertyTypeCategory() == QQmlProperty::List) { + QQmlListReference list = qvariant_cast<QQmlListReference>(property.read()); + + if (!QQuickDesignerSupportProperties::hasFullImplementedListInterface(list)) { + qWarning() << "Property list interface not fully implemented for Class " << property.property().typeName() << " in property " << property.name() << "!"; + return; + } + + list.clear(); + } else if (property.isWritable()) { + if (property.read() == getResetValue(propertyName)) + return; + + property.write(getResetValue(propertyName)); + } +} + +bool QQuickDesignerCustomObjectData::hasValidResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const +{ + return m_resetBindingHash.contains(propertyName) && m_resetBindingHash.value(propertyName).data(); +} + +QQmlAbstractBinding *QQuickDesignerCustomObjectData::getResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const +{ + return m_resetBindingHash.value(propertyName).data(); +} + +bool QQuickDesignerCustomObjectData::hasBindingForProperty(QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName, + bool *hasChanged) const +{ + if (QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName)) + return false; + + QQmlProperty property(object(), QString::fromUtf8(propertyName), context); + + bool hasBinding = QQmlPropertyPrivate::binding(property); + + if (hasChanged) { + *hasChanged = hasBinding != m_hasBindingHash.value(propertyName, false); + if (*hasChanged) + m_hasBindingHash.insert(propertyName, hasBinding); + } + + return QQmlPropertyPrivate::binding(property); +} + +void QQuickDesignerCustomObjectData::setPropertyBinding(QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName, + const QString &expression) +{ + QQmlProperty property(object(), QString::fromUtf8(propertyName), context); + + if (!property.isValid()) + return; + + if (property.isProperty()) { + QQmlBinding *binding = new QQmlBinding(expression, object(), context); + binding->setTarget(property); + binding->setNotifyOnValueChanged(true); + + QQmlPropertyPrivate::setBinding(binding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding); + //Refcounting is taking take care of deletion + binding->update(); + if (binding->hasError()) { + if (property.property().userType() == QVariant::String) + property.write(QVariant(QLatin1Char('#') + expression + QLatin1Char('#'))); + } + + } else { + qWarning() << Q_FUNC_INFO << ": Cannot set binding for property" << propertyName << ": property is unknown for type"; + } +} + +void QQuickDesignerCustomObjectData::keepBindingFromGettingDeleted(QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName) +{ + //Refcounting is taking care + Q_UNUSED(context) + Q_UNUSED(propertyName) +} + +void QQuickDesignerCustomObjectData::handleDestroyed() +{ + s_designerObjectToDataHash()->remove(m_object); + delete this; +} + +QT_END_NAMESPACE + diff --git a/src/quick/designer/qquickdesignercustomobjectdata_p.h b/src/quick/designer/qquickdesignercustomobjectdata_p.h new file mode 100644 index 0000000000..6734540a54 --- /dev/null +++ b/src/quick/designer/qquickdesignercustomobjectdata_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DESIGNERCUSTOMOBJECTDATA_H +#define DESIGNERCUSTOMOBJECTDATA_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickdesignersupport_p.h" + +#include <QHash> +#include <QObject> +#include <QVariant> + +#include <private/qqmlbinding_p.h> + +QT_BEGIN_NAMESPACE +class QQmlContext; + +class QQuickDesignerCustomObjectData +{ +public: + static void registerData(QObject *object); + static QQuickDesignerCustomObjectData *get(QObject *object); + static QVariant getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName); + static void doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName); + static bool hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName); + static bool hasBindingForProperty(QObject *object, + QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName, + bool *hasChanged); + static void setPropertyBinding(QObject *object, + QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName, + const QString &expression); + static void keepBindingFromGettingDeleted(QObject *object, + QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName); + void handleDestroyed(); + +private: + QQuickDesignerCustomObjectData(QObject *object); + void populateResetHashes(); + QObject *object() const; + QVariant getResetValue(const QQuickDesignerSupport::PropertyName &propertyName) const; + void doResetProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName); + bool hasValidResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const; + QQmlAbstractBinding *getResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const; + bool hasBindingForProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName, bool *hasChanged) const; + void setPropertyBinding(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName, const QString &expression); + void keepBindingFromGettingDeleted(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName); + + QObject *m_object; + QHash<QQuickDesignerSupport::PropertyName, QVariant> m_resetValueHash; + QHash<QQuickDesignerSupport::PropertyName, QQmlAbstractBinding::Ptr> m_resetBindingHash; + mutable QHash<QQuickDesignerSupport::PropertyName, bool> m_hasBindingHash; +}; + +QT_END_NAMESPACE + +#endif // DESIGNERCUSTOMOBJECTDATA_H diff --git a/src/quick/designer/designersupport.cpp b/src/quick/designer/qquickdesignersupport.cpp index 56d2badb62..bc6352a677 100644 --- a/src/quick/designer/designersupport.cpp +++ b/src/quick/designer/qquickdesignersupport.cpp @@ -31,7 +31,7 @@ ** ****************************************************************************/ -#include "designersupport.h" +#include "qquickdesignersupport_p.h" #include <private/qquickitem_p.h> #include <QtQuick/private/qquickshadereffectsource_p.h> @@ -46,16 +46,16 @@ #include <private/qqmlcomponentattached_p.h> #include <private/qqmldata_p.h> -#include "designerwindowmanager_p.h" +#include "qquickdesignerwindowmanager_p.h" QT_BEGIN_NAMESPACE -DesignerSupport::DesignerSupport() +QQuickDesignerSupport::QQuickDesignerSupport() { } -DesignerSupport::~DesignerSupport() +QQuickDesignerSupport::~QQuickDesignerSupport() { typedef QHash<QQuickItem*, QSGLayer*>::iterator ItemTextureHashIt; @@ -67,7 +67,7 @@ DesignerSupport::~DesignerSupport() } } -void DesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide) +void QQuickDesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide) { if (referencedItem == 0) return; @@ -100,7 +100,7 @@ void DesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide) } } -void DesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhide) +void QQuickDesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhide) { if (referencedItem == 0) return; @@ -109,7 +109,7 @@ void DesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhid QQuickItemPrivate::get(referencedItem)->derefFromEffectItem(unhide); } -QImage DesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize) +QImage QQuickDesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize) { if (referencedItem == 0 || referencedItem->parentItem() == 0) { qDebug() << __FILE__ << __LINE__ << "Warning: Item can be rendered."; @@ -136,7 +136,7 @@ QImage DesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRe return renderImage; } -bool DesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType) +bool QQuickDesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType) { if (referencedItem == 0) return false; @@ -144,7 +144,7 @@ bool DesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType) return QQuickItemPrivate::get(referencedItem)->dirtyAttributes & dirtyType; } -void DesignerSupport::addDirty(QQuickItem *referencedItem, DesignerSupport::DirtyType dirtyType) +void QQuickDesignerSupport::addDirty(QQuickItem *referencedItem, QQuickDesignerSupport::DirtyType dirtyType) { if (referencedItem == 0) return; @@ -152,7 +152,7 @@ void DesignerSupport::addDirty(QQuickItem *referencedItem, DesignerSupport::Dirt QQuickItemPrivate::get(referencedItem)->dirtyAttributes |= dirtyType; } -void DesignerSupport::resetDirty(QQuickItem *referencedItem) +void QQuickDesignerSupport::resetDirty(QQuickItem *referencedItem) { if (referencedItem == 0) return; @@ -161,7 +161,7 @@ void DesignerSupport::resetDirty(QQuickItem *referencedItem) QQuickItemPrivate::get(referencedItem)->removeFromDirtyList(); } -QTransform DesignerSupport::windowTransform(QQuickItem *referencedItem) +QTransform QQuickDesignerSupport::windowTransform(QQuickItem *referencedItem) { if (referencedItem == 0) return QTransform(); @@ -169,7 +169,7 @@ QTransform DesignerSupport::windowTransform(QQuickItem *referencedItem) return QQuickItemPrivate::get(referencedItem)->itemToWindowTransform(); } -QTransform DesignerSupport::parentTransform(QQuickItem *referencedItem) +QTransform QQuickDesignerSupport::parentTransform(QQuickItem *referencedItem) { if (referencedItem == 0) return QTransform(); @@ -211,12 +211,9 @@ bool isValidAnchorName(const QString &name) return anchorNameList.contains(name); } -bool DesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem) +bool QQuickDesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem) { -#ifndef QT_NO_DYNAMIC_CAST - Q_ASSERT(dynamic_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem))); -#endif - QQuickItemPrivate *fromItemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem)); + QQuickItemPrivate *fromItemPrivate = QQuickItemPrivate::get(fromItem); QQuickAnchors *anchors = fromItemPrivate->anchors(); return anchors->fill() == toItem || anchors->centerIn() == toItem @@ -229,9 +226,9 @@ bool DesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem) || anchors->baseline().item == toItem; } -bool DesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem) +bool QQuickDesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem) { - foreach (QQuickItem *childItem, fromItem->childItems()) { + Q_FOREACH (QQuickItem *childItem, fromItem->childItems()) { if (childItem) { if (isAnchoredTo(childItem, toItem)) return true; @@ -246,7 +243,7 @@ bool DesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *to QQuickAnchors *anchors(QQuickItem *item) { - QQuickItemPrivate *itemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item)); + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); return itemPrivate->anchors(); } @@ -278,7 +275,7 @@ QQuickAnchors::Anchor anchorLineFlagForName(const QString &name) return QQuickAnchors::LeftAnchor; } -bool DesignerSupport::hasAnchor(QQuickItem *item, const QString &name) +bool QQuickDesignerSupport::hasAnchor(QQuickItem *item, const QString &name) { if (!isValidAnchorName(name)) return false; @@ -313,19 +310,19 @@ bool DesignerSupport::hasAnchor(QQuickItem *item, const QString &name) return anchors(item)->usedAnchors().testFlag(anchorLineFlagForName(name)); } -QQuickItem *DesignerSupport::anchorFillTargetItem(QQuickItem *item) +QQuickItem *QQuickDesignerSupport::anchorFillTargetItem(QQuickItem *item) { return anchors(item)->fill(); } -QQuickItem *DesignerSupport::anchorCenterInTargetItem(QQuickItem *item) +QQuickItem *QQuickDesignerSupport::anchorCenterInTargetItem(QQuickItem *item) { return anchors(item)->centerIn(); } -QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QQmlContext *context) +QPair<QString, QObject*> QQuickDesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QQmlContext *context) { QObject *targetObject = 0; QString targetName; @@ -350,7 +347,7 @@ QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QQuickItem *item, con return QPair<QString, QObject*>(targetName, targetObject); } -void DesignerSupport::resetAnchor(QQuickItem *item, const QString &name) +void QQuickDesignerSupport::resetAnchor(QQuickItem *item, const QString &name) { if (name == QLatin1String("anchors.fill")) { anchors(item)->resetFill(); @@ -373,7 +370,7 @@ void DesignerSupport::resetAnchor(QQuickItem *item, const QString &name) } } -void DesignerSupport::emitComponentCompleteSignalForAttachedProperty(QQuickItem *item) +void QQuickDesignerSupport::emitComponentCompleteSignalForAttachedProperty(QQuickItem *item) { QQmlData *data = QQmlData::get(item); if (data && data->context) { @@ -384,24 +381,24 @@ void DesignerSupport::emitComponentCompleteSignalForAttachedProperty(QQuickItem } } -QList<QObject*> DesignerSupport::statesForItem(QQuickItem *item) +QList<QObject*> QQuickDesignerSupport::statesForItem(QQuickItem *item) { QList<QObject*> objectList; QList<QQuickState *> stateList = QQuickItemPrivate::get(item)->_states()->states(); objectList.reserve(stateList.size()); - foreach (QQuickState* state, stateList) + Q_FOREACH (QQuickState* state, stateList) objectList.append(state); return objectList; } -bool DesignerSupport::isComponentComplete(QQuickItem *item) +bool QQuickDesignerSupport::isComponentComplete(QQuickItem *item) { - return static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item))->componentComplete; + return QQuickItemPrivate::get(item)->componentComplete; } -int DesignerSupport::borderWidth(QQuickItem *item) +int QQuickDesignerSupport::borderWidth(QQuickItem *item) { QQuickRectangle *rectangle = qobject_cast<QQuickRectangle*>(item); if (rectangle) @@ -410,60 +407,71 @@ int DesignerSupport::borderWidth(QQuickItem *item) return 0; } -void DesignerSupport::refreshExpressions(QQmlContext *context) +void QQuickDesignerSupport::refreshExpressions(QQmlContext *context) { QQmlContextPrivate::get(context)->data->refreshExpressions(); } -void DesignerSupport::setRootItem(QQuickView *view, QQuickItem *item) +void QQuickDesignerSupport::setRootItem(QQuickView *view, QQuickItem *item) { QQuickViewPrivate::get(view)->setRootObject(item); } -bool DesignerSupport::isValidWidth(QQuickItem *item) +bool QQuickDesignerSupport::isValidWidth(QQuickItem *item) { return QQuickItemPrivate::get(item)->heightValid; } -bool DesignerSupport::isValidHeight(QQuickItem *item) +bool QQuickDesignerSupport::isValidHeight(QQuickItem *item) { return QQuickItemPrivate::get(item)->widthValid; } -void DesignerSupport::updateDirtyNode(QQuickItem *item) +void QQuickDesignerSupport::updateDirtyNode(QQuickItem *item) { if (item->window()) QQuickWindowPrivate::get(item->window())->updateDirtyNode(item); } -void DesignerSupport::activateDesignerWindowManager() +void QQuickDesignerSupport::activateDesignerWindowManager() { - QSGRenderLoop::setInstance(new DesignerWindowManager); + QSGRenderLoop::setInstance(new QQuickDesignerWindowManager); } -void DesignerSupport::activateDesignerMode() +void QQuickDesignerSupport::activateDesignerMode() { QQmlEnginePrivate::activateDesignerMode(); } -void DesignerSupport::disableComponentComplete() +void QQuickDesignerSupport::disableComponentComplete() { QQmlVME::disableComponentComplete(); } -void DesignerSupport::enableComponentComplete() +void QQuickDesignerSupport::enableComponentComplete() { QQmlVME::enableComponentComplete(); } -void DesignerSupport::createOpenGLContext(QQuickWindow *window) +void QQuickDesignerSupport::createOpenGLContext(QQuickWindow *window) { - DesignerWindowManager::createOpenGLContext(window); + QQuickDesignerWindowManager::createOpenGLContext(window); } -void DesignerSupport::polishItems(QQuickWindow *window) +void QQuickDesignerSupport::polishItems(QQuickWindow *window) { QQuickWindowPrivate::get(window)->polishItems(); } +ComponentCompleteDisabler::ComponentCompleteDisabler() +{ + QQuickDesignerSupport::disableComponentComplete(); +} + +ComponentCompleteDisabler::~ComponentCompleteDisabler() +{ + QQuickDesignerSupport::enableComponentComplete(); +} + + QT_END_NAMESPACE diff --git a/src/quick/designer/designersupport.h b/src/quick/designer/qquickdesignersupport_p.h index 51fcef4512..e15c109f7b 100644 --- a/src/quick/designer/designersupport.h +++ b/src/quick/designer/qquickdesignersupport_p.h @@ -45,7 +45,6 @@ // We mean it. // - #include <QtQuick/qtquickglobal.h> #include <QtCore/QtGlobal> #include <QtCore/QHash> @@ -62,9 +61,13 @@ class QQuickView; class QObject; class QQuickWindow; -class Q_QUICK_EXPORT DesignerSupport +class Q_QUICK_EXPORT QQuickDesignerSupport { public: + typedef QByteArray PropertyName; + typedef QList<PropertyName> PropertyNameList; + typedef QByteArray TypeName; + enum DirtyType { TransformOrigin = 0x00000001, Transform = 0x00000002, @@ -95,8 +98,8 @@ public: }; - DesignerSupport(); - ~DesignerSupport(); + QQuickDesignerSupport(); + ~QQuickDesignerSupport(); void refFromEffectItem(QQuickItem *referencedItem, bool hide = true); void derefFromEffectItem(QQuickItem *referencedItem, bool unhide = true); @@ -119,7 +122,6 @@ public: static void resetAnchor(QQuickItem *item, const QString &name); static void emitComponentCompleteSignalForAttachedProperty(QQuickItem *item); - static QList<QObject*> statesForItem(QQuickItem *item); static bool isComponentComplete(QQuickItem *item); @@ -149,6 +151,16 @@ private: QHash<QQuickItem*, QSGLayer*> m_itemTextureHash; }; +class Q_QUICK_EXPORT ComponentCompleteDisabler +{ +public: + ComponentCompleteDisabler(); + + ~ComponentCompleteDisabler(); +}; + +typedef QQuickDesignerSupport DesignerSupport; + QT_END_NAMESPACE #endif // DESIGNERSUPPORT_H diff --git a/src/quick/designer/qquickdesignersupportitems.cpp b/src/quick/designer/qquickdesignersupportitems.cpp new file mode 100644 index 0000000000..4f23fe6630 --- /dev/null +++ b/src/quick/designer/qquickdesignersupportitems.cpp @@ -0,0 +1,320 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickdesignersupportitems_p.h" +#include "qquickdesignersupportproperties_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/qquickanimation_p.h> +#include <private/qqmlmetatype_p.h> +#include <private/qqmltimer_p.h> + +QT_BEGIN_NAMESPACE + +static void (*fixResourcePathsForObjectCallBack)(QObject*) = 0; + +static void stopAnimation(QObject *object) +{ + if (object == 0) + return; + + QQuickTransition *transition = qobject_cast<QQuickTransition*>(object); + QQuickAbstractAnimation *animation = qobject_cast<QQuickAbstractAnimation*>(object); + QQmlTimer *timer = qobject_cast<QQmlTimer*>(object); + if (transition) { + transition->setFromState(QString()); + transition->setToState(QString()); + } else if (animation) { +// QQuickScriptAction *scriptAimation = qobject_cast<QQuickScriptAction*>(animation); +// if (scriptAimation) FIXME +// scriptAimation->setScript(QQmlScriptString()); + animation->setLoops(1); + animation->complete(); + animation->setDisableUserControl(); + } else if (timer) { + timer->blockSignals(true); + } +} + +static void allSubObjects(QObject *object, QObjectList &objectList) +{ + // don't add null pointer and stop if the object is already in the list + if (!object || objectList.contains(object)) + return; + + objectList.append(object); + + for (int index = QObject::staticMetaObject.propertyOffset(); + index < object->metaObject()->propertyCount(); + index++) { + QMetaProperty metaProperty = object->metaObject()->property(index); + + // search recursive in property objects + if (metaProperty.isReadable() + && metaProperty.isWritable() + && QQmlMetaType::isQObject(metaProperty.userType())) { + if (qstrcmp(metaProperty.name(), "parent")) { + QObject *propertyObject = QQmlMetaType::toQObject(metaProperty.read(object)); + allSubObjects(propertyObject, objectList); + } + + } + + // search recursive in property object lists + if (metaProperty.isReadable() + && QQmlMetaType::isList(metaProperty.userType())) { + QQmlListReference list(object, metaProperty.name()); + if (list.canCount() && list.canAt()) { + for (int i = 0; i < list.count(); i++) { + QObject *propertyObject = list.at(i); + allSubObjects(propertyObject, objectList); + + } + } + } + } + + // search recursive in object children list + Q_FOREACH (QObject *childObject, object->children()) { + allSubObjects(childObject, objectList); + } + + // search recursive in quick item childItems list + QQuickItem *quickItem = qobject_cast<QQuickItem*>(object); + if (quickItem) { + Q_FOREACH (QQuickItem *childItem, quickItem->childItems()) { + allSubObjects(childItem, objectList); + } + } +} + +void QQuickDesignerSupportItems::tweakObjects(QObject *object) +{ + QObjectList objectList; + allSubObjects(object, objectList); + Q_FOREACH (QObject* childObject, objectList) { + stopAnimation(childObject); + if (fixResourcePathsForObjectCallBack) + fixResourcePathsForObjectCallBack(childObject); + } +} + +static QObject *createDummyWindow(QQmlEngine *engine) +{ + QQmlComponent component(engine, QUrl(QStringLiteral("qrc:/qtquickplugin/mockfiles/Window.qml"))); + return component.create(); +} + +static bool isWindowMetaObject(const QMetaObject *metaObject) +{ + if (metaObject) { + if (metaObject->className() == QByteArrayLiteral("QWindow")) + return true; + + return isWindowMetaObject(metaObject->superClass()); + } + + return false; +} + +static bool isWindow(QObject *object) { + if (object) + return isWindowMetaObject(object->metaObject()); + + return false; +} + +static QQmlType *getQmlType(const QString &typeName, int majorNumber, int minorNumber) +{ + return QQmlMetaType::qmlType(typeName, majorNumber, minorNumber); +} + +static bool isCrashingType(QQmlType *type) +{ + if (type) { + if (type->qmlTypeName() == QStringLiteral("QtMultimedia/MediaPlayer")) + return true; + + if (type->qmlTypeName() == QStringLiteral("QtMultimedia/Audio")) + return true; + + if (type->qmlTypeName() == QStringLiteral("QtQuick.Controls/MenuItem")) + return true; + + if (type->qmlTypeName() == QStringLiteral("QtQuick.Controls/Menu")) + return true; + + if (type->qmlTypeName() == QStringLiteral("QtQuick/Timer")) + return true; + } + + return false; +} + +QObject *QQuickDesignerSupportItems::createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context) +{ + ComponentCompleteDisabler disableComponentComplete; + + Q_UNUSED(disableComponentComplete) + + QObject *object = 0; + QQmlType *type = getQmlType(typeName, majorNumber, minorNumber); + + if (isCrashingType(type)) { + object = new QObject; + } else if (type) { + if ( type->isComposite()) { + object = createComponent(type->sourceUrl(), context); + } else + { + if (type->typeName() == "QQmlComponent") { + object = new QQmlComponent(context->engine(), 0); + } else { + object = type->create(); + } + } + + if (isWindow(object)) { + delete object; + object = createDummyWindow(context->engine()); + } + + } + + if (!object) { + qWarning() << "QuickDesigner: Cannot create an object of type" + << QString::fromLatin1("%1 %2,%3").arg(typeName).arg(majorNumber).arg(minorNumber) + << "- type isn't known to declarative meta type system"; + } + + tweakObjects(object); + + if (object && QQmlEngine::contextForObject(object) == 0) + QQmlEngine::setContextForObject(object, context); + + QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership); + + return object; +} + +QObject *QQuickDesignerSupportItems::createComponent(const QUrl &componentUrl, QQmlContext *context) +{ + ComponentCompleteDisabler disableComponentComplete; + Q_UNUSED(disableComponentComplete) + + QQmlComponent component(context->engine(), componentUrl); + + QObject *object = component.beginCreate(context); + tweakObjects(object); + component.completeCreate(); + QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership); + + if (component.isError()) { + qWarning() << "Error in:" << Q_FUNC_INFO << componentUrl; + Q_FOREACH (const QQmlError &error, component.errors()) + qWarning() << error; + } + return object; +} + +bool QQuickDesignerSupportItems::objectWasDeleted(QObject *object) +{ + return QObjectPrivate::get(object)->wasDeleted; +} + +void QQuickDesignerSupportItems::disableNativeTextRendering(QQuickItem *item) +{ + QQuickText *text = qobject_cast<QQuickText*>(item); + if (text) + text->setRenderType(QQuickText::QtRendering); + + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(item); + if (textInput) + textInput->setRenderType(QQuickTextInput::QtRendering); + + QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(item); + if (textEdit) + textEdit->setRenderType(QQuickTextEdit::QtRendering); +} + +void QQuickDesignerSupportItems::disableTextCursor(QQuickItem *item) +{ + Q_FOREACH (QQuickItem *childItem, item->childItems()) + disableTextCursor(childItem); + + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(item); + if (textInput) + textInput->setCursorVisible(false); + + QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(item); + if (textEdit) + textEdit->setCursorVisible(false); +} + +void QQuickDesignerSupportItems::disableTransition(QObject *object) +{ + QQuickTransition *transition = qobject_cast<QQuickTransition*>(object); + Q_ASSERT(transition); + const QString invalidState = QLatin1String("invalidState"); + transition->setToState(invalidState); + transition->setFromState(invalidState); +} + +void QQuickDesignerSupportItems::disableBehaivour(QObject *object) +{ + QQuickBehavior* behavior = qobject_cast<QQuickBehavior*>(object); + Q_ASSERT(behavior); + behavior->setEnabled(false); +} + +void QQuickDesignerSupportItems::stopUnifiedTimer() +{ + QUnifiedTimer::instance()->setSlowdownFactor(0.00001); + QUnifiedTimer::instance()->setSlowModeEnabled(true); +} + +void QQuickDesignerSupportItems::registerFixResourcePathsForObjectCallBack(void (*callback)(QObject *)) +{ + fixResourcePathsForObjectCallBack = callback; +} + +QT_END_NAMESPACE + + diff --git a/src/quick/designer/qquickdesignersupportitems_p.h b/src/quick/designer/qquickdesignersupportitems_p.h new file mode 100644 index 0000000000..c15d651b33 --- /dev/null +++ b/src/quick/designer/qquickdesignersupportitems_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DESIGNERSUPPORTITEM_H +#define DESIGNERSUPPORTITEM_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickdesignersupport_p.h" + +#include <QObject> +#include <QString> +#include <QVariant> +#include <QList> +#include <QByteArray> +#include <QQmlContext> +#include <QQmlListReference> + +QT_BEGIN_NAMESPACE + +class Q_QUICK_EXPORT QQuickDesignerSupportItems +{ +public: + static QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context); + static QObject *createComponent(const QUrl &componentUrl, QQmlContext *context); + static void tweakObjects(QObject *object); + static bool objectWasDeleted(QObject *object); + static void disableNativeTextRendering(QQuickItem *item); + static void disableTextCursor(QQuickItem *item); + static void disableTransition(QObject *object); + static void disableBehaivour(QObject *object); + static void stopUnifiedTimer(); + static void registerFixResourcePathsForObjectCallBack(void (*callback)(QObject *)); +}; + +QT_END_NAMESPACE + +#endif // DESIGNERSUPPORTITEM_H diff --git a/src/quick/designer/qquickdesignersupportmetainfo.cpp b/src/quick/designer/qquickdesignersupportmetainfo.cpp new file mode 100644 index 0000000000..c6c7ed38b9 --- /dev/null +++ b/src/quick/designer/qquickdesignersupportmetainfo.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickdesignersupportmetainfo_p.h" +#include "qqmldesignermetaobject_p.h" + +#include <private/qqmlmetatype_p.h> + +QT_BEGIN_NAMESPACE + +bool QQuickDesignerSupportMetaInfo::isSubclassOf(QObject *object, const QByteArray &superTypeName) +{ + if (object == 0) + return false; + + const QMetaObject *metaObject = object->metaObject(); + + while (metaObject) { + QQmlType *qmlType = QQmlMetaType::qmlType(metaObject); + if (qmlType && qmlType->qmlTypeName() == QLatin1String(superTypeName)) // ignore version numbers + return true; + + if (metaObject->className() == superTypeName) + return true; + + metaObject = metaObject->superClass(); + } + + return false; +} + +void QQuickDesignerSupportMetaInfo::registerNotifyPropertyChangeCallBack(void (*callback)(QObject *, const QQuickDesignerSupport::PropertyName &)) +{ + QQmlDesignerMetaObject::registerNotifyPropertyChangeCallBack(callback); +} + +QT_END_NAMESPACE + diff --git a/src/quick/designer/qquickdesignersupportmetainfo_p.h b/src/quick/designer/qquickdesignersupportmetainfo_p.h new file mode 100644 index 0000000000..52bf8e3ac0 --- /dev/null +++ b/src/quick/designer/qquickdesignersupportmetainfo_p.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DESIGNERSUPPORTMETAINFO_H +#define DESIGNERSUPPORTMETAINFO_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickdesignersupport_p.h" + +#include <QObject> +#include <QByteArray> + +QT_BEGIN_NAMESPACE + +class Q_QUICK_EXPORT QQuickDesignerSupportMetaInfo +{ +public: + static bool isSubclassOf(QObject *object, const QByteArray &superTypeName); + static void registerNotifyPropertyChangeCallBack(void (*callback)(QObject *, const QQuickDesignerSupport::PropertyName &)); +}; + +QT_END_NAMESPACE + +#endif // DESIGNERSUPPORTMETAINFO_H diff --git a/src/quick/designer/qquickdesignersupportproperties.cpp b/src/quick/designer/qquickdesignersupportproperties.cpp new file mode 100644 index 0000000000..96f09ada48 --- /dev/null +++ b/src/quick/designer/qquickdesignersupportproperties.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickdesignersupportproperties_p.h" + +#include "qqmldesignermetaobject_p.h" +#include "qquickdesignercustomobjectdata_p.h" + +QT_BEGIN_NAMESPACE + +static void addToPropertyNameListIfNotBlackListed(QQuickDesignerSupport::PropertyNameList *propertyNameList, + const QQuickDesignerSupport::PropertyName &propertyName) +{ + if (!QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName)) + propertyNameList->append(propertyName); +} + +void QQuickDesignerSupportProperties::createNewDynamicProperty(QObject *object, QQmlEngine *engine, const QString &name) +{ + QQmlDesignerMetaObject::getNodeInstanceMetaObject(object, engine)->createNewDynamicProperty(name); +} + +void QQuickDesignerSupportProperties::registerNodeInstanceMetaObject(QObject *object, QQmlEngine *engine) +{ + // we just create one and the ownership goes automatically to the object in nodeinstance see init method + QQmlDesignerMetaObject::getNodeInstanceMetaObject(object, engine); +} + +bool QQuickDesignerSupportProperties::hasFullImplementedListInterface(const QQmlListReference &list) +{ + return list.isValid() && list.canCount() && list.canAt() && list.canAppend() && list.canClear(); +} + +void QQuickDesignerSupportProperties::registerCustomData(QObject *object) +{ + QQuickDesignerCustomObjectData::registerData(object); +} + +QVariant QQuickDesignerSupportProperties::getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName) +{ + return QQuickDesignerCustomObjectData::getResetValue(object, propertyName); +} + +void QQuickDesignerSupportProperties::doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName) +{ + QQuickDesignerCustomObjectData::doResetProperty(object, context, propertyName); +} + +bool QQuickDesignerSupportProperties::hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName) +{ + return QQuickDesignerCustomObjectData::hasValidResetBinding(object, propertyName); +} + +bool QQuickDesignerSupportProperties::hasBindingForProperty(QObject *object, + QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName, + bool *hasChanged) +{ + return QQuickDesignerCustomObjectData::hasBindingForProperty(object, context, propertyName, hasChanged); +} + +void QQuickDesignerSupportProperties::setPropertyBinding(QObject *object, + QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName, + const QString &expression) +{ + QQuickDesignerCustomObjectData::setPropertyBinding(object, context, propertyName, expression); +} + +void QQuickDesignerSupportProperties::keepBindingFromGettingDeleted(QObject *object, + QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName) +{ + QQuickDesignerCustomObjectData::keepBindingFromGettingDeleted(object, context, propertyName); +} + +bool QQuickDesignerSupportProperties::isPropertyQObject(const QMetaProperty &metaProperty) +{ + return QQmlMetaType::isQObject(metaProperty.userType()); +} + + +QObject *QQuickDesignerSupportProperties::readQObjectProperty(const QMetaProperty &metaProperty, QObject *object) +{ + return QQmlMetaType::toQObject(metaProperty.read(object)); +} + +void QQuickDesignerSupportProperties::getPropertyCache(QObject *object, QQmlEngine *engine) +{ + QQmlEnginePrivate::get(engine)->cache(object->metaObject()); +} + +QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::propertyNameListForWritableProperties(QObject *object, + const QQuickDesignerSupport::PropertyName &baseName, + QObjectList *inspectedObjects) +{ + QQuickDesignerSupport::PropertyNameList propertyNameList; + + QObjectList localObjectList; + + if (inspectedObjects == 0) + inspectedObjects = &localObjectList; + + + if (inspectedObjects->contains(object)) + return propertyNameList; + + inspectedObjects->append(object); + + const QMetaObject *metaObject = object->metaObject(); + for (int index = 0; index < metaObject->propertyCount(); ++index) { + QMetaProperty metaProperty = metaObject->property(index); + QQmlProperty declarativeProperty(object, QString::fromUtf8(metaProperty.name())); + if (declarativeProperty.isValid() && !declarativeProperty.isWritable() && declarativeProperty.propertyTypeCategory() == QQmlProperty::Object) { + if (declarativeProperty.name() != QLatin1String("parent")) { + QObject *childObject = QQmlMetaType::toQObject(declarativeProperty.read()); + if (childObject) + propertyNameList.append(propertyNameListForWritableProperties(childObject, + baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()) + + '.', inspectedObjects)); + } + } else if (QQmlValueTypeFactory::valueType(metaProperty.userType())) { + QQmlValueType *valueType = QQmlValueTypeFactory::valueType(metaProperty.userType()); + valueType->setValue(metaProperty.read(object)); + propertyNameList.append(propertyNameListForWritableProperties(valueType, + baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()) + + '.', inspectedObjects)); + } + + if (metaProperty.isReadable() && metaProperty.isWritable()) { + addToPropertyNameListIfNotBlackListed(&propertyNameList, + baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())); + } + } + + return propertyNameList; +} + +bool QQuickDesignerSupportProperties::isPropertyBlackListed(const QQuickDesignerSupport::PropertyName &propertyName) +{ + if (propertyName.contains(".") && propertyName.contains("__")) + return true; + + if (propertyName.count(".") > 1) + return true; + + return false; +} + +QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::allPropertyNames(QObject *object, + const QQuickDesignerSupport::PropertyName &baseName, + QObjectList *inspectedObjects) +{ + QQuickDesignerSupport::PropertyNameList propertyNameList; + + QObjectList localObjectList; + + if (inspectedObjects == 0) + inspectedObjects = &localObjectList; + + + if (inspectedObjects->contains(object)) + return propertyNameList; + + inspectedObjects->append(object); + + + const QMetaObject *metaObject = object->metaObject(); + 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")) { + QObject *childObject = QQmlMetaType::toQObject(declarativeProperty.read()); + if (childObject) + propertyNameList.append(allPropertyNames(childObject, + baseName + + QQuickDesignerSupport::PropertyName(metaProperty.name()) + + '.', inspectedObjects)); + } + } else if (QQmlValueTypeFactory::valueType(metaProperty.userType())) { + QQmlValueType *valueType = QQmlValueTypeFactory::valueType(metaProperty.userType()); + valueType->setValue(metaProperty.read(object)); + propertyNameList.append(baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())); + propertyNameList.append(allPropertyNames(valueType, + baseName + + QQuickDesignerSupport::PropertyName(metaProperty.name()) + + '.', inspectedObjects)); + } else { + addToPropertyNameListIfNotBlackListed(&propertyNameList, + baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())); + } + } + + return propertyNameList; +} + + +QT_END_NAMESPACE + + + + diff --git a/src/quick/designer/qquickdesignersupportproperties_p.h b/src/quick/designer/qquickdesignersupportproperties_p.h new file mode 100644 index 0000000000..187bc6e2a6 --- /dev/null +++ b/src/quick/designer/qquickdesignersupportproperties_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DESIGNERSUPPORTPROPERTIES_H +#define DESIGNERSUPPORTPROPERTIES_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickdesignersupport_p.h" + +#include <QObject> +#include <QString> +#include <QVariant> +#include <QList> +#include <QByteArray> +#include <QQmlContext> +#include <QQmlListReference> + +QT_BEGIN_NAMESPACE + +class Q_QUICK_EXPORT QQuickDesignerSupportProperties +{ +public: + static void createNewDynamicProperty(QObject *object, QQmlEngine *engine, const QString &name); + static void registerNodeInstanceMetaObject(QObject *object, QQmlEngine *engine); + static void registerCustomData(QObject *object); + static QVariant getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName); + static void doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName); + static bool hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName); + + static bool hasBindingForProperty(QObject *object, + QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName, + bool *hasChanged); + static void setPropertyBinding(QObject *object, + QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName, + const QString &expression); + static void keepBindingFromGettingDeleted(QObject *object, + QQmlContext *context, + const QQuickDesignerSupport::PropertyName &propertyName); + + static bool isPropertyQObject(const QMetaProperty &metaProperty); + static QObject *readQObjectProperty(const QMetaProperty &metaProperty, QObject *object); + + static void getPropertyCache(QObject *object, QQmlEngine *engine); + static bool isPropertyBlackListed(const QQuickDesignerSupport::PropertyName &propertyName); + static QQuickDesignerSupport::PropertyNameList propertyNameListForWritableProperties(QObject *object, + const QQuickDesignerSupport::PropertyName &baseName = QQuickDesignerSupport::PropertyName(), + QObjectList *inspectedObjects = 0); + static QQuickDesignerSupport::PropertyNameList allPropertyNames(QObject *object, + const QQuickDesignerSupport::PropertyName &baseName = QQuickDesignerSupport::PropertyName(), + QObjectList *inspectedObjects = 0); + static bool hasFullImplementedListInterface(const QQmlListReference &list); +}; + +QT_END_NAMESPACE + +#endif // DESIGNERSUPPORTPROPERTIES_H diff --git a/src/quick/designer/qquickdesignersupportpropertychanges.cpp b/src/quick/designer/qquickdesignersupportpropertychanges.cpp new file mode 100644 index 0000000000..92fa637b54 --- /dev/null +++ b/src/quick/designer/qquickdesignersupportpropertychanges.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickdesignersupportpropertychanges_p.h" + +#include <private/qquickpropertychanges_p.h> +#include <private/qquickstateoperations_p.h> + +QT_BEGIN_NAMESPACE + +void QQuickDesignerSupportPropertyChanges::attachToState(QObject *propertyChanges) +{ + QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges); + + if (!propertyChange) + return; + + propertyChange->attachToState(); +} + +QObject *QQuickDesignerSupportPropertyChanges::targetObject(QObject *propertyChanges) +{ + QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges); + + if (!propertyChange) + return 0; + + return propertyChange->object(); +} + +void QQuickDesignerSupportPropertyChanges::removeProperty(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName) +{ + QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges); + + if (!propertyChange) + return; + + propertyChange->removeProperty(QString::fromUtf8(propertyName)); +} + +QVariant QQuickDesignerSupportPropertyChanges::getProperty(QObject *propertyChanges, + const QQuickDesignerSupport::PropertyName &propertyName) +{ + QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges); + + if (!propertyChange) + return QVariant(); + + return propertyChange->property(QString::fromUtf8(propertyName)); +} + +void QQuickDesignerSupportPropertyChanges::changeValue(QObject *propertyChanges, + const QQuickDesignerSupport::PropertyName &propertyName, + const QVariant &value) +{ + QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges); + + if (!propertyChange) + return; + + propertyChange->changeValue(QString::fromUtf8(propertyName), value); +} + +void QQuickDesignerSupportPropertyChanges::changeExpression(QObject *propertyChanges, + const QQuickDesignerSupport::PropertyName &propertyName, + const QString &expression) +{ + QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges); + + if (!propertyChange) + return; + + propertyChange->changeExpression(QString::fromUtf8(propertyName), expression); +} + +QObject *QQuickDesignerSupportPropertyChanges::stateObject(QObject *propertyChanges) +{ + QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges); + + if (!propertyChange) + return 0; + + return propertyChange->state(); +} + +bool QQuickDesignerSupportPropertyChanges::isNormalProperty(const QQuickDesignerSupport::PropertyName &propertyName) +{ + QMetaObject metaObject = QQuickPropertyChanges::staticMetaObject; + + return (metaObject.indexOfProperty(propertyName) > 0); // 'restoreEntryValues', 'explicit' +} + +void QQuickDesignerSupportPropertyChanges::detachFromState(QObject *propertyChanges) +{ + QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges); + + if (!propertyChange) + return; + + propertyChange->detachFromState(); +} + +QT_END_NAMESPACE + + diff --git a/src/quick/designer/qquickdesignersupportpropertychanges_p.h b/src/quick/designer/qquickdesignersupportpropertychanges_p.h new file mode 100644 index 0000000000..432383d5b4 --- /dev/null +++ b/src/quick/designer/qquickdesignersupportpropertychanges_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DESIGNERSUPPORTPROPERTYCHANGES_H +#define DESIGNERSUPPORTPROPERTYCHANGES_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickdesignersupport_p.h" + +#include <QVariant> + +QT_BEGIN_NAMESPACE + +class Q_QUICK_EXPORT QQuickDesignerSupportPropertyChanges +{ +public: + static void detachFromState(QObject *propertyChanges); + static void attachToState(QObject *propertyChanges); + static QObject *targetObject(QObject *propertyChanges); + static void removeProperty(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName); + static QVariant getProperty(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName); + static void changeValue(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName, const QVariant &value); + static void changeExpression(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName, const QString &expression); + static QObject *stateObject(QObject *propertyChanges); + static bool isNormalProperty(const QQuickDesignerSupport::PropertyName &propertyName); +}; + +QT_END_NAMESPACE + +#endif // DESIGNERSUPPORTPROPERTYCHANGES_H diff --git a/src/quick/designer/qquickdesignersupportstates.cpp b/src/quick/designer/qquickdesignersupportstates.cpp new file mode 100644 index 0000000000..b75ec7115a --- /dev/null +++ b/src/quick/designer/qquickdesignersupportstates.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickdesignersupportstates_p.h" + +#include <private/qquickstategroup_p.h> +#include <private/qquickpropertychanges_p.h> + +QT_BEGIN_NAMESPACE + +bool QQuickDesignerSupportStates::isStateActive(QObject *object, QQmlContext *context) +{ + QQuickState *stateObject = qobject_cast<QQuickState*>(object); + + if (!stateObject) + return false; + + QQuickStateGroup *stateGroup = stateObject->stateGroup(); + + QQmlProperty property(object, QLatin1String("name"), context); + + return stateObject && stateGroup && stateGroup->state() == property.read(); +} + +void QQuickDesignerSupportStates::activateState(QObject *object, QQmlContext *context) +{ + QQuickState *stateObject = qobject_cast<QQuickState*>(object); + + if (!stateObject) + return; + + QQuickStateGroup *stateGroup = stateObject->stateGroup(); + + QQmlProperty property(object, QLatin1String("name"), context); + + stateGroup->setState(property.read().toString()); +} + +void QQuickDesignerSupportStates::deactivateState(QObject *object) +{ + QQuickState *stateObject = qobject_cast<QQuickState*>(object); + + if (!stateObject) + return; + + QQuickStateGroup *stateGroup = stateObject->stateGroup(); + + if (stateGroup) + stateGroup->setState(QString()); +} + +bool QQuickDesignerSupportStates::changeValueInRevertList(QObject *state, QObject *target, + const QQuickDesignerSupport::PropertyName &propertyName, + const QVariant &value) +{ + QQuickState *stateObject = qobject_cast<QQuickState*>(state); + + if (!stateObject) + return false; + + return stateObject->changeValueInRevertList(target, QString::fromUtf8(propertyName), value); +} + +bool QQuickDesignerSupportStates::updateStateBinding(QObject *state, QObject *target, + const QQuickDesignerSupport::PropertyName &propertyName, + const QString &expression) +{ + QQuickState *stateObject = qobject_cast<QQuickState*>(state); + + if (!stateObject) + return false; + + return stateObject->changeValueInRevertList(target, QString::fromUtf8(propertyName), expression); +} + +bool QQuickDesignerSupportStates::resetStateProperty(QObject *state, QObject *target, + const QQuickDesignerSupport::PropertyName &propertyName, + const QVariant & /* resetValue */) +{ + QQuickState *stateObject = qobject_cast<QQuickState*>(state); + + if (!stateObject) + return false; + + return stateObject->removeEntryFromRevertList(target, QString::fromUtf8(propertyName)); +} + +QT_END_NAMESPACE + diff --git a/src/quick/designer/qquickdesignersupportstates_p.h b/src/quick/designer/qquickdesignersupportstates_p.h new file mode 100644 index 0000000000..daa5a2ff01 --- /dev/null +++ b/src/quick/designer/qquickdesignersupportstates_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DESIGNERSUPPORTSTATES_H +#define DESIGNERSUPPORTSTATES_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickdesignersupport_p.h" + +#include <QVariant> + +QT_BEGIN_NAMESPACE + +class Q_QUICK_EXPORT QQuickDesignerSupportStates +{ +public: + static bool isStateActive(QObject *object, QQmlContext *context); + static void activateState(QObject *object, QQmlContext *context); + static void deactivateState(QObject *object); + static bool changeValueInRevertList(QObject *state, + QObject *target, + const QQuickDesignerSupport::PropertyName &propertyName, + const QVariant &value); + + static bool updateStateBinding(QObject *state, QObject *target, + const QQuickDesignerSupport::PropertyName &propertyName, + const QString &expression); + + static bool resetStateProperty(QObject *state, QObject *target, + const QQuickDesignerSupport::PropertyName &propertyName, + const QVariant &); +}; + +QT_END_NAMESPACE + +#endif // DESIGNERSUPPORTSTATES_H diff --git a/src/quick/designer/designerwindowmanager.cpp b/src/quick/designer/qquickdesignerwindowmanager.cpp index f37d6a2180..b1ad42ddb4 100644 --- a/src/quick/designer/designerwindowmanager.cpp +++ b/src/quick/designer/qquickdesignerwindowmanager.cpp @@ -31,35 +31,34 @@ ** ****************************************************************************/ -#include "designerwindowmanager_p.h" +#include "qquickdesignerwindowmanager_p.h" #include "private/qquickwindow_p.h" #include <QtGui/QOpenGLContext> #include <QtQuick/QQuickWindow> - QT_BEGIN_NAMESPACE -DesignerWindowManager::DesignerWindowManager() +QQuickDesignerWindowManager::QQuickDesignerWindowManager() : m_sgContext(QSGContext::createDefaultContext()) { m_renderContext.reset(new QSGRenderContext(m_sgContext.data())); } -void DesignerWindowManager::show(QQuickWindow *window) +void QQuickDesignerWindowManager::show(QQuickWindow *window) { makeOpenGLContext(window); } -void DesignerWindowManager::hide(QQuickWindow *) +void QQuickDesignerWindowManager::hide(QQuickWindow *) { } -void DesignerWindowManager::windowDestroyed(QQuickWindow *) +void QQuickDesignerWindowManager::windowDestroyed(QQuickWindow *) { } -void DesignerWindowManager::makeOpenGLContext(QQuickWindow *window) +void QQuickDesignerWindowManager::makeOpenGLContext(QQuickWindow *window) { if (!m_openGlContext) { m_openGlContext.reset(new QOpenGLContext()); @@ -73,31 +72,31 @@ void DesignerWindowManager::makeOpenGLContext(QQuickWindow *window) } } -void DesignerWindowManager::exposureChanged(QQuickWindow *) +void QQuickDesignerWindowManager::exposureChanged(QQuickWindow *) { } -QImage DesignerWindowManager::grab(QQuickWindow *) +QImage QQuickDesignerWindowManager::grab(QQuickWindow *) { return QImage(); } -void DesignerWindowManager::maybeUpdate(QQuickWindow *) +void QQuickDesignerWindowManager::maybeUpdate(QQuickWindow *) { } -QSGContext *DesignerWindowManager::sceneGraphContext() const +QSGContext *QQuickDesignerWindowManager::sceneGraphContext() const { return m_sgContext.data(); } -void DesignerWindowManager::createOpenGLContext(QQuickWindow *window) +void QQuickDesignerWindowManager::createOpenGLContext(QQuickWindow *window) { window->create(); window->update(); } -void DesignerWindowManager::update(QQuickWindow *window) +void QQuickDesignerWindowManager::update(QQuickWindow *window) { makeOpenGLContext(window); } diff --git a/src/quick/designer/designerwindowmanager_p.h b/src/quick/designer/qquickdesignerwindowmanager_p.h index e7a7314c20..6d98e25347 100644 --- a/src/quick/designer/designerwindowmanager_p.h +++ b/src/quick/designer/qquickdesignerwindowmanager_p.h @@ -60,11 +60,11 @@ class QSGRenderContext; class QAnimationDriver; class QOpenGLContext; -class DesignerWindowManager : public QSGRenderLoop +class QQuickDesignerWindowManager : public QSGRenderLoop { Q_OBJECT public: - DesignerWindowManager(); + QQuickDesignerWindowManager(); void show(QQuickWindow *window); void hide(QQuickWindow *window); |