diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp index 6dbb0d471ca..678e5664eca 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include @@ -311,8 +312,19 @@ void PropertyEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qm void PropertyEditorQmlBackend::setValue(const QmlObjectNode & , const PropertyName &name, const QVariant &value) { - if (value.type() == QVariant::Vector3D) { - // Vector3D values need to be split into their subcomponents + // Vector*D values need to be split into their subcomponents + if (value.type() == QVariant::Vector2D) { + const char *suffix[2] = {"_x", "_y"}; + auto vecValue = value.value(); + for (int i = 0; i < 2; ++i) { + PropertyName subPropName(name.size() + 2, '\0'); + subPropName.replace(0, name.size(), name); + subPropName.replace(name.size(), 2, suffix[i]); + auto propertyValue = qobject_cast(variantToQObject(m_backendValuesPropertyMap.value(QString::fromUtf8(subPropName)))); + if (propertyValue) + propertyValue->setValue(QVariant(vecValue[i])); + } + } else if (value.type() == QVariant::Vector3D) { const char *suffix[3] = {"_x", "_y", "_z"}; auto vecValue = value.value(); for (int i = 0; i < 3; ++i) { diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp index 719ad8d8ec9..fbfc017d40b 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp @@ -225,8 +225,9 @@ void PropertyEditorView::changeValue(const QString &name) if (!value->value().isValid()) { //reset removePropertyFromModel(propertyName); } else { - // QVector3D(0, 0, 0) detects as null variant though it is valid value + // QVector*D(0, 0, 0) detects as null variant though it is valid value if (castedValue.isValid() && (!castedValue.isNull() + || castedValue.type() == QVariant::Vector2D || castedValue.type() == QVariant::Vector3D)) { commitVariantValueToModel(propertyName, castedValue); } diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp index 535350055db..b74179fdef8 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp @@ -33,6 +33,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE void qt_blurImage(QPainter *painter, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); @@ -316,7 +317,23 @@ QVariant NodeInstance::property(const PropertyName &name) const if (index != -1) { PropertyName parentPropName = name.left(index); QVariant varValue = d->propertyValues.value(parentPropName); - if (varValue.type() == QVariant::Vector3D) { + if (varValue.type() == QVariant::Vector2D) { + auto value = varValue.value(); + char subProp = name.right(1)[0]; + float subValue = 0.f; + switch (subProp) { + case 'x': + subValue = value.x(); + break; + case 'y': + subValue = value.y(); + break; + default: + subValue = 0.f; + break; + } + return QVariant(subValue); + } else if (varValue.type() == QVariant::Vector3D) { auto value = varValue.value(); char subProp = name.right(1)[0]; float subValue = 0.f; @@ -397,22 +414,38 @@ void NodeInstance::setProperty(const PropertyName &name, const QVariant &value) if (index != -1) { PropertyName parentPropName = name.left(index); QVariant oldValue = d->propertyValues.value(parentPropName); - QVector3D newValue; - if (oldValue.type() == QVariant::Vector3D) - newValue = oldValue.value(); + QVariant newValueVar; bool update = false; - if (name.endsWith(".x")) { - newValue.setX(value.toFloat()); - update = true; - } else if (name.endsWith(".y")) { - newValue.setY(value.toFloat()); - update = true; - } else if (name.endsWith(".z")) { - newValue.setZ(value.toFloat()); - update = true; + if (oldValue.type() == QVariant::Vector2D) { + QVector2D newValue; + if (oldValue.type() == QVariant::Vector2D) + newValue = oldValue.value(); + if (name.endsWith(".x")) { + newValue.setX(value.toFloat()); + update = true; + } else if (name.endsWith(".y")) { + newValue.setY(value.toFloat()); + update = true; + } + newValueVar = newValue; + } else if (oldValue.type() == QVariant::Vector3D) { + QVector3D newValue; + if (oldValue.type() == QVariant::Vector3D) + newValue = oldValue.value(); + if (name.endsWith(".x")) { + newValue.setX(value.toFloat()); + update = true; + } else if (name.endsWith(".y")) { + newValue.setY(value.toFloat()); + update = true; + } else if (name.endsWith(".z")) { + newValue.setZ(value.toFloat()); + update = true; + } + newValueVar = newValue; } if (update) { - d->propertyValues.insert(parentPropName, newValue); + d->propertyValues.insert(parentPropName, newValueVar); return; } } diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp index 73fca899526..02e95e6aecd 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp @@ -336,14 +336,14 @@ private: static inline bool isValueType(const TypeName &type) { static const PropertyTypeList objectValuesList({"QFont", "QPoint", "QPointF", - "QSize", "QSizeF", "QVector3D", "QVector2D", "font"}); + "QSize", "QSizeF", "QVector3D", "QVector2D", "vector2d", "vector3d", "font"}); return objectValuesList.contains(type); } static inline bool isValueType(const QString &type) { static const QStringList objectValuesList({"QFont", "QPoint", "QPointF", - "QSize", "QSizeF", "QVector3D", "QVector2D", "font"}); + "QSize", "QSizeF", "QVector3D", "QVector2D", "vector2d", "vector3d", "font"}); return objectValuesList.contains(type); } @@ -494,8 +494,28 @@ QVector getObjectTypes(const ObjectValue *objectValue, const Conte PropertyMemberProcessor processor(context); objectValue->processMembers(&processor); + const auto props = processor.properties(); - propertyList.append(processor.properties()); + for (const PropertyInfo &property : props) { + const PropertyName name = property.first; + const QString nameAsString = QString::fromUtf8(name); + + if (isValueType(property.second)) { + const Value *dotValue = objectValue->lookupMember(nameAsString, context); + if (const Reference *ref = dotValue->asReference()) + dotValue = context->lookupReference(ref); + + if (const ObjectValue *dotObjectValue = dotValue->asObjectValue()) { + const QVector dotProperties = getObjectTypes(dotObjectValue, context, false, rec + 1); + for (const PropertyInfo &propertyInfo : dotProperties) { + const PropertyName dotName = name + '.' + propertyInfo.first; + const TypeName type = propertyInfo.second; + propertyList.append({dotName, type}); + } + } + } + propertyList.append(property); + } if (!local) { const ObjectValue* prototype = objectValue->prototype(context); @@ -1067,6 +1087,9 @@ QVariant::Type NodeMetaInfoPrivate::variantTypeId(const PropertyName &propertyNa if (typeName == "var") return QVariant::UserType; + if (typeName == "vector2d") + return QVariant::Vector2D; + if (typeName == "vector3d") return QVariant::Vector3D; diff --git a/src/plugins/qmldesigner/designercore/model/propertyparser.cpp b/src/plugins/qmldesigner/designercore/model/propertyparser.cpp index b4af8564675..b832d21de82 100644 --- a/src/plugins/qmldesigner/designercore/model/propertyparser.cpp +++ b/src/plugins/qmldesigner/designercore/model/propertyparser.cpp @@ -31,6 +31,7 @@ #include #include +#include #include namespace { @@ -151,6 +152,29 @@ QSizeF sizeFFromString(const QString &s, bool *ok) return QSizeF(width, height); } +QVector2D vector2DFromString(const QString &s, bool *ok) +{ + if (s.count(QLatin1Char(',')) != 1) { + if (ok) + *ok = false; + return {}; + } + + bool xGood, yGood; + int index = s.indexOf(QLatin1Char(',')); + qreal xCoord = s.leftRef(index).toDouble(&xGood); + qreal yCoord = s.midRef(index + 1).toDouble(&yGood); + if (!xGood || !yGood) { + if (ok) + *ok = false; + return QVector2D(); + } + + if (ok) + *ok = true; + return QVector2D(xCoord, yCoord); +} + QVector3D vector3DFromString(const QString &s, bool *ok) { if (s.count(QLatin1Char(',')) != 2) { @@ -241,6 +265,9 @@ QVariant read(int variantType, const QString &str) case QMetaType::QColor: value = colorFromString(str, &conversionOk); break; + case QMetaType::QVector2D: + value = vector2DFromString(str, &conversionOk); + break; case QMetaType::QVector3D: value = vector3DFromString(str, &conversionOk); break; @@ -277,8 +304,10 @@ QVariant variantFromString(const QString &s) if (ok) return QVariant(p); QSizeF sz = sizeFFromString(s, &ok); if (ok) return QVariant(sz); - QVector3D v = vector3DFromString(s, &ok); - if (ok) return QVariant::fromValue(v); + QVector3D v3 = vector3DFromString(s, &ok); + if (ok) return QVariant::fromValue(v3); + QVector2D v2 = vector2DFromString(s, &ok); + if (ok) return QVariant::fromValue(v2); return QVariant(s); } diff --git a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp index 6e06970c76b..9534752282a 100644 --- a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "bindingproperty.h" #include "signalhandlerproperty.h" @@ -150,6 +151,10 @@ QString QmlTextGenerator::toQml(const AbstractProperty &property, int indentDept case QMetaType::QString: case QMetaType::QChar: return QStringLiteral("\"%1\"").arg(escape(unicodeEscape(stringValue))); + case QMetaType::QVector2D: { + auto vec = value.value(); + return QStringLiteral("Qt.vector2d(%1, %2)").arg(vec.x()).arg(vec.y()); + } case QMetaType::QVector3D: { auto vec = value.value(); return QStringLiteral("Qt.vector3d(%1, %2, %3)").arg(vec.x()).arg(vec.y()).arg(vec.z()); diff --git a/src/plugins/qmldesigner/designercore/model/variantproperty.cpp b/src/plugins/qmldesigner/designercore/model/variantproperty.cpp index c067b111d93..498faea6ecb 100644 --- a/src/plugins/qmldesigner/designercore/model/variantproperty.cpp +++ b/src/plugins/qmldesigner/designercore/model/variantproperty.cpp @@ -57,8 +57,8 @@ void VariantProperty::setValue(const QVariant &value) if (isDynamic()) qWarning() << "Calling VariantProperty::setValue on dynamic property."; - // QVector3D(0, 0, 0) detects as null variant though it is valid value - if (value.isNull() && value.type() != QVariant::Vector3D) + // QVector*D(0, 0, 0) detects as null variant though it is valid value + if (value.isNull() && (value.type() != QVariant::Vector3D && value.type() != QVariant::Vector2D)) throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, name()); if (internalNode()->hasProperty(name())) { //check if oldValue != value