diff options
Diffstat (limited to 'share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp')
-rw-r--r-- | share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp | 1177 |
1 files changed, 1177 insertions, 0 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp new file mode 100644 index 0000000000..c2ed5183dd --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp @@ -0,0 +1,1177 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ +#include "nodeinstanceserver.h" + +#include <QQmlEngine> +#include <QFileSystemWatcher> +#include <QUrl> +#include <QSet> +#include <QDir> +#include <QVariant> +#include <QMetaType> +#include <QQmlComponent> +#include <QQmlContext> +#include <qqmllist.h> +#include <QAbstractAnimation> +#include <private/qabstractanimation_p.h> +#include <QMutableVectorIterator> +#include <private/qquickview_p.h> + +#include "servernodeinstance.h" +#include "objectnodeinstance.h" +#include "childrenchangeeventfilter.h" +#include "propertyabstractcontainer.h" +#include "propertybindingcontainer.h" +#include "propertyvaluecontainer.h" +#include "instancecontainer.h" +#include "createinstancescommand.h" +#include "changefileurlcommand.h" +#include "clearscenecommand.h" +#include "reparentinstancescommand.h" +#include "changevaluescommand.h" +#include "changeauxiliarycommand.h" +#include "changebindingscommand.h" +#include "changeidscommand.h" +#include "removeinstancescommand.h" +#include "nodeinstanceclientinterface.h" +#include "removepropertiescommand.h" +#include "valueschangedcommand.h" +#include "informationchangedcommand.h" +#include "pixmapchangedcommand.h" +#include "commondefines.h" +#include "childrenchangeeventfilter.h" +#include "changestatecommand.h" +#include "childrenchangedcommand.h" +#include "completecomponentcommand.h" +#include "componentcompletedcommand.h" +#include "createscenecommand.h" +#include "changenodesourcecommand.h" +#include "tokencommand.h" +#include "removesharedmemorycommand.h" + +#include "dummycontextobject.h" + + +namespace QmlDesigner { + +NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) : + NodeInstanceServerInterface(), + m_childrenChangeEventFilter(new Internal::ChildrenChangeEventFilter(this)), + m_nodeInstanceClient(nodeInstanceClient), + m_timer(0), + m_renderTimerInterval(16), + m_slowRenderTimer(false), + m_slowRenderTimerInterval(200) +{ + qmlRegisterType<DummyContextObject>("QmlDesigner", 1, 0, "DummyContextObject"); + + connect(m_childrenChangeEventFilter.data(), SIGNAL(childrenChanged(QObject*)), this, SLOT(emitParentChanged(QObject*))); +} + +NodeInstanceServer::~NodeInstanceServer() +{ +} + +QList<ServerNodeInstance> NodeInstanceServer::createInstances(const QVector<InstanceContainer> &containerVector) +{ + Q_ASSERT(declarativeView() || quickView()); + QList<ServerNodeInstance> instanceList; + foreach (const InstanceContainer &instanceContainer, containerVector) { + ServerNodeInstance instance; + if (instanceContainer.nodeSourceType() == InstanceContainer::ComponentSource) { + instance = ServerNodeInstance::create(this, instanceContainer, ServerNodeInstance::WrapAsComponent); + } else { + instance = ServerNodeInstance::create(this, instanceContainer, ServerNodeInstance::DoNotWrapAsComponent); + } + insertInstanceRelationship(instance); + instanceList.append(instance); + instance.internalObject()->installEventFilter(childrenChangeEventFilter()); + if (instanceContainer.instanceId() == 0) { + m_rootNodeInstance = instance; + resizeCanvasSizeToRootItemSize(); + } + + foreach (QQmlContext* context, allSubContextsForObject(instance.internalObject())) + setupDummysForContext(context); + } + + return instanceList; +} + +void NodeInstanceServer::createInstances(const CreateInstancesCommand &command) +{ + createInstances(command.instances()); + refreshBindings(); + startRenderTimer(); +} + +ServerNodeInstance NodeInstanceServer::instanceForId(qint32 id) const +{ + if (id < 0) + return ServerNodeInstance(); + + Q_ASSERT(m_idInstanceHash.contains(id)); + return m_idInstanceHash.value(id); +} + +bool NodeInstanceServer::hasInstanceForId(qint32 id) const +{ + if (id < 0) + return false; + + return m_idInstanceHash.contains(id); +} + +ServerNodeInstance NodeInstanceServer::instanceForObject(QObject *object) const +{ + Q_ASSERT(m_objectInstanceHash.contains(object)); + return m_objectInstanceHash.value(object); +} + +bool NodeInstanceServer::hasInstanceForObject(QObject *object) const +{ + if (object == 0) + return false; + + return m_objectInstanceHash.contains(object); +} + +void NodeInstanceServer::setRenderTimerInterval(int timerInterval) +{ + m_renderTimerInterval = timerInterval; +} + +void NodeInstanceServer::setSlowRenderTimerInterval(int timerInterval) +{ + m_slowRenderTimerInterval = timerInterval; +} + +void NodeInstanceServer::setTimerId(int timerId) +{ + m_timer = timerId; +} + +int NodeInstanceServer::timerId() const +{ + return m_timer; +} + +int NodeInstanceServer::renderTimerInterval() const +{ + return m_renderTimerInterval; +} + +void NodeInstanceServer::startRenderTimer() +{ + if (m_slowRenderTimer) + stopRenderTimer(); + + if (m_timer == 0) + m_timer = startTimer(m_renderTimerInterval); + + m_slowRenderTimer = false; +} + +void NodeInstanceServer::slowDownRenderTimer() +{ + if (!m_slowRenderTimer) + stopRenderTimer(); + + if (m_timer != 0) { + killTimer(m_timer); + m_timer = 0; + } + + if (m_timer == 0) + m_timer = startTimer(m_slowRenderTimerInterval); + + m_slowRenderTimer = true; +} + +void NodeInstanceServer::stopRenderTimer() +{ + if (m_timer) { + killTimer(m_timer); + m_timer = 0; + } +} + +void NodeInstanceServer::createScene(const CreateSceneCommand &command) +{ + initializeView(command.imports()); + QUnifiedTimer::instance()->setSlowdownFactor(0.00001); + QUnifiedTimer::instance()->setSlowModeEnabled(true); + + QList<ServerNodeInstance> instanceList = setupScene(command); + + refreshBindings(); + + startRenderTimer(); +} + +void NodeInstanceServer::clearScene(const ClearSceneCommand &/*command*/) +{ + stopRenderTimer(); + + removeAllInstanceRelationships(); + m_fileSystemWatcherHash.clear(); + m_rootNodeInstance.makeInvalid(); + m_changedPropertyList.clear(); + m_fileUrl.clear(); +} + +void NodeInstanceServer::removeInstances(const RemoveInstancesCommand &command) +{ + ServerNodeInstance oldState = activeStateInstance(); + if (activeStateInstance().isValid()) + activeStateInstance().deactivateState(); + + foreach (qint32 instanceId, command.instanceIds()) { + removeInstanceRelationsip(instanceId); + } + + if (oldState.isValid()) + oldState.activateState(); + + refreshBindings(); + startRenderTimer(); +} + +void NodeInstanceServer::removeProperties(const RemovePropertiesCommand &command) +{ + bool hasDynamicProperties = false; + foreach (const PropertyAbstractContainer &container, command.properties()) { + hasDynamicProperties |= container.isDynamic(); + resetInstanceProperty(container); + } + + if (hasDynamicProperties) + refreshBindings(); + + startRenderTimer(); +} + +void NodeInstanceServer::reparentInstances(const QVector<ReparentContainer> &containerVector) +{ + foreach (const ReparentContainer &container, containerVector) { + ServerNodeInstance instance = instanceForId(container.instanceId()); + if (instance.isValid()) { + instance.reparent(instanceForId(container.oldParentInstanceId()), container.oldParentProperty(), instanceForId(container.newParentInstanceId()), container.newParentProperty()); + } + } + +} + +void NodeInstanceServer::reparentInstances(const ReparentInstancesCommand &command) +{ + reparentInstances(command.reparentInstances()); + refreshBindings(); + startRenderTimer(); +} + +void NodeInstanceServer::changeState(const ChangeStateCommand &command) +{ + if (hasInstanceForId(command.stateInstanceId())) { + if (activeStateInstance().isValid()) + activeStateInstance().deactivateState(); + ServerNodeInstance instance = instanceForId(command.stateInstanceId()); + instance.activateState(); + } else { + if (activeStateInstance().isValid()) + activeStateInstance().deactivateState(); + } + + startRenderTimer(); +} + +void NodeInstanceServer::completeComponent(const CompleteComponentCommand &command) +{ + QList<ServerNodeInstance> instanceList; + + foreach (qint32 instanceId, command.instances()) { + if (hasInstanceForId(instanceId)) { + ServerNodeInstance instance = instanceForId(instanceId); + instance.doComponentComplete(); + instanceList.append(instance); + } + } + + refreshBindings(); + + startRenderTimer(); +} + +void NodeInstanceServer::changeNodeSource(const ChangeNodeSourceCommand &command) +{ + if (hasInstanceForId(command.instanceId())) { + ServerNodeInstance instance = instanceForId(command.instanceId()); + if (instance.isValid()) + instance.setNodeSource(command.nodeSource()); + } + + startRenderTimer(); +} + +void NodeInstanceServer::token(const TokenCommand &/*command*/) +{ + +} + +void NodeInstanceServer::removeSharedMemory(const RemoveSharedMemoryCommand &/*command*/) +{ +} + +void NodeInstanceServer::setupImports(const QVector<AddImportContainer> &containerVector) +{ + foreach (const AddImportContainer &container, containerVector) { + QString importStatement = QString("import "); + + if (!container.fileName().isEmpty()) + importStatement += '"' + container.fileName() + '"'; + else if (!container.url().isEmpty()) + importStatement += container.url().toString(); + + if (!container.version().isEmpty()) + importStatement += ' ' + container.version(); + + if (!container.alias().isEmpty()) + importStatement += " as " + container.alias(); + + importStatement.append('\n'); + + if (!m_importList.contains(importStatement)) + m_importList.append(importStatement); + } + + delete m_importComponent.data(); + delete m_importComponentObject.data(); + + QString componentString; + foreach (const QString &importStatement, m_importList) + componentString += QString("%1").arg(importStatement); + + componentString += QString("Item {}\n"); + + if (quickView()) { + QQuickViewPrivate::get(quickView())->component = new QQmlComponent(engine(), quickView()); + m_importComponent = QQuickViewPrivate::get(quickView())->component; + } else { + m_importComponent = new QQmlComponent(engine(), 0); + } + + m_importComponent->setData(componentString.toUtf8(), fileUrl()); + m_importComponentObject = m_importComponent->create(); + + if (!m_importComponent->errorString().isEmpty()) + qDebug() << "QmlDesigner.NodeInstances: import wrong: " << m_importComponent->errorString(); +} + +void NodeInstanceServer::setupFileUrl(const QUrl &fileUrl) +{ + if (!fileUrl.isEmpty()) { + engine()->setBaseUrl(fileUrl); + m_fileUrl = fileUrl; + } +} + +void NodeInstanceServer::setupDummyData(const QUrl &fileUrl) +{ + if (!fileUrl.isEmpty()) { + QStringList dummyDataDirectoryList = dummyDataDirectories(QFileInfo(fileUrl.toLocalFile()).path()); + foreach (const QString &dummyDataDirectory, dummyDataDirectoryList) { + loadDummyDataFiles(dummyDataDirectory); + loadDummyDataContext(dummyDataDirectory); + } + } + + if (m_dummyContextObject.isNull()) + setupDefaultDummyData(); +} + +void NodeInstanceServer::setupDefaultDummyData() +{ + QQmlComponent component(engine()); + QByteArray defaultContextObjectArray("import QtQuick 1.0\n" + "import QmlDesigner 1.0\n" + "DummyContextObject {\n" + " parent: QtObject {\n" + " property real width: 360\n" + " property real height: 640\n" + " }\n" + "}\n"); + + component.setData(defaultContextObjectArray, fileUrl()); + m_dummyContextObject = component.create(); + + if (component.isError()) { + QList<QQmlError> errors = component.errors(); + foreach (const QQmlError &error, errors) { + qWarning() << error; + } + } + + if (m_dummyContextObject) { + qWarning() << "Loaded default dummy context object."; + m_dummyContextObject->setParent(this); + } + + refreshBindings(); +} + +QList<ServerNodeInstance> NodeInstanceServer::setupInstances(const CreateSceneCommand &command) +{ + QList<ServerNodeInstance> instanceList = createInstances(command.instances()); + + foreach (const IdContainer &container, command.ids()) { + if (hasInstanceForId(container.instanceId())) + instanceForId(container.instanceId()).setId(container.id()); + } + + foreach (const PropertyValueContainer &container, command.valueChanges()) { + if (container.isDynamic()) + setInstancePropertyVariant(container); + } + + foreach (const PropertyValueContainer &container, command.valueChanges()) { + if (!container.isDynamic()) + setInstancePropertyVariant(container); + } + + reparentInstances(command.reparentInstances()); + + foreach (const PropertyBindingContainer &container, command.bindingChanges()) { + if (container.isDynamic()) + setInstancePropertyBinding(container); + } + + foreach (const PropertyBindingContainer &container, command.bindingChanges()) { + if (!container.isDynamic()) + setInstancePropertyBinding(container); + } + + foreach (const PropertyValueContainer &container, command.auxiliaryChanges()) { + setInstanceAuxiliaryData(container); + } + + foreach (ServerNodeInstance instance, instanceList) + instance.doComponentComplete(); + + return instanceList; +} + +void NodeInstanceServer::changeFileUrl(const ChangeFileUrlCommand &command) +{ + m_fileUrl = command.fileUrl(); + + if (engine()) + engine()->setBaseUrl(m_fileUrl); + + refreshBindings(); + startRenderTimer(); +} + +void NodeInstanceServer::changePropertyValues(const ChangeValuesCommand &command) +{ + bool hasDynamicProperties = false; + foreach (const PropertyValueContainer &container, command.valueChanges()) { + hasDynamicProperties |= container.isDynamic(); + setInstancePropertyVariant(container); + } + + if (hasDynamicProperties) + refreshBindings(); + + startRenderTimer(); +} + +void NodeInstanceServer::changeAuxiliaryValues(const ChangeAuxiliaryCommand &command) +{ + foreach (const PropertyValueContainer &container, command.auxiliaryChanges()) { + setInstanceAuxiliaryData(container); + } + + startRenderTimer(); +} + +void NodeInstanceServer::changePropertyBindings(const ChangeBindingsCommand &command) +{ + bool hasDynamicProperties = false; + foreach (const PropertyBindingContainer &container, command.bindingChanges()) { + hasDynamicProperties |= container.isDynamic(); + setInstancePropertyBinding(container); + } + + if (hasDynamicProperties) + refreshBindings(); + + startRenderTimer(); +} + +void NodeInstanceServer::changeIds(const ChangeIdsCommand &command) +{ + foreach (const IdContainer &container, command.ids()) { + if (hasInstanceForId(container.instanceId())) + instanceForId(container.instanceId()).setId(container.id()); + } + + refreshBindings(); + startRenderTimer(); +} + +QQmlContext *NodeInstanceServer::context() const +{ + if (m_importComponentObject) { + QQmlContext *importComponentContext = QQmlEngine::contextForObject(m_importComponentObject.data()); + if (importComponentContext) // this should be the default + return importComponentContext; + } + + if (engine()) + return rootContext(); + + return 0; +} + +QQmlContext *NodeInstanceServer::rootContext() const +{ + return engine()->rootContext(); +} + +const QVector<NodeInstanceServer::InstancePropertyPair> NodeInstanceServer::changedPropertyList() const +{ + return m_changedPropertyList; +} + +void NodeInstanceServer::clearChangedPropertyList() +{ + m_changedPropertyList.clear(); +} + +void NodeInstanceServer::setupDummysForContext(QQmlContext *context) +{ + foreach (const DummyPair& dummyPair, m_dummyObjectList) { + if (dummyPair.second) { + context->setContextProperty(dummyPair.first, dummyPair.second.data()); + } + } +} + + +QList<QQmlContext*> NodeInstanceServer::allSubContextsForObject(QObject *object) +{ + QList<QQmlContext*> contextList; + + if (object) { + foreach (QObject *subObject, allSubObjectsForObject(object)) { + QQmlContext *contextOfObject = QQmlEngine::contextForObject(subObject); + if (contextOfObject) { + if (contextOfObject != context() && !contextList.contains(contextOfObject)) + contextList.append(contextOfObject); + } + } + } + + return contextList; +} + +QList<QObject*> NodeInstanceServer::allSubObjectsForObject(QObject *object) +{ + QList<QObject*> subChildren; + if (object) { + subChildren = object->findChildren<QObject*>(); + } + + return subChildren; +} + +void NodeInstanceServer::removeAllInstanceRelationships() +{ + // prevent destroyed() signals calling back + + foreach (ServerNodeInstance instance, m_objectInstanceHash) { + if (instance.isValid()) + instance.setId(QString()); + } + + //first the root object + if (rootNodeInstance().internalObject()) + rootNodeInstance().internalObject()->disconnect(); + + rootNodeInstance().makeInvalid(); + + + foreach (ServerNodeInstance instance, m_objectInstanceHash) { + if (instance.internalObject()) + instance.internalObject()->disconnect(); + instance.makeInvalid(); + } + + m_idInstanceHash.clear(); + m_objectInstanceHash.clear(); +} + +QFileSystemWatcher *NodeInstanceServer::dummydataFileSystemWatcher() +{ + if (m_dummdataFileSystemWatcher.isNull()) { + m_dummdataFileSystemWatcher = new QFileSystemWatcher(this); + connect(m_dummdataFileSystemWatcher.data(), SIGNAL(fileChanged(QString)), this, SLOT(refreshDummyData(QString))); + } + + return m_dummdataFileSystemWatcher.data(); +} + +QFileSystemWatcher *NodeInstanceServer::fileSystemWatcher() +{ + if (m_fileSystemWatcher.isNull()) { + m_fileSystemWatcher = new QFileSystemWatcher(this); + connect(m_fileSystemWatcher.data(), SIGNAL(fileChanged(QString)), this, SLOT(refreshLocalFileProperty(QString))); + } + + return m_fileSystemWatcher.data(); +} + +Internal::ChildrenChangeEventFilter *NodeInstanceServer::childrenChangeEventFilter() const +{ + return m_childrenChangeEventFilter.data(); +} + +void NodeInstanceServer::addFilePropertyToFileSystemWatcher(QObject *object, const QString &propertyName, const QString &path) +{ + if (!m_fileSystemWatcherHash.contains(path)) { + m_fileSystemWatcherHash.insert(path, ObjectPropertyPair(object, propertyName)); + fileSystemWatcher()->addPath(path); + } +} + +void NodeInstanceServer::removeFilePropertyFromFileSystemWatcher(QObject *object, const QString &propertyName, const QString &path) +{ + if (m_fileSystemWatcherHash.contains(path)) { + fileSystemWatcher()->removePath(path); + m_fileSystemWatcherHash.remove(path, ObjectPropertyPair(object, propertyName)); + } +} + +void NodeInstanceServer::refreshLocalFileProperty(const QString &path) +{ + if (m_fileSystemWatcherHash.contains(path)) { + foreach (const ObjectPropertyPair &objectPropertyPair, m_fileSystemWatcherHash) { + QObject *object = objectPropertyPair.first.data(); + QString propertyName = objectPropertyPair.second; + + if (hasInstanceForObject(object)) { + instanceForObject(object).refreshProperty(propertyName); + } + } + } +} + +void NodeInstanceServer::refreshDummyData(const QString &path) +{ + engine()->clearComponentCache(); + QFileInfo filePath(path); + if (filePath.completeBaseName().contains("_dummycontext")) { + loadDummyContextObjectFile(filePath); + } else { + loadDummyDataFile(filePath); + } + + refreshBindings(); + startRenderTimer(); +} + +void NodeInstanceServer::addChangedProperty(const InstancePropertyPair &property) +{ + if (!m_changedPropertyList.contains(property)) + m_changedPropertyList.append(property); +} + +void NodeInstanceServer::emitParentChanged(QObject *child) +{ + if (hasInstanceForObject(child)) { + addChangedProperty(InstancePropertyPair(instanceForObject(child), "parent")); + } +} + +Internal::ChildrenChangeEventFilter *NodeInstanceServer::childrenChangeEventFilter() +{ + if (m_childrenChangeEventFilter.isNull()) { + m_childrenChangeEventFilter = new Internal::ChildrenChangeEventFilter(this); + connect(m_childrenChangeEventFilter.data(), SIGNAL(childrenChanged(QObject*)), this, SLOT(emitParentChanged(QObject*))); + } + + return m_childrenChangeEventFilter.data(); +} + +void NodeInstanceServer::resetInstanceProperty(const PropertyAbstractContainer &propertyContainer) +{ + if (hasInstanceForId(propertyContainer.instanceId())) { // TODO ugly workaround + ServerNodeInstance instance = instanceForId(propertyContainer.instanceId()); + Q_ASSERT(instance.isValid()); + + const QString name = propertyContainer.name(); + + if (activeStateInstance().isValid() && !instance.isSubclassOf("QtQuick/PropertyChanges")) { + bool statePropertyWasReseted = activeStateInstance().resetStateProperty(instance, name, instance.resetVariant(name)); + if (!statePropertyWasReseted) + instance.resetProperty(name); + } else { + instance.resetProperty(name); + } + + if (propertyContainer.isDynamic() && propertyContainer.instanceId() == 0 && engine()) + rootContext()->setContextProperty(name, QVariant()); + } +} + + +void NodeInstanceServer::setInstancePropertyBinding(const PropertyBindingContainer &bindingContainer) +{ + if (hasInstanceForId(bindingContainer.instanceId())) { + ServerNodeInstance instance = instanceForId(bindingContainer.instanceId()); + + const QString name = bindingContainer.name(); + const QString expression = bindingContainer.expression(); + + + if (activeStateInstance().isValid() && !instance.isSubclassOf("QtQuick/PropertyChanges")) { + bool stateBindingWasUpdated = activeStateInstance().updateStateBinding(instance, name, expression); + if (!stateBindingWasUpdated) { + if (bindingContainer.isDynamic()) + instance.setPropertyDynamicBinding(name, bindingContainer.dynamicTypeName(), expression); + else + instance.setPropertyBinding(name, expression); + } + } else { + if (bindingContainer.isDynamic()) + instance.setPropertyDynamicBinding(name, bindingContainer.dynamicTypeName(), expression); + else + instance.setPropertyBinding(name, expression); + } + } +} + + +void NodeInstanceServer::removeProperties(const QList<PropertyAbstractContainer> &propertyList) +{ + foreach (const PropertyAbstractContainer &property, propertyList) + resetInstanceProperty(property); +} + +void NodeInstanceServer::setInstancePropertyVariant(const PropertyValueContainer &valueContainer) +{ + if (hasInstanceForId(valueContainer.instanceId())) { + ServerNodeInstance instance = instanceForId(valueContainer.instanceId()); + + + const QString name = valueContainer.name(); + const QVariant value = valueContainer.value(); + + + if (activeStateInstance().isValid() && !instance.isSubclassOf("QtQuick/PropertyChanges")) { + bool stateValueWasUpdated = activeStateInstance().updateStateVariant(instance, name, value); + if (!stateValueWasUpdated) { + if (valueContainer.isDynamic()) + instance.setPropertyDynamicVariant(name, valueContainer.dynamicTypeName(), value); + else + instance.setPropertyVariant(name, value); + } + } else { //base state + if (valueContainer.isDynamic()) + instance.setPropertyDynamicVariant(name, valueContainer.dynamicTypeName(), value); + else + instance.setPropertyVariant(name, value); + } + + if (valueContainer.isDynamic() && valueContainer.instanceId() == 0 && engine()) + rootContext()->setContextProperty(name, Internal::ObjectNodeInstance::fixResourcePaths(value)); + } +} + +void NodeInstanceServer::setInstanceAuxiliaryData(const PropertyValueContainer &auxiliaryContainer) +{ + //instanceId() == 0: the item is root + if (auxiliaryContainer.instanceId() == 0 && (auxiliaryContainer.name() == QLatin1String("width") || + auxiliaryContainer.name() == QLatin1String("height"))) { + + if (!auxiliaryContainer.value().isNull()) { + setInstancePropertyVariant(auxiliaryContainer); + } else { + rootNodeInstance().resetProperty(auxiliaryContainer.name()); + } + } + if (auxiliaryContainer.name().endsWith(QLatin1String("@NodeInstance"))) { + QString propertyName = auxiliaryContainer.name().leftRef(auxiliaryContainer.name().count() - 12).toString(); + if (!auxiliaryContainer.value().isNull()) { + setInstancePropertyVariant(PropertyValueContainer(auxiliaryContainer.instanceId(), + propertyName, + auxiliaryContainer.value(), + auxiliaryContainer.dynamicTypeName())); + } else { + rootNodeInstance().resetProperty(propertyName); + } + } +} + + +QUrl NodeInstanceServer::fileUrl() const +{ + return m_fileUrl; +} + +ServerNodeInstance NodeInstanceServer::activeStateInstance() const +{ + return m_activeStateInstance; +} + +ServerNodeInstance NodeInstanceServer::rootNodeInstance() const +{ + return m_rootNodeInstance; +} + +void NodeInstanceServer::setStateInstance(const ServerNodeInstance &stateInstance) +{ + m_activeStateInstance = stateInstance; +} + +void NodeInstanceServer::clearStateInstance() +{ + m_activeStateInstance = ServerNodeInstance(); +} + +void NodeInstanceServer::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == m_timer) { + collectItemChangesAndSendChangeCommands(); + } + + NodeInstanceServerInterface::timerEvent(event); +} + +NodeInstanceClientInterface *NodeInstanceServer::nodeInstanceClient() const +{ + return m_nodeInstanceClient; +} + +static QVector<InformationContainer> createInformationVector(const QList<ServerNodeInstance> &instanceList, bool initial) +{ + QVector<InformationContainer> informationVector; + + foreach (const ServerNodeInstance &instance, instanceList) { + informationVector.append(InformationContainer(instance.instanceId(), Position, instance.position())); + informationVector.append(InformationContainer(instance.instanceId(), Transform, instance.transform())); + informationVector.append(InformationContainer(instance.instanceId(), SceneTransform, instance.sceneTransform())); + informationVector.append(InformationContainer(instance.instanceId(), Size, instance.size())); + informationVector.append(InformationContainer(instance.instanceId(), BoundingRect, instance.boundingRect())); + informationVector.append(InformationContainer(instance.instanceId(), Transform, instance.transform())); + informationVector.append(InformationContainer(instance.instanceId(), HasContent, instance.hasContent())); + informationVector.append(InformationContainer(instance.instanceId(), IsMovable, instance.isMovable())); + informationVector.append(InformationContainer(instance.instanceId(), IsResizable, instance.isResizable())); + informationVector.append(InformationContainer(instance.instanceId(), IsInPositioner, instance.isInPositioner())); + informationVector.append(InformationContainer(instance.instanceId(), PenWidth, instance.penWidth())); + informationVector.append(InformationContainer(instance.instanceId(), IsAnchoredByChildren, instance.isAnchoredByChildren())); + informationVector.append(InformationContainer(instance.instanceId(), IsAnchoredBySibling, instance.isAnchoredBySibling())); + + informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.fill"), instance.hasAnchor("anchors.fill"))); + informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.centerIn"), instance.hasAnchor("anchors.centerIn"))); + informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.right"), instance.hasAnchor("anchors.right"))); + informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.top"), instance.hasAnchor("anchors.top"))); + informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.left"), instance.hasAnchor("anchors.left"))); + informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.bottom"), instance.hasAnchor("anchors.bottom"))); + informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.horizontalCenter"), instance.hasAnchor("anchors.horizontalCenter"))); + informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.verticalCenter"), instance.hasAnchor("anchors.verticalCenter"))); + informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.baseline"), instance.hasAnchor("anchors.baseline"))); + + QPair<QString, ServerNodeInstance> anchorPair = instance.anchor("anchors.fill"); + informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.fill"), anchorPair.first, anchorPair.second.instanceId())); + + anchorPair = instance.anchor("anchors.centerIn"); + informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.centerIn"), anchorPair.first, anchorPair.second.instanceId())); + + anchorPair = instance.anchor("anchors.right"); + informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.right"), anchorPair.first, anchorPair.second.instanceId())); + + anchorPair = instance.anchor("anchors.top"); + informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.top"), anchorPair.first, anchorPair.second.instanceId())); + + anchorPair = instance.anchor("anchors.left"); + informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.left"), anchorPair.first, anchorPair.second.instanceId())); + + anchorPair = instance.anchor("anchors.bottom"); + informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.bottom"), anchorPair.first, anchorPair.second.instanceId())); + + anchorPair = instance.anchor("anchors.horizontalCenter"); + informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.horizontalCenter"), anchorPair.first, anchorPair.second.instanceId())); + + anchorPair = instance.anchor("anchors.verticalCenter"); + informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.verticalCenter"), anchorPair.first, anchorPair.second.instanceId())); + + anchorPair = instance.anchor("anchors.baseline"); + informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.baseline"), anchorPair.first, anchorPair.second.instanceId())); + + QStringList propertyNames = instance.propertyNames(); + + if (initial) { + foreach (const QString &propertyName,propertyNames) + informationVector.append(InformationContainer(instance.instanceId(), InstanceTypeForProperty, propertyName, instance.instanceType(propertyName))); + } + + foreach (const QString &propertyName,instance.propertyNames()) { + bool hasChanged = false; + bool hasBinding = instance.hasBindingForProperty(propertyName, &hasChanged); + if (hasChanged) + informationVector.append(InformationContainer(instance.instanceId(), HasBindingForProperty, propertyName, hasBinding)); + } + + } + + return informationVector; +} + + +ChildrenChangedCommand NodeInstanceServer::createChildrenChangedCommand(const ServerNodeInstance &parentInstance, const QList<ServerNodeInstance> &instanceList) const +{ + QVector<qint32> instanceVector; + + foreach (const ServerNodeInstance &instance, instanceList) + instanceVector.append(instance.instanceId()); + + return ChildrenChangedCommand(parentInstance.instanceId(), instanceVector, createInformationVector(instanceList, false)); +} + +InformationChangedCommand NodeInstanceServer::createAllInformationChangedCommand(const QList<ServerNodeInstance> &instanceList, bool initial) const +{ + return InformationChangedCommand(createInformationVector(instanceList, initial)); +} + +static bool supportedVariantType(int type) +{ + return type < int(QVariant::UserType) && type != QMetaType::QObjectStar; +} + +ValuesChangedCommand NodeInstanceServer::createValuesChangedCommand(const QList<ServerNodeInstance> &instanceList) const +{ + QVector<PropertyValueContainer> valueVector; + + foreach (const ServerNodeInstance &instance, instanceList) { + foreach (const QString &propertyName, instance.propertyNames()) { + QVariant propertyValue = instance.property(propertyName); + if (supportedVariantType(propertyValue.userType())) + valueVector.append(PropertyValueContainer(instance.instanceId(), propertyName, propertyValue, QString())); + } + } + + return ValuesChangedCommand(valueVector); +} + +ComponentCompletedCommand NodeInstanceServer::createComponentCompletedCommand(const QList<ServerNodeInstance> &instanceList) +{ + QVector<qint32> idVector; + foreach (const ServerNodeInstance &instance, instanceList) { + if (instance.instanceId() >= 0) + idVector.append(instance.instanceId()); + } + + return ComponentCompletedCommand(idVector); +} + +ValuesChangedCommand NodeInstanceServer::createValuesChangedCommand(const QVector<InstancePropertyPair> &propertyList) const +{ + QVector<PropertyValueContainer> valueVector; + + foreach (const InstancePropertyPair &property, propertyList) { + const QString propertyName = property.second; + const ServerNodeInstance instance = property.first; + + if (instance.isValid()) { + QVariant propertyValue = instance.property(propertyName); + if (QMetaType::isRegistered(propertyValue.userType()) && supportedVariantType(propertyValue.type())) { + valueVector.append(PropertyValueContainer(instance.instanceId(), propertyName, propertyValue, QString())); + } + } + } + + return ValuesChangedCommand(valueVector); +} + +QStringList NodeInstanceServer::imports() const +{ + return m_importList; +} + +void NodeInstanceServer::addImportString(const QString &import) +{ + m_importList.append(import); +} + +QObject *NodeInstanceServer::dummyContextObject() const +{ + return m_dummyContextObject.data(); +} + +void NodeInstanceServer::notifyPropertyChange(qint32 instanceid, const QString &propertyName) +{ + if (hasInstanceForId(instanceid)) + addChangedProperty(InstancePropertyPair(instanceForId(instanceid), propertyName)); +} + +void NodeInstanceServer::insertInstanceRelationship(const ServerNodeInstance &instance) +{ + Q_ASSERT(instance.isValid()); + Q_ASSERT(!m_idInstanceHash.contains(instance.instanceId())); + Q_ASSERT(!m_objectInstanceHash.contains(instance.internalObject())); + m_objectInstanceHash.insert(instance.internalObject(), instance); + m_idInstanceHash.insert(instance.instanceId(), instance); +} + +void NodeInstanceServer::removeInstanceRelationsip(qint32 instanceId) +{ + if (hasInstanceForId(instanceId)) { + ServerNodeInstance instance = instanceForId(instanceId); + if (instance.isValid()) + instance.setId(QString()); + m_idInstanceHash.remove(instanceId); + m_objectInstanceHash.remove(instance.internalObject()); + instance.makeInvalid(); + } +} + +PixmapChangedCommand NodeInstanceServer::createPixmapChangedCommand(const QList<ServerNodeInstance> &instanceList) const +{ + QVector<ImageContainer> imageVector; + + foreach (const ServerNodeInstance &instance, instanceList) { + if (instance.isValid() && instance.hasContent()) + imageVector.append(ImageContainer(instance.instanceId(), instance.renderImage(), instance.instanceId())); + } + + return PixmapChangedCommand(imageVector); +} + +void NodeInstanceServer::loadDummyDataFile(const QFileInfo& qmlFileInfo) +{ + QQmlComponent component(engine(), qmlFileInfo.filePath()); + QObject *dummyData = component.create(); + if (component.isError()) { + QList<QQmlError> errors = component.errors(); + foreach (const QQmlError &error, errors) { + qWarning() << error; + } + } + + QVariant oldDummyDataObject = rootContext()->contextProperty(qmlFileInfo.completeBaseName()); + + if (dummyData) { + qWarning() << "Loaded dummy data:" << qmlFileInfo.filePath(); + rootContext()->setContextProperty(qmlFileInfo.completeBaseName(), dummyData); + dummyData->setParent(this); + m_dummyObjectList.append(DummyPair(qmlFileInfo.completeBaseName(), dummyData)); + } + + if (!oldDummyDataObject.isNull()) + delete oldDummyDataObject.value<QObject*>(); + + if (!dummydataFileSystemWatcher()->files().contains(qmlFileInfo.filePath())) + dummydataFileSystemWatcher()->addPath(qmlFileInfo.filePath()); + + if (rootNodeInstance().isValid() && rootNodeInstance().internalObject()) { + foreach (QQmlContext *context, allSubContextsForObject(rootNodeInstance().internalObject())) + setupDummysForContext(context); + } +} + +void NodeInstanceServer::loadDummyContextObjectFile(const QFileInfo& qmlFileInfo) +{ + delete m_dummyContextObject.data(); + + QQmlComponent component(engine(), qmlFileInfo.filePath()); + m_dummyContextObject = component.create(); + + if (component.isError()) { + QList<QQmlError> errors = component.errors(); + foreach (const QQmlError &error, errors) { + qWarning() << error; + } + } + + if (m_dummyContextObject) { + qWarning() << "Loaded dummy context object:" << qmlFileInfo.filePath(); + m_dummyContextObject->setParent(this); + } + + if (!dummydataFileSystemWatcher()->files().contains(qmlFileInfo.filePath())) + dummydataFileSystemWatcher()->addPath(qmlFileInfo.filePath()); + + refreshBindings(); +} + +void NodeInstanceServer::loadDummyDataFiles(const QString& directory) +{ + QDir dir(directory, "*.qml"); + QList<QFileInfo> filePathList = dir.entryInfoList(); + foreach (const QFileInfo &qmlFileInfo, filePathList) { + loadDummyDataFile(qmlFileInfo); + } +} + +void NodeInstanceServer::loadDummyDataContext(const QString& directory) +{ + QDir dir(directory+"/context", "*.qml"); + QList<QFileInfo> filePathList = dir.entryInfoList(); + QString baseName = QFileInfo(fileUrl().toLocalFile()).completeBaseName(); + foreach (const QFileInfo &qmlFileInfo, filePathList) { + if (qmlFileInfo.completeBaseName() == baseName) + loadDummyContextObjectFile(qmlFileInfo); + } +} + +void NodeInstanceServer::sendDebugOutput(DebugOutputCommand::Type type, const QString &message) +{ + DebugOutputCommand command(message, type); + nodeInstanceClient()->debugOutput(command); +} + +QStringList NodeInstanceServer::dummyDataDirectories(const QString& directoryPath) +{ + QStringList dummyDataDirectoryList; + QDir directory(directoryPath); + while (true) { + if (directory.isRoot() || !directory.exists()) + return dummyDataDirectoryList; + + if (directory.exists("dummydata")) + dummyDataDirectoryList.prepend(directory.absoluteFilePath("dummydata")); + + directory.cdUp(); + } +} + +} + + + |