1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
33 #include "nodeinstanceserver.h"
35 #include <QGraphicsItem>
36 #include <private/qgraphicsitem_p.h>
37 #include <private/qgraphicsscene_p.h>
38 #include <QDeclarativeEngine>
39 #include <QDeclarativeView>
40 #include <QFileSystemWatcher>
46 #include <QDeclarativeComponent>
47 #include <QDeclarativeContext>
48 #include <private/qlistmodelinterface_p.h>
49 #include <QAbstractAnimation>
50 #include <private/qabstractanimation_p.h>
52 #include "servernodeinstance.h"
53 #include "childrenchangeeventfilter.h"
54 #include "propertyabstractcontainer.h"
55 #include "propertybindingcontainer.h"
56 #include "propertyvaluecontainer.h"
57 #include "instancecontainer.h"
58 #include "createinstancescommand.h"
59 #include "changefileurlcommand.h"
60 #include "clearscenecommand.h"
61 #include "reparentinstancescommand.h"
62 #include "changevaluescommand.h"
63 #include "changebindingscommand.h"
64 #include "changeidscommand.h"
65 #include "removeinstancescommand.h"
66 #include "nodeinstanceclientinterface.h"
67 #include "removepropertiescommand.h"
68 #include "valueschangedcommand.h"
69 #include "informationchangedcommand.h"
70 #include "pixmapchangedcommand.h"
71 #include "commondefines.h"
72 #include "childrenchangeeventfilter.h"
73 #include "changestatecommand.h"
74 #include "addimportcommand.h"
75 #include "childrenchangedcommand.h"
76 #include "completecomponentcommand.h"
77 #include "componentcompletedcommand.h"
78 #include "createscenecommand.h"
80 #include "dummycontextobject.h"
86 namespace QmlDesigner {
88 NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) :
89 NodeInstanceServerInterface(),
90 m_childrenChangeEventFilter(new Internal::ChildrenChangeEventFilter(this)),
91 m_nodeInstanceClient(nodeInstanceClient),
93 m_renderTimerInterval(16),
94 m_slowRenderTimer(false),
95 m_slowRenderTimerInterval(200)
97 qmlRegisterType<DummyContextObject>("QmlDesigner", 1, 0, "DummyContextObject");
99 m_importList.append("import Qt 4.7\n");
100 connect(m_childrenChangeEventFilter.data(), SIGNAL(childrenChanged(QObject*)), this, SLOT(emitParentChanged(QObject*)));
103 NodeInstanceServer::~NodeInstanceServer()
105 delete m_declarativeView.data();
108 QList<ServerNodeInstance> NodeInstanceServer::createInstances(const QVector<InstanceContainer> &containerVector)
110 Q_ASSERT(m_declarativeView);
111 QList<ServerNodeInstance> instanceList;
112 foreach(const InstanceContainer &instanceContainer, containerVector) {
113 ServerNodeInstance instance = ServerNodeInstance::create(this, instanceContainer);
114 insertInstanceRelationship(instance);
115 instanceList.append(instance);
116 instance.internalObject()->installEventFilter(childrenChangeEventFilter());
117 if (instanceContainer.instanceId() == 0) {
118 m_rootNodeInstance = instance;
119 QGraphicsObject *rootGraphicsObject = qobject_cast<QGraphicsObject*>(instance.internalObject());
120 if (rootGraphicsObject) {
121 m_declarativeView->scene()->addItem(rootGraphicsObject);
122 m_declarativeView->setSceneRect(rootGraphicsObject->boundingRect());
127 foreach (QDeclarativeContext* context, allSubContextsForObject(instance.internalObject()))
128 setupDummysForContext(context);
134 void NodeInstanceServer::createInstances(const CreateInstancesCommand &command)
136 createInstances(command.instances());
141 ServerNodeInstance NodeInstanceServer::instanceForId(qint32 id) const
144 return ServerNodeInstance();
146 Q_ASSERT(m_idInstanceHash.contains(id));
147 return m_idInstanceHash.value(id);
150 bool NodeInstanceServer::hasInstanceForId(qint32 id) const
155 return m_idInstanceHash.contains(id);
158 ServerNodeInstance NodeInstanceServer::instanceForObject(QObject *object) const
160 Q_ASSERT(m_objectInstanceHash.contains(object));
161 return m_objectInstanceHash.value(object);
164 bool NodeInstanceServer::hasInstanceForObject(QObject *object) const
169 return m_objectInstanceHash.contains(object);
172 void NodeInstanceServer::setRenderTimerInterval(int timerInterval)
174 m_renderTimerInterval = timerInterval;
177 void NodeInstanceServer::setSlowRenderTimerInterval(int timerInterval)
179 m_slowRenderTimerInterval = timerInterval;
182 void NodeInstanceServer::setTimerId(int timerId)
187 int NodeInstanceServer::timerId() const
192 int NodeInstanceServer::renderTimerInterval() const
194 return m_renderTimerInterval;
197 void NodeInstanceServer::startRenderTimer()
199 if (m_slowRenderTimer)
203 m_timer = startTimer(m_renderTimerInterval);
205 m_slowRenderTimer = false;
208 void NodeInstanceServer::slowDownRenderTimer()
210 if (!m_slowRenderTimer)
219 m_timer = startTimer(m_slowRenderTimerInterval);
221 m_slowRenderTimer = true;
224 void NodeInstanceServer::stopRenderTimer()
232 void NodeInstanceServer::createScene(const CreateSceneCommand &command)
234 initializeDeclarativeView();
235 QList<ServerNodeInstance> instanceList = setupScene(command);
239 nodeInstanceClient()->informationChanged(createAllInformationChangedCommand(instanceList, true));
240 nodeInstanceClient()->valuesChanged(createValuesChangedCommand(instanceList));
241 sendChildrenChangedCommand(instanceList);
242 nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand(instanceList));
243 nodeInstanceClient()->componentCompleted(createComponentCompletedCommand(instanceList));
248 void NodeInstanceServer::clearScene(const ClearSceneCommand &/*command*/)
252 removeAllInstanceRelationships();
253 m_fileSystemWatcherHash.clear();
254 m_rootNodeInstance.makeInvalid();
255 m_changedPropertyList.clear();
258 delete m_declarativeView.data();
261 void NodeInstanceServer::removeInstances(const RemoveInstancesCommand &command)
263 ServerNodeInstance oldState = activeStateInstance();
264 if (activeStateInstance().isValid())
265 activeStateInstance().deactivateState();
267 foreach(qint32 instanceId, command.instanceIds()) {
268 removeInstanceRelationsip(instanceId);
271 if (oldState.isValid())
272 oldState.activateState();
278 void NodeInstanceServer::removeProperties(const RemovePropertiesCommand &command)
280 bool hasDynamicProperties = false;
281 foreach(const PropertyAbstractContainer &container, command.properties()) {
282 hasDynamicProperties |= container.isDynamic();
283 resetInstanceProperty(container);
286 if (hasDynamicProperties)
292 void NodeInstanceServer::reparentInstances(const QVector<ReparentContainer> &containerVector)
294 foreach(const ReparentContainer &container, containerVector) {
295 ServerNodeInstance instance = instanceForId(container.instanceId());
296 if (instance.isValid()) {
297 instance.reparent(instanceForId(container.oldParentInstanceId()), container.oldParentProperty(), instanceForId(container.newParentInstanceId()), container.newParentProperty());
303 void NodeInstanceServer::reparentInstances(const ReparentInstancesCommand &command)
305 reparentInstances(command.reparentInstances());
310 void NodeInstanceServer::changeState(const ChangeStateCommand &command)
312 if (hasInstanceForId(command.stateInstanceId())) {
313 if (activeStateInstance().isValid())
314 activeStateInstance().deactivateState();
315 ServerNodeInstance instance = instanceForId(command.stateInstanceId());
316 instance.activateState();
318 if (activeStateInstance().isValid())
319 activeStateInstance().deactivateState();
325 void NodeInstanceServer::completeComponent(const CompleteComponentCommand &command)
327 QList<ServerNodeInstance> instanceList;
329 foreach(qint32 instanceId, command.instances()) {
330 if (hasInstanceForId(instanceId)) {
331 ServerNodeInstance instance = instanceForId(instanceId);
332 instance.doComponentComplete();
333 instanceList.append(instance);
337 m_completedComponentList.append(instanceList);
340 nodeInstanceClient()->valuesChanged(createValuesChangedCommand(instanceList));
341 nodeInstanceClient()->informationChanged(createAllInformationChangedCommand(instanceList, true));
342 nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand(instanceList));
347 void NodeInstanceServer::addImports(const QVector<AddImportContainer> &containerVector)
349 foreach (const AddImportContainer &container, containerVector) {
350 QString importStatement = QString("import ");
352 if (!container.fileName().isEmpty())
353 importStatement += '"' + container.fileName() + '"';
354 else if (!container.url().isEmpty())
355 importStatement += container.url().toString();
357 if (!container.version().isEmpty())
358 importStatement += ' ' + container.version();
360 if (!container.alias().isEmpty())
361 importStatement += " as " + container.alias();
363 importStatement.append('\n');
365 if (!m_importList.contains(importStatement))
366 m_importList.append(importStatement);
369 delete m_importComponent.data();
370 delete m_importComponentObject.data();
372 m_importComponent = new QDeclarativeComponent(engine(), 0);
373 QString componentString;
374 foreach(const QString &importStatement, m_importList)
375 componentString += QString("%1").arg(importStatement);
377 componentString += QString("Item {}\n");
379 m_importComponent->setData(componentString.toUtf8(), fileUrl());
380 m_importComponentObject = m_importComponent->create();
382 if (!m_importComponent->errorString().isEmpty())
383 qDebug() << "QmlDesigner.NodeInstances: import wrong: " << m_importComponent->errorString();
386 void NodeInstanceServer::addImport(const AddImportCommand &command)
388 addImports(QVector<AddImportContainer>() << command.import());
391 void NodeInstanceServer::changeFileUrl(const ChangeFileUrlCommand &command)
393 m_fileUrl = command.fileUrl();
396 engine()->setBaseUrl(m_fileUrl);
402 void NodeInstanceServer::changePropertyValues(const ChangeValuesCommand &command)
404 bool hasDynamicProperties = false;
405 foreach(const PropertyValueContainer &container, command.valueChanges()) {
406 hasDynamicProperties |= container.isDynamic();
407 setInstancePropertyVariant(container);
410 if (hasDynamicProperties)
417 void NodeInstanceServer::changePropertyBindings(const ChangeBindingsCommand &command)
419 bool hasDynamicProperties = false;
420 foreach(const PropertyBindingContainer &container, command.bindingChanges()) {
421 hasDynamicProperties |= container.isDynamic();
422 setInstancePropertyBinding(container);
425 if (hasDynamicProperties)
431 void NodeInstanceServer::changeIds(const ChangeIdsCommand &command)
433 foreach(const IdContainer &container, command.ids()) {
434 if (hasInstanceForId(container.instanceId()))
435 instanceForId(container.instanceId()).setId(container.id());
442 QDeclarativeEngine *NodeInstanceServer::engine() const
444 if (m_declarativeView)
445 return m_declarativeView->engine();
450 QDeclarativeContext *NodeInstanceServer::context() const
452 if (m_importComponentObject) {
453 QDeclarativeContext *importComponentContext = QDeclarativeEngine::contextForObject(m_importComponentObject.data());
454 if (importComponentContext) // this should be the default
455 return importComponentContext;
459 return engine()->rootContext();
464 QDeclarativeView *NodeInstanceServer::delcarativeView() const
466 return m_declarativeView.data();
469 const QVector<NodeInstanceServer::InstancePropertyPair> NodeInstanceServer::changedPropertyList() const
471 return m_changedPropertyList;
474 void NodeInstanceServer::clearChangedPropertyList()
476 m_changedPropertyList.clear();
479 void NodeInstanceServer::setupDummysForContext(QDeclarativeContext *context)
481 foreach (const DummyPair& dummyPair, m_dummyObjectList) {
482 if (dummyPair.second) {
483 context->setContextProperty(dummyPair.first, dummyPair.second.data());
489 QList<QDeclarativeContext*> NodeInstanceServer::allSubContextsForObject(QObject *object)
491 QList<QDeclarativeContext*> contextList;
494 foreach (QObject *subObject, allSubObjectsForObject(object)) {
495 QDeclarativeContext *contextOfObject = QDeclarativeEngine::contextForObject(subObject);
496 if (contextOfObject) {
497 if (contextOfObject != context() && !contextList.contains(contextOfObject))
498 contextList.append(contextOfObject);
506 QList<QObject*> NodeInstanceServer::allSubObjectsForObject(QObject *object)
508 QList<QObject*> subChildren;
510 subChildren = object->findChildren<QObject*>();
516 void NodeInstanceServer::refreshBindings()
518 static int counter = 0;
519 engine()->rootContext()->setContextProperty(QString("__%1").arg(counter++), 0); // refreshing bindings
522 void NodeInstanceServer::removeAllInstanceRelationships()
524 // prevent destroyed() signals calling back
526 foreach (ServerNodeInstance instance, m_objectInstanceHash.values()) {
527 if (instance.isValid())
528 instance.setId(QString());
531 //first the root object
532 if (rootNodeInstance().internalObject())
533 rootNodeInstance().internalObject()->disconnect();
535 rootNodeInstance().makeInvalid();
538 foreach (ServerNodeInstance instance, m_objectInstanceHash.values()) {
539 if (instance.internalObject())
540 instance.internalObject()->disconnect();
541 instance.makeInvalid();
544 m_idInstanceHash.clear();
545 m_objectInstanceHash.clear();
548 QFileSystemWatcher *NodeInstanceServer::dummydataFileSystemWatcher()
550 if (m_dummdataFileSystemWatcher.isNull()) {
551 m_dummdataFileSystemWatcher = new QFileSystemWatcher(this);
552 connect(m_dummdataFileSystemWatcher.data(), SIGNAL(fileChanged(QString)), this, SLOT(refreshDummyData(QString)));
555 return m_dummdataFileSystemWatcher.data();
558 QFileSystemWatcher *NodeInstanceServer::fileSystemWatcher()
560 if (m_fileSystemWatcher.isNull()) {
561 m_fileSystemWatcher = new QFileSystemWatcher(this);
562 connect(m_fileSystemWatcher.data(), SIGNAL(fileChanged(QString)), this, SLOT(refreshLocalFileProperty(QString)));
565 return m_fileSystemWatcher.data();
568 Internal::ChildrenChangeEventFilter *NodeInstanceServer::childrenChangeEventFilter() const
570 return m_childrenChangeEventFilter.data();
573 void NodeInstanceServer::addFilePropertyToFileSystemWatcher(QObject *object, const QString &propertyName, const QString &path)
575 if (!m_fileSystemWatcherHash.contains(path)) {
576 m_fileSystemWatcherHash.insert(path, ObjectPropertyPair(object, propertyName));
577 fileSystemWatcher()->addPath(path);
581 void NodeInstanceServer::removeFilePropertyFromFileSystemWatcher(QObject *object, const QString &propertyName, const QString &path)
583 if (m_fileSystemWatcherHash.contains(path)) {
584 fileSystemWatcher()->removePath(path);
585 m_fileSystemWatcherHash.remove(path, ObjectPropertyPair(object, propertyName));
589 void NodeInstanceServer::refreshLocalFileProperty(const QString &path)
591 if (m_fileSystemWatcherHash.contains(path)) {
592 QList<ObjectPropertyPair> objectPropertyPairList = m_fileSystemWatcherHash.values();
593 foreach(const ObjectPropertyPair &objectPropertyPair, objectPropertyPairList) {
594 QObject *object = objectPropertyPair.first.data();
595 QString propertyName = objectPropertyPair.second;
597 if (hasInstanceForObject(object)) {
598 instanceForObject(object).refreshProperty(propertyName);
604 void NodeInstanceServer::refreshDummyData(const QString &path)
606 engine()->clearComponentCache();
607 QFileInfo filePath(path);
608 if (filePath.completeBaseName().contains("_dummycontext")) {
609 loadDummyContextObjectFile(filePath);
611 loadDummyDataFile(filePath);
618 void NodeInstanceServer::addChangedProperty(const InstancePropertyPair &property)
620 if (!m_changedPropertyList.contains(property))
621 m_changedPropertyList.append(property);
624 void NodeInstanceServer::emitParentChanged(QObject *child)
626 if (hasInstanceForObject(child)) {
627 addChangedProperty(InstancePropertyPair(instanceForObject(child), "parent"));
631 Internal::ChildrenChangeEventFilter *NodeInstanceServer::childrenChangeEventFilter()
633 if (m_childrenChangeEventFilter.isNull()) {
634 m_childrenChangeEventFilter = new Internal::ChildrenChangeEventFilter(this);
635 connect(m_childrenChangeEventFilter.data(), SIGNAL(childrenChanged(QObject*)), this, SLOT(emitParentChanged(QObject*)));
638 return m_childrenChangeEventFilter.data();
641 void NodeInstanceServer::resetInstanceProperty(const PropertyAbstractContainer &propertyContainer)
643 if (hasInstanceForId(propertyContainer.instanceId())) { // TODO ugly workaround
644 ServerNodeInstance instance = instanceForId(propertyContainer.instanceId());
645 Q_ASSERT(instance.isValid());
647 const QString name = propertyContainer.name();
649 if (activeStateInstance().isValid() && !instance.isSubclassOf("QtQuick/PropertyChanges")) {
650 bool statePropertyWasReseted = activeStateInstance().resetStateProperty(instance, name, instance.resetVariant(name));
651 if (!statePropertyWasReseted)
652 instance.resetProperty(name);
654 instance.resetProperty(name);
660 void NodeInstanceServer::setInstancePropertyBinding(const PropertyBindingContainer &bindingContainer)
662 if (hasInstanceForId(bindingContainer.instanceId())) {
663 ServerNodeInstance instance = instanceForId(bindingContainer.instanceId());
665 const QString name = bindingContainer.name();
666 const QString expression = bindingContainer.expression();
669 if (activeStateInstance().isValid() && !instance.isSubclassOf("QtQuick/PropertyChanges")) {
670 bool stateBindingWasUpdated = activeStateInstance().updateStateBinding(instance, name, expression);
671 if (!stateBindingWasUpdated) {
672 if (bindingContainer.isDynamic())
673 instance.setPropertyDynamicBinding(name, bindingContainer.dynamicTypeName(), expression);
675 instance.setPropertyBinding(name, expression);
678 if (bindingContainer.isDynamic())
679 instance.setPropertyDynamicBinding(name, bindingContainer.dynamicTypeName(), expression);
681 instance.setPropertyBinding(name, expression);
687 void NodeInstanceServer::removeProperties(const QList<PropertyAbstractContainer> &propertyList)
689 foreach (const PropertyAbstractContainer &property, propertyList)
690 resetInstanceProperty(property);
693 void NodeInstanceServer::setInstancePropertyVariant(const PropertyValueContainer &valueContainer)
695 if (hasInstanceForId(valueContainer.instanceId())) {
696 ServerNodeInstance instance = instanceForId(valueContainer.instanceId());
699 const QString name = valueContainer.name();
700 const QVariant value = valueContainer.value();
703 if (activeStateInstance().isValid() && !instance.isSubclassOf("QtQuick/PropertyChanges")) {
704 bool stateValueWasUpdated = activeStateInstance().updateStateVariant(instance, name, value);
705 if (!stateValueWasUpdated) {
706 if (valueContainer.isDynamic())
707 instance.setPropertyDynamicVariant(name, valueContainer.dynamicTypeName(), value);
709 instance.setPropertyVariant(name, value);
711 } else { //base state
712 if (valueContainer.isDynamic())
713 instance.setPropertyDynamicVariant(name, valueContainer.dynamicTypeName(), value);
715 instance.setPropertyVariant(name, value);
718 // instance.paintUpdate();
723 QUrl NodeInstanceServer::fileUrl() const
728 ServerNodeInstance NodeInstanceServer::activeStateInstance() const
730 return m_activeStateInstance;
733 ServerNodeInstance NodeInstanceServer::rootNodeInstance() const
735 return m_rootNodeInstance;
738 void NodeInstanceServer::setStateInstance(const ServerNodeInstance &stateInstance)
740 m_activeStateInstance = stateInstance;
743 void NodeInstanceServer::clearStateInstance()
745 m_activeStateInstance = ServerNodeInstance();
748 void NodeInstanceServer::timerEvent(QTimerEvent *event)
750 if (event->timerId() == m_timer) {
751 findItemChangesAndSendChangeCommands();
754 NodeInstanceServerInterface::timerEvent(event);
757 NodeInstanceClientInterface *NodeInstanceServer::nodeInstanceClient() const
759 return m_nodeInstanceClient;
762 void NodeInstanceServer::sendChildrenChangedCommand(const QList<ServerNodeInstance> childList)
764 QSet<ServerNodeInstance> parentSet;
765 QList<ServerNodeInstance> noParentList;
767 foreach (const ServerNodeInstance &child, childList) {
768 if (!child.hasParent())
769 noParentList.append(child);
771 parentSet.insert(child.parent());
775 foreach (const ServerNodeInstance &parent, parentSet)
776 nodeInstanceClient()->childrenChanged(createChildrenChangedCommand(parent, parent.childItems()));
778 if (!noParentList.isEmpty())
779 nodeInstanceClient()->childrenChanged(createChildrenChangedCommand(ServerNodeInstance(), noParentList));
783 ChildrenChangedCommand NodeInstanceServer::createChildrenChangedCommand(const ServerNodeInstance &parentInstance, const QList<ServerNodeInstance> &instanceList) const
785 QVector<qint32> instanceVector;
787 foreach(const ServerNodeInstance &instance, instanceList)
788 instanceVector.append(instance.instanceId());
790 return ChildrenChangedCommand(parentInstance.instanceId(), instanceVector);
793 InformationChangedCommand NodeInstanceServer::createAllInformationChangedCommand(const QList<ServerNodeInstance> &instanceList, bool initial) const
795 QVector<InformationContainer> informationVector;
797 foreach(const ServerNodeInstance &instance, instanceList) {
798 informationVector.append(InformationContainer(instance.instanceId(), Position, instance.position()));
799 informationVector.append(InformationContainer(instance.instanceId(), Transform, instance.transform()));
800 informationVector.append(InformationContainer(instance.instanceId(), SceneTransform, instance.sceneTransform()));
801 informationVector.append(InformationContainer(instance.instanceId(), Size, instance.size()));
802 informationVector.append(InformationContainer(instance.instanceId(), BoundingRect, instance.boundingRect()));
803 informationVector.append(InformationContainer(instance.instanceId(), Transform, instance.transform()));
804 informationVector.append(InformationContainer(instance.instanceId(), HasContent, instance.hasContent()));
805 informationVector.append(InformationContainer(instance.instanceId(), IsMovable, instance.isMovable()));
806 informationVector.append(InformationContainer(instance.instanceId(), IsResizable, instance.isResizable()));
807 informationVector.append(InformationContainer(instance.instanceId(), IsInPositioner, instance.isInPositioner()));
808 informationVector.append(InformationContainer(instance.instanceId(), PenWidth, instance.penWidth()));
809 informationVector.append(InformationContainer(instance.instanceId(), IsAnchoredByChildren, instance.isAnchoredByChildren()));
810 informationVector.append(InformationContainer(instance.instanceId(), IsAnchoredBySibling, instance.isAnchoredBySibling()));
812 informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.fill"), instance.hasAnchor("anchors.fill")));
813 informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.centerIn"), instance.hasAnchor("anchors.centerIn")));
814 informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.right"), instance.hasAnchor("anchors.right")));
815 informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.top"), instance.hasAnchor("anchors.top")));
816 informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.left"), instance.hasAnchor("anchors.left")));
817 informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.bottom"), instance.hasAnchor("anchors.bottom")));
818 informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.horizontalCenter"), instance.hasAnchor("anchors.horizontalCenter")));
819 informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.verticalCenter"), instance.hasAnchor("anchors.verticalCenter")));
820 informationVector.append(InformationContainer(instance.instanceId(), HasAnchor, QString("anchors.baseline"), instance.hasAnchor("anchors.baseline")));
822 QPair<QString, ServerNodeInstance> anchorPair = instance.anchor("anchors.fill");
823 informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.fill"), anchorPair.first, anchorPair.second.instanceId()));
825 anchorPair = instance.anchor("anchors.centerIn");
826 informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.centerIn"), anchorPair.first, anchorPair.second.instanceId()));
828 anchorPair = instance.anchor("anchors.right");
829 informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.right"), anchorPair.first, anchorPair.second.instanceId()));
831 anchorPair = instance.anchor("anchors.top");
832 informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.top"), anchorPair.first, anchorPair.second.instanceId()));
834 anchorPair = instance.anchor("anchors.left");
835 informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.left"), anchorPair.first, anchorPair.second.instanceId()));
837 anchorPair = instance.anchor("anchors.bottom");
838 informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.bottom"), anchorPair.first, anchorPair.second.instanceId()));
840 anchorPair = instance.anchor("anchors.horizontalCenter");
841 informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.horizontalCenter"), anchorPair.first, anchorPair.second.instanceId()));
843 anchorPair = instance.anchor("anchors.verticalCenter");
844 informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.verticalCenter"), anchorPair.first, anchorPair.second.instanceId()));
846 anchorPair = instance.anchor("anchors.baseline");
847 informationVector.append(InformationContainer(instance.instanceId(), Anchor, QString("anchors.baseline"), anchorPair.first, anchorPair.second.instanceId()));
849 QStringList propertyNames = instance.propertyNames();
852 foreach (const QString &propertyName,propertyNames)
853 informationVector.append(InformationContainer(instance.instanceId(), InstanceTypeForProperty, propertyName, instance.instanceType(propertyName)));
856 foreach (const QString &propertyName,instance.propertyNames()) {
857 bool hasChanged = false;
858 bool hasBinding = instance.hasBindingForProperty(propertyName, &hasChanged);
860 informationVector.append(InformationContainer(instance.instanceId(), HasBindingForProperty, propertyName, hasBinding));
865 return InformationChangedCommand(informationVector);
868 ValuesChangedCommand NodeInstanceServer::createValuesChangedCommand(const QList<ServerNodeInstance> &instanceList) const
870 QVector<PropertyValueContainer> valueVector;
872 foreach(const ServerNodeInstance &instance, instanceList) {
873 foreach(const QString &propertyName, instance.propertyNames()) {
874 QVariant propertyValue = instance.property(propertyName);
875 if (propertyValue.type() < QVariant::UserType)
876 valueVector.append(PropertyValueContainer(instance.instanceId(), propertyName, propertyValue, QString()));
880 return ValuesChangedCommand(valueVector);
883 ComponentCompletedCommand NodeInstanceServer::createComponentCompletedCommand(const QList<ServerNodeInstance> &instanceList)
885 QVector<qint32> idVector;
886 foreach (const ServerNodeInstance &instance, instanceList) {
887 if (instance.instanceId() >= 0)
888 idVector.append(instance.instanceId());
891 return ComponentCompletedCommand(idVector);
894 ValuesChangedCommand NodeInstanceServer::createValuesChangedCommand(const QVector<InstancePropertyPair> &propertyList) const
896 QVector<PropertyValueContainer> valueVector;
898 foreach (const InstancePropertyPair &property, propertyList) {
899 const QString propertyName = property.second;
900 const ServerNodeInstance instance = property.first;
902 if( instance.isValid()) {
903 QVariant propertyValue = instance.property(propertyName);
904 if (propertyValue.type() < QVariant::UserType)
905 valueVector.append(PropertyValueContainer(instance.instanceId(), propertyName, propertyValue, QString()));
909 return ValuesChangedCommand(valueVector);
912 QStringList NodeInstanceServer::imports() const
917 QObject *NodeInstanceServer::dummyContextObject() const
919 return m_dummyContextObject.data();
922 void NodeInstanceServer::notifyPropertyChange(qint32 instanceid, const QString &propertyName)
924 if (hasInstanceForId(instanceid))
925 addChangedProperty(InstancePropertyPair(instanceForId(instanceid), propertyName));
928 void NodeInstanceServer::insertInstanceRelationship(const ServerNodeInstance &instance)
930 Q_ASSERT(instance.isValid());
931 Q_ASSERT(!m_idInstanceHash.contains(instance.instanceId()));
932 Q_ASSERT(!m_objectInstanceHash.contains(instance.internalObject()));
933 m_objectInstanceHash.insert(instance.internalObject(), instance);
934 m_idInstanceHash.insert(instance.instanceId(), instance);
937 void NodeInstanceServer::removeInstanceRelationsip(qint32 instanceId)
939 if (hasInstanceForId(instanceId)) {
940 ServerNodeInstance instance = instanceForId(instanceId);
941 if (instance.isValid())
942 instance.setId(QString());
943 m_idInstanceHash.remove(instanceId);
944 m_objectInstanceHash.remove(instance.internalObject());
945 instance.makeInvalid();
949 PixmapChangedCommand NodeInstanceServer::createPixmapChangedCommand(const QList<ServerNodeInstance> &instanceList) const
951 QVector<ImageContainer> imageVector;
953 foreach (const ServerNodeInstance &instance, instanceList) {
954 if (instance.isValid())
955 imageVector.append(ImageContainer(instance.instanceId(), instance.renderImage()));
958 return PixmapChangedCommand(imageVector);
961 bool NodeInstanceServer::nonInstanceChildIsDirty(QGraphicsObject *graphicsObject) const
963 QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(graphicsObject);
964 if (d->dirtyChildren) {
965 foreach(QGraphicsItem *child, graphicsObject->childItems()) {
966 QGraphicsObject *childGraphicsObject = child->toGraphicsObject();
967 if (hasInstanceForObject(childGraphicsObject))
970 QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child);
971 if (childPrivate->dirty || nonInstanceChildIsDirty(childGraphicsObject))
979 void NodeInstanceServer::resetAllItems()
981 // m_declarativeView->scene()->update();
982 // m_declarativeView->viewport()->repaint();
983 static_cast<QGraphicsScenePrivate*>(QObjectPrivate::get(m_declarativeView->scene()))->processDirtyItemsEmitted = true;
985 foreach (QGraphicsItem *item, m_declarativeView->items())
986 static_cast<QGraphicsScenePrivate*>(QObjectPrivate::get(m_declarativeView->scene()))->resetDirtyItem(item);
989 void NodeInstanceServer::initializeDeclarativeView()
991 Q_ASSERT(!m_declarativeView.data());
993 m_declarativeView = new QDeclarativeView;
995 m_declarativeView->setAttribute(Qt::WA_DontShowOnScreen, true);
997 m_declarativeView->setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
998 m_declarativeView->show();
1000 m_declarativeView->setAttribute(Qt::WA_DontShowOnScreen, true);
1002 QUnifiedTimer::instance()->setSlowdownFactor(0.00001);
1003 QUnifiedTimer::instance()->setSlowModeEnabled(true);
1006 QImage NodeInstanceServer::renderPreviewImage()
1008 QSize size = rootNodeInstance().boundingRect().size().toSize();
1009 size.scale(100, 100, Qt::KeepAspectRatio);
1011 QImage image(size, QImage::Format_ARGB32);
1012 image.fill(0xFFFFFFFF);
1014 if (m_declarativeView) {
1015 QPainter painter(&image);
1016 painter.setRenderHint(QPainter::Antialiasing, true);
1017 painter.setRenderHint(QPainter::TextAntialiasing, true);
1018 painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
1019 painter.setRenderHint(QPainter::HighQualityAntialiasing, true);
1020 painter.setRenderHint(QPainter::NonCosmeticDefaultPen, true);
1022 m_declarativeView->scene()->render(&painter, image.rect(), rootNodeInstance().boundingRect().toRect(), Qt::IgnoreAspectRatio);
1028 void NodeInstanceServer::loadDummyDataFile(const QFileInfo& qmlFileInfo)
1030 QDeclarativeComponent component(engine(), qmlFileInfo.filePath());
1031 QObject *dummyData = component.create();
1032 if(component.isError()) {
1033 QList<QDeclarativeError> errors = component.errors();
1034 foreach (const QDeclarativeError &error, errors) {
1035 qWarning() << error;
1039 QVariant oldDummyDataObject = m_declarativeView->rootContext()->contextProperty(qmlFileInfo.completeBaseName());
1042 qWarning() << "Loaded dummy data:" << qmlFileInfo.filePath();
1043 m_declarativeView->rootContext()->setContextProperty(qmlFileInfo.completeBaseName(), dummyData);
1044 dummyData->setParent(this);
1045 m_dummyObjectList.append(DummyPair(qmlFileInfo.completeBaseName(), dummyData));
1048 if (!oldDummyDataObject.isNull())
1049 delete oldDummyDataObject.value<QObject*>();
1051 if (!dummydataFileSystemWatcher()->files().contains(qmlFileInfo.filePath()))
1052 dummydataFileSystemWatcher()->addPath(qmlFileInfo.filePath());
1054 if (rootNodeInstance().isValid() && rootNodeInstance().internalObject()) {
1055 foreach (QDeclarativeContext *context, allSubContextsForObject(rootNodeInstance().internalObject()))
1056 setupDummysForContext(context);
1060 void NodeInstanceServer::loadDummyContextObjectFile(const QFileInfo& qmlFileInfo)
1062 delete m_dummyContextObject.data();
1064 QDeclarativeComponent component(engine(), qmlFileInfo.filePath());
1065 m_dummyContextObject = component.create();
1067 if(component.isError()) {
1068 QList<QDeclarativeError> errors = component.errors();
1069 foreach (const QDeclarativeError &error, errors) {
1070 qWarning() << error;
1074 if (m_dummyContextObject) {
1075 qWarning() << "Loaded dummy context object:" << qmlFileInfo.filePath();
1076 m_dummyContextObject->setParent(this);
1079 if (!dummydataFileSystemWatcher()->files().contains(qmlFileInfo.filePath()))
1080 dummydataFileSystemWatcher()->addPath(qmlFileInfo.filePath());
1085 void NodeInstanceServer::loadDummyDataFiles(const QString& directory)
1087 QDir dir(directory, "*.qml");
1088 QList<QFileInfo> filePathList = dir.entryInfoList();
1089 QString baseName = QFileInfo(fileUrl().toLocalFile()).completeBaseName();
1090 foreach (const QFileInfo &qmlFileInfo, filePathList) {
1091 if (!qmlFileInfo.completeBaseName().contains("_dummycontext")) {
1092 loadDummyDataFile(qmlFileInfo);
1093 } else if (qmlFileInfo.completeBaseName() == baseName+"_dummycontext") {
1094 loadDummyContextObjectFile(qmlFileInfo);
1099 QStringList dummyDataDirectories(const QString& directoryPath)
1101 QStringList dummyDataDirectoryList;
1102 QDir directory(directoryPath);
1104 if (directory.isRoot() || !directory.exists())
1105 return dummyDataDirectoryList;
1107 if (directory.exists("dummydata"))
1108 dummyDataDirectoryList.prepend(directory.absoluteFilePath("dummydata"));
1114 QList<ServerNodeInstance> NodeInstanceServer::setupScene(const CreateSceneCommand &command)
1116 if (!command.fileUrl().isEmpty()) {
1117 engine()->setBaseUrl(command.fileUrl());
1118 m_fileUrl = command.fileUrl();
1121 addImports(command.imports());
1123 if (!command.fileUrl().isEmpty()) {
1124 QStringList dummyDataDirectoryList = dummyDataDirectories(QFileInfo(command.fileUrl().toLocalFile()).path());
1125 foreach(const QString &dummyDataDirectory, dummyDataDirectoryList)
1126 loadDummyDataFiles(dummyDataDirectory);
1129 static_cast<QGraphicsScenePrivate*>(QObjectPrivate::get(m_declarativeView->scene()))->processDirtyItemsEmitted = true;
1131 QList<ServerNodeInstance> instanceList = createInstances(command.instances());
1132 reparentInstances(command.reparentInstances());
1134 foreach(const IdContainer &container, command.ids()) {
1135 if (hasInstanceForId(container.instanceId()))
1136 instanceForId(container.instanceId()).setId(container.id());
1139 foreach(const PropertyValueContainer &container, command.valueChanges()) {
1140 if (container.isDynamic())
1141 setInstancePropertyVariant(container);
1144 foreach(const PropertyValueContainer &container, command.valueChanges()) {
1145 if (!container.isDynamic())
1146 setInstancePropertyVariant(container);
1149 foreach(const PropertyBindingContainer &container, command.bindingChanges()) {
1150 if (container.isDynamic())
1151 setInstancePropertyBinding(container);
1154 foreach(const PropertyBindingContainer &container, command.bindingChanges()) {
1155 if (!container.isDynamic())
1156 setInstancePropertyBinding(container);
1159 foreach(ServerNodeInstance instance, instanceList)
1160 instance.doComponentComplete();
1162 m_declarativeView->scene()->setSceneRect(rootNodeInstance().boundingRect());
1164 return instanceList;
1167 void NodeInstanceServer::findItemChangesAndSendChangeCommands()
1169 static bool inFunction = false;
1173 QSet<ServerNodeInstance> informationChangedInstanceSet;
1174 QVector<InstancePropertyPair> propertyChangedList;
1175 QSet<ServerNodeInstance> parentChangedSet;
1176 bool adjustSceneRect = false;
1178 if (m_declarativeView) {
1179 foreach (QGraphicsItem *item, m_declarativeView->items()) {
1180 QGraphicsObject *graphicsObject = item->toGraphicsObject();
1181 if (graphicsObject && hasInstanceForObject(graphicsObject)) {
1182 ServerNodeInstance instance = instanceForObject(graphicsObject);
1183 QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item);
1185 if (d->dirtySceneTransform || d->geometryChanged || d->dirty)
1186 informationChangedInstanceSet.insert(instance);
1188 if (d->geometryChanged) {
1189 if (instance.isRootNodeInstance())
1190 m_declarativeView->scene()->setSceneRect(item->boundingRect());
1196 foreach (const InstancePropertyPair& property, m_changedPropertyList) {
1197 const ServerNodeInstance instance = property.first;
1198 const QString propertyName = property.second;
1200 if (instance.isValid()) {
1201 if (instance.isRootNodeInstance() && (propertyName == "width" || propertyName == "height"))
1202 adjustSceneRect = true;
1204 if (propertyName.contains("anchors"))
1205 informationChangedInstanceSet.insert(instance);
1207 if (propertyName == "parent") {
1208 informationChangedInstanceSet.insert(instance);
1209 parentChangedSet.insert(instance);
1212 propertyChangedList.append(property);
1216 m_changedPropertyList.clear();
1219 if (!informationChangedInstanceSet.isEmpty())
1220 nodeInstanceClient()->informationChanged(createAllInformationChangedCommand(informationChangedInstanceSet.toList()));
1222 if (!propertyChangedList.isEmpty())
1223 nodeInstanceClient()->valuesChanged(createValuesChangedCommand(propertyChangedList));
1225 if (!parentChangedSet.isEmpty())
1226 sendChildrenChangedCommand(parentChangedSet.toList());
1228 if (adjustSceneRect) {
1229 QRectF boundingRect = m_rootNodeInstance.boundingRect();
1230 if (boundingRect.isValid()) {
1231 m_declarativeView->setSceneRect(boundingRect);
1235 if (!m_completedComponentList.isEmpty()) {
1236 nodeInstanceClient()->componentCompleted(createComponentCompletedCommand(m_completedComponentList));
1237 m_completedComponentList.clear();
1240 slowDownRenderTimer();
1241 nodeInstanceClient()->flush();
1242 nodeInstanceClient()->synchronizeWithClientProcess();