forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user