1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "qmlobjectnode.h"
27 #include "qmlitemnode.h"
28 #include "qmlstate.h"
29 #include "qmltimelinekeyframegroup.h"
30 #include "qmlvisualnode.h"
31 #include "qml3dnode.h"
32 #include "variantproperty.h"
33 #include "nodeproperty.h"
34 #include <invalidmodelnodeexception.h>
35 #include "abstractview.h"
36 #include "nodeinstance.h"
37 #include "nodemetainfo.h"
38 #include "bindingproperty.h"
39 #include "nodelistproperty.h"
40 #include "nodeinstanceview.h"
41
42 #include <qmltimeline.h>
43
44 #ifndef QMLDESIGNER_TEST
45 #include <qmldesignerplugin.h>
46 #endif
47
48 #include <utils/qtcassert.h>
49
50 #include <QRegularExpression>
51
52 namespace QmlDesigner {
53
setVariantProperty(const PropertyName & name,const QVariant & value)54 void QmlObjectNode::setVariantProperty(const PropertyName &name, const QVariant &value)
55 {
56 if (!isValid())
57 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
58
59 if (timelineIsActive() && currentTimeline().isRecording()) {
60 modelNode().validId();
61
62 QmlTimelineKeyframeGroup timelineFrames(currentTimeline().keyframeGroup(modelNode(), name));
63
64 Q_ASSERT(timelineFrames.isValid());
65
66 qreal frame = currentTimeline().modelNode().auxiliaryData("currentFrame@NodeInstance").toReal();
67 timelineFrames.setValue(value, frame);
68
69 return;
70 } else if (modelNode().hasId() && timelineIsActive() && currentTimeline().hasKeyframeGroup(modelNode(), name)) {
71 QmlTimelineKeyframeGroup timelineFrames(currentTimeline().keyframeGroup(modelNode(), name));
72
73 Q_ASSERT(timelineFrames.isValid());
74
75 if (timelineFrames.isRecording()) {
76 qreal frame = currentTimeline().modelNode().auxiliaryData("currentFrame@NodeInstance").toReal();
77 timelineFrames.setValue(value, frame);
78
79 return;
80 }
81 }
82
83 if (isInBaseState()) {
84 modelNode().variantProperty(name).setValue(value); //basestate
85 } else {
86 modelNode().validId();
87
88 QmlPropertyChanges changeSet(currentState().propertyChanges(modelNode()));
89 Q_ASSERT(changeSet.isValid());
90 changeSet.modelNode().variantProperty(name).setValue(value);
91 }
92 }
93
setBindingProperty(const PropertyName & name,const QString & expression)94 void QmlObjectNode::setBindingProperty(const PropertyName &name, const QString &expression)
95 {
96 if (!isValid())
97 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
98
99 if (isInBaseState()) {
100 modelNode().bindingProperty(name).setExpression(expression); //basestate
101 } else {
102 modelNode().validId();
103
104 QmlPropertyChanges changeSet(currentState().propertyChanges(modelNode()));
105 Q_ASSERT(changeSet.isValid());
106 changeSet.modelNode().bindingProperty(name).setExpression(expression);
107 }
108 }
109
currentState() const110 QmlModelState QmlObjectNode::currentState() const
111 {
112 if (isValid())
113 return QmlModelState(view()->currentStateNode());
114 else
115 return QmlModelState();
116 }
117
currentTimeline() const118 QmlTimeline QmlObjectNode::currentTimeline() const
119 {
120 if (isValid())
121 return view()->currentTimeline();
122 else
123 return QmlTimeline();
124 }
125
isRootModelNode() const126 bool QmlObjectNode::isRootModelNode() const
127 {
128 return modelNode().isRootNode();
129 }
130
131
132 /*!
133 Returns the value of the property specified by \name that is based on an
134 actual instance. The return value is not the value in the model, but the
135 value of a real instantiated instance of this object.
136 */
instanceValue(const PropertyName & name) const137 QVariant QmlObjectNode::instanceValue(const PropertyName &name) const
138 {
139 return nodeInstance().property(name);
140 }
141
142
hasProperty(const PropertyName & name) const143 bool QmlObjectNode::hasProperty(const PropertyName &name) const
144 {
145 if (!isValid())
146 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
147
148 if (currentState().hasPropertyChanges(modelNode())) {
149 QmlPropertyChanges propertyChanges = currentState().propertyChanges(modelNode());
150 if (propertyChanges.modelNode().hasProperty(name))
151 return true;
152 }
153
154 return modelNode().hasProperty(name);
155 }
156
hasBindingProperty(const PropertyName & name) const157 bool QmlObjectNode::hasBindingProperty(const PropertyName &name) const
158 {
159 if (!isValid())
160 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
161
162 if (currentState().hasPropertyChanges(modelNode())) {
163 QmlPropertyChanges propertyChanges = currentState().propertyChanges(modelNode());
164 if (propertyChanges.modelNode().hasBindingProperty(name))
165 return true;
166 }
167
168 return modelNode().hasBindingProperty(name);
169 }
170
nodeAbstractProperty(const PropertyName & name) const171 NodeAbstractProperty QmlObjectNode::nodeAbstractProperty(const PropertyName &name) const
172 {
173 return modelNode().nodeAbstractProperty(name);
174 }
175
defaultNodeAbstractProperty() const176 NodeAbstractProperty QmlObjectNode::defaultNodeAbstractProperty() const
177 {
178 return modelNode().defaultNodeAbstractProperty();
179 }
180
nodeProperty(const PropertyName & name) const181 NodeProperty QmlObjectNode::nodeProperty(const PropertyName &name) const
182 {
183 return modelNode().nodeProperty(name);
184 }
185
nodeListProperty(const PropertyName & name) const186 NodeListProperty QmlObjectNode::nodeListProperty(const PropertyName &name) const
187 {
188 return modelNode().nodeListProperty(name);
189 }
190
instanceHasValue(const PropertyName & name) const191 bool QmlObjectNode::instanceHasValue(const PropertyName &name) const
192 {
193 return nodeInstance().hasProperty(name);
194 }
195
propertyAffectedByCurrentState(const PropertyName & name) const196 bool QmlObjectNode::propertyAffectedByCurrentState(const PropertyName &name) const
197 {
198 if (!isValid())
199 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
200
201 if (currentState().isBaseState())
202 return modelNode().hasProperty(name);
203
204 if (timelineIsActive() && currentTimeline().hasTimeline(modelNode(), name))
205 return true;
206
207 if (!currentState().hasPropertyChanges(modelNode()))
208 return false;
209
210 return currentState().propertyChanges(modelNode()).modelNode().hasProperty(name);
211 }
212
modelValue(const PropertyName & name) const213 QVariant QmlObjectNode::modelValue(const PropertyName &name) const
214 {
215 if (!isValid())
216 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
217
218 if (timelineIsActive() && currentTimeline().hasTimeline(modelNode(), name)) {
219 QmlTimelineKeyframeGroup timelineFrames(currentTimeline().keyframeGroup(modelNode(), name));
220
221 Q_ASSERT(timelineFrames.isValid());
222
223 qreal frame = currentTimeline().modelNode().auxiliaryData("currentFrame@NodeInstance").toReal();
224
225 QVariant value = timelineFrames.value(frame);
226
227 if (!value.isValid()) //interpolation is not done in the model
228 value = instanceValue(name);
229
230 return value;
231 }
232
233 if (currentState().isBaseState())
234 return modelNode().variantProperty(name).value();
235
236 if (!currentState().hasPropertyChanges(modelNode()))
237 return modelNode().variantProperty(name).value();
238
239 QmlPropertyChanges propertyChanges(currentState().propertyChanges(modelNode()));
240
241 if (!propertyChanges.modelNode().hasProperty(name))
242 return modelNode().variantProperty(name).value();
243
244 return propertyChanges.modelNode().variantProperty(name).value();
245 }
246
isTranslatableText(const PropertyName & name) const247 bool QmlObjectNode::isTranslatableText(const PropertyName &name) const
248 {
249 if (modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name))
250 if (modelNode().metaInfo().propertyTypeName(name) == "QString" || modelNode().metaInfo().propertyTypeName(name) == "string") {
251 if (modelNode().hasBindingProperty(name)) {
252 static QRegularExpression regularExpressionPattern(
253 QLatin1String("^qsTr(|Id|anslate)\\(\".*\"\\)$"));
254 return modelNode().bindingProperty(name).expression().contains(regularExpressionPattern);
255 }
256
257 return false;
258 }
259
260 return false;
261 }
262
stripedTranslatableText(const PropertyName & name) const263 QString QmlObjectNode::stripedTranslatableText(const PropertyName &name) const
264 {
265 if (modelNode().hasBindingProperty(name)) {
266 static QRegularExpression regularExpressionPattern(
267 QLatin1String("^qsTr(|Id|anslate)\\(\"(.*)\"\\)$"));
268 const QRegularExpressionMatch match = regularExpressionPattern.match(
269 modelNode().bindingProperty(name).expression());
270 if (match.hasMatch())
271 return match.captured(2);
272 return instanceValue(name).toString();
273 }
274 return instanceValue(name).toString();
275 }
276
expression(const PropertyName & name) const277 QString QmlObjectNode::expression(const PropertyName &name) const
278 {
279 if (!isValid())
280 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
281
282 if (currentState().isBaseState())
283 return modelNode().bindingProperty(name).expression();
284
285 if (!currentState().hasPropertyChanges(modelNode()))
286 return modelNode().bindingProperty(name).expression();
287
288 QmlPropertyChanges propertyChanges(currentState().propertyChanges(modelNode()));
289
290 if (!propertyChanges.modelNode().hasProperty(name))
291 return modelNode().bindingProperty(name).expression();
292
293 return propertyChanges.modelNode().bindingProperty(name).expression();
294 }
295
296 /*!
297 Returns \c true if the ObjectNode is in the BaseState.
298 */
isInBaseState() const299 bool QmlObjectNode::isInBaseState() const
300 {
301 return currentState().isBaseState();
302 }
303
timelineIsActive() const304 bool QmlObjectNode::timelineIsActive() const
305 {
306 return currentTimeline().isValid();
307 }
308
instanceCanReparent() const309 bool QmlObjectNode::instanceCanReparent() const
310 {
311 return isInBaseState();
312 }
313
propertyChangeForCurrentState() const314 QmlPropertyChanges QmlObjectNode::propertyChangeForCurrentState() const
315 {
316 if (!isValid())
317 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
318
319 if (currentState().isBaseState())
320 return QmlPropertyChanges();
321
322 if (!currentState().hasPropertyChanges(modelNode()))
323 return QmlPropertyChanges();
324
325 return currentState().propertyChanges(modelNode());
326 }
327
removeStateOperationsForChildren(const QmlObjectNode & node)328 static void removeStateOperationsForChildren(const QmlObjectNode &node)
329 {
330 if (node.isValid()) {
331 foreach (QmlModelStateOperation stateOperation, node.allAffectingStatesOperations()) {
332 stateOperation.modelNode().destroy(); //remove of belonging StatesOperations
333 }
334
335 foreach (const QmlObjectNode &childNode, node.modelNode().directSubModelNodes()) {
336 removeStateOperationsForChildren(childNode);
337 }
338 }
339 }
340
removeAliasExports(const QmlObjectNode & node)341 static void removeAliasExports(const QmlObjectNode &node)
342 {
343
344 PropertyName propertyName = node.id().toUtf8();
345
346 ModelNode rootNode = node.view()->rootModelNode();
347 bool hasAliasExport = !propertyName.isEmpty()
348 && rootNode.isValid()
349 && rootNode.hasBindingProperty(propertyName)
350 && rootNode.bindingProperty(propertyName).isAliasExport();
351
352 if (hasAliasExport)
353 rootNode.removeProperty(propertyName);
354
355 foreach (const ModelNode &childNode, node.modelNode().directSubModelNodes()) {
356 removeAliasExports(childNode);
357 }
358
359 }
360
removeLayerEnabled(const ModelNode & node)361 static void removeLayerEnabled(const ModelNode &node)
362 {
363 QTC_ASSERT(node.isValid(), return );
364 if (node.parentProperty().isValid() && node.parentProperty().name() == "layer.effect") {
365 ModelNode parent = node.parentProperty().parentModelNode();
366 if (parent.isValid() && parent.hasProperty("layer.enabled"))
367 parent.removeProperty("layer.enabled");
368 }
369 }
370
371 /*!
372 Deletes this object's node and its dependencies from the model.
373 Everything that belongs to this Object, the ModelNode, and ChangeOperations
374 is deleted from the model.
375 */
destroy()376 void QmlObjectNode::destroy()
377 {
378 if (!isValid())
379 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
380
381 removeLayerEnabled(modelNode());
382 removeAliasExports(modelNode());
383
384 for (QmlModelStateOperation stateOperation : allAffectingStatesOperations()) {
385 stateOperation.modelNode().destroy(); //remove of belonging StatesOperations
386 }
387
388 QVector<ModelNode> timelineNodes;
389 const auto allNodes = view()->allModelNodes();
390 for (const auto &timelineNode : allNodes) {
391 if (QmlTimeline::isValidQmlTimeline(timelineNode))
392 timelineNodes.append(timelineNode);
393 }
394
395 const auto subNodes = modelNode().allSubModelNodesAndThisNode();
396 for (auto &timelineNode : qAsConst(timelineNodes)) {
397 QmlTimeline timeline(timelineNode);
398 for (const auto &subNode : subNodes)
399 timeline.destroyKeyframesForTarget(subNode);
400 }
401
402 bool wasFlowEditorTarget = false;
403 if (QmlFlowTargetNode::isFlowEditorTarget(modelNode())) {
404 QmlFlowTargetNode(modelNode()).destroyTargets();
405 wasFlowEditorTarget = true;
406 }
407
408 removeStateOperationsForChildren(modelNode());
409 BindingProperty::deleteAllReferencesTo(modelNode());
410
411 QmlFlowViewNode root(view()->rootModelNode());
412
413 modelNode().destroy();
414
415 if (wasFlowEditorTarget && root.isValid())
416 root.removeDanglingTransitions();
417 }
418
ensureAliasExport()419 void QmlObjectNode::ensureAliasExport()
420 {
421 if (!isValid())
422 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
423
424 if (!isAliasExported()) {
425 modelNode().validId();
426 ModelNode rootModelNode = view()->rootModelNode();
427 rootModelNode.bindingProperty(modelNode().id().toUtf8()).
428 setDynamicTypeNameAndExpression("alias", modelNode().id());
429 }
430 }
431
isAliasExported() const432 bool QmlObjectNode::isAliasExported() const
433 {
434
435 if (modelNode().isValid() && !modelNode().id().isEmpty()) {
436 PropertyName modelNodeId = modelNode().id().toUtf8();
437 ModelNode rootModelNode = view()->rootModelNode();
438 Q_ASSERT(rootModelNode.isValid());
439 if (rootModelNode.hasBindingProperty(modelNodeId)
440 && rootModelNode.bindingProperty(modelNodeId).isDynamic()
441 && rootModelNode.bindingProperty(modelNodeId).expression() == modelNode().id())
442 return true;
443 }
444
445 return false;
446 }
447
448 /*!
449 Returns a list of states the affect this object.
450 */
451
allAffectingStates() const452 QList<QmlModelState> QmlObjectNode::allAffectingStates() const
453 {
454 if (!isValid())
455 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
456
457 QList<QmlModelState> returnList;
458
459 foreach (const QmlModelState &state, allDefinedStates()) {
460 if (state.affectsModelNode(modelNode()))
461 returnList.append(state);
462 }
463 return returnList;
464 }
465
466 /*!
467 Returns a list of all state operations that affect this object.
468 */
469
allAffectingStatesOperations() const470 QList<QmlModelStateOperation> QmlObjectNode::allAffectingStatesOperations() const
471 {
472 if (!isValid())
473 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
474
475 QList<QmlModelStateOperation> returnList;
476 foreach (const QmlModelState &state, allDefinedStates()) {
477 if (state.affectsModelNode(modelNode()))
478 returnList.append(state.stateOperations(modelNode()));
479 }
480
481 return returnList;
482 }
483
allQmlVisualNodesRecursive(const QmlItemNode & qmlItemNode)484 static QList<QmlVisualNode> allQmlVisualNodesRecursive(const QmlItemNode &qmlItemNode)
485 {
486 QList<QmlVisualNode> qmlVisualNodeList;
487
488 if (qmlItemNode.isValid()) {
489 qmlVisualNodeList.append(qmlItemNode);
490
491 foreach (const ModelNode &modelNode, qmlItemNode.modelNode().directSubModelNodes()) {
492 if (QmlVisualNode::isValidQmlVisualNode(modelNode))
493 qmlVisualNodeList.append(allQmlVisualNodesRecursive(modelNode));
494 }
495 }
496
497 return qmlVisualNodeList;
498 }
499
allDefinedStates() const500 QList<QmlModelState> QmlObjectNode::allDefinedStates() const
501 {
502 if (!isValid())
503 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
504
505 QList<QmlModelState> returnList;
506
507 QList<QmlVisualNode> allVisualNodes;
508
509 if (QmlVisualNode::isValidQmlVisualNode(view()->rootModelNode()))
510 allVisualNodes.append(allQmlVisualNodesRecursive(view()->rootModelNode()));
511
512 for (const QmlVisualNode &node : qAsConst(allVisualNodes))
513 returnList.append(node.states().allStates());
514
515 return returnList;
516 }
517
518
519 /*!
520 Removes a variant property of the object specified by \a name from the
521 model.
522 */
523
removeProperty(const PropertyName & name)524 void QmlObjectNode::removeProperty(const PropertyName &name)
525 {
526 if (!isValid())
527 throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
528
529 if (isInBaseState()) {
530 modelNode().removeProperty(name); //basestate
531 } else {
532 QmlPropertyChanges changeSet(currentState().propertyChanges(modelNode()));
533 Q_ASSERT(changeSet.isValid());
534 changeSet.removeProperty(name);
535 }
536 }
537
toModelNodeList(const QList<QmlObjectNode> & qmlObjectNodeList)538 QList<ModelNode> toModelNodeList(const QList<QmlObjectNode> &qmlObjectNodeList)
539 {
540 QList<ModelNode> modelNodeList;
541
542 foreach (const QmlObjectNode &qmlObjectNode, qmlObjectNodeList)
543 modelNodeList.append(qmlObjectNode.modelNode());
544
545 return modelNodeList;
546 }
547
toQmlObjectNodeList(const QList<ModelNode> & modelNodeList)548 QList<QmlObjectNode> toQmlObjectNodeList(const QList<ModelNode> &modelNodeList)
549 {
550 QList<QmlObjectNode> qmlObjectNodeList;
551
552 foreach (const ModelNode &modelNode, modelNodeList) {
553 if (QmlObjectNode::isValidQmlObjectNode(modelNode))
554 qmlObjectNodeList.append(modelNode);
555 }
556
557 return qmlObjectNodeList;
558 }
559
isAncestorOf(const QmlObjectNode & objectNode) const560 bool QmlObjectNode::isAncestorOf(const QmlObjectNode &objectNode) const
561 {
562 return modelNode().isAncestorOf(objectNode.modelNode());
563 }
564
instanceValue(const ModelNode & modelNode,const PropertyName & name)565 QVariant QmlObjectNode::instanceValue(const ModelNode &modelNode, const PropertyName &name)
566 {
567 Q_ASSERT(modelNode.view()->nodeInstanceView()->hasInstanceForModelNode(modelNode));
568 return modelNode.view()->nodeInstanceView()->instanceForModelNode(modelNode).property(name);
569 }
570
generateTranslatableText(const QString & text)571 QString QmlObjectNode::generateTranslatableText(const QString &text)
572 {
573 #ifndef QMLDESIGNER_TEST
574
575 if (QmlDesignerPlugin::instance()->settings().value(
576 DesignerSettingsKey::TYPE_OF_QSTR_FUNCTION).toInt())
577
578 switch (QmlDesignerPlugin::instance()->settings().value(
579 DesignerSettingsKey::TYPE_OF_QSTR_FUNCTION).toInt()) {
580 case 0: return QString(QStringLiteral("qsTr(\"%1\")")).arg(text);
581 case 1: return QString(QStringLiteral("qsTrId(\"%1\")")).arg(text);
582 case 2: return QString(QStringLiteral("qsTranslate(\"\"\"%1\")")).arg(text);
583 default:
584 break;
585
586 }
587 return QString(QStringLiteral("qsTr(\"%1\")")).arg(text);
588 #else
589 Q_UNUSED(text)
590 return QString();
591 #endif
592 }
593
instanceType(const PropertyName & name) const594 TypeName QmlObjectNode::instanceType(const PropertyName &name) const
595 {
596 return nodeInstance().instanceType(name);
597 }
598
instanceHasBinding(const PropertyName & name) const599 bool QmlObjectNode::instanceHasBinding(const PropertyName &name) const
600 {
601 return nodeInstance().hasBindingForProperty(name);
602 }
603
nodeInstance() const604 NodeInstance QmlObjectNode::nodeInstance() const
605 {
606 return nodeInstanceView()->instanceForModelNode(modelNode());
607 }
608
nodeForInstance(const NodeInstance & instance) const609 QmlObjectNode QmlObjectNode::nodeForInstance(const NodeInstance &instance) const
610 {
611 return QmlObjectNode(ModelNode(instance.modelNode(), view()));
612 }
613
itemForInstance(const NodeInstance & instance) const614 QmlItemNode QmlObjectNode::itemForInstance(const NodeInstance &instance) const
615 {
616 return QmlItemNode(ModelNode(instance.modelNode(), view()));
617 }
618
QmlObjectNode()619 QmlObjectNode::QmlObjectNode()
620 {
621 }
622
QmlObjectNode(const ModelNode & modelNode)623 QmlObjectNode::QmlObjectNode(const ModelNode &modelNode)
624 : QmlModelNodeFacade(modelNode)
625 {
626 }
627
isValidQmlObjectNode(const ModelNode & modelNode)628 bool QmlObjectNode::isValidQmlObjectNode(const ModelNode &modelNode)
629 {
630 return isValidQmlModelNodeFacade(modelNode);
631 }
632
isValid() const633 bool QmlObjectNode::isValid() const
634 {
635 return isValidQmlObjectNode(modelNode());
636 }
637
hasError() const638 bool QmlObjectNode::hasError() const
639 {
640 if (isValid())
641 return nodeInstance().hasError();
642 else
643 qDebug() << "called hasError() on an invalid QmlObjectNode";
644 return false;
645 }
646
error() const647 QString QmlObjectNode::error() const
648 {
649 if (hasError())
650 return nodeInstance().error();
651 return QString();
652 }
653
hasNodeParent() const654 bool QmlObjectNode::hasNodeParent() const
655 {
656 return modelNode().hasParentProperty();
657 }
658
hasInstanceParent() const659 bool QmlObjectNode::hasInstanceParent() const
660 {
661 return nodeInstance().parentId() >= 0 && nodeInstanceView()->hasInstanceForId(nodeInstance().parentId());
662 }
663
hasInstanceParentItem() const664 bool QmlObjectNode::hasInstanceParentItem() const
665 {
666 return isValid()
667 && nodeInstance().parentId() >= 0
668 && nodeInstanceView()->hasInstanceForId(nodeInstance().parentId())
669 && QmlItemNode::isItemOrWindow(view()->modelNodeForInternalId(nodeInstance().parentId()));
670 }
671
672
setParentProperty(const NodeAbstractProperty & parentProeprty)673 void QmlObjectNode::setParentProperty(const NodeAbstractProperty &parentProeprty)
674 {
675 return modelNode().setParentProperty(parentProeprty);
676 }
677
instanceParent() const678 QmlObjectNode QmlObjectNode::instanceParent() const
679 {
680 if (hasInstanceParent())
681 return nodeForInstance(nodeInstanceView()->instanceForId(nodeInstance().parentId()));
682
683 return QmlObjectNode();
684 }
685
instanceParentItem() const686 QmlItemNode QmlObjectNode::instanceParentItem() const
687 {
688 if (hasInstanceParentItem())
689 return itemForInstance(nodeInstanceView()->instanceForId(nodeInstance().parentId()));
690
691 return QmlItemNode();
692 }
693
modelParentItem() const694 QmlItemNode QmlObjectNode::modelParentItem() const
695 {
696 return modelNode().parentProperty().parentModelNode();
697 }
698
setId(const QString & id)699 void QmlObjectNode::setId(const QString &id)
700 {
701 modelNode().setIdWithRefactoring(id);
702 }
703
id() const704 QString QmlObjectNode::id() const
705 {
706 return modelNode().id();
707 }
708
validId()709 QString QmlObjectNode::validId()
710 {
711 return modelNode().validId();
712 }
713
hasDefaultPropertyName() const714 bool QmlObjectNode::hasDefaultPropertyName() const
715 {
716 return modelNode().metaInfo().hasDefaultProperty();
717 }
718
defaultPropertyName() const719 PropertyName QmlObjectNode::defaultPropertyName() const
720 {
721 return modelNode().metaInfo().defaultPropertyName();
722 }
723
setParent(const QmlObjectNode & newParent)724 void QmlObjectNode::setParent(const QmlObjectNode &newParent)
725 {
726 if (newParent.hasDefaultPropertyName())
727 newParent.modelNode().defaultNodeAbstractProperty().reparentHere(modelNode());
728 }
729
toQmlItemNode() const730 QmlItemNode QmlObjectNode::toQmlItemNode() const
731 {
732 return QmlItemNode(modelNode());
733 }
734
toQmlVisualNode() const735 QmlVisualNode QmlObjectNode::toQmlVisualNode() const
736 {
737 return QmlVisualNode(modelNode());
738 }
739
qHash(const QmlObjectNode & node)740 uint qHash(const QmlObjectNode &node)
741 {
742 return qHash(node.modelNode());
743 }
744
simplifiedTypeName() const745 QString QmlObjectNode::simplifiedTypeName() const
746 {
747 return modelNode().simplifiedTypeName();
748 }
749
allStateNames() const750 QStringList QmlObjectNode::allStateNames() const
751 {
752 return nodeInstance().allStateNames();
753 }
754
getQmlObjectNodeOfCorrectType(const ModelNode & modelNode)755 QmlObjectNode *QmlObjectNode::getQmlObjectNodeOfCorrectType(const ModelNode &modelNode)
756 {
757 // Create QmlObjectNode of correct type for the modelNode
758 // Note: Currently we are only interested in differentiating 3D nodes, so no check for
759 // visual nodes is done for efficiency reasons
760 if (modelNode.isValid() && modelNode.isSubclassOf("QtQuick3D.Node"))
761 return new Qml3DNode(modelNode);
762 return new QmlObjectNode(modelNode);
763 }
764
isBlocked(const PropertyName & propName) const765 bool QmlObjectNode::isBlocked(const PropertyName &propName) const
766 {
767 Q_UNUSED(propName)
768 return false;
769 }
770
771 } //QmlDesigner
772