diff --git a/share/qtcreator/qml/qmlpuppet/interfaces/nodeinstanceglobal.h b/share/qtcreator/qml/qmlpuppet/interfaces/nodeinstanceglobal.h index a7f9b3629bc..6466ace7f9c 100644 --- a/share/qtcreator/qml/qmlpuppet/interfaces/nodeinstanceglobal.h +++ b/share/qtcreator/qml/qmlpuppet/interfaces/nodeinstanceglobal.h @@ -28,10 +28,13 @@ #include #include +#include + namespace QmlDesigner { using PropertyName = QByteArray; using PropertyNameList = QList; +using PropertyNames = std::vector; using TypeName = QByteArray; } diff --git a/src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp b/src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp index ce4f124d340..c10c7498f99 100644 --- a/src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp +++ b/src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp @@ -143,6 +143,8 @@ void ActionEditor::setModelNode(const ModelNode &modelNode) m_modelNode = modelNode; } +namespace { + bool isLiteral(QmlJS::AST::Node *ast) { if (QmlJS::AST::cast(ast) @@ -154,6 +156,17 @@ bool isLiteral(QmlJS::AST::Node *ast) return false; } +TypeName skipCpp(TypeName typeName) +{ + // TODO remove after project storage introduction + + if (typeName.contains(".")) + typeName.remove(0, 6); + + return typeName; +} + +} // namespace void ActionEditor::prepareConnections() { if (!m_modelNode.isValid()) @@ -197,17 +210,15 @@ void ActionEditor::prepareConnections() ActionEditorDialog::ConnectionOption connection(modelNode.id()); - for (const auto &propertyName : modelNode.metaInfo().propertyNames()) { - if (!typeWhiteList.contains(modelNode.metaInfo().propertyTypeName(propertyName))) + for (const auto &property : modelNode.metaInfo().properties()) { + const auto &propertyTypeName = property.propertyTypeName(); + if (!typeWhiteList.contains(propertyTypeName)) continue; - const QString name = QString::fromUtf8(propertyName); - const bool writeable = modelNode.metaInfo().propertyIsWritable(propertyName); - TypeName type = modelNode.metaInfo().propertyTypeName(propertyName); - if (type.contains(".")) - type.remove(0, 6); - - connection.properties.append(ActionEditorDialog::PropertyOption(name, type, writeable)); + connection.properties.append( + ActionEditorDialog::PropertyOption(QString::fromUtf8(property.name()), + skipCpp(std::move(propertyTypeName)), + property.isWritable())); } for (const VariantProperty &variantProperty : modelNode.variantProperties()) { @@ -216,12 +227,12 @@ void ActionEditor::prepareConnections() continue; const QString name = QString::fromUtf8(variantProperty.name()); - const bool writeable = modelNode.metaInfo().propertyIsWritable(variantProperty.name()); - TypeName type = variantProperty.dynamicTypeName(); - if (type.contains(".")) - type.remove(0, 6); + const bool writeable = modelNode.metaInfo().property(variantProperty.name()).isWritable(); - connection.properties.append(ActionEditorDialog::PropertyOption(name, type, writeable)); + connection.properties.append( + ActionEditorDialog::PropertyOption(name, + skipCpp(variantProperty.dynamicTypeName()), + writeable)); } } @@ -259,18 +270,16 @@ void ActionEditor::prepareConnections() NodeMetaInfo metaInfo = m_modelNode.view()->model()->metaInfo(data.typeName.toUtf8()); if (metaInfo.isValid()) { ActionEditorDialog::SingletonOption singelton; - for (const PropertyName &propertyName : metaInfo.propertyNames()) { - TypeName type = metaInfo.propertyTypeName(propertyName); + for (const auto &property : metaInfo.properties()) { + const TypeName &typeName = property.propertyTypeName(); - if (!typeWhiteList.contains(type)) + if (!typeWhiteList.contains(typeName)) continue; - const QString name = QString::fromUtf8(propertyName); - const bool writeable = metaInfo.propertyIsWritable(propertyName); - if (type.contains(".")) - type.remove(0, 6); - - singelton.properties.append(ActionEditorDialog::PropertyOption(name, type, writeable)); + singelton.properties.append( + ActionEditorDialog::PropertyOption(QString::fromUtf8(property.name()), + skipCpp(typeName), + property.isWritable())); } if (!singelton.properties.isEmpty()) { diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp index eff90366a0a..27e8a41cb3c 100644 --- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp @@ -113,7 +113,7 @@ void BindingEditor::setBackendValue(const QVariant &backendValue) const ModelNode node = propertyEditorValue->modelNode(); if (node.isValid()) { - m_backendValueTypeName = node.metaInfo().propertyTypeName(propertyEditorValue->name()); + m_backendValueTypeName = node.metaInfo().property(propertyEditorValue->name()).propertyTypeName(); QString nodeId = node.id(); if (nodeId.isEmpty()) @@ -205,14 +205,14 @@ void BindingEditor::prepareBindings() for (const auto &objnode : allNodes) { BindingEditorDialog::BindingOption binding; - for (const auto &propertyName : objnode.metaInfo().propertyNames()) { - TypeName propertyTypeName = objnode.metaInfo().propertyTypeName(propertyName); + for (const auto &property : objnode.metaInfo().properties()) { + const TypeName &propertyTypeName = property.propertyTypeName(); if (skipTypeFiltering || (m_backendValueTypeName == propertyTypeName) || isVariant(propertyTypeName) || (targetTypeIsNumeric && isNumeric(propertyTypeName))) { - binding.properties.append(QString::fromUtf8(propertyName)); + binding.properties.append(QString::fromUtf8(property.name())); } } @@ -259,15 +259,15 @@ void BindingEditor::prepareBindings() if (metaInfo.isValid()) { BindingEditorDialog::BindingOption binding; - for (const PropertyName &propertyName : metaInfo.propertyNames()) { - TypeName propertyTypeName = metaInfo.propertyTypeName(propertyName); + for (const auto &property : metaInfo.properties()) { + TypeName propertyTypeName = property.propertyTypeName(); if (skipTypeFiltering || (m_backendValueTypeName == propertyTypeName) || (isVariant(propertyTypeName)) || (targetTypeIsNumeric && isNumeric(propertyTypeName)) || (isColor(m_backendValueTypeName) && isColor(propertyTypeName))) { - binding.properties.append(QString::fromUtf8(propertyName)); + binding.properties.append(QString::fromUtf8(property.name())); } } diff --git a/src/plugins/qmldesigner/components/bindingeditor/signallist.cpp b/src/plugins/qmldesigner/components/bindingeditor/signallist.cpp index f87000ddbab..603f2004fd4 100644 --- a/src/plugins/qmldesigner/components/bindingeditor/signallist.cpp +++ b/src/plugins/qmldesigner/components/bindingeditor/signallist.cpp @@ -39,6 +39,8 @@ #include #include +#include + #include #include #include @@ -137,6 +139,20 @@ void SignalList::setModelNode(const ModelNode &modelNode) m_modelNode = modelNode; } +namespace { +template +void callOnlyMouseSignalNames(const PropertyNameList &signalNames, + const PropertyNameList &mouseSignalNames, + const Callback &callback) +{ + std::set_union(signalNames.begin(), + signalNames.end(), + mouseSignalNames.begin(), + mouseSignalNames.end(), + Utils::make_iterator(callback)); +} +} // namespace + void SignalList::prepareSignals() { if (!m_modelNode.isValid()) @@ -145,27 +161,21 @@ void SignalList::prepareSignals() QList connections = QmlFlowViewNode::getAssociatedConnections(m_modelNode); for (ModelNode &node : m_modelNode.view()->allModelNodes()) { - // Collect all items which contain at least one of the specified signals - const PropertyNameList signalNames = node.metaInfo().signalNames(); - // Put the signals into a QSet to avoid duplicates - auto signalNamesSet = QSet(signalNames.begin(), signalNames.end()); - for (const PropertyName &signal : signalNamesSet) { - if (QmlFlowViewNode::st_mouseSignals.contains(signal)) - appendSignalToModel(connections, node, signal); - } + callOnlyMouseSignalNames(node.metaInfo().signalNames(), + QmlFlowViewNode::mouseSignals(), + [&](const PropertyName &signal) { + appendSignalToModel(connections, node, signal); + }); // Gather valid properties and aliases from components - for (const PropertyName &property : node.metaInfo().propertyNames()) { - const TypeName propertyType = node.metaInfo().propertyTypeName(property); - const NodeMetaInfo info = m_modelNode.model()->metaInfo(propertyType); - // Collect all items which contain at least one of the specified signals - const PropertyNameList signalNames = info.signalNames(); - // Put the signals into a QSet to avoid duplicates - auto signalNamesSet = QSet(signalNames.begin(), signalNames.end()); - for (const PropertyName &signal : signalNamesSet) { - if (QmlFlowViewNode::st_mouseSignals.contains(signal)) - appendSignalToModel(connections, node, signal, property); - } + for (const auto &property : node.metaInfo().properties()) { + const NodeMetaInfo info = m_modelNode.model()->metaInfo(property.propertyTypeName()); + + callOnlyMouseSignalNames(info.signalNames(), + QmlFlowViewNode::mouseSignals(), + [&](const PropertyName &signal) { + appendSignalToModel(connections, node, signal); + }); } } } diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index 068e9cf2fd8..9b7c6e2757b 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -568,11 +568,17 @@ void layoutGridLayout(const SelectionContext &selectionContext) } } -static PropertyNameList sortedPropertyNameList(const PropertyNameList &nameList) +static PropertyNameList sortedPropertyNameList(const PropertyMetaInfos &properties) { - PropertyNameList sortedPropertyNameList = nameList; - std::stable_sort(sortedPropertyNameList.begin(), sortedPropertyNameList.end()); - return sortedPropertyNameList; + auto propertyNames = Utils::transform(properties, [](const auto &property) { + return property.name(); + }); + + std::sort(propertyNames.begin(), propertyNames.end()); + + propertyNames.erase(std::unique(propertyNames.begin(), propertyNames.end()), propertyNames.end()); + + return propertyNames; } static QString toUpper(const QString &signal) @@ -628,12 +634,14 @@ static QStringList getSortedSignalNameList(const ModelNode &modelNode) QStringList signalNames; if (metaInfo.isValid()) { - const PropertyNameList signalNameList = sortedPropertyNameList(metaInfo.signalNames()); + // TODO seem to be broken because there can be properties without notifier and the notifier can be even have a different name + + const PropertyNameList signalNameList = metaInfo.signalNames(); for (const PropertyName &signalName : signalNameList) if (!signalName.contains("Changed")) signalNames.append(QString::fromUtf8(signalName)); - const PropertyNameList propertyNameList = sortedPropertyNameList(metaInfo.propertyNames()); + const PropertyNameList propertyNameList = sortedPropertyNameList(metaInfo.properties()); for (const PropertyName &propertyName : propertyNameList) if (!propertyName.contains(".")) signalNames.append(QString::fromUtf8(propertyName + "Changed")); diff --git a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp index 03c08f96c46..b0368793ccd 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp +++ b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp @@ -138,14 +138,15 @@ QStringList BindingModel::possibleTargetProperties(const BindingProperty &bindin NodeMetaInfo metaInfo = modelNode.metaInfo(); if (metaInfo.isValid()) { - QStringList possibleProperties; - const QList propertyNames = metaInfo.propertyNames(); - for (const PropertyName &propertyName : propertyNames) { - if (metaInfo.propertyIsWritable(propertyName)) - possibleProperties << QString::fromUtf8(propertyName); + const auto properties = metaInfo.properties(); + QStringList writableProperties; + writableProperties.reserve(static_cast(properties.size())); + for (const auto &property : properties) { + if (property.isWritable()) + writableProperties.push_back(QString::fromUtf8(property.name())); } - return possibleProperties; + return writableProperties; } return QStringList(); @@ -159,11 +160,10 @@ QStringList BindingModel::possibleSourceProperties(const BindingProperty &bindin TypeName typeName; - if (bindingProperty.parentModelNode().metaInfo().isValid()) { - typeName = bindingProperty.parentModelNode().metaInfo().propertyTypeName(bindingProperty.name()); - } else { + if (auto metaInfo = bindingProperty.parentModelNode().metaInfo(); metaInfo.isValid()) + typeName = metaInfo.property(bindingProperty.name()).propertyTypeName(); + else qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for target node"; - } const QString &id = stringlist.constFirst(); @@ -178,9 +178,9 @@ QStringList BindingModel::possibleSourceProperties(const BindingProperty &bindin NodeMetaInfo metaInfo = connectionView()->model()->metaInfo(data.typeName.toUtf8()); if (metaInfo.isValid()) { - for (const PropertyName &propertyName : metaInfo.propertyNames()) { + for (const auto &property : metaInfo.properties()) { //without check for now - possibleProperties << QString::fromUtf8(propertyName); + possibleProperties.push_back(QString::fromUtf8(property.name())); } return possibleProperties; @@ -207,9 +207,9 @@ QStringList BindingModel::possibleSourceProperties(const BindingProperty &bindin } if (metaInfo.isValid()) { - for (const PropertyName &propertyName : metaInfo.propertyNames()) { - if (metaInfo.propertyTypeName(propertyName) == typeName) //### todo proper check - possibleProperties << QString::fromUtf8(propertyName); + for (const auto &property : metaInfo.properties()) { + if (property.propertyTypeName() == typeName) //### todo proper check + possibleProperties.push_back(QString::fromUtf8(property.name())); } } else { qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for source node"; @@ -233,10 +233,9 @@ static PropertyName unusedProperty(const ModelNode &modelNode) { PropertyName propertyName = "none"; if (modelNode.metaInfo().isValid()) { - const QList propertyNames = modelNode.metaInfo().propertyNames(); - for (const PropertyName &propertyName : propertyNames) { - if (modelNode.metaInfo().propertyIsWritable(propertyName) && !modelNode.hasProperty(propertyName)) - return propertyName; + for (const auto &property : modelNode.metaInfo().properties()) { + if (property.isWritable() && !modelNode.hasProperty(propertyName)) + return property.name(); } } diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp index c9d2de9e72d..bf5d24ddd0d 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp +++ b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp @@ -475,7 +475,7 @@ QStringList ConnectionModel::getPossibleSignalsForConnection(const ModelNode &co auto getAliasMetaSignals = [&](QString aliasPart, NodeMetaInfo metaInfo) { if (metaInfo.isValid() && metaInfo.hasProperty(aliasPart.toUtf8())) { NodeMetaInfo propertyMetaInfo = connectionView()->model()->metaInfo( - metaInfo.propertyTypeName(aliasPart.toUtf8())); + metaInfo.property(aliasPart.toUtf8()).propertyTypeName()); if (propertyMetaInfo.isValid()) { return propertyNameListToStringList(propertyMetaInfo.signalNames()); } diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp index de64139cb91..06998b58c50 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp +++ b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp @@ -216,8 +216,9 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event) return; const ModelNode node = property.parentModelNode(); - const TypeName typeName = property.isDynamic() ? property.dynamicTypeName() - : node.metaInfo().propertyTypeName(property.name()); + const TypeName typeName = property.isDynamic() + ? property.dynamicTypeName() + : node.metaInfo().property(property.name()).propertyTypeName(); const QString targetName = node.displayName() + "." + property.name(); diff --git a/src/plugins/qmldesigner/components/connectioneditor/delegates.cpp b/src/plugins/qmldesigner/components/connectioneditor/delegates.cpp index 67a8473e5a4..a46cd9cb8a9 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/delegates.cpp +++ b/src/plugins/qmldesigner/components/connectioneditor/delegates.cpp @@ -298,23 +298,19 @@ QWidget *ConnectionDelegate::createEditor(QWidget *parent, const QStyleOptionVie auto addMetaInfoProperties = [&](const NodeMetaInfo& itemMetaInfo, QString itemName){ if (itemMetaInfo.isValid()) { - for (const PropertyName &propertyName : itemMetaInfo.propertyNames()) { - TypeName propertyType = itemMetaInfo.propertyTypeName(propertyName); + for (const auto &property : itemMetaInfo.properties()) { + TypeName propertyType = property.propertyTypeName(); if (!propertyType.isEmpty()) { //first letter is a reliable item indicator QChar firstLetter = QString::fromUtf8(propertyType).at(0); if (firstLetter.isLetter() && firstLetter.isUpper()) { - if (!itemMetaInfo.propertyIsEnumType(propertyName) - && !itemMetaInfo.propertyIsPrivate(propertyName) - && !itemMetaInfo.propertyIsListProperty(propertyName) - && !itemMetaInfo.propertyIsPointer(propertyName)) { + if (!property.isEnumType() && !property.isPrivate() + && !property.isListProperty() && !property.isPointer()) { NodeMetaInfo propertyMetaInfo = connectionModel->connectionView()->model()->metaInfo(propertyType); if (propertyMetaInfo.isValid()) { if (propertyMetaInfo.isQmlItem()) { - connectionComboBox->addItem(itemName - + "." - + propertyName); + connectionComboBox->addItem(itemName + "." + property.name()); } } } diff --git a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp index 52401a74009..e45cac43287 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp +++ b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp @@ -36,6 +36,7 @@ #include #include +#include #include #include @@ -345,10 +346,9 @@ QStringList DynamicPropertiesModel::possibleTargetProperties(const BindingProper if (metaInfo.isValid()) { QStringList possibleProperties; - const QList propertyNames = metaInfo.propertyNames(); - for (const PropertyName &propertyName : propertyNames) { - if (metaInfo.propertyIsWritable(propertyName)) - possibleProperties << QString::fromUtf8(propertyName); + for (const auto &property : metaInfo.properties()) { + if (property.isWritable()) + possibleProperties.push_back(QString::fromUtf8(property.name())); } return possibleProperties; @@ -383,8 +383,8 @@ QStringList DynamicPropertiesModel::possibleSourceProperties(const BindingProper PropertyName typeName; - if (bindingProperty.parentModelNode().metaInfo().isValid()) { - typeName = bindingProperty.parentModelNode().metaInfo().propertyTypeName(bindingProperty.name()); + if (auto metaInfo = bindingProperty.parentModelNode().metaInfo(); metaInfo.isValid()) { + typeName = metaInfo.property(bindingProperty.name()).propertyTypeName(); } else { qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for target node"; } @@ -402,10 +402,9 @@ QStringList DynamicPropertiesModel::possibleSourceProperties(const BindingProper if (metaInfo.isValid()) { QStringList possibleProperties; - const QList propertyNames = metaInfo.propertyNames(); - for (const PropertyName &propertyName : propertyNames) { - if (metaInfo.propertyTypeName(propertyName) == typeName) //### todo proper check - possibleProperties << QString::fromUtf8(propertyName); + for (const auto &property : metaInfo.properties()) { + if (property.propertyTypeName() == typeName) //### todo proper check + possibleProperties.push_back(QString::fromUtf8(property.name())); } return possibleProperties; } else { diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp index e9e76c29cba..2ee52dc947e 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp @@ -658,7 +658,7 @@ void DesignDocument::paste() PropertyName defaultProperty(targetNode.metaInfo().defaultPropertyName()); scatterItem(pastedNode, targetNode); - if (targetNode.metaInfo().propertyIsListProperty(defaultProperty)) + if (targetNode.metaInfo().property(defaultProperty).isListProperty()) targetNode.nodeListProperty(defaultProperty).reparentHere(pastedNode); else qWarning() << "Cannot reparent to" << targetNode; diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp index 435c5318979..cf789bcd66e 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp @@ -99,7 +99,8 @@ void MaterialEditorContextObject::changeTypeName(const QString &typeName) QTC_ASSERT(metaInfo.isValid(), return); // Create a list of properties available for the new type - PropertyNameList propertiesAndSignals(metaInfo.propertyNames()); + PropertyNameList propertiesAndSignals = Utils::transform( + metaInfo.properties(), [](const auto &property) { return property.name(); }); // Add signals to the list const PropertyNameList signalNames = metaInfo.signalNames(); for (const PropertyName &signal : signalNames) { diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp index 7c5d8436226..8611f41aca4 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp @@ -270,9 +270,12 @@ void MaterialEditorQmlBackend::setup(const QmlObjectNode &selectedMaterialNode, if (selectedMaterialNode.isValid()) { m_contextObject->setModel(materialEditor->model()); - const PropertyNameList propertyNames = selectedMaterialNode.modelNode().metaInfo().propertyNames(); - for (const PropertyName &propertyName : propertyNames) - createPropertyEditorValue(selectedMaterialNode, propertyName, selectedMaterialNode.instanceValue(propertyName), materialEditor); + for (const auto &property : selectedMaterialNode.modelNode().metaInfo().properties()) { + createPropertyEditorValue(selectedMaterialNode, + property.name(), + selectedMaterialNode.instanceValue(property.name()), + materialEditor); + } // model node m_backendModelNode.setup(selectedMaterialNode.modelNode()); diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp index 3184c718d99..bd86d1b0430 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp @@ -125,7 +125,7 @@ void MaterialEditorView::changeValue(const QString &name) QVariant castedValue; if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) { - castedValue = metaInfo.propertyCastedValue(propertyName, value->value()); + castedValue = metaInfo.property(propertyName).castedValue(value->value()); } else { qWarning() << __FUNCTION__ << propertyName << "cannot be casted (metainfo)"; return; @@ -139,8 +139,7 @@ void MaterialEditorView::changeValue(const QString &name) bool propertyTypeUrl = false; if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) { - if (metaInfo.propertyTypeName(propertyName) == "QUrl" - || metaInfo.propertyTypeName(propertyName) == "url") { + if (metaInfo.property(propertyName).hasPropertyTypeName("QUrl", "url")) { // turn absolute local file paths into relative paths propertyTypeUrl = true; QString filePath = castedValue.toUrl().toString(); @@ -202,13 +201,15 @@ void MaterialEditorView::changeExpression(const QString &propertyName) return; } - if (m_selectedMaterial.metaInfo().isValid() && m_selectedMaterial.metaInfo().hasProperty(name)) { - if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "QColor") { + if (auto metaInfo = m_selectedMaterial.metaInfo(); + metaInfo.isValid() && metaInfo.hasProperty(name)) { + auto propertyTypeName = metaInfo.property(name).propertyTypeName(); + if (propertyTypeName == "QColor") { if (QColor(value->expression().remove('"')).isValid()) { qmlObjectNode.setVariantProperty(name, QColor(value->expression().remove('"'))); return; } - } else if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "bool") { + } else if (propertyTypeName == "bool") { if (isTrueFalseLiteral(value->expression())) { if (value->expression().compare("true", Qt::CaseInsensitive) == 0) qmlObjectNode.setVariantProperty(name, true); @@ -216,21 +217,21 @@ void MaterialEditorView::changeExpression(const QString &propertyName) qmlObjectNode.setVariantProperty(name, false); return; } - } else if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "int") { + } else if (propertyTypeName == "int") { bool ok; int intValue = value->expression().toInt(&ok); if (ok) { qmlObjectNode.setVariantProperty(name, intValue); return; } - } else if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "qreal") { + } else if (propertyTypeName == "qreal") { bool ok; qreal realValue = value->expression().toDouble(&ok); if (ok) { qmlObjectNode.setVariantProperty(name, realValue); return; } - } else if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "QVariant") { + } else if (propertyTypeName == "QVariant") { bool ok; qreal realValue = value->expression().toDouble(&ok); if (ok) { @@ -809,7 +810,7 @@ void QmlDesigner::MaterialEditorView::highlightSupportedProperties(bool highligh QTC_ASSERT(metaInfo.isValid(), return); for (const QString &propName : propNames) { - if (metaInfo.propertyTypeName(propName.toLatin1()) == "QtQuick3D.Texture") { + if (metaInfo.property(propName.toUtf8()).hasPropertyTypeName("QtQuick3D.Texture")) { QObject *propEditorValObj = propMap.value(propName).value(); PropertyEditorValue *propEditorVal = qobject_cast(propEditorValObj); propEditorVal->setHasActiveDrag(highlight); diff --git a/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp b/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp index 178f79e18a3..833d72917b1 100644 --- a/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp +++ b/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp @@ -65,11 +65,10 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i if (parentInfo.isSubclassOf("QtQuick3D.DefaultMaterial") || parentInfo.isSubclassOf("QtQuick3D.PrincipledMaterial")) { // All texture properties are valid targets - const PropertyNameList targetNodeNameList = parentInfo.propertyNames(); - for (const PropertyName &name : targetNodeNameList) { - TypeName propType = parentInfo.propertyTypeName(name); + for (const auto &property : parentInfo.properties()) { + const TypeName &propType = property.propertyTypeName(); if (propType == textureType || propType == textureTypeCpp) { - propertyList.append(QString::fromLatin1(name)); + propertyList.append(QString::fromUtf8(property.name())); if (breakOnFirst) return; } @@ -168,15 +167,13 @@ ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded( // Create dialog for selecting writable properties of exact property type ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded( - const ModelNode &targetNode, TypeName type, QWidget *parent) + const ModelNode &targetNode, TypeName propertyType, QWidget *parent) { const NodeMetaInfo metaInfo = targetNode.metaInfo(); - const PropertyNameList propNames = metaInfo.propertyNames(); - const TypeName property(type); QStringList matchingNames; - for (const auto &propName : propNames) { - if (metaInfo.propertyTypeName(propName) == property && metaInfo.propertyIsWritable(propName)) - matchingNames.append(QString::fromLatin1(propName)); + for (const auto &property : metaInfo.properties()) { + if (property.hasPropertyTypeName(propertyType) && property.isWritable()) + matchingNames.append(QString::fromUtf8(property.name())); } if (!matchingNames.isEmpty()) diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index d347854f004..015b8cf9d6c 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -725,7 +725,7 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in } } - if (targetNode.metaInfo().propertyIsListProperty(selectedProp)) { + if (targetNode.metaInfo().property(selectedProp).isListProperty()) { BindingProperty listProp = targetNode.bindingProperty(selectedProp); listProp.addModelNodeToArray(newModelNode); validContainer = true; @@ -1105,7 +1105,7 @@ ModelNode NavigatorTreeModel::createTextureNode(const NodeAbstractProperty &targ TypeName propertyType(const NodeAbstractProperty &property) { - return property.parentModelNode().metaInfo().propertyTypeName(property.name()); + return property.parentModelNode().metaInfo().property(property.name()).propertyTypeName(); } void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProperty, diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp index 8ba1325efaf..aad8a8120b5 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp @@ -220,7 +220,10 @@ void PropertyEditorContextObject::changeTypeName(const QString &typeName) } // Create a list of properties available for the new type - QList propertiesAndSignals(metaInfo.propertyNames()); + auto propertiesAndSignals = Utils::transform(metaInfo.properties(), + [](const auto &property) { + return property.name(); + }); // Add signals to the list for (const auto &signal : metaInfo.signalNames()) { if (signal.isEmpty()) diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp index c3e201bf1d9..c336d02314e 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp @@ -25,8 +25,9 @@ #include "propertyeditorqmlbackend.h" -#include "propertyeditorvalue.h" #include "propertyeditortransaction.h" +#include "propertyeditorvalue.h" +#include "propertymetainfo.h" #include #include #include @@ -415,10 +416,13 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q if (propertyEditorBenchmark().isInfoEnabled()) time.start(); - const QList propertyNames = qmlObjectNode.modelNode().metaInfo().propertyNames(); - for (const PropertyName &propertyName : propertyNames) - createPropertyEditorValue(qmlObjectNode, propertyName, qmlObjectNode.instanceValue(propertyName), propertyEditor); - + for (const auto &property : qmlObjectNode.modelNode().metaInfo().properties()) { + auto propertyName = property.name(); + createPropertyEditorValue(qmlObjectNode, + propertyName, + qmlObjectNode.instanceValue(propertyName), + propertyEditor); + } setupLayoutAttachedProperties(qmlObjectNode, propertyEditor); setupAuxiliaryProperties(qmlObjectNode, propertyEditor); @@ -514,9 +518,11 @@ void PropertyEditorQmlBackend::initialSetup(const TypeName &typeName, const QUrl { NodeMetaInfo metaInfo = propertyEditor->model()->metaInfo(typeName); - const QList propertyNames = metaInfo.propertyNames(); - for (const PropertyName &propertyName : propertyNames) - setupPropertyEditorValue(propertyName, propertyEditor, QString::fromUtf8(metaInfo.propertyTypeName(propertyName))); + for (const auto &property : metaInfo.properties()) { + setupPropertyEditorValue(property.name(), + propertyEditor, + QString::fromUtf8(property.propertyTypeName())); + } auto valueObject = qobject_cast(variantToQObject( m_backendValuesPropertyMap.value(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY))); @@ -579,7 +585,7 @@ inline bool dotPropertyHeuristic(const QmlObjectNode &node, const NodeMetaInfo & const PropertyName parentProperty = list.first(); const PropertyName itemProperty = list.last(); - TypeName typeName = type.propertyTypeName(parentProperty); + TypeName typeName = type.property(parentProperty).propertyTypeName(); NodeMetaInfo itemInfo = node.view()->model()->metaInfo("QtQuick.Item"); NodeMetaInfo textInfo = node.view()->model()->metaInfo("QtQuick.Text"); @@ -596,7 +602,7 @@ inline bool dotPropertyHeuristic(const QmlObjectNode &node, const NodeMetaInfo & return true; } -QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, +QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &metaType, const NodeMetaInfo &superType, const QmlObjectNode &node) { @@ -615,20 +621,22 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, allTypes.append(variantToStringList(node->property("typeNames").value)); } - const QList allProperties = type.propertyNames(); - - QMap> propertyMap; - QList separateSectionProperties; + auto propertyMetaInfoCompare = [](const auto &first, const auto &second) { + return first.name() < second.name(); + }; + std::map propertyMap( + propertyMetaInfoCompare); + PropertyMetaInfos separateSectionProperties; // Iterate over all properties and isolate the properties which have their own template - for (const PropertyName &propertyName : allProperties) { + for (const auto &property : metaType.properties()) { + const auto &propertyName = property.name(); if (propertyName.startsWith("__")) continue; // private API - if (!superType.hasProperty(propertyName) - && type.propertyIsWritable(propertyName) - && dotPropertyHeuristic(node, type, propertyName)) { - QString typeName = QString::fromLatin1(type.propertyTypeName(propertyName)); + if (!superType.hasProperty(propertyName) // TODO add property.isLocalProperty() + && property.isWritable() && dotPropertyHeuristic(node, metaType, propertyName)) { + QString typeName = QString::fromUtf8(property.propertyTypeName()); if (typeName == "alias" && node.isValid()) typeName = QString::fromLatin1(node.instanceType(propertyName)); @@ -636,18 +644,16 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, // Check if a template for the type exists if (allTypes.contains(typeName)) { if (separateSectionTypes.contains(typeName)) { // template enforces separate section - separateSectionProperties.append(propertyName); + separateSectionProperties.push_back(property); } else { if (propertyName.contains('.')) { - const PropertyName parentProperty = propertyName.split('.').first(); + const PropertyName parentPropertyName = propertyName.split('.').first(); + const PropertyMetaInfo parentProperty = metaType.property( + parentPropertyName); - if (propertyMap.contains(parentProperty)) - propertyMap[parentProperty].append(propertyName); - else - propertyMap[parentProperty] = { propertyName }; + propertyMap[parentProperty].push_back(property); } else { - if (!propertyMap.contains(propertyName)) - propertyMap[propertyName] = {}; + propertyMap[property]; } } } @@ -655,28 +661,29 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, } // Filter out the properties which have a basic type e.g. int, string, bool - QList basicProperties; + PropertyMetaInfos basicProperties; auto it = propertyMap.begin(); while (it != propertyMap.end()) { - if (it.value().empty()) { - basicProperties.append(it.key()); + if (it->second.empty()) { + basicProperties.push_back(it->first); it = propertyMap.erase(it); } else { ++it; } } - Utils::sort(basicProperties); + Utils::sort(basicProperties, propertyMetaInfoCompare); - auto findAndFillTemplate = [&nodes, &node, &type](const PropertyName &label, - const PropertyName &property) { - PropertyName underscoreProperty = property; + auto findAndFillTemplate = [&nodes, &node](const PropertyName &label, + const PropertyMetaInfo &property) { + const auto &propertyName = property.name(); + PropertyName underscoreProperty = propertyName; underscoreProperty.replace('.', '_'); - TypeName typeName = type.propertyTypeName(property); + TypeName typeName = property.propertyTypeName(); // alias resolution only possible with instance if (typeName == "alias" && node.isValid()) - typeName = node.instanceType(property); + typeName = node.instanceType(propertyName); QString filledTemplate; for (const QmlJS::SimpleReaderNode::Ptr &n : nodes) { @@ -730,8 +737,8 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, qmlInnerTemplate += "bottomPadding: 10\n"; qmlInnerTemplate += "SectionLayout {\n"; - for (const auto &p : qAsConst(basicProperties)) - qmlInnerTemplate += findAndFillTemplate(p, p); + for (const auto &basicProperty : std::as_const(basicProperties)) + qmlInnerTemplate += findAndFillTemplate(basicProperty.name(), basicProperty); qmlInnerTemplate += "}\n"; // SectionLayout qmlInnerTemplate += "}\n"; // Column @@ -740,16 +747,17 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, // Second the section containing properties of complex type for which no specific template exists e.g. Button if (!propertyMap.empty()) { emptyTemplate = false; - for (auto it = propertyMap.cbegin(); it != propertyMap.cend(); ++it) { - const auto &key = it.key(); - TypeName parentTypeName = type.propertyTypeName(key); + for (auto &[property, properties] : propertyMap) { + // for (auto it = propertyMap.cbegin(); it != propertyMap.cend(); ++it) { + TypeName parentTypeName = property.propertyTypeName(); // alias resolution only possible with instance if (parentTypeName == "alias" && node.isValid()) - parentTypeName = node.instanceType(key); + parentTypeName = node.instanceType(property.name()); qmlInnerTemplate += "Section {\n"; qmlInnerTemplate += QStringLiteral("caption: \"%1 - %2\"\n") - .arg(QString::fromUtf8(key), QString::fromUtf8(parentTypeName)); + .arg(QString::fromUtf8(property.name()), + QString::fromUtf8(parentTypeName)); qmlInnerTemplate += anchorLeftRight; qmlInnerTemplate += "leftPadding: 8\n"; qmlInnerTemplate += "rightPadding: 0\n"; @@ -757,12 +765,14 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, qmlInnerTemplate += "level: 1\n"; qmlInnerTemplate += "SectionLayout {\n"; - auto properties = it.value(); - Utils::sort(properties); + Utils::sort(properties, propertyMetaInfoCompare); - for (const auto &p : qAsConst(properties)) { - const PropertyName shortName = p.contains('.') ? p.split('.').last() : p; - qmlInnerTemplate += findAndFillTemplate(shortName, p); + for (const auto &subProperty : properties) { + const auto &propertyName = subProperty.name(); + auto found = std::find(propertyName.rbegin(), propertyName.rend(), '.'); + const PropertyName shortName{found.base(), + std::distance(found.base(), propertyName.end())}; + qmlInnerTemplate += findAndFillTemplate(shortName, property); } qmlInnerTemplate += "}\n"; // SectionLayout @@ -773,9 +783,9 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, // Third the section containing properties of complex type for which a specific template exists e.g. Rectangle, Image if (!separateSectionProperties.empty()) { emptyTemplate = false; - Utils::sort(separateSectionProperties); - for (const auto &p : qAsConst(separateSectionProperties)) - qmlInnerTemplate += findAndFillTemplate(p, p); + Utils::sort(separateSectionProperties, propertyMetaInfoCompare); + for (const auto &property : separateSectionProperties) + qmlInnerTemplate += findAndFillTemplate(property.name(), property); } qmlInnerTemplate += "}\n"; // Column diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp index c68db4c57f7..6384dcb24df 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp @@ -60,9 +60,13 @@ PropertyEditorValue::PropertyEditorValue(QObject *parent) QVariant PropertyEditorValue::value() const { QVariant returnValue = m_value; - if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name())) - if (modelNode().metaInfo().propertyTypeName(name()) == "QUrl") + if (modelNode().isValid()) { + if (auto metaInfo = modelNode().metaInfo(); + metaInfo.isValid() && metaInfo.hasProperty(name()) + && metaInfo.property(name()).hasPropertyTypeName("QUrl", "url")) { returnValue = returnValue.toUrl().toString(); + } + } return returnValue; } @@ -100,28 +104,30 @@ static void fixAmbigousColorNames(const QmlDesigner::ModelNode &modelNode, const QmlDesigner::PropertyName &name, QVariant *value) { - if (modelNode.isValid() && modelNode.metaInfo().isValid() - && (modelNode.metaInfo().propertyTypeName(name) == "QColor" - || modelNode.metaInfo().propertyTypeName(name) == "color")) { - if ((value->type() == QVariant::Color)) { - QColor color = value->value(); - int alpha = color.alpha(); - color = QColor(color.name()); - color.setAlpha(alpha); - *value = color; - } else if (value->toString() != QStringLiteral("transparent")) { - *value = QColor(value->toString()).name(QColor::HexArgb); + if (modelNode.isValid()) { + if (auto metaInfo = modelNode.metaInfo(); + metaInfo.isValid() && metaInfo.property(name).hasPropertyTypeName("QColor", "color")) { + if ((value->type() == QVariant::Color)) { + QColor color = value->value(); + int alpha = color.alpha(); + color = QColor(color.name()); + color.setAlpha(alpha); + *value = color; + } else if (value->toString() != QStringLiteral("transparent")) { + *value = QColor(value->toString()).name(QColor::HexArgb); + } } } } static void fixUrl(const QmlDesigner::ModelNode &modelNode, const QmlDesigner::PropertyName &name, QVariant *value) { - if (modelNode.isValid() && modelNode.metaInfo().isValid() - && (modelNode.metaInfo().propertyTypeName(name) == "QUrl" - || modelNode.metaInfo().propertyTypeName(name) == "url")) { - if (!value->isValid()) - *value = QStringLiteral(""); + if (modelNode.isValid()) { + if (auto metaInfo = modelNode.metaInfo(); + metaInfo.isValid() && metaInfo.property(name).hasPropertyTypeName("QUrl", "url")) + + if (!value->isValid()) + *value = QStringLiteral(""); } } @@ -140,9 +146,13 @@ void PropertyEditorValue::setValueWithEmit(const QVariant &value) { if (!compareVariants(value, m_value ) || isBound()) { QVariant newValue = value; - if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name())) - if (modelNode().metaInfo().propertyTypeName(name()) == "QUrl") + if (modelNode().isValid()) { + if (auto metaInfo = modelNode().metaInfo(); + metaInfo.isValid() && metaInfo.hasProperty(name()) + && metaInfo.property(name()).hasPropertyTypeName("QUrl")) { newValue = QUrl(newValue.toString()); + } + } if (cleverDoubleCompare(newValue, m_value)) return; @@ -255,12 +265,14 @@ void PropertyEditorValue::setIsValid(bool valid) bool PropertyEditorValue::isTranslated() const { - if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name())) { - if (modelNode().metaInfo().propertyTypeName(name()) == "QString" || modelNode().metaInfo().propertyTypeName(name()) == "string") { + if (modelNode().isValid()) { + if (auto metaInfo = modelNode().metaInfo(); + metaInfo.isValid() && metaInfo.hasProperty(name()) + && metaInfo.property(name()).hasPropertyTypeName("QString", "string")) { const QmlDesigner::QmlObjectNode objectNode(modelNode()); if (objectNode.isValid() && objectNode.hasBindingProperty(name())) { - const QRegularExpression rx(QRegularExpression::anchoredPattern( - "qsTr(|Id|anslate)\\(\".*\"\\)")); + const QRegularExpression rx( + QRegularExpression::anchoredPattern("qsTr(|Id|anslate)\\(\".*\"\\)")); //qsTr() if (objectNode.propertyAffectedByCurrentState(name())) { return expression().contains(rx); @@ -268,7 +280,6 @@ bool PropertyEditorValue::isTranslated() const return modelNode().bindingProperty(name()).expression().contains(rx); } } - return false; } } return false; @@ -424,12 +435,14 @@ void PropertyEditorValue::removeAliasExport() QString PropertyEditorValue::getTranslationContext() const { - if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name())) { - if (modelNode().metaInfo().propertyTypeName(name()) == "QString" || modelNode().metaInfo().propertyTypeName(name()) == "string") { + if (modelNode().isValid()) { + if (auto metaInfo = modelNode().metaInfo(); + metaInfo.isValid() && metaInfo.hasProperty(name()) + && metaInfo.property(name()).hasPropertyTypeName("QString", "string")) { const QmlDesigner::QmlObjectNode objectNode(modelNode()); if (objectNode.isValid() && objectNode.hasBindingProperty(name())) { const QRegularExpression rx(QRegularExpression::anchoredPattern( - "qsTranslate\\(\"(.*)\"\\s*,\\s*\".*\"\\s*\\)")); + "qsTranslate\\(\"(.*)\"\\s*,\\s*\".*\"\\s*\\)")); const QRegularExpressionMatch match = rx.match(expression()); if (match.hasMatch()) return match.captured(1); @@ -519,7 +532,7 @@ bool PropertyEditorValue::idListReplace(int idx, const QString &value) void PropertyEditorValue::commitDrop(const QString &path) { if (m_modelNode.isSubclassOf("QtQuick3D.Material") - && m_modelNode.metaInfo().propertyTypeName(m_name) == "QtQuick3D.Texture") { + && m_modelNode.metaInfo().property(m_name).hasPropertyTypeName("QtQuick3D.Texture")) { // create a texture node QmlDesigner::NodeMetaInfo metaInfo = m_modelNode.view()->model()->metaInfo("QtQuick3D.Texture"); QmlDesigner::ModelNode texture = m_modelNode.view()->createModelNode("QtQuick3D.Texture", @@ -618,8 +631,12 @@ void PropertyEditorNodeWrapper::add(const QString &type) QmlDesigner::TypeName propertyType = type.toUtf8(); if ((m_editorValue && m_editorValue->modelNode().isValid())) { - if (propertyType.isEmpty()) - propertyType = m_editorValue->modelNode().metaInfo().propertyTypeName(m_editorValue->name()); + if (propertyType.isEmpty()) { + propertyType = m_editorValue->modelNode() + .metaInfo() + .property(m_editorValue->name()) + .propertyTypeName(); + } while (propertyType.contains('*')) //strip star propertyType.chop(1); m_modelNode = m_editorValue->modelNode().view()->createModelNode(propertyType, 4, 7); @@ -681,9 +698,9 @@ void PropertyEditorNodeWrapper::setup() m_valuesPropertyMap.clear(propertyName); qDeleteAll(m_valuesPropertyMap.children()); - const QList propertyNameList = m_modelNode.metaInfo().propertyNames(); - for (const QmlDesigner::PropertyName &propertyName : propertyNameList) { - if (qmlObjectNode.isValid()) { + if (qmlObjectNode.isValid()) { + for (const auto &property : m_modelNode.metaInfo().properties()) { + const auto &propertyName = property.name(); auto valueObject = new PropertyEditorValue(&m_valuesPropertyMap); valueObject->setName(propertyName); valueObject->setValue(qmlObjectNode.instanceValue(propertyName)); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp index fb1be16dc73..21cbfef72cd 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp @@ -185,7 +185,7 @@ void PropertyEditorView::changeValue(const QString &name) QVariant castedValue; if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) { - castedValue = metaInfo.propertyCastedValue(propertyName, value->value()); + castedValue = metaInfo.property(propertyName).castedValue(value->value()); } else if (propertyIsAttachedLayoutProperty(propertyName)) { castedValue = value->value(); } else { @@ -200,17 +200,15 @@ void PropertyEditorView::changeValue(const QString &name) bool propertyTypeUrl = false; - if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) { - if (metaInfo.propertyTypeName(propertyName) == "QUrl" - || metaInfo.propertyTypeName(propertyName) == "url") { - // turn absolute local file paths into relative paths - propertyTypeUrl = true; - QString filePath = castedValue.toUrl().toString(); - QFileInfo fi(filePath); - if (fi.exists() && fi.isAbsolute()) { - QDir fileDir(QFileInfo(model()->fileUrl().toLocalFile()).absolutePath()); - castedValue = QUrl(fileDir.relativeFilePath(filePath)); - } + if (metaInfo.isValid() && metaInfo.hasProperty(propertyName) + && metaInfo.property(propertyName).hasPropertyTypeName("QUrl", "url")) { + // turn absolute local file paths into relative paths + propertyTypeUrl = true; + QString filePath = castedValue.toUrl().toString(); + QFileInfo fi(filePath); + if (fi.exists() && fi.isAbsolute()) { + QDir fileDir(QFileInfo(model()->fileUrl().toLocalFile()).absolutePath()); + castedValue = QUrl(fileDir.relativeFilePath(filePath)); } } @@ -272,13 +270,15 @@ void PropertyEditorView::changeExpression(const QString &propertyName) return; } - if (qmlObjectNode->modelNode().metaInfo().isValid() && qmlObjectNode->modelNode().metaInfo().hasProperty(name)) { - if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "QColor") { + if (auto metaInfo = qmlObjectNode->modelNode().metaInfo(); + metaInfo.isValid() && metaInfo.hasProperty(name)) { + const auto &propertTypeName = metaInfo.property(name).propertyTypeName(); + if (propertTypeName == "QColor") { if (QColor(value->expression().remove('"')).isValid()) { qmlObjectNode->setVariantProperty(name, QColor(value->expression().remove('"'))); return; } - } else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "bool") { + } else if (propertTypeName == "bool") { if (isTrueFalseLiteral(value->expression())) { if (value->expression().compare("true", Qt::CaseInsensitive) == 0) qmlObjectNode->setVariantProperty(name, true); @@ -286,21 +286,21 @@ void PropertyEditorView::changeExpression(const QString &propertyName) qmlObjectNode->setVariantProperty(name, false); return; } - } else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "int") { + } else if (propertTypeName == "int") { bool ok; int intValue = value->expression().toInt(&ok); if (ok) { qmlObjectNode->setVariantProperty(name, intValue); return; } - } else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "qreal") { + } else if (propertTypeName == "qreal") { bool ok; qreal realValue = value->expression().toDouble(&ok); if (ok) { qmlObjectNode->setVariantProperty(name, realValue); return; } - } else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "QVariant") { + } else if (propertTypeName == "QVariant") { bool ok; qreal realValue = value->expression().toDouble(&ok); if (ok) { diff --git a/src/plugins/qmldesigner/components/sourcetool/sourcetool.cpp b/src/plugins/qmldesigner/components/sourcetool/sourcetool.cpp index 9d49adb41d2..751624e9758 100644 --- a/src/plugins/qmldesigner/components/sourcetool/sourcetool.cpp +++ b/src/plugins/qmldesigner/components/sourcetool/sourcetool.cpp @@ -53,15 +53,8 @@ namespace { bool modelNodeHasUrlSource(const QmlDesigner::ModelNode &modelNode) { QmlDesigner::NodeMetaInfo metaInfo = modelNode.metaInfo(); - if (metaInfo.isValid()) { - if (metaInfo.hasProperty("source")) { - if (metaInfo.propertyTypeName("source") == "QUrl") - return true; - if (metaInfo.propertyTypeName("source") == "url") - return true; - } - } - return false; + return metaInfo.isValid() && metaInfo.hasProperty("source") + && metaInfo.property("source").hasPropertyTypeName("QUrl", "url"); } } //namespace diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp index 77f0bbf34cb..65d567a7b3b 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp @@ -234,8 +234,10 @@ TimelinePropertyItem *TimelinePropertyItem::create(const QmlTimelineKeyframeGrou if (!objectNode.isValid()) return item; - auto nameOfType = objectNode.modelNode().metaInfo().propertyTypeName( - item->m_frames.propertyName()); + auto nameOfType = objectNode.modelNode() + .metaInfo() + .property(item->m_frames.propertyName()) + .propertyTypeName(); item->m_control = createTimelineControl(nameOfType); if (item->m_control) { item->m_control->setSize((TimelineConstants::sectionWidth / 2.6) - 10, diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp index 09e9b9f05a3..bfe7ae0cd3c 100644 --- a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp +++ b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp @@ -226,7 +226,7 @@ ModelNode TransitionEditorView::addNewTransition() if (target.isValid() && target.hasMetaInfo()) { const QString targetId = target.id(); for (const VariantProperty &property : change.modelNode().variantProperties()) { - TypeName typeName = target.metaInfo().propertyTypeName(property.name()); + TypeName typeName = target.metaInfo().property(property.name()).propertyTypeName(); if (typeName.startsWith(".")) typeName.remove(0, 6); diff --git a/src/plugins/qmldesigner/designercore/include/enumerationmetainfo.h b/src/plugins/qmldesigner/designercore/include/enumerationmetainfo.h new file mode 100644 index 00000000000..a487a92bad7 --- /dev/null +++ b/src/plugins/qmldesigner/designercore/include/enumerationmetainfo.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +#include +#include + +#include + +namespace QmlDesigner { + +class EnumerationMetaInfo +{ +public: + EnumerationMetaInfo(QSharedPointer nodeMetaInfoPrivateData, + const TypeName &enumeration); + ~EnumerationMetaInfo(); + +private: + QSharedPointer m_nodeMetaInfoPrivateData; + const TypeName &m_enumeration; +}; + +using EnumerationMetaInfos = std::vector; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/include/metainfo.h b/src/plugins/qmldesigner/designercore/include/metainfo.h index eb17139b8e2..4a2a4417d61 100644 --- a/src/plugins/qmldesigner/designercore/include/metainfo.h +++ b/src/plugins/qmldesigner/designercore/include/metainfo.h @@ -42,6 +42,7 @@ class ItemLibraryInfo; namespace Internal { class MetaInfoPrivate; class ModelPrivate; + class MetaInfoReader; class SubComponentManagerPrivate; using MetaInfoPrivatePointer = QSharedPointer; } diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h index 6b8dfab4314..3f92e1160c2 100644 --- a/src/plugins/qmldesigner/designercore/include/model.h +++ b/src/plugins/qmldesigner/designercore/include/model.h @@ -44,8 +44,7 @@ namespace QmlDesigner { namespace Internal { class ModelPrivate; class WriteLocker; -class NodeMetaInfoPrivate; -} // namespace Internal +} //Internal class AnchorLine; class ModelNode; @@ -70,7 +69,7 @@ class QMLDESIGNERCORE_EXPORT Model : public QObject friend AbstractView; friend Internal::ModelPrivate; friend Internal::WriteLocker; - friend Internal::NodeMetaInfoPrivate; + friend class NodeMetaInfoPrivate; Q_OBJECT @@ -141,4 +140,4 @@ private: Internal::ModelPrivate *d; }; -} // namespace QmlDesigner +} diff --git a/src/plugins/qmldesigner/designercore/include/modelnode.h b/src/plugins/qmldesigner/designercore/include/modelnode.h index 92884a9710e..5517336fdb8 100644 --- a/src/plugins/qmldesigner/designercore/include/modelnode.h +++ b/src/plugins/qmldesigner/designercore/include/modelnode.h @@ -174,7 +174,7 @@ public: Model *model() const; AbstractView *view() const; - const NodeMetaInfo metaInfo() const; + NodeMetaInfo metaInfo() const; bool hasMetaInfo() const; bool isSelected() const; diff --git a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h index 3cafe30e7cd..695f7dbfe6e 100644 --- a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h +++ b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h @@ -25,12 +25,15 @@ #pragma once +#include "invalidmetainfoexception.h" +#include "propertymetainfo.h" +#include "qmldesignercorelib_global.h" + #include #include #include -#include "qmldesignercorelib_global.h" -#include "invalidmetainfoexception.h" +#include QT_BEGIN_NAMESPACE class QDeclarativeContext; @@ -42,14 +45,6 @@ class MetaInfo; class Model; class AbstractProperty; -namespace Internal { - class MetaInfoPrivate; - class MetaInfoReader; - class SubComponentManagerPrivate; - class ItemLibraryEntryData; - class NodeMetaInfoPrivate; -} - class QMLDESIGNERCORE_EXPORT NodeMetaInfo { public: @@ -64,20 +59,13 @@ public: bool isValid() const; bool isFileComponent() const; bool hasProperty(const PropertyName &propertyName) const; - PropertyNameList propertyNames() const; + PropertyMetaInfos properties() const; + PropertyMetaInfos localProperties() const; + PropertyMetaInfo property(const PropertyName &propertyName) const; PropertyNameList signalNames() const; PropertyNameList slotNames() const; - PropertyNameList directPropertyNames() const; PropertyName defaultPropertyName() const; bool hasDefaultProperty() const; - TypeName propertyTypeName(const PropertyName &propertyName) const; - bool propertyIsWritable(const PropertyName &propertyName) const; - bool propertyIsListProperty(const PropertyName &propertyName) const; - bool propertyIsEnumType(const PropertyName &propertyName) const; - bool propertyIsPrivate(const PropertyName &propertyName) const; - bool propertyIsPointer(const PropertyName &propertyName) const; - QStringList propertyKeysForEnum(const PropertyName &propertyName) const; - QVariant propertyCastedValue(const PropertyName &propertyName, const QVariant &value) const; QList classHierarchy() const; QList superClasses() const; @@ -104,7 +92,9 @@ public: QString importDirectoryPath() const; private: - QSharedPointer m_privateData; + QSharedPointer m_privateData; }; +using NodeMetaInfos = std::vector; + } //QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/include/propertymetainfo.h b/src/plugins/qmldesigner/designercore/include/propertymetainfo.h new file mode 100644 index 00000000000..6375437e65a --- /dev/null +++ b/src/plugins/qmldesigner/designercore/include/propertymetainfo.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +#include +#include + +#include + +namespace QmlDesigner { + +class PropertyMetaInfo +{ +public: + PropertyMetaInfo(QSharedPointer nodeMetaInfoPrivateData, + const PropertyName &propertyName); + ~PropertyMetaInfo(); + + const TypeName &propertyTypeName() const; + class NodeMetaInfo propertyNodeMetaInfo() const; + + bool isWritable() const; + bool isListProperty() const; + bool isEnumType() const; + bool isPrivate() const; + bool isPointer() const; + QVariant castedValue(const QVariant &value) const; + const PropertyName &name() const & { return m_propertyName; } + + template + bool hasPropertyTypeName(const TypeName &...typeName) const + { + auto propertyTypeName_ = propertyTypeName(); + return ((propertyTypeName_ == typeName) || ...); + } + +private: + QSharedPointer m_nodeMetaInfoPrivateData; + PropertyName m_propertyName; +}; + +using PropertyMetaInfos = std::vector; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h index 3a3498e6c9a..15e12d2fdad 100644 --- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h +++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h @@ -212,12 +212,14 @@ public: void setStartFlowItem(const QmlFlowItemNode &flowItem); ModelNode createTransition(); - static PropertyNameList st_mouseSignals; static QList getAssociatedConnections(const ModelNode &node); - + static const PropertyNameList &mouseSignals() { return s_mouseSignals; } protected: QList transitionsForProperty(const PropertyName &propertyName, const ModelNode &modelNode); + +private: + static PropertyNameList s_mouseSignals; }; diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp index 634c9aa64b6..ea84e8528f4 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp @@ -46,17 +46,6 @@ namespace QmlDesigner { -namespace Internal { - -struct TypeDescription -{ - QString className; - int minorVersion{}; - int majorVersion{}; -}; - -} //Internal - /*! \class QmlDesigner::NodeMetaInfo \ingroup CoreModel @@ -74,7 +63,14 @@ NodeMetaInfo object will result in an InvalidMetaInfoException being thrown. \see QmlDesigner::MetaInfo, QmlDesigner::PropertyMetaInfo, QmlDesigner::EnumeratorMetaInfo */ -namespace Internal { +namespace { + +struct TypeDescription +{ + QString className; + int minorVersion{}; + int majorVersion{}; +}; using namespace QmlJS; @@ -516,6 +512,9 @@ PropertyNameList getSignals(const ObjectValue *objectValue, const ContextPtr &co signalList.append(getSignals(prototype, context, true)); } + std::sort(signalList.begin(), signalList.end()); + signalList.erase(std::unique(signalList.begin(), signalList.end()), signalList.end()); + return signalList; } @@ -544,6 +543,9 @@ PropertyNameList getSlots(const ObjectValue *objectValue, const ContextPtr &cont slotList.append(getSlots(prototype, context, true)); } + std::sort(slotList.begin(), slotList.end()); + slotList.erase(std::unique(slotList.begin(), slotList.end()), slotList.end()); + return slotList; } @@ -604,6 +606,7 @@ QVector getObjectTypes(const ObjectValue *objectValue, const Conte return propertyList; } +} // namespace class NodeMetaInfoPrivate { @@ -614,12 +617,12 @@ public: bool isValid() const; bool isFileComponent() const; - PropertyNameList properties() const; - PropertyNameList localProperties() const; + const PropertyNameList &properties() const; + const PropertyNameList &localProperties() const; PropertyNameList signalNames() const; PropertyNameList slotNames() const; PropertyName defaultPropertyName() const; - TypeName propertyType(const PropertyName &propertyName) const; + const TypeName &propertyType(const PropertyName &propertyName) const; void setupPrototypes(); QList prototypes() const; @@ -634,7 +637,7 @@ public: int majorVersion() const; int minorVersion() const; - TypeName qualfiedTypeName() const; + const TypeName &qualfiedTypeName() const; Model *model() const; QByteArray cppPackageName() const; @@ -691,14 +694,14 @@ bool NodeMetaInfoPrivate::isFileComponent() const return m_isFileComponent; } -PropertyNameList NodeMetaInfoPrivate::properties() const +const PropertyNameList &NodeMetaInfoPrivate::properties() const { ensureProperties(); return m_properties; } -PropertyNameList NodeMetaInfoPrivate::localProperties() const +const PropertyNameList &NodeMetaInfoPrivate::localProperties() const { ensureProperties(); @@ -741,8 +744,9 @@ static inline TypeName stringIdentifier( const TypeName &type, int maj, int min) NodeMetaInfoPrivate::Pointer NodeMetaInfoPrivate::create(Model *model, const TypeName &type, int major, int minor) { - if (model->d->m_nodeMetaInfoCache.contains(stringIdentifier(type, major, minor))) - return model->d->m_nodeMetaInfoCache.value(stringIdentifier(type, major, minor)); + auto &&cache = model->d->m_nodeMetaInfoCache; + if (auto found = cache.find(stringIdentifier(type, major, minor)); found != cache.end()) + return *found; Pointer newData(new NodeMetaInfoPrivate(model, type, major, minor)); if (newData->isValid()) @@ -1144,7 +1148,7 @@ int NodeMetaInfoPrivate::minorVersion() const return m_minorVersion; } -TypeName NodeMetaInfoPrivate::qualfiedTypeName() const +const TypeName &NodeMetaInfoPrivate::qualfiedTypeName() const { return m_qualfiedTypeName; } @@ -1248,12 +1252,16 @@ bool NodeMetaInfoPrivate::isValid() const return m_isValid && context() && document(); } -TypeName NodeMetaInfoPrivate::propertyType(const PropertyName &propertyName) const +namespace { +TypeName nonexistingTypeName("Property does not exist..."); +} + +const TypeName &NodeMetaInfoPrivate::propertyType(const PropertyName &propertyName) const { ensureProperties(); if (!m_properties.contains(propertyName)) - return TypeName("Property does not exist..."); + return nonexistingTypeName; return m_propertyTypes.at(m_properties.indexOf(propertyName)); } @@ -1386,14 +1394,14 @@ void NodeMetaInfoPrivate::initialiseProperties() m_slots = getSlots(m_objectValue, context()); } -} //namespace Internal - -NodeMetaInfo::NodeMetaInfo() : m_privateData(new Internal::NodeMetaInfoPrivate()) +NodeMetaInfo::NodeMetaInfo() + : m_privateData(QSharedPointer::create()) { } -NodeMetaInfo::NodeMetaInfo(Model *model, const TypeName &type, int maj, int min) : m_privateData(Internal::NodeMetaInfoPrivate::create(model, type, maj, min)) +NodeMetaInfo::NodeMetaInfo(Model *model, const TypeName &type, int maj, int min) + : m_privateData(NodeMetaInfoPrivate::create(model, type, maj, min)) { } @@ -1422,12 +1430,38 @@ bool NodeMetaInfo::isFileComponent() const bool NodeMetaInfo::hasProperty(const PropertyName &propertyName) const { - return propertyNames().contains(propertyName); + return m_privateData->properties().contains(propertyName); } -PropertyNameList NodeMetaInfo::propertyNames() const +PropertyMetaInfos NodeMetaInfo::properties() const { - return m_privateData->properties(); + const auto &properties = m_privateData->properties(); + + PropertyMetaInfos propertyMetaInfos; + propertyMetaInfos.reserve(static_cast(properties.size())); + + for (const auto &name : properties) + propertyMetaInfos.emplace_back(m_privateData, name); + + return propertyMetaInfos; +} + +PropertyMetaInfos NodeMetaInfo::localProperties() const +{ + const auto &properties = m_privateData->localProperties(); + + PropertyMetaInfos propertyMetaInfos; + propertyMetaInfos.reserve(static_cast(properties.size())); + + for (const auto &name : properties) + propertyMetaInfos.emplace_back(m_privateData, name); + + return propertyMetaInfos; +} + +PropertyMetaInfo NodeMetaInfo::property(const PropertyName &propertyName) const +{ + return PropertyMetaInfo{m_privateData, propertyName}; } PropertyNameList NodeMetaInfo::signalNames() const @@ -1440,11 +1474,6 @@ PropertyNameList NodeMetaInfo::slotNames() const return m_privateData->slotNames(); } -PropertyNameList NodeMetaInfo::directPropertyNames() const -{ - return m_privateData->localProperties(); -} - PropertyName NodeMetaInfo::defaultPropertyName() const { return m_privateData->defaultPropertyName(); @@ -1455,84 +1484,6 @@ bool NodeMetaInfo::hasDefaultProperty() const return !defaultPropertyName().isEmpty(); } -TypeName NodeMetaInfo::propertyTypeName(const PropertyName &propertyName) const -{ - return m_privateData->propertyType(propertyName); -} - -bool NodeMetaInfo::propertyIsWritable(const PropertyName &propertyName) const -{ - return m_privateData->isPropertyWritable(propertyName); -} - -bool NodeMetaInfo::propertyIsListProperty(const PropertyName &propertyName) const -{ - return m_privateData->isPropertyList(propertyName); -} - -bool NodeMetaInfo::propertyIsEnumType(const PropertyName &propertyName) const -{ - return m_privateData->isPropertyEnum(propertyName); -} - -bool NodeMetaInfo::propertyIsPrivate(const PropertyName &propertyName) const -{ - return propertyName.startsWith("__"); -} - -bool NodeMetaInfo::propertyIsPointer(const PropertyName &propertyName) const -{ - return m_privateData->isPropertyPointer(propertyName); -} - -QStringList NodeMetaInfo::propertyKeysForEnum(const PropertyName &propertyName) const -{ - return m_privateData->keysForEnum(QString::fromUtf8(propertyTypeName(propertyName))); -} - -QVariant NodeMetaInfo::propertyCastedValue(const PropertyName &propertyName, const QVariant &value) const -{ - const QVariant variant = value; - QVariant copyVariant = variant; - if (propertyIsEnumType(propertyName) - || variant.canConvert()) - return variant; - - const TypeName typeName = propertyTypeName(propertyName); - - QVariant::Type typeId = m_privateData->variantTypeId(propertyName); - - if (variant.type() == QVariant::UserType && variant.userType() == ModelNode::variantUserType()) { - return variant; - } else if (typeId == QVariant::UserType && typeName == "QVariant") { - return variant; - } else if (typeId == QVariant::UserType && typeName == "variant") { - return variant; - } else if (typeId == QVariant::UserType && typeName == "var") { - return variant; - } else if (variant.type() == QVariant::List) { - // TODO: check the contents of the list - return variant; - } else if (typeName == "var" || typeName == "variant") { - return variant; - } else if (typeName == "alias") { - // TODO: The QML compiler resolves the alias type. We probably should do the same. - return variant; - } else if (typeName == ".double") { - return variant.toDouble(); - } else if (typeName == ".float") { - return variant.toFloat(); - } else if (typeName == ".int") { - return variant.toInt(); - } else if (typeName == ".bool") { - return variant.toBool(); - } else if (copyVariant.convert(typeId)) { - return copyVariant; - } - - return Internal::PropertyParser::variantFromString(variant.toString()); -} - QList NodeMetaInfo::classHierarchy() const { QList hierarchy = {*this}; @@ -1543,7 +1494,7 @@ QList NodeMetaInfo::classHierarchy() const QList NodeMetaInfo::superClasses() const { Model *model = m_privateData->model(); - return Utils::transform(m_privateData->prototypes(), [model](const Internal::TypeDescription &type) { + return Utils::transform(m_privateData->prototypes(), [model](const TypeDescription &type) { return NodeMetaInfo(model, type.className.toUtf8(), type.majorVersion, type.minorVersion); }); } @@ -1556,7 +1507,7 @@ NodeMetaInfo NodeMetaInfo::directSuperClass() const bool NodeMetaInfo::defaultPropertyIsComponent() const { if (hasDefaultProperty()) - return propertyTypeName(defaultPropertyName()) == "Component"; + return property(defaultPropertyName()).hasPropertyTypeName("Component"); return false; } @@ -1613,21 +1564,24 @@ bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int mino if (typeName() == type && availableInVersion(majorVersion, minorVersion)) return true; - if (m_privateData->prototypeCachePositives().contains(Internal::stringIdentifier(type, majorVersion, minorVersion))) + if (m_privateData->prototypeCachePositives().contains( + stringIdentifier(type, majorVersion, minorVersion))) return true; //take a shortcut - optimization - if (m_privateData->prototypeCacheNegatives().contains(Internal::stringIdentifier(type, majorVersion, minorVersion))) + if (m_privateData->prototypeCacheNegatives().contains( + stringIdentifier(type, majorVersion, minorVersion))) return false; //take a shortcut - optimization const QList superClassList = superClasses(); for (const NodeMetaInfo &superClass : superClassList) { if (superClass.m_privateData->cleverCheckType(type) && superClass.availableInVersion(majorVersion, minorVersion)) { - m_privateData->prototypeCachePositives().insert(Internal::stringIdentifier(type, majorVersion, minorVersion)); + m_privateData->prototypeCachePositives().insert( + stringIdentifier(type, majorVersion, minorVersion)); return true; } } - m_privateData->prototypeCacheNegatives().insert(Internal::stringIdentifier(type, majorVersion, minorVersion)); + m_privateData->prototypeCacheNegatives().insert(stringIdentifier(type, majorVersion, minorVersion)); return false; } @@ -1668,4 +1622,90 @@ bool NodeMetaInfo::isTabView() const return isSubclassOf("QtQuick.Controls.TabView"); } +PropertyMetaInfo::PropertyMetaInfo(QSharedPointer nodeMetaInfoPrivateData, + const PropertyName &propertyName) + : m_nodeMetaInfoPrivateData{nodeMetaInfoPrivateData} + , m_propertyName{propertyName} + +{} + +PropertyMetaInfo::~PropertyMetaInfo() {} + +const TypeName &PropertyMetaInfo::propertyTypeName() const +{ + return m_nodeMetaInfoPrivateData->propertyType(m_propertyName); +} + +NodeMetaInfo PropertyMetaInfo::propertyNodeMetaInfo() const +{ + return m_nodeMetaInfoPrivateData->model()->metaInfo(propertyTypeName()); +} + +bool PropertyMetaInfo::isWritable() const +{ + return m_nodeMetaInfoPrivateData->isPropertyWritable(m_propertyName); +} + +bool PropertyMetaInfo::isListProperty() const +{ + return m_nodeMetaInfoPrivateData->isPropertyList(m_propertyName); +} + +bool PropertyMetaInfo::isEnumType() const +{ + return m_nodeMetaInfoPrivateData->isPropertyEnum(m_propertyName); +} + +bool PropertyMetaInfo::isPrivate() const +{ + return m_propertyName.startsWith("__"); +} + +bool PropertyMetaInfo::isPointer() const +{ + return m_nodeMetaInfoPrivateData->isPropertyPointer(m_propertyName); +} + +QVariant PropertyMetaInfo::castedValue(const QVariant &value) const +{ + const QVariant variant = value; + QVariant copyVariant = variant; + if (isEnumType() || variant.canConvert()) + return variant; + + const TypeName &typeName = propertyTypeName(); + + QVariant::Type typeId = m_nodeMetaInfoPrivateData->variantTypeId(m_propertyName); + + if (variant.type() == QVariant::UserType && variant.userType() == ModelNode::variantUserType()) { + return variant; + } else if (typeId == QVariant::UserType && typeName == "QVariant") { + return variant; + } else if (typeId == QVariant::UserType && typeName == "variant") { + return variant; + } else if (typeId == QVariant::UserType && typeName == "var") { + return variant; + } else if (variant.type() == QVariant::List) { + // TODO: check the contents of the list + return variant; + } else if (typeName == "var" || typeName == "variant") { + return variant; + } else if (typeName == "alias") { + // TODO: The QML compiler resolves the alias type. We probably should do the same. + return variant; + } else if (typeName == ".double") { + return variant.toDouble(); + } else if (typeName == ".float") { + return variant.toFloat(); + } else if (typeName == ".int") { + return variant.toInt(); + } else if (typeName == ".bool") { + return variant.toBool(); + } else if (copyVariant.convert(typeId)) { + return copyVariant; + } + + return Internal::PropertyParser::variantFromString(variant.toString()); +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h index c6ed24f681f..9cd1bceeded 100644 --- a/src/plugins/qmldesigner/designercore/model/model_p.h +++ b/src/plugins/qmldesigner/designercore/model/model_p.h @@ -46,6 +46,7 @@ namespace QmlDesigner { class AbstractProperty; class RewriterView; class NodeInstanceView; +class NodeMetaInfoPrivate; namespace Internal { @@ -85,7 +86,7 @@ class ModelPrivate : public QObject { friend Model; friend Internal::WriteLocker; - friend Internal::NodeMetaInfoPrivate; + friend NodeMetaInfoPrivate; public: ModelPrivate(Model *model); diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp index bb1d874db6c..97c1ddfcba9 100644 --- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp @@ -855,7 +855,7 @@ bool ModelNode::hasAnySubModelNodes() const return !nodeAbstractProperties().isEmpty(); } -const NodeMetaInfo ModelNode::metaInfo() const +NodeMetaInfo ModelNode::metaInfo() const { if (!isValid()) { Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid"); diff --git a/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp b/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp index b34c6fefc05..47ba20a3511 100644 --- a/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp +++ b/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp @@ -33,6 +33,8 @@ #include "model.h" #include "model_p.h" +#include + namespace QmlDesigner { NodeAbstractProperty::NodeAbstractProperty() = default; @@ -53,10 +55,14 @@ NodeAbstractProperty::NodeAbstractProperty(const Internal::InternalNodeAbstractP void NodeAbstractProperty::reparentHere(const ModelNode &modelNode) { - if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isNodeAbstractProperty()) + if (internalNode()->hasProperty(name()) + && !internalNode()->property(name())->isNodeAbstractProperty()) { reparentHere(modelNode, isNodeListProperty()); - else - reparentHere(modelNode, parentModelNode().metaInfo().propertyIsListProperty(name()) || isDefaultProperty()); //we could use the metasystem instead? + } else { + reparentHere(modelNode, + parentModelNode().metaInfo().property(name()).isListProperty() + || isDefaultProperty()); //we could use the metasystem instead? + } } void NodeAbstractProperty::reparentHere(const ModelNode &modelNode, bool isNodeList, const TypeName &dynamicTypeName) diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp index 6d0eaf4132b..cbebb539f13 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp @@ -993,8 +993,14 @@ QList QmlFlowViewNode::transitionsForProperty(const PropertyName &pro return list; } -PropertyNameList QmlFlowViewNode::st_mouseSignals = { "clicked", "doubleClicked", "pressAndHold", - "pressed", "released", "wheel" }; +PropertyNameList QmlFlowViewNode::s_mouseSignals = []() { + PropertyNameList mouseSignals = { + "clicked", "doubleClicked", "pressed", "pressAndHold", "released", "wheel"}; + + Q_ASSERT(std::is_sorted(mouseSignals.begin(), mouseSignals.end())); + + return mouseSignals; +}(); QList QmlFlowViewNode::getAssociatedConnections(const ModelNode &node) { @@ -1020,8 +1026,7 @@ QList QmlFlowViewNode::getAssociatedConnections(const ModelNode sourceProperty = sourceComponents[1]; } - if (st_mouseSignals.contains(signalWithoutPrefix) - && sourceId == node.id() + if (mouseSignals().contains(signalWithoutPrefix) && sourceId == node.id() && sourceProperty == "trigger()") return true; } diff --git a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp index 5e137b06b87..88bf0a426d4 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp @@ -246,17 +246,17 @@ QVariant QmlObjectNode::modelValue(const PropertyName &name) const bool QmlObjectNode::isTranslatableText(const PropertyName &name) const { - if (modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name)) - if (modelNode().metaInfo().propertyTypeName(name) == "QString" || modelNode().metaInfo().propertyTypeName(name) == "string") { - if (modelNode().hasBindingProperty(name)) { - static QRegularExpression regularExpressionPattern( - QLatin1String("^qsTr(|Id|anslate)\\(\".*\"\\)$")); - return modelNode().bindingProperty(name).expression().contains(regularExpressionPattern); - } - - return false; + if (modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name) + && modelNode().metaInfo().property(name).hasPropertyTypeName("QString", "string")) { + if (modelNode().hasBindingProperty(name)) { + static QRegularExpression regularExpressionPattern( + QLatin1String("^qsTr(|Id|anslate)\\(\".*\"\\)$")); + return modelNode().bindingProperty(name).expression().contains(regularExpressionPattern); } + return false; + } + return false; } diff --git a/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp b/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp index 2f0ab2500b9..2a605e0102a 100644 --- a/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp @@ -213,7 +213,7 @@ TypeName QmlTimelineKeyframeGroup::valueType() const TypeName typeName; if (targetNode.isValid() && targetNode.hasMetaInfo()) - typeName = targetNode.metaInfo().propertyTypeName(propertyName()); + typeName = targetNode.metaInfo().property(propertyName()).propertyTypeName(); if (typeName.startsWith(".")) typeName.remove(0, 6); diff --git a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp index cc7ab776152..347cf20e90d 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp @@ -223,7 +223,7 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view, if (!forceNonDefaultProperty.isEmpty()) { const NodeMetaInfo metaInfo = parentQmlItemNode.modelNode().metaInfo(); if (metaInfo.hasProperty(forceNonDefaultProperty)) { - if (!metaInfo.propertyIsListProperty(forceNonDefaultProperty) + if (!metaInfo.property(forceNonDefaultProperty).isListProperty() && parentQmlItemNode.modelNode().hasNodeProperty(forceNonDefaultProperty)) { parentQmlItemNode.removeProperty(forceNonDefaultProperty); } @@ -324,7 +324,7 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view, const ModelNode parentNode = parentProperty.parentModelNode(); const NodeMetaInfo metaInfo = parentNode.metaInfo(); - if (metaInfo.isValid() && !metaInfo.propertyIsListProperty(propertyName) + if (metaInfo.isValid() && !metaInfo.property(propertyName).isListProperty() && parentProperty.isNodeProperty()) { parentNode.removeProperty(propertyName); } diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index 2cddff7dfd0..848e06870aa 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -337,8 +337,9 @@ bool propertyIsComponentType(const QmlDesigner::NodeAbstractProperty &property, if (model->metaInfo(type).isSubclassOf("QtQuick.Component") && !isComponentType(type)) return false; //If the type is already a subclass of Component keep it - return property.parentModelNode().isValid() && - isComponentType(property.parentModelNode().metaInfo().propertyTypeName(property.name())); + return property.parentModelNode().isValid() + && isComponentType( + property.parentModelNode().metaInfo().property(property.name()).propertyTypeName()); } QString extractComponentFromQml(const QString &source) diff --git a/src/plugins/qmldesigner/qmldesignercore.cmake b/src/plugins/qmldesigner/qmldesignercore.cmake index 8795659c691..6fb21afc490 100644 --- a/src/plugins/qmldesigner/qmldesignercore.cmake +++ b/src/plugins/qmldesigner/qmldesignercore.cmake @@ -153,6 +153,7 @@ function(extend_with_qmldesigner_core target_name) include/componenttextmodifier.h include/customnotifications.h include/documentmessage.h + include/enumerationmetainfo.h include/exception.h include/forwardview.h include/imagecacheauxiliarydata.h @@ -184,6 +185,7 @@ function(extend_with_qmldesigner_core target_name) include/notimplementedexception.h include/plaintexteditmodifier.h include/propertycontainer.h + include/propertymetainfo.h include/propertynode.h include/propertyparser.h include/qmlanchors.h diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index db508d25ba9..a32bd8988c6 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.qbs +++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs @@ -266,6 +266,7 @@ Project { "include/bindingproperty.h", "include/componenttextmodifier.h", "include/customnotifications.h", + "include/enumerationmetainfo.h", "include/exception.h", "include/forwardview.h", "include/import.h", @@ -296,6 +297,7 @@ Project { "include/notimplementedexception.h", "include/plaintexteditmodifier.h", "include/propertycontainer.h", + "include/propertymetainfo.h", "include/propertynode.h", "include/propertyparser.h", "include/qmlanchors.h", diff --git a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp index 02b398282e4..8fdf4b94df0 100644 --- a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp +++ b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp @@ -130,7 +130,7 @@ public: QSize{300, 300}, QSize{1000, 1000}, ImageCacheCollectorNullImageHandling::DontCaptureNullImage}; - TimeStampProvider timeStampProvider; + PreviewTimeStampProvider timeStampProvider; AsynchronousExplicitImageCache cache{storage}; AsynchronousImageFactory factory{storage, timeStampProvider, collector}; }; diff --git a/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt b/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt index 253c91e4b72..3af5854d40f 100644 --- a/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt +++ b/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt @@ -1,5 +1,5 @@ add_qtc_test(tst_qml_testcore - CONDITION TARGET QmlProjectManager + CONDITION TARGET QmlProjectManager AND Qt5_VERSION VERSION_GREATER_EQUAL 6.2.0 DEFINES QT_CREATOR QMLDESIGNER_TEST diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp index 1c0239b542e..ca938fe48e7 100644 --- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp +++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp @@ -4232,6 +4232,17 @@ void tst_TestCore::testCopyModelRewriter2() QCOMPARE(stripWhiteSpaces(textEdit2.toPlainText()), stripWhiteSpaces(qmlString1)); } +namespace { +bool contains(const QmlDesigner::PropertyMetaInfos &properties, QUtf8StringView propertyName) +{ + auto found = std::find_if(properties.begin(), properties.end(), [&](const auto &property) { + return property.name() == propertyName; + }); + + return found != properties.end(); +} +} // namespace + void tst_TestCore::testSubComponentManager() { const QString qmlString("import QtQuick 2.15\n" @@ -4267,7 +4278,7 @@ void tst_TestCore::testSubComponentManager() subComponentManager->update(QUrl::fromLocalFile(fileName), model->imports()); QVERIFY(model->hasNodeMetaInfo("QtQuick.Rectangle", 2, 15)); - QVERIFY(model->metaInfo("QtQuick.Rectangle").propertyNames().contains("border.width")); + QVERIFY(contains(model->metaInfo("QtQuick.Rectangle").properties(), "border.width")); model->rewriterView()->setTextModifier(&modifier); @@ -4276,14 +4287,14 @@ void tst_TestCore::testSubComponentManager() QVERIFY(model->rewriterView()->rootModelNode().isValid()); QVERIFY(model->hasNodeMetaInfo("QtQuick.Rectangle", 2, 15)); - QVERIFY(model->metaInfo("QtQuick.Rectangle").propertyNames().contains("border.width")); + QVERIFY(contains(model->metaInfo("QtQuick.Rectangle").properties(), "border.width")); QVERIFY(model->metaInfo(".QQuickPen").isValid()); QSKIP("File components not working TODO", SkipAll); NodeMetaInfo myButtonMetaInfo = model->metaInfo("MyButton"); QVERIFY(myButtonMetaInfo.isValid()); - QVERIFY(myButtonMetaInfo.propertyNames().contains("border.width")); + QVERIFY(contains(myButtonMetaInfo.properties(), "border.width")); QVERIFY(myButtonMetaInfo.hasProperty("border.width")); } @@ -4638,7 +4649,7 @@ void tst_TestCore::testMetaInfoCustomType() QCOMPARE(propertyChangesInfo.superClasses().size(), 3); // DeclarativePropertyChanges just has 3 properties - QCOMPARE(propertyChangesInfo.propertyNames().size() - stateOperationInfo.propertyNames().size(), 3); + QCOMPARE(propertyChangesInfo.properties().size() - stateOperationInfo.properties().size(), 3); QApplication::processEvents(); } @@ -4656,15 +4667,13 @@ void tst_TestCore::testMetaInfoEnums() QVERIFY(view->rootModelNode().metaInfo().hasProperty("transformOrigin")); - QVERIFY(view->rootModelNode().metaInfo().propertyIsEnumType("transformOrigin")); - QCOMPARE(view->rootModelNode().metaInfo().propertyTypeName("transformOrigin"), QmlDesigner::TypeName("TransformOrigin")); - QVERIFY(view->rootModelNode().metaInfo().propertyKeysForEnum("transformOrigin").contains(QLatin1String("Bottom"))); - QVERIFY(view->rootModelNode().metaInfo().propertyKeysForEnum("transformOrigin").contains(QLatin1String("Top"))); + QVERIFY(view->rootModelNode().metaInfo().property("transformOrigin").isEnumType()); + QCOMPARE(view->rootModelNode().metaInfo().property("transformOrigin").propertyTypeName(), + QmlDesigner::TypeName("TransformOrigin")); - QVERIFY(view->rootModelNode().metaInfo().propertyIsEnumType("horizontalAlignment")); - QCOMPARE(view->rootModelNode().metaInfo().propertyTypeName("horizontalAlignment"), QmlDesigner::TypeName("HAlignment")); - QVERIFY(view->rootModelNode().metaInfo().propertyKeysForEnum("horizontalAlignment").contains(QLatin1String("AlignLeft"))); - QVERIFY(view->rootModelNode().metaInfo().propertyKeysForEnum("horizontalAlignment").contains(QLatin1String("AlignRight"))); + QVERIFY(view->rootModelNode().metaInfo().property("horizontalAlignment").isEnumType()); + QCOMPARE(view->rootModelNode().metaInfo().property("horizontalAlignment").propertyTypeName(), + QmlDesigner::TypeName("HAlignment")); QApplication::processEvents(); } @@ -4743,8 +4752,8 @@ void tst_TestCore::testMetaInfoProperties() QVERIFY(textNodeMetaInfo.hasProperty("objectName")); // QtQuick.QObject QVERIFY(!textNodeMetaInfo.hasProperty("bla")); - QVERIFY(textNodeMetaInfo.propertyIsWritable("text")); - QVERIFY(textNodeMetaInfo.propertyIsWritable("x")); + QVERIFY(textNodeMetaInfo.property("text").isWritable()); + QVERIFY(textNodeMetaInfo.property("x").isWritable()); QApplication::processEvents(); } @@ -4761,22 +4770,23 @@ void tst_TestCore::testMetaInfoDotProperties() QVERIFY(model->hasNodeMetaInfo("QtQuick.Text")); QVERIFY(model->metaInfo("QtQuick.Rectangle").hasProperty("border")); - QCOMPARE(model->metaInfo("QtQuick.Rectangle").propertyTypeName("border"), QmlDesigner::TypeName(".QQuickPen")); + QCOMPARE(model->metaInfo("QtQuick.Rectangle").property("border").propertyTypeName(), + QmlDesigner::TypeName(".QQuickPen")); QCOMPARE(view->rootModelNode().metaInfo().typeName(), QmlDesigner::TypeName("QtQuick.Text")); QVERIFY(view->rootModelNode().metaInfo().hasProperty("font")); QVERIFY(view->rootModelNode().metaInfo().hasProperty("font.bold")); - QVERIFY(view->rootModelNode().metaInfo().propertyNames().contains("font.bold")); - QVERIFY(view->rootModelNode().metaInfo().propertyNames().contains("font.pointSize")); + QVERIFY(contains(view->rootModelNode().metaInfo().properties(), "font.bold")); + QVERIFY(contains(view->rootModelNode().metaInfo().properties(), "font.pointSize")); QVERIFY(view->rootModelNode().metaInfo().hasProperty("font.pointSize")); ModelNode rectNode(addNodeListChild(view->rootModelNode(), "QtQuick.Rectangle", 2, 0, "data")); - QVERIFY(rectNode.metaInfo().propertyNames().contains("implicitHeight")); - QVERIFY(rectNode.metaInfo().propertyNames().contains("implicitWidth")); - QVERIFY(rectNode.metaInfo().propertyNames().contains("anchors.topMargin")); - QVERIFY(rectNode.metaInfo().propertyNames().contains("border.width")); + QVERIFY(contains(rectNode.metaInfo().properties(), "implicitHeight")); + QVERIFY(contains(rectNode.metaInfo().properties(), "implicitWidth")); + QVERIFY(contains(rectNode.metaInfo().properties(), "anchors.topMargin")); + QVERIFY(contains(rectNode.metaInfo().properties(), "border.width")); QVERIFY(rectNode.metaInfo().hasProperty("border")); QVERIFY(rectNode.metaInfo().hasProperty("border.width")); @@ -4796,20 +4806,20 @@ void tst_TestCore::testMetaInfoListProperties() QCOMPARE(view->rootModelNode().metaInfo().typeName(), QmlDesigner::TypeName("QtQuick.Item")); QVERIFY(view->rootModelNode().metaInfo().hasProperty("states")); - QVERIFY(view->rootModelNode().metaInfo().propertyIsListProperty("states")); + QVERIFY(view->rootModelNode().metaInfo().property("states").isListProperty()); QVERIFY(view->rootModelNode().metaInfo().hasProperty("children")); - QVERIFY(view->rootModelNode().metaInfo().propertyIsListProperty("children")); + QVERIFY(view->rootModelNode().metaInfo().property("children").isListProperty()); QVERIFY(view->rootModelNode().metaInfo().hasProperty("data")); - QVERIFY(view->rootModelNode().metaInfo().propertyIsListProperty("data")); + QVERIFY(view->rootModelNode().metaInfo().property("data").isListProperty()); QVERIFY(view->rootModelNode().metaInfo().hasProperty("resources")); - QVERIFY(view->rootModelNode().metaInfo().propertyIsListProperty("resources")); + QVERIFY(view->rootModelNode().metaInfo().property("resources").isListProperty()); QVERIFY(view->rootModelNode().metaInfo().hasProperty("transitions")); - QVERIFY(view->rootModelNode().metaInfo().propertyIsListProperty("transitions")); + QVERIFY(view->rootModelNode().metaInfo().property("transitions").isListProperty()); QVERIFY(view->rootModelNode().metaInfo().hasProperty("transform")); - QVERIFY(view->rootModelNode().metaInfo().propertyIsListProperty("transform")); + QVERIFY(view->rootModelNode().metaInfo().property("transform").isListProperty()); QVERIFY(view->rootModelNode().metaInfo().hasProperty("parent")); - QVERIFY(!view->rootModelNode().metaInfo().propertyIsListProperty("parent")); + QVERIFY(!view->rootModelNode().metaInfo().property("parent").isListProperty()); QApplication::processEvents(); } @@ -4904,8 +4914,8 @@ void tst_TestCore::testQtQuickControls2() QVERIFY(rootModelNode.metaInfo().isGraphicalItem()); QVERIFY(rootModelNode.isSubclassOf("QtQuick.Window.Window", -1, -1)); - QVERIFY(!rootModelNode.metaInfo().directPropertyNames().contains("visible")); - QVERIFY(rootModelNode.metaInfo().propertyNames().contains("visible")); + QVERIFY(!contains(rootModelNode.metaInfo().localProperties(), "visible")); + QVERIFY(contains(rootModelNode.metaInfo().properties(), "visible")); QVERIFY(!rootModelNode.allSubModelNodes().isEmpty()); ModelNode button = rootModelNode.allSubModelNodes().first(); diff --git a/tests/unit/mockup/qmldesigner/designercore/include/nodemetainfo.h b/tests/unit/mockup/qmldesigner/designercore/include/nodemetainfo.h index ed00f71d989..095e634672b 100644 --- a/tests/unit/mockup/qmldesigner/designercore/include/nodemetainfo.h +++ b/tests/unit/mockup/qmldesigner/designercore/include/nodemetainfo.h @@ -25,12 +25,14 @@ #pragma once +#include "propertymetainfo.h" + #include #include #include #include -#include "qmldesignercorelib_global.h" +#include QT_BEGIN_NAMESPACE class QDeclarativeContext; @@ -51,19 +53,14 @@ public: bool isValid() const { return {}; } bool isFileComponent() const { return {}; } bool hasProperty(const PropertyName &) const { return {}; } + PropertyMetaInfos properties() const { return {}; } + PropertyMetaInfos localProperties() const { return {}; } + PropertyMetaInfo property(const PropertyName &) const { return {}; } PropertyNameList propertyNames() const { return {}; } PropertyNameList signalNames() const { return {}; } PropertyNameList directPropertyNames() const { return {}; } PropertyName defaultPropertyName() const { return "data"; } bool hasDefaultProperty() const { return {}; } - TypeName propertyTypeName(const PropertyName &) const { return {}; } - bool propertyIsWritable(const PropertyName &) const { return {}; } - bool propertyIsListProperty(const PropertyName &) const { return {}; } - bool propertyIsEnumType(const PropertyName &) const { return {}; } - bool propertyIsPrivate(const PropertyName &) const { return {}; } - QString propertyEnumScope(const PropertyName &) const { return {}; } - QStringList propertyKeysForEnum(const PropertyName &) const { return {}; } - QVariant propertyCastedValue(const PropertyName &, const QVariant &) const { return {}; } QList classHierarchy() const { return {}; } QList superClasses() const { return {}; } diff --git a/tests/unit/mockup/qmldesigner/designercore/include/propertymetainfo.h b/tests/unit/mockup/qmldesigner/designercore/include/propertymetainfo.h new file mode 100644 index 00000000000..82b0a6ed92b --- /dev/null +++ b/tests/unit/mockup/qmldesigner/designercore/include/propertymetainfo.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +#include +#include + +#include + +namespace QmlDesigner { + +class PropertyMetaInfo +{ +public: + PropertyMetaInfo() = default; + PropertyMetaInfo(QSharedPointer, const PropertyName &) {} + ~PropertyMetaInfo() {} + + const TypeName &propertyTypeName() const + { + static TypeName foo; + return foo; + } + class NodeMetaInfo propertyNodeMetaInfo() const; + + bool isWritable() const { return {}; } + bool isListProperty() const { return {}; } + bool isEnumType() const { return {}; } + bool isPrivate() const { return {}; } + bool isPointer() const { return {}; } + QVariant castedValue(const QVariant &) const { return {}; } + PropertyName name() const & { return {}; } + + template + bool hasPropertyTypeName(const TypeName &...typeName) const + { + auto propertyTypeName_ = propertyTypeName(); + return ((propertyTypeName_ == typeName) && ...); + } +}; + +using PropertyMetaInfos = std::vector; + +} // namespace QmlDesigner