void TestPropertyEditor::createSubNode() { std::auto_ptr<QWidget> widget(new QWidget()); QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}")); QVERIFY(model.data()); QScopedPointer<TestView> view(new TestView); QVERIFY(view.data()); model->attachView(view.data()); setupPropertyEditor(widget.get(), model.data()); QVERIFY(view->rootModelNode().isValid()); selectThrough(view->rootModelNode()); ModelNode childNode = view->createModelNode("Qt/Rectangle", 4, 6); view->rootModelNode().nodeListProperty("data").reparentHere(childNode); QVERIFY(childNode.isValid()); QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode)); QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode()); QCOMPARE(childNode.type(), QString("Qt/Rectangle")); selectThrough(childNode); QVERIFY(childNode.id().isEmpty()); childNode.setId("Blah"); QCOMPARE(childNode.id(), QString("Blah")); QCOMPARE(childNode.id(), QString("Blah")); }
void ComponentView::searchForComponentAndAddToList(const ModelNode &node) { QList<ModelNode> nodeList; nodeList.append(node); nodeList.append(node.allSubModelNodes()); foreach (const ModelNode &node, nodeList) { if (node.nodeSourceType() == ModelNode::ComponentSource) { if (!node.id().isEmpty()) { QStandardItem *item = new QStandardItem(node.id()); item->setData(QVariant::fromValue(node), ModelNodeRole); item->setEditable(false); removeSingleNodeFromList(node); //remove node if already present m_standardItemModel->appendRow(item); } else { QString description; ModelNode parentNode = node.parentProperty().parentModelNode(); if (parentNode.isValid()) if (!parentNode.id().isEmpty()) description = node.parentProperty().parentModelNode().id() + QLatin1Char(' '); else description = node.parentProperty().parentModelNode().simplifiedTypeName() + QLatin1Char(' '); description += node.parentProperty().name(); QStandardItem *item = new QStandardItem(description); item->setData(QVariant::fromValue(node), ModelNodeRole); item->setEditable(false); removeSingleNodeFromList(node); //remove node if already present m_standardItemModel->appendRow(item); } } } }
/*! Returns the node instance for \a node, which must be valid. Returns an invalid node instance if no node instance for this model node exists. \sa NodeInstance */ NodeInstance NodeInstanceView::instanceForModelNode(const ModelNode &node) const { Q_ASSERT(node.isValid()); Q_ASSERT(m_nodeInstanceHash.contains(node)); Q_ASSERT(m_nodeInstanceHash.value(node).modelNode() == node); return m_nodeInstanceHash.value(node); }
void QmlDesignerPlugin::selectModelNodeUnderTextCursor() { const int cursorPos = currentDesignDocument()->plainTextEdit()->textCursor().position(); ModelNode node = currentDesignDocument()->rewriterView()->nodeAtTextCursorPosition(cursorPos); if (currentDesignDocument()->rewriterView() && node.isValid()) currentDesignDocument()->rewriterView()->setSelectedModelNodes(QList<ModelNode>() << node); }
void GradientLineQmlAdaptor::setupGradient() { if (!active()) return; ModelNode modelNode = m_itemNode.modelNode(); QLinearGradient newGradient; QVector<QGradientStop> stops; if (!modelNode.isValid()) return; if (modelNode.hasBindingProperty(gradientName())) return; if (modelNode.hasProperty(gradientName())) { //gradient exists ModelNode gradientNode = modelNode.nodeProperty(gradientName()).modelNode(); QList<ModelNode> stopList = gradientNode.nodeListProperty("stops").toModelNodeList(); foreach (const ModelNode &stopNode, stopList) { QmlObjectNode stopObjectNode = stopNode; if (stopObjectNode.isValid()) { qreal position = stopObjectNode.modelValue("position").toReal(); QColor color = stopObjectNode.modelValue("color").value<QColor>(); stops.append( QPair<qreal, QColor>(position, color)); } }
void ModelToTextMerger::nodeSlidAround(const ModelNode &movingNode, const ModelNode &inFrontOfNode) { if (!inFrontOfNode.isValid() || movingNode.parentProperty() == inFrontOfNode.parentProperty()) schedule(new MoveNodeRewriteAction(movingNode, inFrontOfNode)); else Q_ASSERT(!"Nodes do not belong to the same containing property"); }
static ModelNode resolveBinding(const QString &binding, ModelNode currentNode, AbstractView* view) { int i = 0; QString element = binding.split(QLatin1Char('.')).at(0); while (!element.isEmpty()) { if (element == "parent") { if (currentNode.hasParentProperty()) currentNode = currentNode.parentProperty().toNodeAbstractProperty().parentModelNode(); else return ModelNode(); //binding not valid } else if (currentNode.hasProperty(element)) { if (currentNode.property(element).isNodeProperty()) { currentNode = currentNode.nodeProperty(element).modelNode(); } else { currentNode = view->modelNodeForId(element); //id if (!currentNode.isValid()) return ModelNode(); //binding not valid } } else { currentNode = view->modelNodeForId(element); //id } i++; if (i < binding.split(QLatin1Char('.')).count()) element = binding.split(QLatin1Char('.')).at(i); else element.clear(); } return currentNode; }
// TODO: this need to e updated for states static bool compareTree(const ModelNode &node1, const ModelNode &node2) { if (!node1.isValid() || !node2.isValid()) { return false; } if (node1.type() != node2.type()) { return false; } // Compare properties { const QList<AbstractProperty> propList1 = node1.properties(); const QList<AbstractProperty> propList2 = node2.properties(); QList<AbstractProperty>::const_iterator iter1 = propList1.constBegin(); QList<AbstractProperty>::const_iterator iter2 = propList2.constBegin(); for (; iter1 != propList1.constEnd() && iter2 != propList2.constEnd(); iter1++, iter2++) { if (!compareProperty(*iter1, *iter2)) return false; } if (iter1 != propList1.constEnd() || iter2 != propList2.constEnd()) return false; } // Compare list of children { const QList<ModelNode> childList1 = node1.allDirectSubModelNodes(); const QList<ModelNode> childList2 = node2.allDirectSubModelNodes(); QList<ModelNode>::const_iterator iter1; QList<ModelNode>::const_iterator iter2; for (iter1 = childList1.constBegin(), iter2 = childList2.constBegin(); iter1 != childList1.constEnd() && iter2 != childList2.constEnd(); iter1++, iter2++) { if (!compareTree((*iter1), (*iter2))) return false; } if (iter1 != childList1.constEnd() || iter2 != childList2.constEnd()) return false; } return true; }
QVariant StatesEditorModel::data(const QModelIndex &index, int role) const { if (index.parent().isValid() || index.column() != 0 || m_statesEditorView.isNull() || !m_statesEditorView->hasModelNodeForInternalId(index.internalId())) return QVariant(); ModelNode stateNode; if (index.internalId() > 0) stateNode = m_statesEditorView->modelNodeForInternalId(index.internalId()); switch (role) { case StateNameRole: { if (index.row() == 0) { return QString(tr("base state", "Implicit default state")); } else { if (stateNode.hasVariantProperty("name")) return stateNode.variantProperty("name").value(); else return QVariant(); } } case StateImageSourceRole: { static int randomNumber = 0; randomNumber++; if (index.row() == 0) return QString("image://qmldesigner_stateseditor/baseState-%1").arg(randomNumber); else return QString("image://qmldesigner_stateseditor/%1-%2").arg(index.internalId()).arg(randomNumber); } case InternalNodeId: return index.internalId(); case HasWhenCondition: return stateNode.isValid() && stateNode.hasProperty("when"); case WhenConditionString: { if (stateNode.isValid() && stateNode.hasBindingProperty("when")) return stateNode.bindingProperty("when").expression(); else return QString(); } } return QVariant(); }
static bool isFileComponent(const ModelNode &node) { if (node.isValid() && node.metaInfo().isValid() && node.metaInfo().isFileComponent()) return true; return false; }
void NameItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (option.state & QStyle::State_Selected) drawSelectionBackground(painter, option); QString displayString; QPoint displayStringOffset; painter->save(); QFontMetrics fm(option.font); int width = 0; if (index.data(Qt::UserRole).isValid()) { int pixmapSide = 16; if (m_TreeModel->isNodeInvisible( index )) painter->setOpacity(0.5); ModelNode node = m_TreeModel->nodeForIndex(index); QIcon icon; if (node.isValid()) { // if node has no own icon, search for it in the itemlibrary const ItemLibraryInfo *libraryInfo = node.model()->metaInfo().itemLibraryInfo(); QList <ItemLibraryEntry> infoList = libraryInfo->entriesForType(node.type(), node.majorVersion(), node.minorVersion()); foreach (const ItemLibraryEntry &entry, infoList) { if (icon.isNull()) { icon = entry.icon(); break; } } } // if the library was also empty, use the default icon if (icon.isNull()) icon = QIcon(QLatin1String(":/ItemLibrary/images/item-default-icon.png")); if (!node.metaInfo().isValid()) icon = QIcon(QLatin1String(":/ItemLibrary/images/item-invalid-icon.png")); // If no icon is present, leave an empty space of 24 pixels anyway QPixmap pixmap = icon.pixmap(pixmapSide, pixmapSide); painter->drawPixmap(option.rect.x()+1,option.rect.y()+2,pixmap); displayString = node.id(); if (displayString.isEmpty()) displayString = node.simplifiedTypeName(); // Check text length does not exceed available space int extraSpace=12+pixmapSide; displayString = fm.elidedText(displayString,Qt::ElideMiddle,option.rect.width()-extraSpace); displayStringOffset = QPoint(5+pixmapSide,-5); width = fm.width(displayString); }
static bool hasSourceWithFileComponent(const ModelNode &modelNode) { if (modelNode.isValid() && modelNode.metaInfo().isValid() && modelNode.metaInfo().isSubclassOf("QtQuick.Loader") && modelNode.hasVariantProperty("source")) return true; return false; }
void TestPropertyEditor::removeNode() { std::auto_ptr<QWidget> widget(new QWidget()); QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}")); QVERIFY(model.data()); QScopedPointer<TestView> view(new TestView); QVERIFY(view.data()); model->attachView(view.data()); setupPropertyEditor(widget.get(), model.data()); QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 0); selectThrough(view->rootModelNode()); ModelNode childNode = view->createModelNode("Qt/Rectangle", 4, 6); view->rootModelNode().nodeListProperty("data").reparentHere(childNode); QVERIFY(childNode.isValid()); QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 1); QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode)); QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode()); selectThrough(childNode); ModelNode subChildNode = view->createModelNode("Qt/Rectangle", 4, 6); childNode.nodeListProperty("data").reparentHere(subChildNode); QVERIFY(subChildNode.isValid()); QCOMPARE(childNode.allDirectSubModelNodes().count(), 1); QVERIFY(childNode.allDirectSubModelNodes().contains(subChildNode)); QVERIFY(subChildNode.parentProperty().parentModelNode() == childNode); selectThrough(subChildNode); childNode.destroy(); QCOMPARE(view->rootModelNode().allDirectSubModelNodes().count(), 0); QVERIFY(!view->rootModelNode().allDirectSubModelNodes().contains(childNode)); QVERIFY(!childNode.isValid()); QVERIFY(!subChildNode.isValid()); }
static bool hasDelegateWithFileComponent(const ModelNode &node) { if (node.isValid() && node.metaInfo().isValid() && node.metaInfo().isView() && node.hasNodeProperty("delegate") && node.nodeProperty("delegate").modelNode().metaInfo().isFileComponent()) return true; return false; }
VariantProperty DynamicPropertiesModel::variantPropertyForRow(int rowNumber) const { const int internalId = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 1).toInt(); const QString targetPropertyName = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 2).toString(); ModelNode modelNode = connectionView()->modelNodeForInternalId(internalId); if (modelNode.isValid()) return modelNode.variantProperty(targetPropertyName.toLatin1()); return VariantProperty(); }
void ModelNodePositionStorage::cleanupInvalidOffsets() { QHash<ModelNode, RewriterData> validModelNodes; QHashIterator<ModelNode, RewriterData> iter(m_rewriterData); while (iter.hasNext()) { iter.next(); const ModelNode modelNode = iter.key(); if (modelNode.isValid()) validModelNodes.insert(modelNode, iter.value()); } m_rewriterData = validModelNodes; }
bool detectVerticalCycle(const ModelNode &node, QList<ModelNode> knownNodeList) { if (!node.isValid()) return false; if (knownNodeList.contains(node)) return true; knownNodeList.append(node); static QStringList validAnchorLines(QStringList() << "top" << "bottom" << "verticalCenter" << "baseline"); static QStringList anchorNames(QStringList() << "anchors.top" << "anchors.bottom" << "anchors.verticalCenter" << "anchors.baseline"); foreach (const QString &anchorName, anchorNames) { if (node.hasBindingProperty(anchorName)) { AbstractProperty targetProperty = node.bindingProperty(anchorName).resolveToProperty(); if (targetProperty.isValid()) { if (!validAnchorLines.contains(targetProperty.name())) return true; if (detectVerticalCycle(targetProperty.parentModelNode(), knownNodeList)) return true; } } } static QStringList anchorShortcutNames(QStringList() << "anchors.fill" << "anchors.centerIn"); foreach (const QString &anchorName, anchorShortcutNames) { if (node.hasBindingProperty(anchorName)) { ModelNode targetNode = node.bindingProperty(anchorName).resolveToModelNode(); if (targetNode.isValid() && detectVerticalCycle(targetNode, knownNodeList)) return true; } } return false; }
static bool isLoaderWithSourceComponent(const ModelNode &modelNode) { if (modelNode.isValid() && modelNode.metaInfo().isValid() && modelNode.metaInfo().isSubclassOf("QtQuick.Loader")) { if (modelNode.hasNodeProperty("sourceComponent")) return true; if (modelNode.hasNodeListProperty("component")) return true; } return false; }
static bool isInEditedPath(const NodeAbstractProperty &propertyParent, const ModelNode &editingPathViewModelNode) { if (editingPathViewModelNode.isValid()) { if (editingPathViewModelNode.hasNodeProperty("path")) { ModelNode pathModelNode = editingPathViewModelNode.nodeProperty("path").modelNode(); if (pathModelNode.metaInfo().isSubclassOf("QtQuick.Path")) { if (propertyParent.name() == "pathElements" && propertyParent.parentModelNode() == pathModelNode) return true; } } } return false; }
void TestPropertyEditor::createRect() { try { std::auto_ptr<QWidget> widget(new QWidget()); QScopedPointer<Model> model(Model::create("import Qt 4.6\n Item {}")); QVERIFY(model.data()); QScopedPointer<TestView> view(new TestView); QVERIFY(view.data()); model->attachView(view.data()); setupPropertyEditor(widget.get(), model.data()); QVERIFY(view->rootModelNode().isValid()); //selectThrough(view->rootModelNode()); ModelNode childNode = view->createModelNode("Qt/Rectangle", 4, 6); view->rootModelNode().nodeListProperty("data").reparentHere(childNode); QVERIFY(childNode.isValid()); QVERIFY(view->rootModelNode().allDirectSubModelNodes().contains(childNode)); QVERIFY(childNode.parentProperty().parentModelNode() == view->rootModelNode()); QCOMPARE(childNode.type(), QString("Qt/Rectangle")); QVERIFY(childNode.id().isEmpty()); childNode.setId("Rect01"); QCOMPARE(childNode.id(), QString("Rect01")); childNode.variantProperty("x") = 100; QCOMPARE(QmlObjectNode(childNode).instanceValue("x").toInt(), 100); childNode.variantProperty("y") = 100; QCOMPARE(QmlObjectNode(childNode).instanceValue("y").toInt(), 100); childNode.variantProperty("width") = 100; QCOMPARE(QmlObjectNode(childNode).instanceValue("width").toInt(), 100); childNode.variantProperty("height") = 100; QCOMPARE(QmlObjectNode(childNode).instanceValue("height").toInt(), 100); selectThrough(childNode); QCOMPARE(childNode.propertyNames().count(), 4); QCOMPARE(childNode.variantProperty("scale").value(), QVariant()); } catch (Exception &) { QFAIL("Exception thrown"); } }
static bool nodeOrParentInSet(const ModelNode &node, const QSet<ModelNode> &nodeSet) { ModelNode n = node; while (n.isValid()) { if (nodeSet.contains(n)) return true; if (!n.hasParentProperty()) return false; n = n.parentProperty().parentModelNode(); } return false; }
bool QmlObjectNode::isAliasExported() const { if (modelNode().isValid() && !modelNode().id().isEmpty()) { PropertyName modelNodeId = modelNode().id().toUtf8(); ModelNode rootModelNode = view()->rootModelNode(); Q_ASSERT(rootModelNode.isValid()); if (rootModelNode.hasBindingProperty(modelNodeId) && rootModelNode.bindingProperty(modelNodeId).isDynamic() && rootModelNode.bindingProperty(modelNodeId).expression().toUtf8() == modelNodeId) return true; } return false; }
static bool nodeOrParentInSet(const ModelNode &modelNode, const QSet<ModelNode> &nodeSet) { ModelNode currentModelnode = modelNode; while (currentModelnode.isValid()) { if (nodeSet.contains(currentModelnode)) return true; if (!currentModelnode.hasParentProperty()) return false; currentModelnode = currentModelnode.parentProperty().parentModelNode(); } return false; }
void DocumentManager::goIntoComponent(const ModelNode &modelNode) { if (modelNode.isValid() && modelNode.isComponent()) { QmlDesignerPlugin::instance()->viewManager().setComponentNode(modelNode); if (isFileComponent(modelNode)) openFileComponent(modelNode); else if (hasDelegateWithFileComponent(modelNode)) openFileComponentForDelegate(modelNode); else if (hasSourceWithFileComponent(modelNode)) openSourcePropertyOfLoader(modelNode); else if (isLoaderWithSourceComponent(modelNode)) openComponentSourcePropertyOfLoader(modelNode); else openInlineComponent(modelNode); } }
void NodeInstanceView::modelAttached(Model *model) { AbstractView::modelAttached(model); m_nodeInstanceServer = new NodeInstanceServerProxy(this, m_runModus, m_currentKit); m_lastCrashTime.start(); connect(m_nodeInstanceServer.data(), SIGNAL(processCrashed()), this, SLOT(handleChrash())); if (!isSkippedRootNode(rootModelNode())) nodeInstanceServer()->createScene(createCreateSceneCommand()); ModelNode stateNode = currentStateNode(); if (stateNode.isValid() && stateNode.metaInfo().isSubclassOf("QtQuick.State", 1, 0)) { NodeInstance newStateInstance = instanceForModelNode(stateNode); activateState(newStateInstance); } }
NavigatorTreeModel::ItemRow NavigatorTreeModel::createItemRow(const ModelNode &node) { Q_ASSERT(node.isValid()); uint hash = node.internalId(); const bool dropEnabled = node.metaInfo().isValid(); QStandardItem *idItem = new QStandardItem; idItem->setDragEnabled(true); idItem->setDropEnabled(dropEnabled); idItem->setEditable(true); idItem->setData(hash, NavigatorRole); if (node.metaInfo().isValid()) idItem->setToolTip(node.type()); else idItem->setToolTip(msgUnknownItem(node.type())); # ifdef _LOCK_ITEMS_ QStandardItem *lockItem = new QStandardItem; lockItem->setDragEnabled(true); lockItem->setDropEnabled(dropEnabled); lockItem->setEditable(false); lockItem->setCheckable(true); lockItem->setData(hash, NavigatorRole); # endif QStandardItem *visibilityItem = new QStandardItem; visibilityItem->setDropEnabled(dropEnabled); visibilityItem->setCheckable(true); visibilityItem->setEditable(false); visibilityItem->setData(hash, NavigatorRole); if (node.isRootNode()) visibilityItem->setCheckable(false); QMap<QString, QStandardItem *> propertyItems; foreach (const QString &propertyName, visibleProperties(node)) { QStandardItem *propertyItem = new QStandardItem; propertyItem->setSelectable(false); propertyItem->setDragEnabled(false); propertyItem->setDropEnabled(dropEnabled); propertyItem->setEditable(false); propertyItem->setData(propertyName, Qt::DisplayRole); propertyItems.insert(propertyName, propertyItem); idItem->appendRow(propertyItem); }
static void removeAliasExports(const QmlObjectNode &node) { PropertyName propertyName = node.id().toUtf8(); ModelNode rootNode = node.view()->rootModelNode(); bool hasAliasExport = !propertyName.isEmpty() && rootNode.isValid() && rootNode.hasBindingProperty(propertyName) && rootNode.bindingProperty(propertyName).isAliasExport(); if (hasAliasExport) rootNode.removeProperty(propertyName); foreach (const ModelNode &childNode, node.modelNode().directSubModelNodes()) { removeAliasExports(childNode); } }
void DocumentManager::goIntoComponent(const ModelNode &modelNode) { if (modelNode.isValid() && modelNode.isComponent() && designDocument()) { QmlDesignerPlugin::instance()->viewManager().setComponentNode(modelNode); QHash<PropertyName, QVariant> oldProperties = getProperties(modelNode); if (isFileComponent(modelNode)) openFileComponent(modelNode); else if (hasDelegateWithFileComponent(modelNode)) openFileComponentForDelegate(modelNode); else if (hasSourceWithFileComponent(modelNode)) openSourcePropertyOfLoader(modelNode); else if (isLoaderWithSourceComponent(modelNode)) openComponentSourcePropertyOfLoader(modelNode); else openInlineComponent(modelNode); ModelNode rootModelNode = designDocument()->rewriterView()->rootModelNode(); applyProperties(rootModelNode, oldProperties); } }
static inline void openInlineComponent(const ModelNode &modelNode) { if (!modelNode.isValid() || !modelNode.metaInfo().isValid()) return; if (!currentDesignDocument()) return; QHash<PropertyName, QVariant> propertyHash; getProperties(modelNode, propertyHash); handleComponent(modelNode); handleDelegate(modelNode); handleTabComponent(modelNode); ModelNode rootModelNode = currentDesignDocument()->rewriterView()->rootModelNode(); applyProperties(rootModelNode, propertyHash); }
void QmlDesignerPlugin::jumpTextCursorToSelectedModelNode() { // visual editor -> text editor ModelNode selectedNode; if (!currentDesignDocument()->rewriterView()->selectedModelNodes().isEmpty()) selectedNode = currentDesignDocument()->rewriterView()->selectedModelNodes().first(); if (selectedNode.isValid()) { const int nodeOffset = currentDesignDocument()->rewriterView()->nodeOffset(selectedNode); if (nodeOffset > 0) { const ModelNode currentSelectedNode = currentDesignDocument()->rewriterView()->nodeAtTextCursorPosition(currentDesignDocument()->plainTextEdit()->textCursor().position()); if (currentSelectedNode != selectedNode) { int line, column; currentDesignDocument()->textEditor()->convertPosition(nodeOffset, &line, &column); currentDesignDocument()->textEditor()->gotoLine(line, column); } } } }