/************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #include "qmlpropertychangesnodeinstance.h" #include "qmlstatenodeinstance.h" #include #include #include #include #include namespace QmlDesigner { namespace Internal { QmlPropertyChangesObject::QmlPropertyChangesObject() : QDeclarativeStateOperation(), m_restoreEntryValues(true), m_isExplicit(false) { } QDeclarativeStateOperation::ActionList QmlPropertyChangesObject::actions() { ActionList list; foreach (const QString &property, m_properties.keys()) { QDeclarativeAction a(m_targetObject.data(), property, m_properties.value(property)); if (a.property.isValid()) { a.restore = restoreEntryValues(); if (a.property.propertyType() == QVariant::Url && (a.toValue.type() == QVariant::String || a.toValue.type() == QVariant::ByteArray) && !a.toValue.isNull()) a.toValue.setValue(qmlContext(this)->resolvedUrl(QUrl(a.toValue.toString()))); list << a; } } // for (int ii = 0; ii < d->signalReplacements.count(); ++ii) { // // QmlReplaceSignalHandler *handler = d->signalReplacements.at(ii); // // if (handler->property.isValid()) { // Action a; // a.event = handler; // list << a; // } // } foreach (const QString &property, m_expressions.keys()) { QDeclarativeProperty mProperty = metaProperty(property); if (mProperty.isValid()) { QDeclarativeAction a; a.restore = restoreEntryValues(); a.property = mProperty; a.fromValue = a.property.read(); a.specifiedObject = m_targetObject.data(); a.specifiedProperty = property; if (m_isExplicit) { a.toValue = QDeclarativeExpression(qmlContext(object()), m_expressions.value(property), object()).value(); } else { QDeclarativeBinding *newBinding = new QDeclarativeBinding(m_expressions.value(property), object(), qmlContext(object())); newBinding->setTarget(mProperty); a.toBinding = newBinding; a.deletableToBinding = true; } list << a; } } return list; } QDeclarativeProperty QmlPropertyChangesObject::metaProperty(const QString &property) { QDeclarativeProperty prop(m_targetObject.data(), property); if (!prop.isValid()) { qWarning() << "Cannot assign to non-existent property" << property; return QDeclarativeProperty(); } else if (!prop.isWritable()) { qWarning() << "Cannot assign to read-only property" << property; return QDeclarativeProperty(); } return prop; } QmlPropertyChangesNodeInstance::QmlPropertyChangesNodeInstance(QmlPropertyChangesObject *propertyChangesObject) : ObjectNodeInstance(propertyChangesObject) { } QmlPropertyChangesNodeInstance::Pointer QmlPropertyChangesNodeInstance::create(const NodeMetaInfo & /*metaInfo*/, QDeclarativeContext *context, QObject *objectToBeWrapped) { Q_ASSERT(!objectToBeWrapped); QmlPropertyChangesObject *object = new QmlPropertyChangesObject; QDeclarativeEngine::setContextForObject(object, context); Pointer instance(new QmlPropertyChangesNodeInstance(object)); return instance; } void QmlPropertyChangesNodeInstance::setPropertyVariant(const QString &name, const QVariant &value) { QMetaObject metaObject = QmlPropertyChangesObject::staticMetaObject; if (metaObject.indexOfProperty(name.toLatin1()) > 0) { // 'restoreEntryValues', 'explicit' ObjectNodeInstance::setPropertyVariant(name, value); return; } else { changesObject()->m_properties.insert(name, value); updateStateInstance(); } } void QmlPropertyChangesNodeInstance::setPropertyBinding(const QString &name, const QString &expression) { QMetaObject metaObject = QmlPropertyChangesObject::staticMetaObject; if (metaObject.indexOfProperty(name.toLatin1()) > 0) { // 'restoreEntryValues', 'explicit' ObjectNodeInstance::setPropertyBinding(name, expression); return; } else { changesObject()->m_expressions.insert(name, expression); updateStateInstance(); } } QVariant QmlPropertyChangesNodeInstance::property(const QString &name) const { if (changesObject()->m_properties.contains(name)) return changesObject()->m_properties.value(name); if (changesObject()->m_expressions.contains(name)) return changesObject()->m_expressions.value(name); return QVariant(); } void QmlPropertyChangesNodeInstance::resetProperty(const QString &name) { if (changesObject()->m_properties.contains(name)) changesObject()->m_properties.remove(name); else if (changesObject()->m_expressions.contains(name)) changesObject()->m_expressions.remove(name); // TODO: How to force states object to update? updateStateInstance(); } QmlPropertyChangesObject *QmlPropertyChangesNodeInstance::changesObject() const { Q_ASSERT(qobject_cast(object())); return static_cast(object()); } void QmlPropertyChangesNodeInstance::updateStateInstance() const { if (!nodeInstanceView()->hasInstanceForNode(modelNode())) return; NodeInstance myInstance = nodeInstanceView()->instanceForNode(modelNode()); Q_ASSERT(myInstance.isValid()); NodeInstance qmlStateInstance = myInstance.parent(); if (!qmlStateInstance.isValid() || !qmlStateInstance.modelNode().isValid()) return; qmlStateInstance.refreshState(); } } // namespace Internal } // namespace QmlDesigner