QmlDesigner: Introduction of PropertyMetaInfo

Because the project storage is integer id based the string based API
isn't fitting well for the new approach. PropertyMetaInfo can be easier
mapped to the project storage.

Task-number: QDS-7197
Change-Id: I49bc650abdaacf4b039d76c2514b5ad05ec84abe
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2022-06-09 17:03:42 +02:00
parent ae0032dfd5
commit fd41105191
46 changed files with 747 additions and 450 deletions

View File

@@ -28,10 +28,13 @@
#include <QByteArray> #include <QByteArray>
#include <QList> #include <QList>
#include <vector>
namespace QmlDesigner { namespace QmlDesigner {
using PropertyName = QByteArray; using PropertyName = QByteArray;
using PropertyNameList = QList<PropertyName>; using PropertyNameList = QList<PropertyName>;
using PropertyNames = std::vector<PropertyName>;
using TypeName = QByteArray; using TypeName = QByteArray;
} }

View File

@@ -143,6 +143,8 @@ void ActionEditor::setModelNode(const ModelNode &modelNode)
m_modelNode = modelNode; m_modelNode = modelNode;
} }
namespace {
bool isLiteral(QmlJS::AST::Node *ast) bool isLiteral(QmlJS::AST::Node *ast)
{ {
if (QmlJS::AST::cast<QmlJS::AST::StringLiteral *>(ast) if (QmlJS::AST::cast<QmlJS::AST::StringLiteral *>(ast)
@@ -154,6 +156,17 @@ bool isLiteral(QmlJS::AST::Node *ast)
return false; return false;
} }
TypeName skipCpp(TypeName typeName)
{
// TODO remove after project storage introduction
if (typeName.contains("<cpp>."))
typeName.remove(0, 6);
return typeName;
}
} // namespace
void ActionEditor::prepareConnections() void ActionEditor::prepareConnections()
{ {
if (!m_modelNode.isValid()) if (!m_modelNode.isValid())
@@ -197,17 +210,15 @@ void ActionEditor::prepareConnections()
ActionEditorDialog::ConnectionOption connection(modelNode.id()); ActionEditorDialog::ConnectionOption connection(modelNode.id());
for (const auto &propertyName : modelNode.metaInfo().propertyNames()) { for (const auto &property : modelNode.metaInfo().properties()) {
if (!typeWhiteList.contains(modelNode.metaInfo().propertyTypeName(propertyName))) const auto &propertyTypeName = property.propertyTypeName();
if (!typeWhiteList.contains(propertyTypeName))
continue; continue;
const QString name = QString::fromUtf8(propertyName); connection.properties.append(
const bool writeable = modelNode.metaInfo().propertyIsWritable(propertyName); ActionEditorDialog::PropertyOption(QString::fromUtf8(property.name()),
TypeName type = modelNode.metaInfo().propertyTypeName(propertyName); skipCpp(std::move(propertyTypeName)),
if (type.contains("<cpp>.")) property.isWritable()));
type.remove(0, 6);
connection.properties.append(ActionEditorDialog::PropertyOption(name, type, writeable));
} }
for (const VariantProperty &variantProperty : modelNode.variantProperties()) { for (const VariantProperty &variantProperty : modelNode.variantProperties()) {
@@ -216,12 +227,12 @@ void ActionEditor::prepareConnections()
continue; continue;
const QString name = QString::fromUtf8(variantProperty.name()); const QString name = QString::fromUtf8(variantProperty.name());
const bool writeable = modelNode.metaInfo().propertyIsWritable(variantProperty.name()); const bool writeable = modelNode.metaInfo().property(variantProperty.name()).isWritable();
TypeName type = variantProperty.dynamicTypeName();
if (type.contains("<cpp>."))
type.remove(0, 6);
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()); NodeMetaInfo metaInfo = m_modelNode.view()->model()->metaInfo(data.typeName.toUtf8());
if (metaInfo.isValid()) { if (metaInfo.isValid()) {
ActionEditorDialog::SingletonOption singelton; ActionEditorDialog::SingletonOption singelton;
for (const PropertyName &propertyName : metaInfo.propertyNames()) { for (const auto &property : metaInfo.properties()) {
TypeName type = metaInfo.propertyTypeName(propertyName); const TypeName &typeName = property.propertyTypeName();
if (!typeWhiteList.contains(type)) if (!typeWhiteList.contains(typeName))
continue; continue;
const QString name = QString::fromUtf8(propertyName); singelton.properties.append(
const bool writeable = metaInfo.propertyIsWritable(propertyName); ActionEditorDialog::PropertyOption(QString::fromUtf8(property.name()),
if (type.contains("<cpp>.")) skipCpp(typeName),
type.remove(0, 6); property.isWritable()));
singelton.properties.append(ActionEditorDialog::PropertyOption(name, type, writeable));
} }
if (!singelton.properties.isEmpty()) { if (!singelton.properties.isEmpty()) {

View File

@@ -113,7 +113,7 @@ void BindingEditor::setBackendValue(const QVariant &backendValue)
const ModelNode node = propertyEditorValue->modelNode(); const ModelNode node = propertyEditorValue->modelNode();
if (node.isValid()) { if (node.isValid()) {
m_backendValueTypeName = node.metaInfo().propertyTypeName(propertyEditorValue->name()); m_backendValueTypeName = node.metaInfo().property(propertyEditorValue->name()).propertyTypeName();
QString nodeId = node.id(); QString nodeId = node.id();
if (nodeId.isEmpty()) if (nodeId.isEmpty())
@@ -205,14 +205,14 @@ void BindingEditor::prepareBindings()
for (const auto &objnode : allNodes) { for (const auto &objnode : allNodes) {
BindingEditorDialog::BindingOption binding; BindingEditorDialog::BindingOption binding;
for (const auto &propertyName : objnode.metaInfo().propertyNames()) { for (const auto &property : objnode.metaInfo().properties()) {
TypeName propertyTypeName = objnode.metaInfo().propertyTypeName(propertyName); const TypeName &propertyTypeName = property.propertyTypeName();
if (skipTypeFiltering if (skipTypeFiltering
|| (m_backendValueTypeName == propertyTypeName) || (m_backendValueTypeName == propertyTypeName)
|| isVariant(propertyTypeName) || isVariant(propertyTypeName)
|| (targetTypeIsNumeric && isNumeric(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()) { if (metaInfo.isValid()) {
BindingEditorDialog::BindingOption binding; BindingEditorDialog::BindingOption binding;
for (const PropertyName &propertyName : metaInfo.propertyNames()) { for (const auto &property : metaInfo.properties()) {
TypeName propertyTypeName = metaInfo.propertyTypeName(propertyName); TypeName propertyTypeName = property.propertyTypeName();
if (skipTypeFiltering if (skipTypeFiltering
|| (m_backendValueTypeName == propertyTypeName) || (m_backendValueTypeName == propertyTypeName)
|| (isVariant(propertyTypeName)) || (isVariant(propertyTypeName))
|| (targetTypeIsNumeric && isNumeric(propertyTypeName)) || (targetTypeIsNumeric && isNumeric(propertyTypeName))
|| (isColor(m_backendValueTypeName) && isColor(propertyTypeName))) { || (isColor(m_backendValueTypeName) && isColor(propertyTypeName))) {
binding.properties.append(QString::fromUtf8(propertyName)); binding.properties.append(QString::fromUtf8(property.name()));
} }
} }

View File

@@ -39,6 +39,8 @@
#include <qmlitemnode.h> #include <qmlitemnode.h>
#include <nodeabstractproperty.h> #include <nodeabstractproperty.h>
#include <utils/set_algorithm.h>
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include <QTableView> #include <QTableView>
@@ -137,6 +139,20 @@ void SignalList::setModelNode(const ModelNode &modelNode)
m_modelNode = modelNode; m_modelNode = modelNode;
} }
namespace {
template<typename Callback>
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() void SignalList::prepareSignals()
{ {
if (!m_modelNode.isValid()) if (!m_modelNode.isValid())
@@ -145,27 +161,21 @@ void SignalList::prepareSignals()
QList<QmlConnections> connections = QmlFlowViewNode::getAssociatedConnections(m_modelNode); QList<QmlConnections> connections = QmlFlowViewNode::getAssociatedConnections(m_modelNode);
for (ModelNode &node : m_modelNode.view()->allModelNodes()) { for (ModelNode &node : m_modelNode.view()->allModelNodes()) {
// Collect all items which contain at least one of the specified signals callOnlyMouseSignalNames(node.metaInfo().signalNames(),
const PropertyNameList signalNames = node.metaInfo().signalNames(); QmlFlowViewNode::mouseSignals(),
// Put the signals into a QSet to avoid duplicates [&](const PropertyName &signal) {
auto signalNamesSet = QSet<PropertyName>(signalNames.begin(), signalNames.end());
for (const PropertyName &signal : signalNamesSet) {
if (QmlFlowViewNode::st_mouseSignals.contains(signal))
appendSignalToModel(connections, node, signal); appendSignalToModel(connections, node, signal);
} });
// Gather valid properties and aliases from components // Gather valid properties and aliases from components
for (const PropertyName &property : node.metaInfo().propertyNames()) { for (const auto &property : node.metaInfo().properties()) {
const TypeName propertyType = node.metaInfo().propertyTypeName(property); const NodeMetaInfo info = m_modelNode.model()->metaInfo(property.propertyTypeName());
const NodeMetaInfo info = m_modelNode.model()->metaInfo(propertyType);
// Collect all items which contain at least one of the specified signals callOnlyMouseSignalNames(info.signalNames(),
const PropertyNameList signalNames = info.signalNames(); QmlFlowViewNode::mouseSignals(),
// Put the signals into a QSet to avoid duplicates [&](const PropertyName &signal) {
auto signalNamesSet = QSet<PropertyName>(signalNames.begin(), signalNames.end()); appendSignalToModel(connections, node, signal);
for (const PropertyName &signal : signalNamesSet) { });
if (QmlFlowViewNode::st_mouseSignals.contains(signal))
appendSignalToModel(connections, node, signal, property);
}
} }
} }
} }

View File

@@ -568,11 +568,17 @@ void layoutGridLayout(const SelectionContext &selectionContext)
} }
} }
static PropertyNameList sortedPropertyNameList(const PropertyNameList &nameList) static PropertyNameList sortedPropertyNameList(const PropertyMetaInfos &properties)
{ {
PropertyNameList sortedPropertyNameList = nameList; auto propertyNames = Utils::transform<PropertyNameList>(properties, [](const auto &property) {
std::stable_sort(sortedPropertyNameList.begin(), sortedPropertyNameList.end()); return property.name();
return sortedPropertyNameList; });
std::sort(propertyNames.begin(), propertyNames.end());
propertyNames.erase(std::unique(propertyNames.begin(), propertyNames.end()), propertyNames.end());
return propertyNames;
} }
static QString toUpper(const QString &signal) static QString toUpper(const QString &signal)
@@ -628,12 +634,14 @@ static QStringList getSortedSignalNameList(const ModelNode &modelNode)
QStringList signalNames; QStringList signalNames;
if (metaInfo.isValid()) { 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) for (const PropertyName &signalName : signalNameList)
if (!signalName.contains("Changed")) if (!signalName.contains("Changed"))
signalNames.append(QString::fromUtf8(signalName)); signalNames.append(QString::fromUtf8(signalName));
const PropertyNameList propertyNameList = sortedPropertyNameList(metaInfo.propertyNames()); const PropertyNameList propertyNameList = sortedPropertyNameList(metaInfo.properties());
for (const PropertyName &propertyName : propertyNameList) for (const PropertyName &propertyName : propertyNameList)
if (!propertyName.contains(".")) if (!propertyName.contains("."))
signalNames.append(QString::fromUtf8(propertyName + "Changed")); signalNames.append(QString::fromUtf8(propertyName + "Changed"));

View File

@@ -138,14 +138,15 @@ QStringList BindingModel::possibleTargetProperties(const BindingProperty &bindin
NodeMetaInfo metaInfo = modelNode.metaInfo(); NodeMetaInfo metaInfo = modelNode.metaInfo();
if (metaInfo.isValid()) { if (metaInfo.isValid()) {
QStringList possibleProperties; const auto properties = metaInfo.properties();
const QList<PropertyName> propertyNames = metaInfo.propertyNames(); QStringList writableProperties;
for (const PropertyName &propertyName : propertyNames) { writableProperties.reserve(static_cast<int>(properties.size()));
if (metaInfo.propertyIsWritable(propertyName)) for (const auto &property : properties) {
possibleProperties << QString::fromUtf8(propertyName); if (property.isWritable())
writableProperties.push_back(QString::fromUtf8(property.name()));
} }
return possibleProperties; return writableProperties;
} }
return QStringList(); return QStringList();
@@ -159,11 +160,10 @@ QStringList BindingModel::possibleSourceProperties(const BindingProperty &bindin
TypeName typeName; TypeName typeName;
if (bindingProperty.parentModelNode().metaInfo().isValid()) { if (auto metaInfo = bindingProperty.parentModelNode().metaInfo(); metaInfo.isValid())
typeName = bindingProperty.parentModelNode().metaInfo().propertyTypeName(bindingProperty.name()); typeName = metaInfo.property(bindingProperty.name()).propertyTypeName();
} else { else
qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for target node"; qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for target node";
}
const QString &id = stringlist.constFirst(); const QString &id = stringlist.constFirst();
@@ -178,9 +178,9 @@ QStringList BindingModel::possibleSourceProperties(const BindingProperty &bindin
NodeMetaInfo metaInfo = connectionView()->model()->metaInfo(data.typeName.toUtf8()); NodeMetaInfo metaInfo = connectionView()->model()->metaInfo(data.typeName.toUtf8());
if (metaInfo.isValid()) { if (metaInfo.isValid()) {
for (const PropertyName &propertyName : metaInfo.propertyNames()) { for (const auto &property : metaInfo.properties()) {
//without check for now //without check for now
possibleProperties << QString::fromUtf8(propertyName); possibleProperties.push_back(QString::fromUtf8(property.name()));
} }
return possibleProperties; return possibleProperties;
@@ -207,9 +207,9 @@ QStringList BindingModel::possibleSourceProperties(const BindingProperty &bindin
} }
if (metaInfo.isValid()) { if (metaInfo.isValid()) {
for (const PropertyName &propertyName : metaInfo.propertyNames()) { for (const auto &property : metaInfo.properties()) {
if (metaInfo.propertyTypeName(propertyName) == typeName) //### todo proper check if (property.propertyTypeName() == typeName) //### todo proper check
possibleProperties << QString::fromUtf8(propertyName); possibleProperties.push_back(QString::fromUtf8(property.name()));
} }
} else { } else {
qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for source node"; qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for source node";
@@ -233,10 +233,9 @@ static PropertyName unusedProperty(const ModelNode &modelNode)
{ {
PropertyName propertyName = "none"; PropertyName propertyName = "none";
if (modelNode.metaInfo().isValid()) { if (modelNode.metaInfo().isValid()) {
const QList<PropertyName> propertyNames = modelNode.metaInfo().propertyNames(); for (const auto &property : modelNode.metaInfo().properties()) {
for (const PropertyName &propertyName : propertyNames) { if (property.isWritable() && !modelNode.hasProperty(propertyName))
if (modelNode.metaInfo().propertyIsWritable(propertyName) && !modelNode.hasProperty(propertyName)) return property.name();
return propertyName;
} }
} }

View File

@@ -475,7 +475,7 @@ QStringList ConnectionModel::getPossibleSignalsForConnection(const ModelNode &co
auto getAliasMetaSignals = [&](QString aliasPart, NodeMetaInfo metaInfo) { auto getAliasMetaSignals = [&](QString aliasPart, NodeMetaInfo metaInfo) {
if (metaInfo.isValid() && metaInfo.hasProperty(aliasPart.toUtf8())) { if (metaInfo.isValid() && metaInfo.hasProperty(aliasPart.toUtf8())) {
NodeMetaInfo propertyMetaInfo = connectionView()->model()->metaInfo( NodeMetaInfo propertyMetaInfo = connectionView()->model()->metaInfo(
metaInfo.propertyTypeName(aliasPart.toUtf8())); metaInfo.property(aliasPart.toUtf8()).propertyTypeName());
if (propertyMetaInfo.isValid()) { if (propertyMetaInfo.isValid()) {
return propertyNameListToStringList(propertyMetaInfo.signalNames()); return propertyNameListToStringList(propertyMetaInfo.signalNames());
} }

View File

@@ -216,8 +216,9 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
return; return;
const ModelNode node = property.parentModelNode(); const ModelNode node = property.parentModelNode();
const TypeName typeName = property.isDynamic() ? property.dynamicTypeName() const TypeName typeName = property.isDynamic()
: node.metaInfo().propertyTypeName(property.name()); ? property.dynamicTypeName()
: node.metaInfo().property(property.name()).propertyTypeName();
const QString targetName = node.displayName() + "." + property.name(); const QString targetName = node.displayName() + "." + property.name();

View File

@@ -298,23 +298,19 @@ QWidget *ConnectionDelegate::createEditor(QWidget *parent, const QStyleOptionVie
auto addMetaInfoProperties = [&](const NodeMetaInfo& itemMetaInfo, QString itemName){ auto addMetaInfoProperties = [&](const NodeMetaInfo& itemMetaInfo, QString itemName){
if (itemMetaInfo.isValid()) { if (itemMetaInfo.isValid()) {
for (const PropertyName &propertyName : itemMetaInfo.propertyNames()) { for (const auto &property : itemMetaInfo.properties()) {
TypeName propertyType = itemMetaInfo.propertyTypeName(propertyName); TypeName propertyType = property.propertyTypeName();
if (!propertyType.isEmpty()) { if (!propertyType.isEmpty()) {
//first letter is a reliable item indicator //first letter is a reliable item indicator
QChar firstLetter = QString::fromUtf8(propertyType).at(0); QChar firstLetter = QString::fromUtf8(propertyType).at(0);
if (firstLetter.isLetter() && firstLetter.isUpper()) { if (firstLetter.isLetter() && firstLetter.isUpper()) {
if (!itemMetaInfo.propertyIsEnumType(propertyName) if (!property.isEnumType() && !property.isPrivate()
&& !itemMetaInfo.propertyIsPrivate(propertyName) && !property.isListProperty() && !property.isPointer()) {
&& !itemMetaInfo.propertyIsListProperty(propertyName)
&& !itemMetaInfo.propertyIsPointer(propertyName)) {
NodeMetaInfo propertyMetaInfo = NodeMetaInfo propertyMetaInfo =
connectionModel->connectionView()->model()->metaInfo(propertyType); connectionModel->connectionView()->model()->metaInfo(propertyType);
if (propertyMetaInfo.isValid()) { if (propertyMetaInfo.isValid()) {
if (propertyMetaInfo.isQmlItem()) { if (propertyMetaInfo.isQmlItem()) {
connectionComboBox->addItem(itemName connectionComboBox->addItem(itemName + "." + property.name());
+ "."
+ propertyName);
} }
} }
} }

View File

@@ -36,6 +36,7 @@
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <qmldesignerconstants.h> #include <qmldesignerconstants.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <QMessageBox> #include <QMessageBox>
@@ -345,10 +346,9 @@ QStringList DynamicPropertiesModel::possibleTargetProperties(const BindingProper
if (metaInfo.isValid()) { if (metaInfo.isValid()) {
QStringList possibleProperties; QStringList possibleProperties;
const QList<PropertyName> propertyNames = metaInfo.propertyNames(); for (const auto &property : metaInfo.properties()) {
for (const PropertyName &propertyName : propertyNames) { if (property.isWritable())
if (metaInfo.propertyIsWritable(propertyName)) possibleProperties.push_back(QString::fromUtf8(property.name()));
possibleProperties << QString::fromUtf8(propertyName);
} }
return possibleProperties; return possibleProperties;
@@ -383,8 +383,8 @@ QStringList DynamicPropertiesModel::possibleSourceProperties(const BindingProper
PropertyName typeName; PropertyName typeName;
if (bindingProperty.parentModelNode().metaInfo().isValid()) { if (auto metaInfo = bindingProperty.parentModelNode().metaInfo(); metaInfo.isValid()) {
typeName = bindingProperty.parentModelNode().metaInfo().propertyTypeName(bindingProperty.name()); typeName = metaInfo.property(bindingProperty.name()).propertyTypeName();
} else { } else {
qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for target node"; qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for target node";
} }
@@ -402,10 +402,9 @@ QStringList DynamicPropertiesModel::possibleSourceProperties(const BindingProper
if (metaInfo.isValid()) { if (metaInfo.isValid()) {
QStringList possibleProperties; QStringList possibleProperties;
const QList<PropertyName> propertyNames = metaInfo.propertyNames(); for (const auto &property : metaInfo.properties()) {
for (const PropertyName &propertyName : propertyNames) { if (property.propertyTypeName() == typeName) //### todo proper check
if (metaInfo.propertyTypeName(propertyName) == typeName) //### todo proper check possibleProperties.push_back(QString::fromUtf8(property.name()));
possibleProperties << QString::fromUtf8(propertyName);
} }
return possibleProperties; return possibleProperties;
} else { } else {

View File

@@ -658,7 +658,7 @@ void DesignDocument::paste()
PropertyName defaultProperty(targetNode.metaInfo().defaultPropertyName()); PropertyName defaultProperty(targetNode.metaInfo().defaultPropertyName());
scatterItem(pastedNode, targetNode); scatterItem(pastedNode, targetNode);
if (targetNode.metaInfo().propertyIsListProperty(defaultProperty)) if (targetNode.metaInfo().property(defaultProperty).isListProperty())
targetNode.nodeListProperty(defaultProperty).reparentHere(pastedNode); targetNode.nodeListProperty(defaultProperty).reparentHere(pastedNode);
else else
qWarning() << "Cannot reparent to" << targetNode; qWarning() << "Cannot reparent to" << targetNode;

View File

@@ -99,7 +99,8 @@ void MaterialEditorContextObject::changeTypeName(const QString &typeName)
QTC_ASSERT(metaInfo.isValid(), return); QTC_ASSERT(metaInfo.isValid(), return);
// Create a list of properties available for the new type // Create a list of properties available for the new type
PropertyNameList propertiesAndSignals(metaInfo.propertyNames()); PropertyNameList propertiesAndSignals = Utils::transform<PropertyNameList>(
metaInfo.properties(), [](const auto &property) { return property.name(); });
// Add signals to the list // Add signals to the list
const PropertyNameList signalNames = metaInfo.signalNames(); const PropertyNameList signalNames = metaInfo.signalNames();
for (const PropertyName &signal : signalNames) { for (const PropertyName &signal : signalNames) {

View File

@@ -270,9 +270,12 @@ void MaterialEditorQmlBackend::setup(const QmlObjectNode &selectedMaterialNode,
if (selectedMaterialNode.isValid()) { if (selectedMaterialNode.isValid()) {
m_contextObject->setModel(materialEditor->model()); m_contextObject->setModel(materialEditor->model());
const PropertyNameList propertyNames = selectedMaterialNode.modelNode().metaInfo().propertyNames(); for (const auto &property : selectedMaterialNode.modelNode().metaInfo().properties()) {
for (const PropertyName &propertyName : propertyNames) createPropertyEditorValue(selectedMaterialNode,
createPropertyEditorValue(selectedMaterialNode, propertyName, selectedMaterialNode.instanceValue(propertyName), materialEditor); property.name(),
selectedMaterialNode.instanceValue(property.name()),
materialEditor);
}
// model node // model node
m_backendModelNode.setup(selectedMaterialNode.modelNode()); m_backendModelNode.setup(selectedMaterialNode.modelNode());

View File

@@ -125,7 +125,7 @@ void MaterialEditorView::changeValue(const QString &name)
QVariant castedValue; QVariant castedValue;
if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) { if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) {
castedValue = metaInfo.propertyCastedValue(propertyName, value->value()); castedValue = metaInfo.property(propertyName).castedValue(value->value());
} else { } else {
qWarning() << __FUNCTION__ << propertyName << "cannot be casted (metainfo)"; qWarning() << __FUNCTION__ << propertyName << "cannot be casted (metainfo)";
return; return;
@@ -139,8 +139,7 @@ void MaterialEditorView::changeValue(const QString &name)
bool propertyTypeUrl = false; bool propertyTypeUrl = false;
if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) { if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) {
if (metaInfo.propertyTypeName(propertyName) == "QUrl" if (metaInfo.property(propertyName).hasPropertyTypeName("QUrl", "url")) {
|| metaInfo.propertyTypeName(propertyName) == "url") {
// turn absolute local file paths into relative paths // turn absolute local file paths into relative paths
propertyTypeUrl = true; propertyTypeUrl = true;
QString filePath = castedValue.toUrl().toString(); QString filePath = castedValue.toUrl().toString();
@@ -202,13 +201,15 @@ void MaterialEditorView::changeExpression(const QString &propertyName)
return; return;
} }
if (m_selectedMaterial.metaInfo().isValid() && m_selectedMaterial.metaInfo().hasProperty(name)) { if (auto metaInfo = m_selectedMaterial.metaInfo();
if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "QColor") { metaInfo.isValid() && metaInfo.hasProperty(name)) {
auto propertyTypeName = metaInfo.property(name).propertyTypeName();
if (propertyTypeName == "QColor") {
if (QColor(value->expression().remove('"')).isValid()) { if (QColor(value->expression().remove('"')).isValid()) {
qmlObjectNode.setVariantProperty(name, QColor(value->expression().remove('"'))); qmlObjectNode.setVariantProperty(name, QColor(value->expression().remove('"')));
return; return;
} }
} else if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "bool") { } else if (propertyTypeName == "bool") {
if (isTrueFalseLiteral(value->expression())) { if (isTrueFalseLiteral(value->expression())) {
if (value->expression().compare("true", Qt::CaseInsensitive) == 0) if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
qmlObjectNode.setVariantProperty(name, true); qmlObjectNode.setVariantProperty(name, true);
@@ -216,21 +217,21 @@ void MaterialEditorView::changeExpression(const QString &propertyName)
qmlObjectNode.setVariantProperty(name, false); qmlObjectNode.setVariantProperty(name, false);
return; return;
} }
} else if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "int") { } else if (propertyTypeName == "int") {
bool ok; bool ok;
int intValue = value->expression().toInt(&ok); int intValue = value->expression().toInt(&ok);
if (ok) { if (ok) {
qmlObjectNode.setVariantProperty(name, intValue); qmlObjectNode.setVariantProperty(name, intValue);
return; return;
} }
} else if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "qreal") { } else if (propertyTypeName == "qreal") {
bool ok; bool ok;
qreal realValue = value->expression().toDouble(&ok); qreal realValue = value->expression().toDouble(&ok);
if (ok) { if (ok) {
qmlObjectNode.setVariantProperty(name, realValue); qmlObjectNode.setVariantProperty(name, realValue);
return; return;
} }
} else if (m_selectedMaterial.metaInfo().propertyTypeName(name) == "QVariant") { } else if (propertyTypeName == "QVariant") {
bool ok; bool ok;
qreal realValue = value->expression().toDouble(&ok); qreal realValue = value->expression().toDouble(&ok);
if (ok) { if (ok) {
@@ -809,7 +810,7 @@ void QmlDesigner::MaterialEditorView::highlightSupportedProperties(bool highligh
QTC_ASSERT(metaInfo.isValid(), return); QTC_ASSERT(metaInfo.isValid(), return);
for (const QString &propName : propNames) { 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<QObject *>(); QObject *propEditorValObj = propMap.value(propName).value<QObject *>();
PropertyEditorValue *propEditorVal = qobject_cast<PropertyEditorValue *>(propEditorValObj); PropertyEditorValue *propEditorVal = qobject_cast<PropertyEditorValue *>(propEditorValObj);
propEditorVal->setHasActiveDrag(highlight); propEditorVal->setHasActiveDrag(highlight);

View File

@@ -65,11 +65,10 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
if (parentInfo.isSubclassOf("QtQuick3D.DefaultMaterial") if (parentInfo.isSubclassOf("QtQuick3D.DefaultMaterial")
|| parentInfo.isSubclassOf("QtQuick3D.PrincipledMaterial")) { || parentInfo.isSubclassOf("QtQuick3D.PrincipledMaterial")) {
// All texture properties are valid targets // All texture properties are valid targets
const PropertyNameList targetNodeNameList = parentInfo.propertyNames(); for (const auto &property : parentInfo.properties()) {
for (const PropertyName &name : targetNodeNameList) { const TypeName &propType = property.propertyTypeName();
TypeName propType = parentInfo.propertyTypeName(name);
if (propType == textureType || propType == textureTypeCpp) { if (propType == textureType || propType == textureTypeCpp) {
propertyList.append(QString::fromLatin1(name)); propertyList.append(QString::fromUtf8(property.name()));
if (breakOnFirst) if (breakOnFirst)
return; return;
} }
@@ -168,15 +167,13 @@ ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded(
// Create dialog for selecting writable properties of exact property type // Create dialog for selecting writable properties of exact property type
ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded( ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded(
const ModelNode &targetNode, TypeName type, QWidget *parent) const ModelNode &targetNode, TypeName propertyType, QWidget *parent)
{ {
const NodeMetaInfo metaInfo = targetNode.metaInfo(); const NodeMetaInfo metaInfo = targetNode.metaInfo();
const PropertyNameList propNames = metaInfo.propertyNames();
const TypeName property(type);
QStringList matchingNames; QStringList matchingNames;
for (const auto &propName : propNames) { for (const auto &property : metaInfo.properties()) {
if (metaInfo.propertyTypeName(propName) == property && metaInfo.propertyIsWritable(propName)) if (property.hasPropertyTypeName(propertyType) && property.isWritable())
matchingNames.append(QString::fromLatin1(propName)); matchingNames.append(QString::fromUtf8(property.name()));
} }
if (!matchingNames.isEmpty()) if (!matchingNames.isEmpty())

View File

@@ -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); BindingProperty listProp = targetNode.bindingProperty(selectedProp);
listProp.addModelNodeToArray(newModelNode); listProp.addModelNodeToArray(newModelNode);
validContainer = true; validContainer = true;
@@ -1105,7 +1105,7 @@ ModelNode NavigatorTreeModel::createTextureNode(const NodeAbstractProperty &targ
TypeName propertyType(const NodeAbstractProperty &property) 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, void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProperty,

View File

@@ -220,7 +220,10 @@ void PropertyEditorContextObject::changeTypeName(const QString &typeName)
} }
// Create a list of properties available for the new type // Create a list of properties available for the new type
QList<PropertyName> propertiesAndSignals(metaInfo.propertyNames()); auto propertiesAndSignals = Utils::transform<PropertyNameList>(metaInfo.properties(),
[](const auto &property) {
return property.name();
});
// Add signals to the list // Add signals to the list
for (const auto &signal : metaInfo.signalNames()) { for (const auto &signal : metaInfo.signalNames()) {
if (signal.isEmpty()) if (signal.isEmpty())

View File

@@ -25,8 +25,9 @@
#include "propertyeditorqmlbackend.h" #include "propertyeditorqmlbackend.h"
#include "propertyeditorvalue.h"
#include "propertyeditortransaction.h" #include "propertyeditortransaction.h"
#include "propertyeditorvalue.h"
#include "propertymetainfo.h"
#include <qmldesignerconstants.h> #include <qmldesignerconstants.h>
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <qmltimeline.h> #include <qmltimeline.h>
@@ -415,10 +416,13 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
if (propertyEditorBenchmark().isInfoEnabled()) if (propertyEditorBenchmark().isInfoEnabled())
time.start(); time.start();
const QList<PropertyName> propertyNames = qmlObjectNode.modelNode().metaInfo().propertyNames(); for (const auto &property : qmlObjectNode.modelNode().metaInfo().properties()) {
for (const PropertyName &propertyName : propertyNames) auto propertyName = property.name();
createPropertyEditorValue(qmlObjectNode, propertyName, qmlObjectNode.instanceValue(propertyName), propertyEditor); createPropertyEditorValue(qmlObjectNode,
propertyName,
qmlObjectNode.instanceValue(propertyName),
propertyEditor);
}
setupLayoutAttachedProperties(qmlObjectNode, propertyEditor); setupLayoutAttachedProperties(qmlObjectNode, propertyEditor);
setupAuxiliaryProperties(qmlObjectNode, propertyEditor); setupAuxiliaryProperties(qmlObjectNode, propertyEditor);
@@ -514,9 +518,11 @@ void PropertyEditorQmlBackend::initialSetup(const TypeName &typeName, const QUrl
{ {
NodeMetaInfo metaInfo = propertyEditor->model()->metaInfo(typeName); NodeMetaInfo metaInfo = propertyEditor->model()->metaInfo(typeName);
const QList<PropertyName> propertyNames = metaInfo.propertyNames(); for (const auto &property : metaInfo.properties()) {
for (const PropertyName &propertyName : propertyNames) setupPropertyEditorValue(property.name(),
setupPropertyEditorValue(propertyName, propertyEditor, QString::fromUtf8(metaInfo.propertyTypeName(propertyName))); propertyEditor,
QString::fromUtf8(property.propertyTypeName()));
}
auto valueObject = qobject_cast<PropertyEditorValue *>(variantToQObject( auto valueObject = qobject_cast<PropertyEditorValue *>(variantToQObject(
m_backendValuesPropertyMap.value(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY))); 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 parentProperty = list.first();
const PropertyName itemProperty = list.last(); 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 itemInfo = node.view()->model()->metaInfo("QtQuick.Item");
NodeMetaInfo textInfo = node.view()->model()->metaInfo("QtQuick.Text"); NodeMetaInfo textInfo = node.view()->model()->metaInfo("QtQuick.Text");
@@ -596,7 +602,7 @@ inline bool dotPropertyHeuristic(const QmlObjectNode &node, const NodeMetaInfo &
return true; return true;
} }
QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &metaType,
const NodeMetaInfo &superType, const NodeMetaInfo &superType,
const QmlObjectNode &node) const QmlObjectNode &node)
{ {
@@ -615,20 +621,22 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
allTypes.append(variantToStringList(node->property("typeNames").value)); allTypes.append(variantToStringList(node->property("typeNames").value));
} }
const QList<PropertyName> allProperties = type.propertyNames(); auto propertyMetaInfoCompare = [](const auto &first, const auto &second) {
return first.name() < second.name();
QMap<PropertyName, QList<PropertyName>> propertyMap; };
QList<PropertyName> separateSectionProperties; std::map<PropertyMetaInfo, PropertyMetaInfos, decltype(propertyMetaInfoCompare)> propertyMap(
propertyMetaInfoCompare);
PropertyMetaInfos separateSectionProperties;
// Iterate over all properties and isolate the properties which have their own template // 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("__")) if (propertyName.startsWith("__"))
continue; // private API continue; // private API
if (!superType.hasProperty(propertyName) if (!superType.hasProperty(propertyName) // TODO add property.isLocalProperty()
&& type.propertyIsWritable(propertyName) && property.isWritable() && dotPropertyHeuristic(node, metaType, propertyName)) {
&& dotPropertyHeuristic(node, type, propertyName)) { QString typeName = QString::fromUtf8(property.propertyTypeName());
QString typeName = QString::fromLatin1(type.propertyTypeName(propertyName));
if (typeName == "alias" && node.isValid()) if (typeName == "alias" && node.isValid())
typeName = QString::fromLatin1(node.instanceType(propertyName)); typeName = QString::fromLatin1(node.instanceType(propertyName));
@@ -636,18 +644,16 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
// Check if a template for the type exists // Check if a template for the type exists
if (allTypes.contains(typeName)) { if (allTypes.contains(typeName)) {
if (separateSectionTypes.contains(typeName)) { // template enforces separate section if (separateSectionTypes.contains(typeName)) { // template enforces separate section
separateSectionProperties.append(propertyName); separateSectionProperties.push_back(property);
} else { } else {
if (propertyName.contains('.')) { 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].push_back(property);
propertyMap[parentProperty].append(propertyName);
else
propertyMap[parentProperty] = { propertyName };
} else { } else {
if (!propertyMap.contains(propertyName)) propertyMap[property];
propertyMap[propertyName] = {};
} }
} }
} }
@@ -655,28 +661,29 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
} }
// Filter out the properties which have a basic type e.g. int, string, bool // Filter out the properties which have a basic type e.g. int, string, bool
QList<PropertyName> basicProperties; PropertyMetaInfos basicProperties;
auto it = propertyMap.begin(); auto it = propertyMap.begin();
while (it != propertyMap.end()) { while (it != propertyMap.end()) {
if (it.value().empty()) { if (it->second.empty()) {
basicProperties.append(it.key()); basicProperties.push_back(it->first);
it = propertyMap.erase(it); it = propertyMap.erase(it);
} else { } else {
++it; ++it;
} }
} }
Utils::sort(basicProperties); Utils::sort(basicProperties, propertyMetaInfoCompare);
auto findAndFillTemplate = [&nodes, &node, &type](const PropertyName &label, auto findAndFillTemplate = [&nodes, &node](const PropertyName &label,
const PropertyName &property) { const PropertyMetaInfo &property) {
PropertyName underscoreProperty = property; const auto &propertyName = property.name();
PropertyName underscoreProperty = propertyName;
underscoreProperty.replace('.', '_'); underscoreProperty.replace('.', '_');
TypeName typeName = type.propertyTypeName(property); TypeName typeName = property.propertyTypeName();
// alias resolution only possible with instance // alias resolution only possible with instance
if (typeName == "alias" && node.isValid()) if (typeName == "alias" && node.isValid())
typeName = node.instanceType(property); typeName = node.instanceType(propertyName);
QString filledTemplate; QString filledTemplate;
for (const QmlJS::SimpleReaderNode::Ptr &n : nodes) { for (const QmlJS::SimpleReaderNode::Ptr &n : nodes) {
@@ -730,8 +737,8 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
qmlInnerTemplate += "bottomPadding: 10\n"; qmlInnerTemplate += "bottomPadding: 10\n";
qmlInnerTemplate += "SectionLayout {\n"; qmlInnerTemplate += "SectionLayout {\n";
for (const auto &p : qAsConst(basicProperties)) for (const auto &basicProperty : std::as_const(basicProperties))
qmlInnerTemplate += findAndFillTemplate(p, p); qmlInnerTemplate += findAndFillTemplate(basicProperty.name(), basicProperty);
qmlInnerTemplate += "}\n"; // SectionLayout qmlInnerTemplate += "}\n"; // SectionLayout
qmlInnerTemplate += "}\n"; // Column 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 // Second the section containing properties of complex type for which no specific template exists e.g. Button
if (!propertyMap.empty()) { if (!propertyMap.empty()) {
emptyTemplate = false; emptyTemplate = false;
for (auto it = propertyMap.cbegin(); it != propertyMap.cend(); ++it) { for (auto &[property, properties] : propertyMap) {
const auto &key = it.key(); // for (auto it = propertyMap.cbegin(); it != propertyMap.cend(); ++it) {
TypeName parentTypeName = type.propertyTypeName(key); TypeName parentTypeName = property.propertyTypeName();
// alias resolution only possible with instance // alias resolution only possible with instance
if (parentTypeName == "alias" && node.isValid()) if (parentTypeName == "alias" && node.isValid())
parentTypeName = node.instanceType(key); parentTypeName = node.instanceType(property.name());
qmlInnerTemplate += "Section {\n"; qmlInnerTemplate += "Section {\n";
qmlInnerTemplate += QStringLiteral("caption: \"%1 - %2\"\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 += anchorLeftRight;
qmlInnerTemplate += "leftPadding: 8\n"; qmlInnerTemplate += "leftPadding: 8\n";
qmlInnerTemplate += "rightPadding: 0\n"; qmlInnerTemplate += "rightPadding: 0\n";
@@ -757,12 +765,14 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
qmlInnerTemplate += "level: 1\n"; qmlInnerTemplate += "level: 1\n";
qmlInnerTemplate += "SectionLayout {\n"; qmlInnerTemplate += "SectionLayout {\n";
auto properties = it.value(); Utils::sort(properties, propertyMetaInfoCompare);
Utils::sort(properties);
for (const auto &p : qAsConst(properties)) { for (const auto &subProperty : properties) {
const PropertyName shortName = p.contains('.') ? p.split('.').last() : p; const auto &propertyName = subProperty.name();
qmlInnerTemplate += findAndFillTemplate(shortName, p); 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 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 // Third the section containing properties of complex type for which a specific template exists e.g. Rectangle, Image
if (!separateSectionProperties.empty()) { if (!separateSectionProperties.empty()) {
emptyTemplate = false; emptyTemplate = false;
Utils::sort(separateSectionProperties); Utils::sort(separateSectionProperties, propertyMetaInfoCompare);
for (const auto &p : qAsConst(separateSectionProperties)) for (const auto &property : separateSectionProperties)
qmlInnerTemplate += findAndFillTemplate(p, p); qmlInnerTemplate += findAndFillTemplate(property.name(), property);
} }
qmlInnerTemplate += "}\n"; // Column qmlInnerTemplate += "}\n"; // Column

View File

@@ -60,9 +60,13 @@ PropertyEditorValue::PropertyEditorValue(QObject *parent)
QVariant PropertyEditorValue::value() const QVariant PropertyEditorValue::value() const
{ {
QVariant returnValue = m_value; QVariant returnValue = m_value;
if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name())) if (modelNode().isValid()) {
if (modelNode().metaInfo().propertyTypeName(name()) == "QUrl") if (auto metaInfo = modelNode().metaInfo();
metaInfo.isValid() && metaInfo.hasProperty(name())
&& metaInfo.property(name()).hasPropertyTypeName("QUrl", "url")) {
returnValue = returnValue.toUrl().toString(); returnValue = returnValue.toUrl().toString();
}
}
return returnValue; return returnValue;
} }
@@ -100,9 +104,9 @@ static void fixAmbigousColorNames(const QmlDesigner::ModelNode &modelNode,
const QmlDesigner::PropertyName &name, const QmlDesigner::PropertyName &name,
QVariant *value) QVariant *value)
{ {
if (modelNode.isValid() && modelNode.metaInfo().isValid() if (modelNode.isValid()) {
&& (modelNode.metaInfo().propertyTypeName(name) == "QColor" if (auto metaInfo = modelNode.metaInfo();
|| modelNode.metaInfo().propertyTypeName(name) == "color")) { metaInfo.isValid() && metaInfo.property(name).hasPropertyTypeName("QColor", "color")) {
if ((value->type() == QVariant::Color)) { if ((value->type() == QVariant::Color)) {
QColor color = value->value<QColor>(); QColor color = value->value<QColor>();
int alpha = color.alpha(); int alpha = color.alpha();
@@ -114,12 +118,14 @@ static void fixAmbigousColorNames(const QmlDesigner::ModelNode &modelNode,
} }
} }
} }
}
static void fixUrl(const QmlDesigner::ModelNode &modelNode, const QmlDesigner::PropertyName &name, QVariant *value) static void fixUrl(const QmlDesigner::ModelNode &modelNode, const QmlDesigner::PropertyName &name, QVariant *value)
{ {
if (modelNode.isValid() && modelNode.metaInfo().isValid() if (modelNode.isValid()) {
&& (modelNode.metaInfo().propertyTypeName(name) == "QUrl" if (auto metaInfo = modelNode.metaInfo();
|| modelNode.metaInfo().propertyTypeName(name) == "url")) { metaInfo.isValid() && metaInfo.property(name).hasPropertyTypeName("QUrl", "url"))
if (!value->isValid()) if (!value->isValid())
*value = QStringLiteral(""); *value = QStringLiteral("");
} }
@@ -140,9 +146,13 @@ void PropertyEditorValue::setValueWithEmit(const QVariant &value)
{ {
if (!compareVariants(value, m_value ) || isBound()) { if (!compareVariants(value, m_value ) || isBound()) {
QVariant newValue = value; QVariant newValue = value;
if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name())) if (modelNode().isValid()) {
if (modelNode().metaInfo().propertyTypeName(name()) == "QUrl") if (auto metaInfo = modelNode().metaInfo();
metaInfo.isValid() && metaInfo.hasProperty(name())
&& metaInfo.property(name()).hasPropertyTypeName("QUrl")) {
newValue = QUrl(newValue.toString()); newValue = QUrl(newValue.toString());
}
}
if (cleverDoubleCompare(newValue, m_value)) if (cleverDoubleCompare(newValue, m_value))
return; return;
@@ -255,12 +265,14 @@ void PropertyEditorValue::setIsValid(bool valid)
bool PropertyEditorValue::isTranslated() const bool PropertyEditorValue::isTranslated() const
{ {
if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name())) { if (modelNode().isValid()) {
if (modelNode().metaInfo().propertyTypeName(name()) == "QString" || modelNode().metaInfo().propertyTypeName(name()) == "string") { if (auto metaInfo = modelNode().metaInfo();
metaInfo.isValid() && metaInfo.hasProperty(name())
&& metaInfo.property(name()).hasPropertyTypeName("QString", "string")) {
const QmlDesigner::QmlObjectNode objectNode(modelNode()); const QmlDesigner::QmlObjectNode objectNode(modelNode());
if (objectNode.isValid() && objectNode.hasBindingProperty(name())) { if (objectNode.isValid() && objectNode.hasBindingProperty(name())) {
const QRegularExpression rx(QRegularExpression::anchoredPattern( const QRegularExpression rx(
"qsTr(|Id|anslate)\\(\".*\"\\)")); QRegularExpression::anchoredPattern("qsTr(|Id|anslate)\\(\".*\"\\)"));
//qsTr() //qsTr()
if (objectNode.propertyAffectedByCurrentState(name())) { if (objectNode.propertyAffectedByCurrentState(name())) {
return expression().contains(rx); return expression().contains(rx);
@@ -268,7 +280,6 @@ bool PropertyEditorValue::isTranslated() const
return modelNode().bindingProperty(name()).expression().contains(rx); return modelNode().bindingProperty(name()).expression().contains(rx);
} }
} }
return false;
} }
} }
return false; return false;
@@ -424,8 +435,10 @@ void PropertyEditorValue::removeAliasExport()
QString PropertyEditorValue::getTranslationContext() const QString PropertyEditorValue::getTranslationContext() const
{ {
if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name())) { if (modelNode().isValid()) {
if (modelNode().metaInfo().propertyTypeName(name()) == "QString" || modelNode().metaInfo().propertyTypeName(name()) == "string") { if (auto metaInfo = modelNode().metaInfo();
metaInfo.isValid() && metaInfo.hasProperty(name())
&& metaInfo.property(name()).hasPropertyTypeName("QString", "string")) {
const QmlDesigner::QmlObjectNode objectNode(modelNode()); const QmlDesigner::QmlObjectNode objectNode(modelNode());
if (objectNode.isValid() && objectNode.hasBindingProperty(name())) { if (objectNode.isValid() && objectNode.hasBindingProperty(name())) {
const QRegularExpression rx(QRegularExpression::anchoredPattern( const QRegularExpression rx(QRegularExpression::anchoredPattern(
@@ -519,7 +532,7 @@ bool PropertyEditorValue::idListReplace(int idx, const QString &value)
void PropertyEditorValue::commitDrop(const QString &path) void PropertyEditorValue::commitDrop(const QString &path)
{ {
if (m_modelNode.isSubclassOf("QtQuick3D.Material") 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 // create a texture node
QmlDesigner::NodeMetaInfo metaInfo = m_modelNode.view()->model()->metaInfo("QtQuick3D.Texture"); QmlDesigner::NodeMetaInfo metaInfo = m_modelNode.view()->model()->metaInfo("QtQuick3D.Texture");
QmlDesigner::ModelNode texture = m_modelNode.view()->createModelNode("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(); QmlDesigner::TypeName propertyType = type.toUtf8();
if ((m_editorValue && m_editorValue->modelNode().isValid())) { if ((m_editorValue && m_editorValue->modelNode().isValid())) {
if (propertyType.isEmpty()) if (propertyType.isEmpty()) {
propertyType = m_editorValue->modelNode().metaInfo().propertyTypeName(m_editorValue->name()); propertyType = m_editorValue->modelNode()
.metaInfo()
.property(m_editorValue->name())
.propertyTypeName();
}
while (propertyType.contains('*')) //strip star while (propertyType.contains('*')) //strip star
propertyType.chop(1); propertyType.chop(1);
m_modelNode = m_editorValue->modelNode().view()->createModelNode(propertyType, 4, 7); m_modelNode = m_editorValue->modelNode().view()->createModelNode(propertyType, 4, 7);
@@ -681,9 +698,9 @@ void PropertyEditorNodeWrapper::setup()
m_valuesPropertyMap.clear(propertyName); m_valuesPropertyMap.clear(propertyName);
qDeleteAll(m_valuesPropertyMap.children()); qDeleteAll(m_valuesPropertyMap.children());
const QList<QmlDesigner::PropertyName> 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); auto valueObject = new PropertyEditorValue(&m_valuesPropertyMap);
valueObject->setName(propertyName); valueObject->setName(propertyName);
valueObject->setValue(qmlObjectNode.instanceValue(propertyName)); valueObject->setValue(qmlObjectNode.instanceValue(propertyName));

View File

@@ -185,7 +185,7 @@ void PropertyEditorView::changeValue(const QString &name)
QVariant castedValue; QVariant castedValue;
if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) { if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) {
castedValue = metaInfo.propertyCastedValue(propertyName, value->value()); castedValue = metaInfo.property(propertyName).castedValue(value->value());
} else if (propertyIsAttachedLayoutProperty(propertyName)) { } else if (propertyIsAttachedLayoutProperty(propertyName)) {
castedValue = value->value(); castedValue = value->value();
} else { } else {
@@ -200,9 +200,8 @@ void PropertyEditorView::changeValue(const QString &name)
bool propertyTypeUrl = false; bool propertyTypeUrl = false;
if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)) { if (metaInfo.isValid() && metaInfo.hasProperty(propertyName)
if (metaInfo.propertyTypeName(propertyName) == "QUrl" && metaInfo.property(propertyName).hasPropertyTypeName("QUrl", "url")) {
|| metaInfo.propertyTypeName(propertyName) == "url") {
// turn absolute local file paths into relative paths // turn absolute local file paths into relative paths
propertyTypeUrl = true; propertyTypeUrl = true;
QString filePath = castedValue.toUrl().toString(); QString filePath = castedValue.toUrl().toString();
@@ -212,7 +211,6 @@ void PropertyEditorView::changeValue(const QString &name)
castedValue = QUrl(fileDir.relativeFilePath(filePath)); castedValue = QUrl(fileDir.relativeFilePath(filePath));
} }
} }
}
if (name == "state" && castedValue.toString() == "base state") if (name == "state" && castedValue.toString() == "base state")
castedValue = ""; castedValue = "";
@@ -272,13 +270,15 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
return; return;
} }
if (qmlObjectNode->modelNode().metaInfo().isValid() && qmlObjectNode->modelNode().metaInfo().hasProperty(name)) { if (auto metaInfo = qmlObjectNode->modelNode().metaInfo();
if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "QColor") { metaInfo.isValid() && metaInfo.hasProperty(name)) {
const auto &propertTypeName = metaInfo.property(name).propertyTypeName();
if (propertTypeName == "QColor") {
if (QColor(value->expression().remove('"')).isValid()) { if (QColor(value->expression().remove('"')).isValid()) {
qmlObjectNode->setVariantProperty(name, QColor(value->expression().remove('"'))); qmlObjectNode->setVariantProperty(name, QColor(value->expression().remove('"')));
return; return;
} }
} else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "bool") { } else if (propertTypeName == "bool") {
if (isTrueFalseLiteral(value->expression())) { if (isTrueFalseLiteral(value->expression())) {
if (value->expression().compare("true", Qt::CaseInsensitive) == 0) if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
qmlObjectNode->setVariantProperty(name, true); qmlObjectNode->setVariantProperty(name, true);
@@ -286,21 +286,21 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
qmlObjectNode->setVariantProperty(name, false); qmlObjectNode->setVariantProperty(name, false);
return; return;
} }
} else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "int") { } else if (propertTypeName == "int") {
bool ok; bool ok;
int intValue = value->expression().toInt(&ok); int intValue = value->expression().toInt(&ok);
if (ok) { if (ok) {
qmlObjectNode->setVariantProperty(name, intValue); qmlObjectNode->setVariantProperty(name, intValue);
return; return;
} }
} else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "qreal") { } else if (propertTypeName == "qreal") {
bool ok; bool ok;
qreal realValue = value->expression().toDouble(&ok); qreal realValue = value->expression().toDouble(&ok);
if (ok) { if (ok) {
qmlObjectNode->setVariantProperty(name, realValue); qmlObjectNode->setVariantProperty(name, realValue);
return; return;
} }
} else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "QVariant") { } else if (propertTypeName == "QVariant") {
bool ok; bool ok;
qreal realValue = value->expression().toDouble(&ok); qreal realValue = value->expression().toDouble(&ok);
if (ok) { if (ok) {

View File

@@ -53,15 +53,8 @@ namespace {
bool modelNodeHasUrlSource(const QmlDesigner::ModelNode &modelNode) bool modelNodeHasUrlSource(const QmlDesigner::ModelNode &modelNode)
{ {
QmlDesigner::NodeMetaInfo metaInfo = modelNode.metaInfo(); QmlDesigner::NodeMetaInfo metaInfo = modelNode.metaInfo();
if (metaInfo.isValid()) { return metaInfo.isValid() && metaInfo.hasProperty("source")
if (metaInfo.hasProperty("source")) { && metaInfo.property("source").hasPropertyTypeName("QUrl", "url");
if (metaInfo.propertyTypeName("source") == "QUrl")
return true;
if (metaInfo.propertyTypeName("source") == "url")
return true;
}
}
return false;
} }
} //namespace } //namespace

View File

@@ -234,8 +234,10 @@ TimelinePropertyItem *TimelinePropertyItem::create(const QmlTimelineKeyframeGrou
if (!objectNode.isValid()) if (!objectNode.isValid())
return item; return item;
auto nameOfType = objectNode.modelNode().metaInfo().propertyTypeName( auto nameOfType = objectNode.modelNode()
item->m_frames.propertyName()); .metaInfo()
.property(item->m_frames.propertyName())
.propertyTypeName();
item->m_control = createTimelineControl(nameOfType); item->m_control = createTimelineControl(nameOfType);
if (item->m_control) { if (item->m_control) {
item->m_control->setSize((TimelineConstants::sectionWidth / 2.6) - 10, item->m_control->setSize((TimelineConstants::sectionWidth / 2.6) - 10,

View File

@@ -226,7 +226,7 @@ ModelNode TransitionEditorView::addNewTransition()
if (target.isValid() && target.hasMetaInfo()) { if (target.isValid() && target.hasMetaInfo()) {
const QString targetId = target.id(); const QString targetId = target.id();
for (const VariantProperty &property : change.modelNode().variantProperties()) { 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("<cpp>.")) if (typeName.startsWith("<cpp>."))
typeName.remove(0, 6); typeName.remove(0, 6);

View File

@@ -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 <qmldesignercorelib_global.h>
#include <QSharedPointer>
#include <QString>
#include <vector>
namespace QmlDesigner {
class EnumerationMetaInfo
{
public:
EnumerationMetaInfo(QSharedPointer<class NodeMetaInfoPrivate> nodeMetaInfoPrivateData,
const TypeName &enumeration);
~EnumerationMetaInfo();
private:
QSharedPointer<class NodeMetaInfoPrivate> m_nodeMetaInfoPrivateData;
const TypeName &m_enumeration;
};
using EnumerationMetaInfos = std::vector<EnumerationMetaInfo>;
} // namespace QmlDesigner

View File

@@ -42,6 +42,7 @@ class ItemLibraryInfo;
namespace Internal { namespace Internal {
class MetaInfoPrivate; class MetaInfoPrivate;
class ModelPrivate; class ModelPrivate;
class MetaInfoReader;
class SubComponentManagerPrivate; class SubComponentManagerPrivate;
using MetaInfoPrivatePointer = QSharedPointer<MetaInfoPrivate>; using MetaInfoPrivatePointer = QSharedPointer<MetaInfoPrivate>;
} }

View File

@@ -44,8 +44,7 @@ namespace QmlDesigner {
namespace Internal { namespace Internal {
class ModelPrivate; class ModelPrivate;
class WriteLocker; class WriteLocker;
class NodeMetaInfoPrivate; } //Internal
} // namespace Internal
class AnchorLine; class AnchorLine;
class ModelNode; class ModelNode;
@@ -70,7 +69,7 @@ class QMLDESIGNERCORE_EXPORT Model : public QObject
friend AbstractView; friend AbstractView;
friend Internal::ModelPrivate; friend Internal::ModelPrivate;
friend Internal::WriteLocker; friend Internal::WriteLocker;
friend Internal::NodeMetaInfoPrivate; friend class NodeMetaInfoPrivate;
Q_OBJECT Q_OBJECT
@@ -141,4 +140,4 @@ private:
Internal::ModelPrivate *d; Internal::ModelPrivate *d;
}; };
} // namespace QmlDesigner }

View File

@@ -174,7 +174,7 @@ public:
Model *model() const; Model *model() const;
AbstractView *view() const; AbstractView *view() const;
const NodeMetaInfo metaInfo() const; NodeMetaInfo metaInfo() const;
bool hasMetaInfo() const; bool hasMetaInfo() const;
bool isSelected() const; bool isSelected() const;

View File

@@ -25,12 +25,15 @@
#pragma once #pragma once
#include "invalidmetainfoexception.h"
#include "propertymetainfo.h"
#include "qmldesignercorelib_global.h"
#include <QList> #include <QList>
#include <QString> #include <QString>
#include <QIcon> #include <QIcon>
#include "qmldesignercorelib_global.h" #include <vector>
#include "invalidmetainfoexception.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QDeclarativeContext; class QDeclarativeContext;
@@ -42,14 +45,6 @@ class MetaInfo;
class Model; class Model;
class AbstractProperty; class AbstractProperty;
namespace Internal {
class MetaInfoPrivate;
class MetaInfoReader;
class SubComponentManagerPrivate;
class ItemLibraryEntryData;
class NodeMetaInfoPrivate;
}
class QMLDESIGNERCORE_EXPORT NodeMetaInfo class QMLDESIGNERCORE_EXPORT NodeMetaInfo
{ {
public: public:
@@ -64,20 +59,13 @@ public:
bool isValid() const; bool isValid() const;
bool isFileComponent() const; bool isFileComponent() const;
bool hasProperty(const PropertyName &propertyName) 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 signalNames() const;
PropertyNameList slotNames() const; PropertyNameList slotNames() const;
PropertyNameList directPropertyNames() const;
PropertyName defaultPropertyName() const; PropertyName defaultPropertyName() const;
bool hasDefaultProperty() 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<NodeMetaInfo> classHierarchy() const; QList<NodeMetaInfo> classHierarchy() const;
QList<NodeMetaInfo> superClasses() const; QList<NodeMetaInfo> superClasses() const;
@@ -104,7 +92,9 @@ public:
QString importDirectoryPath() const; QString importDirectoryPath() const;
private: private:
QSharedPointer<Internal::NodeMetaInfoPrivate> m_privateData; QSharedPointer<class NodeMetaInfoPrivate> m_privateData;
}; };
using NodeMetaInfos = std::vector<NodeMetaInfo>;
} //QmlDesigner } //QmlDesigner

View File

@@ -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 <qmldesignercorelib_global.h>
#include <QSharedPointer>
#include <QString>
#include <vector>
namespace QmlDesigner {
class PropertyMetaInfo
{
public:
PropertyMetaInfo(QSharedPointer<class NodeMetaInfoPrivate> 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<typename... TypeName>
bool hasPropertyTypeName(const TypeName &...typeName) const
{
auto propertyTypeName_ = propertyTypeName();
return ((propertyTypeName_ == typeName) || ...);
}
private:
QSharedPointer<class NodeMetaInfoPrivate> m_nodeMetaInfoPrivateData;
PropertyName m_propertyName;
};
using PropertyMetaInfos = std::vector<PropertyMetaInfo>;
} // namespace QmlDesigner

View File

@@ -212,12 +212,14 @@ public:
void setStartFlowItem(const QmlFlowItemNode &flowItem); void setStartFlowItem(const QmlFlowItemNode &flowItem);
ModelNode createTransition(); ModelNode createTransition();
static PropertyNameList st_mouseSignals;
static QList<QmlConnections> getAssociatedConnections(const ModelNode &node); static QList<QmlConnections> getAssociatedConnections(const ModelNode &node);
static const PropertyNameList &mouseSignals() { return s_mouseSignals; }
protected: protected:
QList<ModelNode> transitionsForProperty(const PropertyName &propertyName, const ModelNode &modelNode); QList<ModelNode> transitionsForProperty(const PropertyName &propertyName, const ModelNode &modelNode);
private:
static PropertyNameList s_mouseSignals;
}; };

View File

@@ -46,17 +46,6 @@
namespace QmlDesigner { namespace QmlDesigner {
namespace Internal {
struct TypeDescription
{
QString className;
int minorVersion{};
int majorVersion{};
};
} //Internal
/*! /*!
\class QmlDesigner::NodeMetaInfo \class QmlDesigner::NodeMetaInfo
\ingroup CoreModel \ingroup CoreModel
@@ -74,7 +63,14 @@ NodeMetaInfo object will result in an InvalidMetaInfoException being thrown.
\see QmlDesigner::MetaInfo, QmlDesigner::PropertyMetaInfo, QmlDesigner::EnumeratorMetaInfo \see QmlDesigner::MetaInfo, QmlDesigner::PropertyMetaInfo, QmlDesigner::EnumeratorMetaInfo
*/ */
namespace Internal { namespace {
struct TypeDescription
{
QString className;
int minorVersion{};
int majorVersion{};
};
using namespace QmlJS; using namespace QmlJS;
@@ -516,6 +512,9 @@ PropertyNameList getSignals(const ObjectValue *objectValue, const ContextPtr &co
signalList.append(getSignals(prototype, context, true)); signalList.append(getSignals(prototype, context, true));
} }
std::sort(signalList.begin(), signalList.end());
signalList.erase(std::unique(signalList.begin(), signalList.end()), signalList.end());
return signalList; return signalList;
} }
@@ -544,6 +543,9 @@ PropertyNameList getSlots(const ObjectValue *objectValue, const ContextPtr &cont
slotList.append(getSlots(prototype, context, true)); slotList.append(getSlots(prototype, context, true));
} }
std::sort(slotList.begin(), slotList.end());
slotList.erase(std::unique(slotList.begin(), slotList.end()), slotList.end());
return slotList; return slotList;
} }
@@ -604,6 +606,7 @@ QVector<PropertyInfo> getObjectTypes(const ObjectValue *objectValue, const Conte
return propertyList; return propertyList;
} }
} // namespace
class NodeMetaInfoPrivate class NodeMetaInfoPrivate
{ {
@@ -614,12 +617,12 @@ public:
bool isValid() const; bool isValid() const;
bool isFileComponent() const; bool isFileComponent() const;
PropertyNameList properties() const; const PropertyNameList &properties() const;
PropertyNameList localProperties() const; const PropertyNameList &localProperties() const;
PropertyNameList signalNames() const; PropertyNameList signalNames() const;
PropertyNameList slotNames() const; PropertyNameList slotNames() const;
PropertyName defaultPropertyName() const; PropertyName defaultPropertyName() const;
TypeName propertyType(const PropertyName &propertyName) const; const TypeName &propertyType(const PropertyName &propertyName) const;
void setupPrototypes(); void setupPrototypes();
QList<TypeDescription> prototypes() const; QList<TypeDescription> prototypes() const;
@@ -634,7 +637,7 @@ public:
int majorVersion() const; int majorVersion() const;
int minorVersion() const; int minorVersion() const;
TypeName qualfiedTypeName() const; const TypeName &qualfiedTypeName() const;
Model *model() const; Model *model() const;
QByteArray cppPackageName() const; QByteArray cppPackageName() const;
@@ -691,14 +694,14 @@ bool NodeMetaInfoPrivate::isFileComponent() const
return m_isFileComponent; return m_isFileComponent;
} }
PropertyNameList NodeMetaInfoPrivate::properties() const const PropertyNameList &NodeMetaInfoPrivate::properties() const
{ {
ensureProperties(); ensureProperties();
return m_properties; return m_properties;
} }
PropertyNameList NodeMetaInfoPrivate::localProperties() const const PropertyNameList &NodeMetaInfoPrivate::localProperties() const
{ {
ensureProperties(); 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) NodeMetaInfoPrivate::Pointer NodeMetaInfoPrivate::create(Model *model, const TypeName &type, int major, int minor)
{ {
if (model->d->m_nodeMetaInfoCache.contains(stringIdentifier(type, major, minor))) auto &&cache = model->d->m_nodeMetaInfoCache;
return model->d->m_nodeMetaInfoCache.value(stringIdentifier(type, major, minor)); if (auto found = cache.find(stringIdentifier(type, major, minor)); found != cache.end())
return *found;
Pointer newData(new NodeMetaInfoPrivate(model, type, major, minor)); Pointer newData(new NodeMetaInfoPrivate(model, type, major, minor));
if (newData->isValid()) if (newData->isValid())
@@ -1144,7 +1148,7 @@ int NodeMetaInfoPrivate::minorVersion() const
return m_minorVersion; return m_minorVersion;
} }
TypeName NodeMetaInfoPrivate::qualfiedTypeName() const const TypeName &NodeMetaInfoPrivate::qualfiedTypeName() const
{ {
return m_qualfiedTypeName; return m_qualfiedTypeName;
} }
@@ -1248,12 +1252,16 @@ bool NodeMetaInfoPrivate::isValid() const
return m_isValid && context() && document(); 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(); ensureProperties();
if (!m_properties.contains(propertyName)) if (!m_properties.contains(propertyName))
return TypeName("Property does not exist..."); return nonexistingTypeName;
return m_propertyTypes.at(m_properties.indexOf(propertyName)); return m_propertyTypes.at(m_properties.indexOf(propertyName));
} }
@@ -1386,14 +1394,14 @@ void NodeMetaInfoPrivate::initialiseProperties()
m_slots = getSlots(m_objectValue, context()); m_slots = getSlots(m_objectValue, context());
} }
} //namespace Internal NodeMetaInfo::NodeMetaInfo()
: m_privateData(QSharedPointer<NodeMetaInfoPrivate>::create())
NodeMetaInfo::NodeMetaInfo() : m_privateData(new Internal::NodeMetaInfoPrivate())
{ {
} }
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 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<std::size_t>(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<std::size_t>(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 PropertyNameList NodeMetaInfo::signalNames() const
@@ -1440,11 +1474,6 @@ PropertyNameList NodeMetaInfo::slotNames() const
return m_privateData->slotNames(); return m_privateData->slotNames();
} }
PropertyNameList NodeMetaInfo::directPropertyNames() const
{
return m_privateData->localProperties();
}
PropertyName NodeMetaInfo::defaultPropertyName() const PropertyName NodeMetaInfo::defaultPropertyName() const
{ {
return m_privateData->defaultPropertyName(); return m_privateData->defaultPropertyName();
@@ -1455,84 +1484,6 @@ bool NodeMetaInfo::hasDefaultProperty() const
return !defaultPropertyName().isEmpty(); 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<Enumeration>())
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 == "<cpp>.double") {
return variant.toDouble();
} else if (typeName == "<cpp>.float") {
return variant.toFloat();
} else if (typeName == "<cpp>.int") {
return variant.toInt();
} else if (typeName == "<cpp>.bool") {
return variant.toBool();
} else if (copyVariant.convert(typeId)) {
return copyVariant;
}
return Internal::PropertyParser::variantFromString(variant.toString());
}
QList<NodeMetaInfo> NodeMetaInfo::classHierarchy() const QList<NodeMetaInfo> NodeMetaInfo::classHierarchy() const
{ {
QList<NodeMetaInfo> hierarchy = {*this}; QList<NodeMetaInfo> hierarchy = {*this};
@@ -1543,7 +1494,7 @@ QList<NodeMetaInfo> NodeMetaInfo::classHierarchy() const
QList<NodeMetaInfo> NodeMetaInfo::superClasses() const QList<NodeMetaInfo> NodeMetaInfo::superClasses() const
{ {
Model *model = m_privateData->model(); 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); return NodeMetaInfo(model, type.className.toUtf8(), type.majorVersion, type.minorVersion);
}); });
} }
@@ -1556,7 +1507,7 @@ NodeMetaInfo NodeMetaInfo::directSuperClass() const
bool NodeMetaInfo::defaultPropertyIsComponent() const bool NodeMetaInfo::defaultPropertyIsComponent() const
{ {
if (hasDefaultProperty()) if (hasDefaultProperty())
return propertyTypeName(defaultPropertyName()) == "Component"; return property(defaultPropertyName()).hasPropertyTypeName("Component");
return false; return false;
} }
@@ -1613,21 +1564,24 @@ bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int mino
if (typeName() == type && availableInVersion(majorVersion, minorVersion)) if (typeName() == type && availableInVersion(majorVersion, minorVersion))
return true; 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 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 return false; //take a shortcut - optimization
const QList<NodeMetaInfo> superClassList = superClasses(); const QList<NodeMetaInfo> superClassList = superClasses();
for (const NodeMetaInfo &superClass : superClassList) { for (const NodeMetaInfo &superClass : superClassList) {
if (superClass.m_privateData->cleverCheckType(type) if (superClass.m_privateData->cleverCheckType(type)
&& superClass.availableInVersion(majorVersion, minorVersion)) { && superClass.availableInVersion(majorVersion, minorVersion)) {
m_privateData->prototypeCachePositives().insert(Internal::stringIdentifier(type, majorVersion, minorVersion)); m_privateData->prototypeCachePositives().insert(
stringIdentifier(type, majorVersion, minorVersion));
return true; return true;
} }
} }
m_privateData->prototypeCacheNegatives().insert(Internal::stringIdentifier(type, majorVersion, minorVersion)); m_privateData->prototypeCacheNegatives().insert(stringIdentifier(type, majorVersion, minorVersion));
return false; return false;
} }
@@ -1668,4 +1622,90 @@ bool NodeMetaInfo::isTabView() const
return isSubclassOf("QtQuick.Controls.TabView"); return isSubclassOf("QtQuick.Controls.TabView");
} }
PropertyMetaInfo::PropertyMetaInfo(QSharedPointer<NodeMetaInfoPrivate> 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<Enumeration>())
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 == "<cpp>.double") {
return variant.toDouble();
} else if (typeName == "<cpp>.float") {
return variant.toFloat();
} else if (typeName == "<cpp>.int") {
return variant.toInt();
} else if (typeName == "<cpp>.bool") {
return variant.toBool();
} else if (copyVariant.convert(typeId)) {
return copyVariant;
}
return Internal::PropertyParser::variantFromString(variant.toString());
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -46,6 +46,7 @@ namespace QmlDesigner {
class AbstractProperty; class AbstractProperty;
class RewriterView; class RewriterView;
class NodeInstanceView; class NodeInstanceView;
class NodeMetaInfoPrivate;
namespace Internal { namespace Internal {
@@ -85,7 +86,7 @@ class ModelPrivate : public QObject {
friend Model; friend Model;
friend Internal::WriteLocker; friend Internal::WriteLocker;
friend Internal::NodeMetaInfoPrivate; friend NodeMetaInfoPrivate;
public: public:
ModelPrivate(Model *model); ModelPrivate(Model *model);

View File

@@ -855,7 +855,7 @@ bool ModelNode::hasAnySubModelNodes() const
return !nodeAbstractProperties().isEmpty(); return !nodeAbstractProperties().isEmpty();
} }
const NodeMetaInfo ModelNode::metaInfo() const NodeMetaInfo ModelNode::metaInfo() const
{ {
if (!isValid()) { if (!isValid()) {
Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid"); Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");

View File

@@ -33,6 +33,8 @@
#include "model.h" #include "model.h"
#include "model_p.h" #include "model_p.h"
#include <nodemetainfo.h>
namespace QmlDesigner { namespace QmlDesigner {
NodeAbstractProperty::NodeAbstractProperty() = default; NodeAbstractProperty::NodeAbstractProperty() = default;
@@ -53,10 +55,14 @@ NodeAbstractProperty::NodeAbstractProperty(const Internal::InternalNodeAbstractP
void NodeAbstractProperty::reparentHere(const ModelNode &modelNode) 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()); reparentHere(modelNode, isNodeListProperty());
else } else {
reparentHere(modelNode, parentModelNode().metaInfo().propertyIsListProperty(name()) || isDefaultProperty()); //we could use the metasystem instead? 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) void NodeAbstractProperty::reparentHere(const ModelNode &modelNode, bool isNodeList, const TypeName &dynamicTypeName)

View File

@@ -993,8 +993,14 @@ QList<ModelNode> QmlFlowViewNode::transitionsForProperty(const PropertyName &pro
return list; return list;
} }
PropertyNameList QmlFlowViewNode::st_mouseSignals = { "clicked", "doubleClicked", "pressAndHold", PropertyNameList QmlFlowViewNode::s_mouseSignals = []() {
"pressed", "released", "wheel" }; PropertyNameList mouseSignals = {
"clicked", "doubleClicked", "pressed", "pressAndHold", "released", "wheel"};
Q_ASSERT(std::is_sorted(mouseSignals.begin(), mouseSignals.end()));
return mouseSignals;
}();
QList<QmlConnections> QmlFlowViewNode::getAssociatedConnections(const ModelNode &node) QList<QmlConnections> QmlFlowViewNode::getAssociatedConnections(const ModelNode &node)
{ {
@@ -1020,8 +1026,7 @@ QList<QmlConnections> QmlFlowViewNode::getAssociatedConnections(const ModelNode
sourceProperty = sourceComponents[1]; sourceProperty = sourceComponents[1];
} }
if (st_mouseSignals.contains(signalWithoutPrefix) if (mouseSignals().contains(signalWithoutPrefix) && sourceId == node.id()
&& sourceId == node.id()
&& sourceProperty == "trigger()") && sourceProperty == "trigger()")
return true; return true;
} }

View File

@@ -246,8 +246,8 @@ QVariant QmlObjectNode::modelValue(const PropertyName &name) const
bool QmlObjectNode::isTranslatableText(const PropertyName &name) const bool QmlObjectNode::isTranslatableText(const PropertyName &name) const
{ {
if (modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name)) if (modelNode().metaInfo().isValid() && modelNode().metaInfo().hasProperty(name)
if (modelNode().metaInfo().propertyTypeName(name) == "QString" || modelNode().metaInfo().propertyTypeName(name) == "string") { && modelNode().metaInfo().property(name).hasPropertyTypeName("QString", "string")) {
if (modelNode().hasBindingProperty(name)) { if (modelNode().hasBindingProperty(name)) {
static QRegularExpression regularExpressionPattern( static QRegularExpression regularExpressionPattern(
QLatin1String("^qsTr(|Id|anslate)\\(\".*\"\\)$")); QLatin1String("^qsTr(|Id|anslate)\\(\".*\"\\)$"));

View File

@@ -213,7 +213,7 @@ TypeName QmlTimelineKeyframeGroup::valueType() const
TypeName typeName; TypeName typeName;
if (targetNode.isValid() && targetNode.hasMetaInfo()) if (targetNode.isValid() && targetNode.hasMetaInfo())
typeName = targetNode.metaInfo().propertyTypeName(propertyName()); typeName = targetNode.metaInfo().property(propertyName()).propertyTypeName();
if (typeName.startsWith("<cpp>.")) if (typeName.startsWith("<cpp>."))
typeName.remove(0, 6); typeName.remove(0, 6);

View File

@@ -223,7 +223,7 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
if (!forceNonDefaultProperty.isEmpty()) { if (!forceNonDefaultProperty.isEmpty()) {
const NodeMetaInfo metaInfo = parentQmlItemNode.modelNode().metaInfo(); const NodeMetaInfo metaInfo = parentQmlItemNode.modelNode().metaInfo();
if (metaInfo.hasProperty(forceNonDefaultProperty)) { if (metaInfo.hasProperty(forceNonDefaultProperty)) {
if (!metaInfo.propertyIsListProperty(forceNonDefaultProperty) if (!metaInfo.property(forceNonDefaultProperty).isListProperty()
&& parentQmlItemNode.modelNode().hasNodeProperty(forceNonDefaultProperty)) { && parentQmlItemNode.modelNode().hasNodeProperty(forceNonDefaultProperty)) {
parentQmlItemNode.removeProperty(forceNonDefaultProperty); parentQmlItemNode.removeProperty(forceNonDefaultProperty);
} }
@@ -324,7 +324,7 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
const ModelNode parentNode = parentProperty.parentModelNode(); const ModelNode parentNode = parentProperty.parentModelNode();
const NodeMetaInfo metaInfo = parentNode.metaInfo(); const NodeMetaInfo metaInfo = parentNode.metaInfo();
if (metaInfo.isValid() && !metaInfo.propertyIsListProperty(propertyName) if (metaInfo.isValid() && !metaInfo.property(propertyName).isListProperty()
&& parentProperty.isNodeProperty()) { && parentProperty.isNodeProperty()) {
parentNode.removeProperty(propertyName); parentNode.removeProperty(propertyName);
} }

View File

@@ -337,8 +337,9 @@ bool propertyIsComponentType(const QmlDesigner::NodeAbstractProperty &property,
if (model->metaInfo(type).isSubclassOf("QtQuick.Component") && !isComponentType(type)) if (model->metaInfo(type).isSubclassOf("QtQuick.Component") && !isComponentType(type))
return false; //If the type is already a subclass of Component keep it return false; //If the type is already a subclass of Component keep it
return property.parentModelNode().isValid() && return property.parentModelNode().isValid()
isComponentType(property.parentModelNode().metaInfo().propertyTypeName(property.name())); && isComponentType(
property.parentModelNode().metaInfo().property(property.name()).propertyTypeName());
} }
QString extractComponentFromQml(const QString &source) QString extractComponentFromQml(const QString &source)

View File

@@ -153,6 +153,7 @@ function(extend_with_qmldesigner_core target_name)
include/componenttextmodifier.h include/componenttextmodifier.h
include/customnotifications.h include/customnotifications.h
include/documentmessage.h include/documentmessage.h
include/enumerationmetainfo.h
include/exception.h include/exception.h
include/forwardview.h include/forwardview.h
include/imagecacheauxiliarydata.h include/imagecacheauxiliarydata.h
@@ -184,6 +185,7 @@ function(extend_with_qmldesigner_core target_name)
include/notimplementedexception.h include/notimplementedexception.h
include/plaintexteditmodifier.h include/plaintexteditmodifier.h
include/propertycontainer.h include/propertycontainer.h
include/propertymetainfo.h
include/propertynode.h include/propertynode.h
include/propertyparser.h include/propertyparser.h
include/qmlanchors.h include/qmlanchors.h

View File

@@ -266,6 +266,7 @@ Project {
"include/bindingproperty.h", "include/bindingproperty.h",
"include/componenttextmodifier.h", "include/componenttextmodifier.h",
"include/customnotifications.h", "include/customnotifications.h",
"include/enumerationmetainfo.h",
"include/exception.h", "include/exception.h",
"include/forwardview.h", "include/forwardview.h",
"include/import.h", "include/import.h",
@@ -296,6 +297,7 @@ Project {
"include/notimplementedexception.h", "include/notimplementedexception.h",
"include/plaintexteditmodifier.h", "include/plaintexteditmodifier.h",
"include/propertycontainer.h", "include/propertycontainer.h",
"include/propertymetainfo.h",
"include/propertynode.h", "include/propertynode.h",
"include/propertyparser.h", "include/propertyparser.h",
"include/qmlanchors.h", "include/qmlanchors.h",

View File

@@ -130,7 +130,7 @@ public:
QSize{300, 300}, QSize{300, 300},
QSize{1000, 1000}, QSize{1000, 1000},
ImageCacheCollectorNullImageHandling::DontCaptureNullImage}; ImageCacheCollectorNullImageHandling::DontCaptureNullImage};
TimeStampProvider timeStampProvider; PreviewTimeStampProvider timeStampProvider;
AsynchronousExplicitImageCache cache{storage}; AsynchronousExplicitImageCache cache{storage};
AsynchronousImageFactory factory{storage, timeStampProvider, collector}; AsynchronousImageFactory factory{storage, timeStampProvider, collector};
}; };

View File

@@ -1,5 +1,5 @@
add_qtc_test(tst_qml_testcore add_qtc_test(tst_qml_testcore
CONDITION TARGET QmlProjectManager CONDITION TARGET QmlProjectManager AND Qt5_VERSION VERSION_GREATER_EQUAL 6.2.0
DEFINES DEFINES
QT_CREATOR QT_CREATOR
QMLDESIGNER_TEST QMLDESIGNER_TEST

View File

@@ -4232,6 +4232,17 @@ void tst_TestCore::testCopyModelRewriter2()
QCOMPARE(stripWhiteSpaces(textEdit2.toPlainText()), stripWhiteSpaces(qmlString1)); 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() void tst_TestCore::testSubComponentManager()
{ {
const QString qmlString("import QtQuick 2.15\n" const QString qmlString("import QtQuick 2.15\n"
@@ -4267,7 +4278,7 @@ void tst_TestCore::testSubComponentManager()
subComponentManager->update(QUrl::fromLocalFile(fileName), model->imports()); subComponentManager->update(QUrl::fromLocalFile(fileName), model->imports());
QVERIFY(model->hasNodeMetaInfo("QtQuick.Rectangle", 2, 15)); 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); model->rewriterView()->setTextModifier(&modifier);
@@ -4276,14 +4287,14 @@ void tst_TestCore::testSubComponentManager()
QVERIFY(model->rewriterView()->rootModelNode().isValid()); QVERIFY(model->rewriterView()->rootModelNode().isValid());
QVERIFY(model->hasNodeMetaInfo("QtQuick.Rectangle", 2, 15)); 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("<cpp>.QQuickPen").isValid()); QVERIFY(model->metaInfo("<cpp>.QQuickPen").isValid());
QSKIP("File components not working TODO", SkipAll); QSKIP("File components not working TODO", SkipAll);
NodeMetaInfo myButtonMetaInfo = model->metaInfo("MyButton"); NodeMetaInfo myButtonMetaInfo = model->metaInfo("MyButton");
QVERIFY(myButtonMetaInfo.isValid()); QVERIFY(myButtonMetaInfo.isValid());
QVERIFY(myButtonMetaInfo.propertyNames().contains("border.width")); QVERIFY(contains(myButtonMetaInfo.properties(), "border.width"));
QVERIFY(myButtonMetaInfo.hasProperty("border.width")); QVERIFY(myButtonMetaInfo.hasProperty("border.width"));
} }
@@ -4638,7 +4649,7 @@ void tst_TestCore::testMetaInfoCustomType()
QCOMPARE(propertyChangesInfo.superClasses().size(), 3); QCOMPARE(propertyChangesInfo.superClasses().size(), 3);
// DeclarativePropertyChanges just has 3 properties // DeclarativePropertyChanges just has 3 properties
QCOMPARE(propertyChangesInfo.propertyNames().size() - stateOperationInfo.propertyNames().size(), 3); QCOMPARE(propertyChangesInfo.properties().size() - stateOperationInfo.properties().size(), 3);
QApplication::processEvents(); QApplication::processEvents();
} }
@@ -4656,15 +4667,13 @@ void tst_TestCore::testMetaInfoEnums()
QVERIFY(view->rootModelNode().metaInfo().hasProperty("transformOrigin")); QVERIFY(view->rootModelNode().metaInfo().hasProperty("transformOrigin"));
QVERIFY(view->rootModelNode().metaInfo().propertyIsEnumType("transformOrigin")); QVERIFY(view->rootModelNode().metaInfo().property("transformOrigin").isEnumType());
QCOMPARE(view->rootModelNode().metaInfo().propertyTypeName("transformOrigin"), QmlDesigner::TypeName("TransformOrigin")); QCOMPARE(view->rootModelNode().metaInfo().property("transformOrigin").propertyTypeName(),
QVERIFY(view->rootModelNode().metaInfo().propertyKeysForEnum("transformOrigin").contains(QLatin1String("Bottom"))); QmlDesigner::TypeName("TransformOrigin"));
QVERIFY(view->rootModelNode().metaInfo().propertyKeysForEnum("transformOrigin").contains(QLatin1String("Top")));
QVERIFY(view->rootModelNode().metaInfo().propertyIsEnumType("horizontalAlignment")); QVERIFY(view->rootModelNode().metaInfo().property("horizontalAlignment").isEnumType());
QCOMPARE(view->rootModelNode().metaInfo().propertyTypeName("horizontalAlignment"), QmlDesigner::TypeName("HAlignment")); QCOMPARE(view->rootModelNode().metaInfo().property("horizontalAlignment").propertyTypeName(),
QVERIFY(view->rootModelNode().metaInfo().propertyKeysForEnum("horizontalAlignment").contains(QLatin1String("AlignLeft"))); QmlDesigner::TypeName("HAlignment"));
QVERIFY(view->rootModelNode().metaInfo().propertyKeysForEnum("horizontalAlignment").contains(QLatin1String("AlignRight")));
QApplication::processEvents(); QApplication::processEvents();
} }
@@ -4743,8 +4752,8 @@ void tst_TestCore::testMetaInfoProperties()
QVERIFY(textNodeMetaInfo.hasProperty("objectName")); // QtQuick.QObject QVERIFY(textNodeMetaInfo.hasProperty("objectName")); // QtQuick.QObject
QVERIFY(!textNodeMetaInfo.hasProperty("bla")); QVERIFY(!textNodeMetaInfo.hasProperty("bla"));
QVERIFY(textNodeMetaInfo.propertyIsWritable("text")); QVERIFY(textNodeMetaInfo.property("text").isWritable());
QVERIFY(textNodeMetaInfo.propertyIsWritable("x")); QVERIFY(textNodeMetaInfo.property("x").isWritable());
QApplication::processEvents(); QApplication::processEvents();
} }
@@ -4761,22 +4770,23 @@ void tst_TestCore::testMetaInfoDotProperties()
QVERIFY(model->hasNodeMetaInfo("QtQuick.Text")); QVERIFY(model->hasNodeMetaInfo("QtQuick.Text"));
QVERIFY(model->metaInfo("QtQuick.Rectangle").hasProperty("border")); QVERIFY(model->metaInfo("QtQuick.Rectangle").hasProperty("border"));
QCOMPARE(model->metaInfo("QtQuick.Rectangle").propertyTypeName("border"), QmlDesigner::TypeName("<cpp>.QQuickPen")); QCOMPARE(model->metaInfo("QtQuick.Rectangle").property("border").propertyTypeName(),
QmlDesigner::TypeName("<cpp>.QQuickPen"));
QCOMPARE(view->rootModelNode().metaInfo().typeName(), QmlDesigner::TypeName("QtQuick.Text")); QCOMPARE(view->rootModelNode().metaInfo().typeName(), QmlDesigner::TypeName("QtQuick.Text"));
QVERIFY(view->rootModelNode().metaInfo().hasProperty("font")); QVERIFY(view->rootModelNode().metaInfo().hasProperty("font"));
QVERIFY(view->rootModelNode().metaInfo().hasProperty("font.bold")); QVERIFY(view->rootModelNode().metaInfo().hasProperty("font.bold"));
QVERIFY(view->rootModelNode().metaInfo().propertyNames().contains("font.bold")); QVERIFY(contains(view->rootModelNode().metaInfo().properties(), "font.bold"));
QVERIFY(view->rootModelNode().metaInfo().propertyNames().contains("font.pointSize")); QVERIFY(contains(view->rootModelNode().metaInfo().properties(), "font.pointSize"));
QVERIFY(view->rootModelNode().metaInfo().hasProperty("font.pointSize")); QVERIFY(view->rootModelNode().metaInfo().hasProperty("font.pointSize"));
ModelNode rectNode(addNodeListChild(view->rootModelNode(), "QtQuick.Rectangle", 2, 0, "data")); ModelNode rectNode(addNodeListChild(view->rootModelNode(), "QtQuick.Rectangle", 2, 0, "data"));
QVERIFY(rectNode.metaInfo().propertyNames().contains("implicitHeight")); QVERIFY(contains(rectNode.metaInfo().properties(), "implicitHeight"));
QVERIFY(rectNode.metaInfo().propertyNames().contains("implicitWidth")); QVERIFY(contains(rectNode.metaInfo().properties(), "implicitWidth"));
QVERIFY(rectNode.metaInfo().propertyNames().contains("anchors.topMargin")); QVERIFY(contains(rectNode.metaInfo().properties(), "anchors.topMargin"));
QVERIFY(rectNode.metaInfo().propertyNames().contains("border.width")); QVERIFY(contains(rectNode.metaInfo().properties(), "border.width"));
QVERIFY(rectNode.metaInfo().hasProperty("border")); QVERIFY(rectNode.metaInfo().hasProperty("border"));
QVERIFY(rectNode.metaInfo().hasProperty("border.width")); QVERIFY(rectNode.metaInfo().hasProperty("border.width"));
@@ -4796,20 +4806,20 @@ void tst_TestCore::testMetaInfoListProperties()
QCOMPARE(view->rootModelNode().metaInfo().typeName(), QmlDesigner::TypeName("QtQuick.Item")); QCOMPARE(view->rootModelNode().metaInfo().typeName(), QmlDesigner::TypeName("QtQuick.Item"));
QVERIFY(view->rootModelNode().metaInfo().hasProperty("states")); 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().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().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().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().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().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().hasProperty("parent"));
QVERIFY(!view->rootModelNode().metaInfo().propertyIsListProperty("parent")); QVERIFY(!view->rootModelNode().metaInfo().property("parent").isListProperty());
QApplication::processEvents(); QApplication::processEvents();
} }
@@ -4904,8 +4914,8 @@ void tst_TestCore::testQtQuickControls2()
QVERIFY(rootModelNode.metaInfo().isGraphicalItem()); QVERIFY(rootModelNode.metaInfo().isGraphicalItem());
QVERIFY(rootModelNode.isSubclassOf("QtQuick.Window.Window", -1, -1)); QVERIFY(rootModelNode.isSubclassOf("QtQuick.Window.Window", -1, -1));
QVERIFY(!rootModelNode.metaInfo().directPropertyNames().contains("visible")); QVERIFY(!contains(rootModelNode.metaInfo().localProperties(), "visible"));
QVERIFY(rootModelNode.metaInfo().propertyNames().contains("visible")); QVERIFY(contains(rootModelNode.metaInfo().properties(), "visible"));
QVERIFY(!rootModelNode.allSubModelNodes().isEmpty()); QVERIFY(!rootModelNode.allSubModelNodes().isEmpty());
ModelNode button = rootModelNode.allSubModelNodes().first(); ModelNode button = rootModelNode.allSubModelNodes().first();

View File

@@ -25,12 +25,14 @@
#pragma once #pragma once
#include "propertymetainfo.h"
#include <QIcon> #include <QIcon>
#include <QList> #include <QList>
#include <QString> #include <QString>
#include <QVariant> #include <QVariant>
#include "qmldesignercorelib_global.h" #include <qmldesignercorelib_global.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QDeclarativeContext; class QDeclarativeContext;
@@ -51,19 +53,14 @@ public:
bool isValid() const { return {}; } bool isValid() const { return {}; }
bool isFileComponent() const { return {}; } bool isFileComponent() const { return {}; }
bool hasProperty(const PropertyName &) 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 propertyNames() const { return {}; }
PropertyNameList signalNames() const { return {}; } PropertyNameList signalNames() const { return {}; }
PropertyNameList directPropertyNames() const { return {}; } PropertyNameList directPropertyNames() const { return {}; }
PropertyName defaultPropertyName() const { return "data"; } PropertyName defaultPropertyName() const { return "data"; }
bool hasDefaultProperty() const { return {}; } 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<NodeMetaInfo> classHierarchy() const { return {}; } QList<NodeMetaInfo> classHierarchy() const { return {}; }
QList<NodeMetaInfo> superClasses() const { return {}; } QList<NodeMetaInfo> superClasses() const { return {}; }

View File

@@ -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 <qmldesignercorelib_global.h>
#include <QSharedPointer>
#include <QString>
#include <vector>
namespace QmlDesigner {
class PropertyMetaInfo
{
public:
PropertyMetaInfo() = default;
PropertyMetaInfo(QSharedPointer<class NodeMetaInfoPrivate>, 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<typename... TypeName>
bool hasPropertyTypeName(const TypeName &...typeName) const
{
auto propertyTypeName_ = propertyTypeName();
return ((propertyTypeName_ == typeName) && ...);
}
};
using PropertyMetaInfos = std::vector<PropertyMetaInfo>;
} // namespace QmlDesigner