diff options
author | Michael BrĂ¼ning <michael.bruning@qt.io> | 2020-05-31 22:58:33 +0200 |
---|---|---|
committer | Michael BrĂ¼ning <michael.bruning@qt.io> | 2020-06-02 20:25:51 +0000 |
commit | 6419059362cefad8a50f212814c31730f708ea41 (patch) | |
tree | 7b8a9fc035cd9dbd4b5371506ea7d4616e84c2e4 | |
parent | c2bba223e6c656fe2e95163aca834f0c331576b6 (diff) |
Correct text alignment preservation and add basic options parsing
Also add a test case and Remove some dead code along the way.
Task-number: QDS-2071
Change-Id: If34d4e152860ec9ab098f07e36e3a5dc4368c67f
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
6 files changed, 302 insertions, 57 deletions
diff --git a/src/plugins/qmldesigner/designercore/include/stylesheetmerger.h b/src/plugins/qmldesigner/designercore/include/stylesheetmerger.h index f752e50419..d6a27d2af7 100644 --- a/src/plugins/qmldesigner/designercore/include/stylesheetmerger.h +++ b/src/plugins/qmldesigner/designercore/include/stylesheetmerger.h @@ -41,6 +41,7 @@ struct ReparentInfo { bool alreadyReparented; }; + class StylesheetMerger { public: StylesheetMerger(AbstractView*, AbstractView*); @@ -60,11 +61,21 @@ private: void syncBindingProperties(ModelNode &outputNode, const ModelNode &inputNode); void syncAuxiliaryProperties(ModelNode &outputNode, const ModelNode &inputNode); void syncVariantProperties(ModelNode &outputNode, const ModelNode &inputNode); + void parseTemplateOptions(); AbstractView *m_templateView; AbstractView *m_styleView; QHash<QString, ReparentInfo> m_reparentInfoHash; QHash<QString, QString> m_idReplacementHash; + + struct Options { + bool preserveTextAlignment; + Options() : preserveTextAlignment(false) + {} + }; + + Options m_options; + }; } diff --git a/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp b/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp index fa6dccaf10..9c08053fdd 100644 --- a/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp @@ -39,6 +39,42 @@ #include <QQueue> #include <QRegularExpression> +namespace { + +QPoint pointForModelNode(const QmlDesigner::ModelNode &node) +{ + int x = 0; + if (node.hasVariantProperty("x")) + x = node.variantProperty("x").value().toInt(); + + int y = 0; + if (node.hasVariantProperty("y")) + y = node.variantProperty("y").value().toInt(); + + return QPoint(x, y); +} + +QPoint parentPosition(const QmlDesigner::ModelNode &node) +{ + QPoint p; + + QmlDesigner::ModelNode currentNode = node; + while (currentNode.hasParentProperty()) { + currentNode = currentNode.parentProperty().parentModelNode(); + p += pointForModelNode(currentNode); + } + + return p; +} + +bool isTextAlignmentProperty(const QmlDesigner::VariantProperty &property) +{ + return property.name() == "horizontalAlignment" + || property.name() == "verticalAlignment" + || property.name() == "elide"; +} +} // namespace + namespace QmlDesigner { static void splitIdInBaseNameAndNumber(const QString &id, QString *baseId, int *number) @@ -139,15 +175,18 @@ void StylesheetMerger::setupIdRenamingHash() ModelNode StylesheetMerger::createReplacementNode(const ModelNode& styleNode, ModelNode &modelNode) { QList<QPair<PropertyName, QVariant> > propertyList; - QList<QPair<PropertyName, QVariant> > variantPropertyList; + QList<QPair<PropertyName, QVariant> > auxPropertyList; NodeMetaInfo nodeMetaInfo = m_templateView->model()->metaInfo(styleNode.type()); for (const VariantProperty &variantProperty : modelNode.variantProperties()) { - if (nodeMetaInfo.hasProperty(variantProperty.name())) - propertyList.append(QPair<PropertyName, QVariant>(variantProperty.name(), variantProperty.value())); + if (!nodeMetaInfo.hasProperty(variantProperty.name())) + continue; + if (isTextAlignmentProperty(variantProperty) && !m_options.preserveTextAlignment && !styleNode.hasProperty(variantProperty.name())) + continue; + propertyList.append(QPair<PropertyName, QVariant>(variantProperty.name(), variantProperty.value())); } ModelNode newNode(m_templateView->createModelNode(styleNode.type(), nodeMetaInfo.majorVersion(), nodeMetaInfo.minorVersion(), - propertyList, variantPropertyList, styleNode.nodeSource(), styleNode.nodeSourceType())); + propertyList, auxPropertyList, styleNode.nodeSource(), styleNode.nodeSourceType())); syncAuxiliaryProperties(newNode, modelNode); syncBindingProperties(newNode, modelNode); @@ -169,32 +208,6 @@ bool StylesheetMerger::idExistsInBothModels(const QString& id) return m_templateView->hasId(id) && m_styleView->hasId(id); } -QPoint pointForModelNode(const ModelNode &node) -{ - int x = 0; - if (node.hasVariantProperty("x")) - x = node.variantProperty("x").value().toInt(); - - int y = 0; - if (node.hasVariantProperty("y")) - y = node.variantProperty("y").value().toInt(); - - return QPoint(x, y); -} - -QPoint parentPosition(const ModelNode &node) -{ - QPoint p; - - ModelNode currentNode = node; - while (currentNode.hasParentProperty()) { - currentNode = currentNode.parentProperty().parentModelNode(); - p += pointForModelNode(currentNode); - } - - return p; -} - void StylesheetMerger::preprocessStyleSheet() { try { @@ -350,7 +363,11 @@ void StylesheetMerger::applyStyleProperties(ModelNode &templateNode, const Model templateNode.variantProperty(variantProperty.name()).setValue(variantProperty.value()); } } else { - templateNode.variantProperty(variantProperty.name()).setValue(variantProperty.value()); + if (variantProperty.holdsEnumeration()) { + templateNode.variantProperty(variantProperty.name()).setEnumeration(variantProperty.enumeration().toEnumerationName()); + } else { + templateNode.variantProperty(variantProperty.name()).setValue(variantProperty.value()); + } } } syncBindingProperties(templateNode, styleNode); @@ -365,12 +382,43 @@ static void removePropertyIfExists(ModelNode node, const PropertyName &propertyN } +void StylesheetMerger::parseTemplateOptions() +{ + if (!m_templateView->hasId(QStringLiteral("qds_stylesheet_merger_options"))) + return; + + ModelNode optionsNode = m_templateView->modelNodeForId(QStringLiteral("qds_stylesheet_merger_options")); + if (optionsNode.hasVariantProperty("preserveTextAlignment")) { + m_options.preserveTextAlignment = optionsNode.variantProperty("preserveTextAlignment").value().toBool(); + } + try { + RewriterTransaction transaction(m_templateView, "remove-options-node"); + optionsNode.destroy(); + transaction.commit(); + } catch (InvalidIdException &ide) { + qDebug().noquote() << "Invalid id exception while removing options from template."; + ide.createWarning(); + } catch (InvalidReparentingException &rpe) { + qDebug().noquote() << "Invalid reparenting exception while removing options from template."; + rpe.createWarning(); + } catch (InvalidModelNodeException &mne) { + qDebug().noquote() << "Invalid model node exception while removing options from template."; + mne.createWarning(); + } catch (Exception &e) { + qDebug().noquote() << "Exception while removing options from template."; + e.createWarning(); + } +} + void StylesheetMerger::merge() { ModelNode templateRootNode = m_templateView->rootModelNode(); ModelNode styleRootNode = m_styleView->rootModelNode(); - // first, build up the hierarchy in the style sheet as we have it in the template + // first, look if there are any options present in the template + parseTemplateOptions(); + + // second, build up the hierarchy in the style sheet as we have it in the template preprocessStyleSheet(); // build a hash of generated replacement ids diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp index dcac5310fc..c99805152c 100644 --- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp +++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp @@ -3706,23 +3706,6 @@ void tst_TestCore::testCopyModelRewriter1() QCOMPARE(textEdit1.toPlainText(), expected); } -static void adjustPreservedProperties(const ModelNode& replacedNode, ModelNode& newNode) { - QSet<PropertyName> preservedProperties; - preservedProperties.insert("x"); - preservedProperties.insert("y"); - preservedProperties.insert("width"); - preservedProperties.insert("height"); - preservedProperties.insert("anchors"); - // preservedProperties.insert("text "); - - for (VariantProperty originalProperty : replacedNode.variantProperties()) { - VariantProperty prop; - if (preservedProperties.contains(originalProperty.name())) { - newNode.variantProperty(originalProperty.name()).setValue(originalProperty.value()); - } - } -} - static QString readQmlFromFile(const QString& fileName) { QFile qmlFile(fileName); @@ -3776,6 +3759,9 @@ void tst_TestCore::testMergeModelRewriter1_data() QString buttonStyleUiQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ButtonStyle.ui.qml"); QString buttonStyleUiExpectedQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ButtonStyle.ui.Expected.qml"); + QString buttonAbsoluteTemplateWithOptionsQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ButtonAbsoluteTemplateWithOptions.qml"); + QString buttonStyleUiWithOptionsExpectedQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ButtonStyleWithOptions.ui.Expected.qml"); + QTest::newRow("Simple style replacement") << simpleTemplateQmlContents << simpleStyleQmlContents << simpleExpectedQmlContents; QTest::newRow("Complex style replacement") << complexTemplateQmlContents << complexStyleQmlContents << complexExpectedQmlContents; QTest::newRow("Empty stylesheet") << emptyTemplateQmlContents << emptyStyleQmlContents << emptyExpectedQmlContents; @@ -3788,6 +3774,8 @@ void tst_TestCore::testMergeModelRewriter1_data() QTest::newRow("Button Outline styling") << buttonAbsoluteTemplateQmlContents << buttonOutlineStyleQmlContents << buttonOutlineExpectedQmlContents; QTest::newRow("Button Designer styling") << buttonAbsoluteTemplateQmlContents << buttonStyleUiQmlContents << buttonStyleUiExpectedQmlContents; + QTest::newRow("Button Designer styling with options") << buttonAbsoluteTemplateWithOptionsQmlContents << buttonStyleUiQmlContents << buttonStyleUiWithOptionsExpectedQmlContents; + } void tst_TestCore::testMergeModelRewriter1() diff --git a/tests/auto/qml/qmldesigner/data/merging/ButtonAbsoluteTemplateWithOptions.qml b/tests/auto/qml/qmldesigner/data/merging/ButtonAbsoluteTemplateWithOptions.qml new file mode 100644 index 0000000000..de34e1ab0c --- /dev/null +++ b/tests/auto/qml/qmldesigner/data/merging/ButtonAbsoluteTemplateWithOptions.qml @@ -0,0 +1,109 @@ +import QtQuick 2.10 +import QtQuick.Templates 2.1 as T + +T.Button { + id: control + + implicitWidth: Math.max( + background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max( + background ? background.implicitHeight : 0, + contentItem.implicitHeight + topPadding + bottomPadding) + leftPadding: 4 + rightPadding: 4 + + text: "My Button" + + background: Item { + implicitWidth: buttonNormal.width + implicitHeight: buttonNormal.height + opacity: enabled ? 1 : 0.3 + + Rectangle { + + id: buttonNormal + color: "#d4d4d4" + width: 100 //Bit of black magic to define the default size + height: 40 + + border.color: "gray" + border.width: 1 + radius: 2 + anchors.fill: parent //binding has to be preserved + + Text { + id: normalText + x: 26 + y: 14 //id only required to preserve binding + text: control.text //binding has to be preserved + //anchors.fill: parent + color: "gray" + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + } + + Rectangle { + id: buttonPressed + color: "#d4d4d4" + width: 100 //Bit of black magic to define the default size + height: 40 + + border.color: "gray" + border.width: 1 + radius: 2 + anchors.fill: parent //binding has to be preserved + + Text { + x: 26 + y: 14 + id: pressedText //id only required to preserve binding + text: control.text //binding has to be preserved + //anchors.fill: parent + color: "black" + + horizontalAlignment: Text.AlignHCenter // should not be preserved + verticalAlignment: Text.AlignVCenter // should not be preserved + elide: Text.ElideRight // should not be preserved + } + } + } + + contentItem: Item {} + + states: [ + State { + name: "normal" + when: !control.down + PropertyChanges { + target: buttonPressed + visible: false + } + PropertyChanges { + target: buttonNormal + visible: true + } + }, + State { + name: "down" + when: control.down + PropertyChanges { + target: buttonPressed + visible: true + } + PropertyChanges { + target: buttonNormal + visible: false + } + } + ] + QtObject { + id: qds_stylesheet_merger_options + property bool preserveTextAlignment: true + } + +} + diff --git a/tests/auto/qml/qmldesigner/data/merging/ButtonStyle.ui.Expected.qml b/tests/auto/qml/qmldesigner/data/merging/ButtonStyle.ui.Expected.qml index 7faf527196..ab54caa5b1 100644 --- a/tests/auto/qml/qmldesigner/data/merging/ButtonStyle.ui.Expected.qml +++ b/tests/auto/qml/qmldesigner/data/merging/ButtonStyle.ui.Expected.qml @@ -32,11 +32,8 @@ T.Button { y: 50 color: "#bbbbbb" text: control.text - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.pixelSize: 24 font.letterSpacing: 0.594 + font.pixelSize: 24 } } @@ -52,11 +49,8 @@ T.Button { y: 50 color: "#e1e1e1" text: control.text - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.pixelSize: 24 font.letterSpacing: 0.594 + font.pixelSize: 24 } } diff --git a/tests/auto/qml/qmldesigner/data/merging/ButtonStyleWithOptions.ui.Expected.qml b/tests/auto/qml/qmldesigner/data/merging/ButtonStyleWithOptions.ui.Expected.qml new file mode 100644 index 0000000000..580a5f1560 --- /dev/null +++ b/tests/auto/qml/qmldesigner/data/merging/ButtonStyleWithOptions.ui.Expected.qml @@ -0,0 +1,95 @@ +import QtQuick 2.10 +import QtQuick.Templates 2.1 as T + +T.Button { + id: control + + implicitWidth: Math.max( + background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max( + background ? background.implicitHeight : 0, + contentItem.implicitHeight + topPadding + bottomPadding) + leftPadding: 4 + rightPadding: 4 + + text: "My Button" + + background: Item { + implicitWidth: buttonNormal.width + implicitHeight: buttonNormal.height + opacity: enabled ? 1 : 0.3 + + Image { + id: buttonNormal + width: 100 + height: 40 + anchors.fill: parent + source: "assets/buttonNormal.png" + Text { + id: normalText + x: 58 + y: 50 + color: "#bbbbbb" + text: control.text + elide: Text.ElideRight + font.letterSpacing: 0.594 + font.pixelSize: 24 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } + + Image { + id: buttonPressed + width: 100 + height: 40 + anchors.fill: parent + source: "assets/buttonPressed.png" + Text { + id: pressedText + x: 58 + y: 50 + color: "#e1e1e1" + text: control.text + elide: Text.ElideRight + font.letterSpacing: 0.594 + font.pixelSize: 24 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } + + } + + contentItem: Item {} + + states: [ + State { + name: "normal" + when: !control.down + PropertyChanges { + target: buttonPressed + visible: false + } + PropertyChanges { + target: buttonNormal + visible: true + } + }, + State { + name: "down" + when: control.down + PropertyChanges { + target: buttonPressed + visible: true + } + PropertyChanges { + target: buttonNormal + visible: false + } + } + ] + +} + |