forked from qt-creator/qt-creator
Add stylesheet merger
Adds classes to merge a template qml file and a qml stylesheet that have been exported from other design tools into a resulting qml file that can be used for further processing in Qt Design Studio. Current issues: * Sometimes it makes sense to define width and height if an anchor is present, but most of the time not. * Actually if the hierachy was defined (e.g. Text item not child of background) most likely the anchors should be ignored. But this would be just a "dirty" heuristic. I suggest to let the template decide. If the template has anchors those have "precedence". It is always possible to define templates without anchors. Task-number: QDS-2071 Change-Id: I9159514a8e884b7ffc31897aef4551b5efbbcb87 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Thomas Hartmann
parent
5b00401850
commit
de8eb93637
@@ -457,6 +457,7 @@ extend_qtc_plugin(QmlDesigner
|
||||
include/rewriterview.h
|
||||
include/rewritingexception.h
|
||||
include/signalhandlerproperty.h
|
||||
include/stylesheetmerger.h
|
||||
include/subcomponentmanager.h
|
||||
include/textmodifier.h
|
||||
include/variantproperty.h
|
||||
@@ -530,6 +531,7 @@ extend_qtc_plugin(QmlDesigner
|
||||
model/rewriteactioncompressor.cpp model/rewriteactioncompressor.h
|
||||
model/rewriterview.cpp
|
||||
model/signalhandlerproperty.cpp
|
||||
model/stylesheetmerger.cpp
|
||||
model/textmodifier.cpp
|
||||
model/texttomodelmerger.cpp model/texttomodelmerger.h
|
||||
model/variantproperty.cpp
|
||||
|
@@ -83,7 +83,8 @@ SOURCES += $$PWD/model/abstractview.cpp \
|
||||
$$PWD/instances/puppetdialog.cpp \
|
||||
$$PWD/model/qmltimeline.cpp \
|
||||
$$PWD/model/qmltimelinekeyframegroup.cpp \
|
||||
$$PWD/model/annotation.cpp
|
||||
$$PWD/model/annotation.cpp \
|
||||
$$PWD/model/stylesheetmerger.cpp
|
||||
|
||||
HEADERS += $$PWD/include/qmldesignercorelib_global.h \
|
||||
$$PWD/include/abstractview.h \
|
||||
@@ -160,7 +161,8 @@ HEADERS += $$PWD/include/qmldesignercorelib_global.h \
|
||||
$$PWD/instances/puppetdialog.h \
|
||||
$$PWD/include/qmltimeline.h \
|
||||
$$PWD/include/qmltimelinekeyframegroup.h \
|
||||
$$PWD/include/annotation.h
|
||||
$$PWD/include/annotation.h \
|
||||
$$PWD/include/stylesheetmerger.h
|
||||
|
||||
FORMS += \
|
||||
$$PWD/instances/puppetdialog.ui
|
||||
|
@@ -0,0 +1,71 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef STYLESHEETMERGER_H
|
||||
#define STYLESHEETMERGER_H
|
||||
|
||||
#include <QString>
|
||||
#include <QHash>
|
||||
#include <modelnode.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class AbstractView;
|
||||
|
||||
struct ReparentInfo {
|
||||
QString generatedId;
|
||||
QString templateId;
|
||||
QString templateParentId;
|
||||
int parentIndex;
|
||||
bool alreadyReparented;
|
||||
};
|
||||
|
||||
class StylesheetMerger {
|
||||
public:
|
||||
StylesheetMerger(AbstractView*, AbstractView*);
|
||||
void merge();
|
||||
private:
|
||||
void preprocessStyleSheet();
|
||||
bool idExistsInBothModels(const QString& id);
|
||||
void replaceNode(ModelNode&, ModelNode&);
|
||||
void replaceRootNode(ModelNode& templateRootNode);
|
||||
void applyStyleProperties(ModelNode &templateNode, const ModelNode &styleNode);
|
||||
void adjustNodeIndex(ModelNode &node);
|
||||
void setupIdRenamingHash();
|
||||
ModelNode createReplacementNode(const ModelNode &styleNode, ModelNode &modelNode);
|
||||
void syncNodeProperties(ModelNode &outputNode, const ModelNode &inputNode, bool skipDuplicates = false);
|
||||
void syncNodeListProperties(ModelNode &outputNode, const ModelNode &inputNode, bool skipDuplicates = false);
|
||||
void syncId(ModelNode &outputNode, ModelNode &inputNode);
|
||||
void syncBindingProperties(ModelNode &outputNode, const ModelNode &inputNode);
|
||||
void syncAuxiliaryProperties(ModelNode &outputNode, const ModelNode &inputNode);
|
||||
void syncVariantProperties(ModelNode &outputNode, const ModelNode &inputNode);
|
||||
|
||||
AbstractView *m_templateView;
|
||||
AbstractView *m_styleView;
|
||||
QHash<QString, ReparentInfo> m_reparentInfoHash;
|
||||
QHash<QString, QString> m_idReplacementHash;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // STYLESHEETMERGER_H
|
404
src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp
Normal file
404
src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp
Normal file
@@ -0,0 +1,404 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
#include "stylesheetmerger.h"
|
||||
|
||||
#include <abstractview.h>
|
||||
#include <bindingproperty.h>
|
||||
#include <modelmerger.h>
|
||||
#include <nodeabstractproperty.h>
|
||||
#include <nodelistproperty.h>
|
||||
#include <nodemetainfo.h>
|
||||
#include <nodeproperty.h>
|
||||
#include <variantproperty.h>
|
||||
|
||||
#include <QQueue>
|
||||
#include <QRegularExpression>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
static void splitIdInBaseNameAndNumber(const QString &id, QString *baseId, int *number)
|
||||
{
|
||||
|
||||
int counter = 0;
|
||||
while (counter < id.count()) {
|
||||
bool canConvertToInteger = false;
|
||||
int newNumber = id.rightRef(counter +1).toInt(&canConvertToInteger);
|
||||
if (canConvertToInteger)
|
||||
*number = newNumber;
|
||||
else
|
||||
break;
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
*baseId = id.left(id.count() - counter);
|
||||
}
|
||||
|
||||
void StylesheetMerger::syncNodeProperties(ModelNode &outputNode, const ModelNode &inputNode, bool skipDuplicates)
|
||||
{
|
||||
foreach (const NodeProperty &nodeProperty, inputNode.nodeProperties()) {
|
||||
ModelNode oldNode = nodeProperty.modelNode();
|
||||
if (m_templateView->hasId(oldNode.id()) && skipDuplicates)
|
||||
continue;
|
||||
ModelNode newNode = createReplacementNode(oldNode, oldNode);
|
||||
// cache the property name as removing it will invalidate it
|
||||
PropertyName propertyName = nodeProperty.name();
|
||||
// remove property first to prevent invalid reparenting situation
|
||||
outputNode.removeProperty(propertyName);
|
||||
outputNode.nodeProperty(propertyName).reparentHere(newNode);
|
||||
}
|
||||
}
|
||||
|
||||
void StylesheetMerger::syncNodeListProperties(ModelNode &outputNode, const ModelNode &inputNode, bool skipDuplicates)
|
||||
{
|
||||
foreach (const NodeListProperty &nodeListProperty, inputNode.nodeListProperties()) {
|
||||
foreach (ModelNode node, nodeListProperty.toModelNodeList()) {
|
||||
if (m_templateView->hasId(node.id()) && skipDuplicates)
|
||||
continue;
|
||||
ModelNode newNode = createReplacementNode(node, node);
|
||||
outputNode.nodeListProperty(nodeListProperty.name()).reparentHere(newNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StylesheetMerger::syncVariantProperties(ModelNode &outputNode, const ModelNode &inputNode)
|
||||
{
|
||||
foreach (const VariantProperty &variantProperty, inputNode.variantProperties()) {
|
||||
outputNode.variantProperty(variantProperty.name()).setValue(variantProperty.value());
|
||||
}
|
||||
}
|
||||
|
||||
void StylesheetMerger::syncAuxiliaryProperties(ModelNode &outputNode, const ModelNode &inputNode)
|
||||
{
|
||||
auto tmp = inputNode.auxiliaryData();
|
||||
for (auto iter = tmp.begin(); iter != tmp.end(); ++iter)
|
||||
outputNode.setAuxiliaryData(iter.key(), iter.value());
|
||||
}
|
||||
|
||||
void StylesheetMerger::syncBindingProperties(ModelNode &outputNode, const ModelNode &inputNode)
|
||||
{
|
||||
foreach (const BindingProperty &bindingProperty, inputNode.bindingProperties()) {
|
||||
outputNode.bindingProperty(bindingProperty.name()).setExpression(bindingProperty.expression());
|
||||
}
|
||||
}
|
||||
|
||||
void StylesheetMerger::syncId(ModelNode &outputNode, ModelNode &inputNode)
|
||||
{
|
||||
if (!inputNode.id().isEmpty()) {
|
||||
QString id = inputNode.id();
|
||||
QString renamedId = m_idReplacementHash.value(inputNode.id());
|
||||
inputNode.setIdWithoutRefactoring(renamedId);
|
||||
outputNode.setIdWithoutRefactoring(id);
|
||||
}
|
||||
}
|
||||
|
||||
void StylesheetMerger::setupIdRenamingHash()
|
||||
{
|
||||
foreach (const ModelNode &node, m_templateView->rootModelNode().allSubModelNodesAndThisNode()) {
|
||||
if (!node.id().isEmpty()) {
|
||||
QString newId = node.id();
|
||||
QString baseId;
|
||||
int number = 1;
|
||||
splitIdInBaseNameAndNumber(newId, &baseId, &number);
|
||||
|
||||
while (m_templateView->hasId(newId) || m_idReplacementHash.values().contains(newId)) {
|
||||
newId = "stylesheet_auto_merge_" + baseId + QString::number(number);
|
||||
number++;
|
||||
}
|
||||
|
||||
m_idReplacementHash.insert(node.id(), newId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ModelNode StylesheetMerger::createReplacementNode(const ModelNode& styleNode, ModelNode &modelNode)
|
||||
{
|
||||
QList<QPair<PropertyName, QVariant> > propertyList;
|
||||
QList<QPair<PropertyName, QVariant> > variantPropertyList;
|
||||
foreach (const VariantProperty &variantProperty, modelNode.variantProperties()) {
|
||||
propertyList.append(QPair<PropertyName, QVariant>(variantProperty.name(), variantProperty.value()));
|
||||
}
|
||||
NodeMetaInfo nodeMetaInfo = m_templateView->model()->metaInfo(styleNode.type());
|
||||
ModelNode newNode(m_templateView->createModelNode(styleNode.type(), nodeMetaInfo.majorVersion(), nodeMetaInfo.minorVersion(),
|
||||
propertyList, variantPropertyList, styleNode.nodeSource(), styleNode.nodeSourceType()));
|
||||
|
||||
syncAuxiliaryProperties(newNode, modelNode);
|
||||
syncBindingProperties(newNode, modelNode);
|
||||
syncId(newNode, modelNode);
|
||||
syncNodeProperties(newNode, modelNode);
|
||||
syncNodeListProperties(newNode, modelNode);
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
StylesheetMerger::StylesheetMerger(AbstractView *templateView, AbstractView *styleView)
|
||||
: m_templateView(templateView)
|
||||
, m_styleView(styleView)
|
||||
{
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
for (ModelNode currentStyleNode : m_styleView->rootModelNode().directSubModelNodes()) {
|
||||
QString id = currentStyleNode.id();
|
||||
|
||||
if (!idExistsInBothModels(id))
|
||||
continue;
|
||||
|
||||
ModelNode templateNode = m_templateView->modelNodeForId(id);
|
||||
NodeAbstractProperty templateParentProperty = templateNode.parentProperty();
|
||||
if (!templateNode.hasParentProperty()
|
||||
|| templateParentProperty.parentModelNode().isRootNode())
|
||||
continue;
|
||||
|
||||
ModelNode templateParentNode = templateParentProperty.parentModelNode();
|
||||
const QString parentId = templateParentNode.id();
|
||||
if (!idExistsInBothModels(parentId))
|
||||
continue;
|
||||
|
||||
// Only get the position properties as the node should have a global
|
||||
// position in the style sheet.
|
||||
const QPoint oldGlobalPos = pointForModelNode(currentStyleNode);
|
||||
|
||||
ModelNode newStyleParent = m_styleView->modelNodeForId(parentId);
|
||||
NodeListProperty newParentProperty = newStyleParent.defaultNodeListProperty();
|
||||
newParentProperty.reparentHere(currentStyleNode);
|
||||
|
||||
// Get the parent position in global coordinates.
|
||||
QPoint parentGlobalPos = parentPosition(currentStyleNode);
|
||||
|
||||
const QPoint newGlobalPos = oldGlobalPos - parentGlobalPos;
|
||||
|
||||
currentStyleNode.variantProperty("x").setValue(newGlobalPos.x());
|
||||
currentStyleNode.variantProperty("y").setValue(newGlobalPos.y());
|
||||
|
||||
int templateParentIndex = templateParentProperty.isNodeListProperty()
|
||||
? templateParentProperty.indexOf(templateNode) : -1;
|
||||
int styleParentIndex = newParentProperty.indexOf(currentStyleNode);
|
||||
if (templateParentIndex >= 0 && styleParentIndex != templateParentIndex)
|
||||
newParentProperty.slide(styleParentIndex, templateParentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void StylesheetMerger::replaceNode(ModelNode &replacedNode, ModelNode &newNode)
|
||||
{
|
||||
NodeListProperty replacedNodeParent;
|
||||
ModelNode parentModelNode = replacedNode.parentProperty().parentModelNode();
|
||||
if (replacedNode.parentProperty().isNodeListProperty())
|
||||
replacedNodeParent = replacedNode.parentProperty().toNodeListProperty();
|
||||
bool isNodeProperty = false;
|
||||
|
||||
PropertyName reparentName;
|
||||
for (NodeProperty prop : parentModelNode.nodeProperties()) {
|
||||
if (prop.modelNode().id() == replacedNode.id()) {
|
||||
isNodeProperty = true;
|
||||
reparentName = prop.name();
|
||||
}
|
||||
}
|
||||
ReparentInfo info;
|
||||
info.parentIndex = replacedNodeParent.isValid() ? replacedNodeParent.indexOf(replacedNode) : -1;
|
||||
info.templateId = replacedNode.id();
|
||||
info.templateParentId = parentModelNode.id();
|
||||
info.generatedId = newNode.id();
|
||||
|
||||
if (!isNodeProperty) {
|
||||
replacedNodeParent.reparentHere(newNode);
|
||||
replacedNode.destroy();
|
||||
info.alreadyReparented = true;
|
||||
} else {
|
||||
parentModelNode.removeProperty(reparentName);
|
||||
parentModelNode.nodeProperty(reparentName).reparentHere(newNode);
|
||||
}
|
||||
m_reparentInfoHash.insert(newNode.id(), info);
|
||||
}
|
||||
|
||||
void StylesheetMerger::replaceRootNode(ModelNode& templateRootNode)
|
||||
{
|
||||
ModelMerger merger(m_templateView);
|
||||
QString rootId = templateRootNode.id();
|
||||
// If we shall replace the root node of the template with the style,
|
||||
// we first replace the whole model.
|
||||
ModelNode rootReplacer = m_styleView->modelNodeForId(rootId);
|
||||
merger.replaceModel(rootReplacer);
|
||||
|
||||
// Then reset the id to the old root's one.
|
||||
ModelNode newRoot = m_templateView->rootModelNode();
|
||||
newRoot.setIdWithoutRefactoring(rootId);
|
||||
}
|
||||
|
||||
// Move the newly created nodes to the correct position in the parent node
|
||||
void StylesheetMerger::adjustNodeIndex(ModelNode &node)
|
||||
{
|
||||
if (!m_reparentInfoHash.contains(node.id()))
|
||||
return;
|
||||
|
||||
ReparentInfo info = m_reparentInfoHash.value(node.id());
|
||||
if (info.parentIndex < 0)
|
||||
return;
|
||||
|
||||
if (!node.parentProperty().isNodeListProperty())
|
||||
return;
|
||||
|
||||
NodeListProperty parentListProperty = node.parentProperty().toNodeListProperty();
|
||||
int currentIndex = parentListProperty.indexOf(node);
|
||||
if (currentIndex == info.parentIndex)
|
||||
return;
|
||||
|
||||
parentListProperty.slide(currentIndex, info.parentIndex);
|
||||
}
|
||||
|
||||
void StylesheetMerger::applyStyleProperties(ModelNode &templateNode, const ModelNode &styleNode)
|
||||
{
|
||||
QRegExp regEx("[a-z]", Qt::CaseInsensitive);
|
||||
foreach (const VariantProperty &variantProperty, styleNode.variantProperties()) {
|
||||
// check for existing bindings with that property name
|
||||
if (templateNode.hasBindingProperty(variantProperty.name())) {
|
||||
// if the binding does not contain any alpha letters (i.e. binds to a term rather than a property,
|
||||
// replace it with the corresponding variant property.
|
||||
if (!templateNode.bindingProperty(variantProperty.name()).expression().contains(regEx)) {
|
||||
templateNode.removeProperty(variantProperty.name());
|
||||
templateNode.variantProperty(variantProperty.name()).setValue(variantProperty.value());
|
||||
}
|
||||
} else {
|
||||
templateNode.variantProperty(variantProperty.name()).setValue(variantProperty.value());
|
||||
}
|
||||
}
|
||||
syncBindingProperties(templateNode, styleNode);
|
||||
syncNodeProperties(templateNode, styleNode, true);
|
||||
syncNodeListProperties(templateNode, styleNode, true);
|
||||
}
|
||||
|
||||
static void removePropertyIfExists(ModelNode node, const PropertyName &propertyName)
|
||||
{
|
||||
if (node.hasProperty(propertyName))
|
||||
node.removeProperty(propertyName);
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
preprocessStyleSheet();
|
||||
|
||||
// build a hash of generated replacement ids
|
||||
setupIdRenamingHash();
|
||||
|
||||
//in case we are replacing the root node, just do that and exit
|
||||
if (m_styleView->hasId(templateRootNode.id())) {
|
||||
replaceRootNode(templateRootNode);
|
||||
return;
|
||||
}
|
||||
|
||||
QQueue<ModelNode> replacementNodes;
|
||||
|
||||
QList<ModelNode> directRootSubNodes = styleRootNode.directSubModelNodes();
|
||||
if (directRootSubNodes.length() == 0 && m_templateView->hasId(styleRootNode.id())) {
|
||||
// if the style sheet has only one node, just replace that one
|
||||
replacementNodes.enqueue(styleRootNode);
|
||||
}
|
||||
// otherwise, the nodes to replace are the direct sub nodes of the style sheet's root
|
||||
for (ModelNode subNode : styleRootNode.allSubModelNodes()) {
|
||||
if (m_templateView->hasId(subNode.id())) {
|
||||
replacementNodes.enqueue(subNode);
|
||||
}
|
||||
}
|
||||
|
||||
for (ModelNode currentNode : replacementNodes) {
|
||||
|
||||
bool hasPos = false;
|
||||
|
||||
// create the replacement nodes for the styled nodes
|
||||
{
|
||||
RewriterTransaction transaction(m_templateView, "create-replacement-node");
|
||||
|
||||
ModelNode replacedNode = m_templateView->modelNodeForId(currentNode.id());
|
||||
hasPos = replacedNode.hasProperty("x") || replacedNode.hasProperty("y");
|
||||
|
||||
ModelNode replacementNode = createReplacementNode(currentNode, replacedNode);
|
||||
|
||||
replaceNode(replacedNode, replacementNode);
|
||||
transaction.commit();
|
||||
}
|
||||
// sync the properties from the stylesheet
|
||||
{
|
||||
RewriterTransaction transaction(m_templateView, "sync-style-node-properties");
|
||||
ModelNode templateNode = m_templateView->modelNodeForId(currentNode.id());
|
||||
applyStyleProperties(templateNode, currentNode);
|
||||
adjustNodeIndex(templateNode);
|
||||
|
||||
/* This we want to do if the parent node in the style is not in the template */
|
||||
if (!currentNode.hasParentProperty() ||
|
||||
!m_templateView->modelNodeForId(currentNode.parentProperty().parentModelNode().id()).isValid()) {
|
||||
|
||||
if (!hasPos) { //If template had postition retain it
|
||||
removePropertyIfExists(templateNode, "x");
|
||||
removePropertyIfExists(templateNode, "y");
|
||||
}
|
||||
if (templateNode.hasProperty("anchors.fill")) {
|
||||
/* Unfortuntly there are cases were width and height have to be defined - see Button
|
||||
* Most likely we need options for this */
|
||||
//removePropertyIfExists(templateNode, "width");
|
||||
//removePropertyIfExists(templateNode, "height");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -297,6 +297,7 @@ Project {
|
||||
"include/rewriterview.h",
|
||||
"include/rewritingexception.h",
|
||||
"include/signalhandlerproperty.h",
|
||||
"include/stylesheetmerger.h",
|
||||
"include/viewmanager.h",
|
||||
"include/subcomponentmanager.h",
|
||||
"include/textmodifier.h",
|
||||
@@ -378,6 +379,7 @@ Project {
|
||||
"model/documentmessage.cpp",
|
||||
"model/rewriterview.cpp",
|
||||
"model/signalhandlerproperty.cpp",
|
||||
"model/stylesheetmerger.cpp",
|
||||
"model/textmodifier.cpp",
|
||||
"model/texttomodelmerger.cpp",
|
||||
"model/texttomodelmerger.h",
|
||||
|
@@ -61,8 +61,10 @@ SOURCES += \
|
||||
../testview.cpp \
|
||||
testrewriterview.cpp \
|
||||
tst_testcore.cpp
|
||||
|
||||
HEADERS += \
|
||||
../testview.h \
|
||||
testrewriterview.h \
|
||||
tst_testcore.h
|
||||
|
||||
RESOURCES += ../data/testfiles.qrc
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include <QScopedPointer>
|
||||
#include <QLatin1String>
|
||||
#include <QGraphicsObject>
|
||||
#include <QQueue>
|
||||
#include <QTest>
|
||||
#include <QVariant>
|
||||
|
||||
@@ -42,6 +43,7 @@
|
||||
#include <nodeinstanceview.h>
|
||||
#include <nodeinstance.h>
|
||||
#include <subcomponentmanager.h>
|
||||
#include <stylesheetmerger.h>
|
||||
#include <QDebug>
|
||||
|
||||
#include "../testview.h"
|
||||
@@ -3704,6 +3706,131 @@ 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);
|
||||
qmlFile.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||
QString qmlFileContents = QString::fromUtf8(qmlFile.readAll());
|
||||
return qmlFileContents;
|
||||
}
|
||||
|
||||
void tst_TestCore::testMergeModelRewriter1_data()
|
||||
{
|
||||
QTest::addColumn<QString>("qmlTemplateString");
|
||||
QTest::addColumn<QString>("qmlStyleString");
|
||||
QTest::addColumn<QString>("qmlExpectedString");
|
||||
|
||||
QString simpleTemplateQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/SimpleTemplate.qml");
|
||||
QString simpleStyleQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/SimpleStyle.qml");
|
||||
QString simpleExpectedQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/SimpleExpected.qml");
|
||||
|
||||
QString complexTemplateQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ComplexTemplate.qml");
|
||||
QString complexStyleQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ComplexStyle.qml");
|
||||
QString complexExpectedQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ComplexExpected.qml");
|
||||
|
||||
QString emptyTemplateQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/EmptyTemplate.qml");
|
||||
QString emptyStyleQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/EmptyStyle.qml");
|
||||
QString emptyExpectedQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/EmptyExpected.qml");
|
||||
|
||||
QString rootReplacementTemplateQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/RootReplacementTemplate.qml");
|
||||
QString rootReplacementStyleQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/RootReplacementStyle.qml");
|
||||
QString rootReplacementExpectedQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/RootReplacementExpected.qml");
|
||||
|
||||
QString switchTemplateQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/SwitchTemplate.qml");
|
||||
QString switchStyleQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/SwitchStyle.qml");
|
||||
QString switchExpectedQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/SwitchExpected.qml");
|
||||
|
||||
QString sliderTemplateQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/SliderTemplate.qml");
|
||||
QString sliderStyleQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/SliderStyle.qml");
|
||||
QString sliderExpectedQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/SliderExpected.qml");
|
||||
|
||||
QString listViewTemplateQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ListViewTemplate.qml");
|
||||
QString listViewStyleQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ListViewStyle.qml");
|
||||
QString listViewExpectedQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ListViewExpected.qml");
|
||||
|
||||
QString buttonTemplateQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ButtonTemplate.qml");
|
||||
QString buttonInlineStyleQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ButtonStyleInline.qml");
|
||||
QString buttonInlineExpectedQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ButtonInlineExpected.qml");
|
||||
|
||||
QString buttonAbsoluteTemplateQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ButtonAbsoluteTemplate.qml");
|
||||
QString buttonOutlineStyleQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ButtonStyleOutline.qml");
|
||||
QString buttonOutlineExpectedQmlContents = readQmlFromFile(QString(TESTSRCDIR) + "/../data/merging/ButtonOutlineExpected.qml");
|
||||
|
||||
QTest::newRow("Simple style replacement") << simpleTemplateQmlContents << simpleStyleQmlContents << simpleExpectedQmlContents;
|
||||
//QTest::newRow("Complex style replacement") << complexTemplateQmlContents << complexStyleQmlContents << complexExpectedQmlContents;
|
||||
QTest::newRow("Empty stylesheet") << emptyTemplateQmlContents << emptyStyleQmlContents << emptyExpectedQmlContents;
|
||||
QTest::newRow("Root node replacement") << rootReplacementTemplateQmlContents << rootReplacementStyleQmlContents << rootReplacementExpectedQmlContents;
|
||||
QTest::newRow("Switch styling") << switchTemplateQmlContents << switchStyleQmlContents << switchExpectedQmlContents;
|
||||
QTest::newRow("Slider styling") << sliderTemplateQmlContents << sliderStyleQmlContents << sliderExpectedQmlContents;
|
||||
QTest::newRow("List View styling") << listViewTemplateQmlContents << listViewStyleQmlContents << listViewExpectedQmlContents;
|
||||
QTest::newRow("Button Inline styling") << buttonTemplateQmlContents << buttonInlineStyleQmlContents << buttonInlineExpectedQmlContents;
|
||||
|
||||
QTest::newRow("Button Outline styling") << buttonAbsoluteTemplateQmlContents << buttonOutlineStyleQmlContents << buttonOutlineExpectedQmlContents;
|
||||
|
||||
}
|
||||
|
||||
void tst_TestCore::testMergeModelRewriter1()
|
||||
{
|
||||
QFETCH(QString, qmlTemplateString);
|
||||
QFETCH(QString, qmlStyleString);
|
||||
QFETCH(QString, qmlExpectedString);
|
||||
|
||||
QPlainTextEdit textEdit1;
|
||||
textEdit1.setPlainText(qmlTemplateString);
|
||||
NotIndentingTextEditModifier textModifier1(&textEdit1);
|
||||
|
||||
QScopedPointer<Model> templateModel(Model::create("QtQuick.Item", 2, 1));
|
||||
QVERIFY(templateModel.data());
|
||||
|
||||
QScopedPointer<TestView> templateView(new TestView(templateModel.data()));
|
||||
templateModel->attachView(templateView.data());
|
||||
|
||||
// read in 1
|
||||
QScopedPointer<TestRewriterView> templateRewriterView(new TestRewriterView());
|
||||
templateRewriterView->setTextModifier(&textModifier1);
|
||||
templateModel->attachView(templateRewriterView.data());
|
||||
|
||||
ModelNode templateRootNode = templateView->rootModelNode();
|
||||
QVERIFY(templateRootNode.isValid());
|
||||
|
||||
QPlainTextEdit textEdit2;
|
||||
textEdit2.setPlainText(qmlStyleString);
|
||||
NotIndentingTextEditModifier textModifier2(&textEdit2);
|
||||
|
||||
QScopedPointer<Model> styleModel(Model::create("QtQuick.Item", 2, 1));
|
||||
QVERIFY(styleModel.data());
|
||||
|
||||
QScopedPointer<TestView> styleView(new TestView(styleModel.data()));
|
||||
styleModel->attachView(styleView.data());
|
||||
|
||||
// read in 2
|
||||
QScopedPointer<TestRewriterView> styleRewriterView(new TestRewriterView());
|
||||
styleRewriterView->setTextModifier(&textModifier2);
|
||||
styleModel->attachView(styleRewriterView.data());
|
||||
|
||||
StylesheetMerger merger(templateView.data(), styleView.data());
|
||||
merger.merge();
|
||||
|
||||
QCOMPARE(textEdit1.toPlainText().trimmed(), qmlExpectedString.trimmed());
|
||||
}
|
||||
|
||||
void tst_TestCore::testCopyModelRewriter2()
|
||||
{
|
||||
const QLatin1String qmlString1("\n"
|
||||
@@ -3756,37 +3883,35 @@ void tst_TestCore::testCopyModelRewriter2()
|
||||
textEdit1.setPlainText(qmlString1);
|
||||
NotIndentingTextEditModifier textModifier1(&textEdit1);
|
||||
|
||||
QScopedPointer<Model> model1(Model::create("QtQuick.Item", 2, 1));
|
||||
QVERIFY(model1.data());
|
||||
QScopedPointer<Model> templateModel(Model::create("QtQuick.Item", 2, 1));
|
||||
QVERIFY(templateModel.data());
|
||||
|
||||
QScopedPointer<TestView> view1(new TestView(model1.data()));
|
||||
model1->attachView(view1.data());
|
||||
QScopedPointer<TestView> view1(new TestView(templateModel.data()));
|
||||
templateModel->attachView(view1.data());
|
||||
|
||||
// read in 1
|
||||
QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView());
|
||||
testRewriterView1->setTextModifier(&textModifier1);
|
||||
model1->attachView(testRewriterView1.data());
|
||||
templateModel->attachView(testRewriterView1.data());
|
||||
|
||||
ModelNode rootNode1 = view1->rootModelNode();
|
||||
QVERIFY(rootNode1.isValid());
|
||||
QCOMPARE(rootNode1.type(), QmlDesigner::TypeName("QtQuick.Rectangle"));
|
||||
|
||||
|
||||
// read in 2
|
||||
|
||||
// read in 2
|
||||
QPlainTextEdit textEdit2;
|
||||
textEdit2.setPlainText(qmlString2);
|
||||
NotIndentingTextEditModifier textModifier2(&textEdit2);
|
||||
|
||||
QScopedPointer<Model> model2(Model::create("QtQuick.Item", 2, 1));
|
||||
QVERIFY(model2.data());
|
||||
QScopedPointer<Model> styleModel(Model::create("QtQuick.Item", 2, 1));
|
||||
QVERIFY(styleModel.data());
|
||||
|
||||
QScopedPointer<TestView> view2(new TestView(model2.data()));
|
||||
model2->attachView(view2.data());
|
||||
QScopedPointer<TestView> view2(new TestView(styleModel.data()));
|
||||
styleModel->attachView(view2.data());
|
||||
|
||||
QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView());
|
||||
testRewriterView2->setTextModifier(&textModifier2);
|
||||
model2->attachView(testRewriterView2.data());
|
||||
QScopedPointer<TestRewriterView> styleRewriterView(new TestRewriterView());
|
||||
styleRewriterView->setTextModifier(&textModifier2);
|
||||
styleModel->attachView(styleRewriterView.data());
|
||||
|
||||
ModelNode rootNode2 = view2->rootModelNode();
|
||||
QVERIFY(rootNode2.isValid());
|
||||
|
@@ -184,6 +184,8 @@ private slots:
|
||||
void testRewriterTransactionRewriter();
|
||||
void testCopyModelRewriter1();
|
||||
void testCopyModelRewriter2();
|
||||
void testMergeModelRewriter1_data();
|
||||
void testMergeModelRewriter1();
|
||||
void testSubComponentManager();
|
||||
void testAnchorsAndRewriting();
|
||||
void testAnchorsAndRewritingCenter();
|
||||
|
@@ -0,0 +1,104 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -0,0 +1,93 @@
|
||||
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
|
||||
width: 100
|
||||
height: 60
|
||||
color: "#d4d4d4"
|
||||
radius: 2
|
||||
border.color: "#808080"
|
||||
border.width: 1
|
||||
anchors.fill: parent
|
||||
Text {
|
||||
id: normalText
|
||||
color: "#808080"
|
||||
text: control.text
|
||||
elide: Text.ElideRight
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: buttonPressed
|
||||
width: 100
|
||||
height: 60
|
||||
color: "#69b5ec"
|
||||
radius: 2
|
||||
border.color: "#808080"
|
||||
border.width: 1
|
||||
anchors.fill: parent
|
||||
Text {
|
||||
id: pressedText
|
||||
color: "#000000"
|
||||
text: control.text
|
||||
elide: Text.ElideRight
|
||||
anchors.fill: parent
|
||||
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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@@ -0,0 +1,97 @@
|
||||
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
|
||||
width: 100
|
||||
height: 60
|
||||
color: "#d4d4d4"
|
||||
radius: 2
|
||||
border.color: "#808080"
|
||||
border.width: 1
|
||||
anchors.fill: parent
|
||||
Text {
|
||||
id: normalText
|
||||
x: 20
|
||||
y: 20
|
||||
color: "#808080"
|
||||
text: control.text
|
||||
elide: Text.ElideRight
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: buttonPressed
|
||||
width: 100
|
||||
height: 60
|
||||
color: "#69b5ec"
|
||||
radius: 2
|
||||
border.color: "#808080"
|
||||
border.width: 1
|
||||
anchors.fill: parent
|
||||
Text {
|
||||
id: pressedText
|
||||
x: 20
|
||||
y: 40
|
||||
color: "#000000"
|
||||
text: control.text
|
||||
elide: Text.ElideRight
|
||||
anchors.fill: parent
|
||||
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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
import QtQuick 2.12
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: artboard
|
||||
width: 640
|
||||
height: 480
|
||||
color: "#ee4040"
|
||||
|
||||
Rectangle {
|
||||
|
||||
id: buttonNormal
|
||||
x: 286
|
||||
y: 62
|
||||
color: "#d4d4d4"
|
||||
width: 100 //Bit of black magic to define the default size
|
||||
height: 60
|
||||
|
||||
border.color: "gray"
|
||||
border.width: 1
|
||||
radius: 2
|
||||
|
||||
Text {
|
||||
id: normalText //id only required to preserve binding
|
||||
//binding has to be preserved
|
||||
anchors.fill: parent //binding has to be preserved
|
||||
color: "gray"
|
||||
text: "Normal"
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
//luckily enums are interpreted as variant properties and not bindings
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: buttonPressed
|
||||
x: 123
|
||||
y: 62
|
||||
color: "#69b5ec"
|
||||
width: 100 //Bit of black magic to define the default size
|
||||
height: 60
|
||||
|
||||
border.color: "gray"
|
||||
border.width: 1
|
||||
radius: 2
|
||||
|
||||
Text {
|
||||
id: pressedText //id only required to preserve binding
|
||||
//binding has to be preserved
|
||||
anchors.fill: parent
|
||||
color: "black"
|
||||
text: "pressed"
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter // should not be preserved -
|
||||
//luckily enums are interpreted as variant properties and not bindings
|
||||
verticalAlignment: Text.AlignVCenter // should not be preserved
|
||||
elide: Text.ElideRight // should not be preserved
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: element
|
||||
x: 1
|
||||
y: 362
|
||||
color: "#eaeaea"
|
||||
text: qsTrId("Some stuff for reference that is thrown away")
|
||||
font.pixelSize: 32
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*##^##
|
||||
Designer {
|
||||
D{i:0;formeditorColor:"#000000"}
|
||||
}
|
||||
##^##*/
|
@@ -0,0 +1,83 @@
|
||||
import QtQuick 2.12
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: artboard
|
||||
width: 640
|
||||
height: 480
|
||||
color: "#ee4040"
|
||||
|
||||
Rectangle {
|
||||
|
||||
id: buttonNormal
|
||||
x: 286
|
||||
y: 62
|
||||
color: "#d4d4d4"
|
||||
width: 100 //Bit of black magic to define the default size
|
||||
height: 60
|
||||
|
||||
border.color: "gray"
|
||||
border.width: 1
|
||||
radius: 2
|
||||
}
|
||||
|
||||
Text {
|
||||
x: 319
|
||||
y: 86
|
||||
id: normalText //id only required to preserve binding
|
||||
//binding has to be preserved
|
||||
|
||||
color: "gray"
|
||||
text: "Normal"
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
//luckily enums are interpreted as variant properties and not bindings
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: buttonPressed
|
||||
x: 123
|
||||
y: 62
|
||||
color: "#69b5ec"
|
||||
width: 100 //Bit of black magic to define the default size
|
||||
height: 60
|
||||
|
||||
border.color: "gray"
|
||||
border.width: 1
|
||||
radius: 2
|
||||
}
|
||||
|
||||
Text {
|
||||
x: 154
|
||||
y: 86
|
||||
id: pressedText //id only required to preserve binding
|
||||
//binding has to be preserved
|
||||
//anchors.fill: parent
|
||||
color: "black"
|
||||
text: "pressed"
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter // should not be preserved -
|
||||
//luckily enums are interpreted as variant properties and not bindings
|
||||
verticalAlignment: Text.AlignVCenter // should not be preserved
|
||||
elide: Text.ElideRight // should not be preserved
|
||||
}
|
||||
|
||||
Text {
|
||||
id: element
|
||||
x: 1
|
||||
y: 362
|
||||
color: "#eaeaea"
|
||||
text: qsTrId("Some stuff for reference that is thrown away")
|
||||
font.pixelSize: 32
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*##^##
|
||||
Designer {
|
||||
D{i:0;formeditorColor:"#000000"}
|
||||
}
|
||||
##^##*/
|
100
tests/auto/qml/qmldesigner/data/merging/ButtonTemplate.qml
Normal file
100
tests/auto/qml/qmldesigner/data/merging/ButtonTemplate.qml
Normal file
@@ -0,0 +1,100 @@
|
||||
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 //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 {
|
||||
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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
62
tests/auto/qml/qmldesigner/data/merging/ComplexExpected.qml
Normal file
62
tests/auto/qml/qmldesigner/data/merging/ComplexExpected.qml
Normal file
@@ -0,0 +1,62 @@
|
||||
import QtQuick 2.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
x: 10;
|
||||
y: 10;
|
||||
Rectangle {
|
||||
id: rectangle0
|
||||
x: 10
|
||||
y: 10
|
||||
width: 200
|
||||
height: 150
|
||||
|
||||
Image {
|
||||
id: rectangle1
|
||||
x: 10
|
||||
y: 10
|
||||
width: 100
|
||||
height: 150
|
||||
source: "qt/icon.png"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rectangle2
|
||||
x: 100;
|
||||
y: 100;
|
||||
anchors.fill: root
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rectangle3
|
||||
x: 140;
|
||||
y: 180;
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "white"
|
||||
}
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
Image {
|
||||
id: rectangle4
|
||||
x: 10
|
||||
y: 20
|
||||
width: 200
|
||||
height: 50
|
||||
Rectangle {
|
||||
id: rectangle5
|
||||
x: 10
|
||||
y: 20
|
||||
width: 200
|
||||
height: 50
|
||||
}
|
||||
source: "qt/realcool.jpg"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
45
tests/auto/qml/qmldesigner/data/merging/ComplexStyle.qml
Normal file
45
tests/auto/qml/qmldesigner/data/merging/ComplexStyle.qml
Normal file
@@ -0,0 +1,45 @@
|
||||
import QtQuick 2.1
|
||||
|
||||
Item {
|
||||
Rectangle {
|
||||
id: rectangle0
|
||||
Image {
|
||||
id: rectangle1
|
||||
x: 10
|
||||
y: 10
|
||||
height: 150
|
||||
width: 100
|
||||
source: "qt/icon.png"
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle3
|
||||
x: 140;
|
||||
y: 180;
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "white"
|
||||
}
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle5
|
||||
x: 10
|
||||
y: 20
|
||||
width: 200
|
||||
height: 50
|
||||
}
|
||||
Image {
|
||||
id: rectangle4
|
||||
x: 10;
|
||||
y: 10;
|
||||
height: 150
|
||||
width: 100
|
||||
source: "qt/realcool.jpg"
|
||||
}
|
||||
}
|
49
tests/auto/qml/qmldesigner/data/merging/ComplexTemplate.qml
Normal file
49
tests/auto/qml/qmldesigner/data/merging/ComplexTemplate.qml
Normal file
@@ -0,0 +1,49 @@
|
||||
import QtQuick 2.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
x: 10;
|
||||
y: 10;
|
||||
Rectangle {
|
||||
id: rectangle0
|
||||
x: 10;
|
||||
y: 10;
|
||||
height: 150
|
||||
width: 200
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle2
|
||||
x: 100;
|
||||
y: 100;
|
||||
anchors.fill: root
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle3
|
||||
x: 140;
|
||||
y: 180;
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "black"
|
||||
}
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle4
|
||||
x: 10
|
||||
y: 20
|
||||
width: 200
|
||||
height: 50
|
||||
Rectangle {
|
||||
id: rectangle5
|
||||
x: 10
|
||||
y: 20
|
||||
width: 200
|
||||
height: 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
// Test that an empty style sheet will leave the original template untouched.
|
||||
import QtQuick 2.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
x: 10;
|
||||
y: 10;
|
||||
Rectangle {
|
||||
id: rectangle0
|
||||
x: 10;
|
||||
y: 10;
|
||||
height: 150
|
||||
width: 200
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle2
|
||||
x: 100;
|
||||
y: 100;
|
||||
anchors.fill: root
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle3
|
||||
x: 140;
|
||||
y: 180;
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "white"
|
||||
}
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle4
|
||||
x: 10
|
||||
y: 20
|
||||
width: 200
|
||||
height: 50
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1 @@
|
||||
import QtQuick 2.1
|
@@ -0,0 +1,43 @@
|
||||
// Test that an empty style sheet will leave the original template untouched.
|
||||
import QtQuick 2.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
x: 10;
|
||||
y: 10;
|
||||
Rectangle {
|
||||
id: rectangle0
|
||||
x: 10;
|
||||
y: 10;
|
||||
height: 150
|
||||
width: 200
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle2
|
||||
x: 100;
|
||||
y: 100;
|
||||
anchors.fill: root
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle3
|
||||
x: 140;
|
||||
y: 180;
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "white"
|
||||
}
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle4
|
||||
x: 10
|
||||
y: 20
|
||||
width: 200
|
||||
height: 50
|
||||
}
|
||||
}
|
||||
}
|
135
tests/auto/qml/qmldesigner/data/merging/ListViewExpected.qml
Normal file
135
tests/auto/qml/qmldesigner/data/merging/ListViewExpected.qml
Normal file
@@ -0,0 +1,135 @@
|
||||
import QtQuick 2.10
|
||||
|
||||
ListView {
|
||||
id: view
|
||||
width: listViewBackground.width
|
||||
height: listViewBackground.height
|
||||
highlight: Rectangle {
|
||||
id: listViewHighLight
|
||||
width: view.width
|
||||
height: 120
|
||||
color: "#343434"
|
||||
radius: 4
|
||||
border.color: "#0d52a4"
|
||||
border.width: 8
|
||||
}
|
||||
|
||||
highlightMoveDuration: 0
|
||||
|
||||
children: [
|
||||
Item {
|
||||
z: -1
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
id: listViewBackground
|
||||
width: 420
|
||||
height: 420
|
||||
color: "#69b5ec"
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
model: ListModel {
|
||||
ListElement {
|
||||
name: "Music"
|
||||
}
|
||||
ListElement {
|
||||
name: "Movies"
|
||||
}
|
||||
ListElement {
|
||||
name: "Camera"
|
||||
}
|
||||
ListElement {
|
||||
name: "Map"
|
||||
}
|
||||
ListElement {
|
||||
name: "Calendar"
|
||||
}
|
||||
ListElement {
|
||||
name: "Messaging"
|
||||
}
|
||||
ListElement {
|
||||
name: "Todo List"
|
||||
}
|
||||
ListElement {
|
||||
name: "Contacts"
|
||||
}
|
||||
ListElement {
|
||||
name: "Settings"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delegate: Item {
|
||||
id: delegate
|
||||
width: ListView.view.width
|
||||
height: delegateNormal.height
|
||||
|
||||
Rectangle {
|
||||
id: delegateNormal
|
||||
width: 420
|
||||
height: 120
|
||||
visible: true
|
||||
color: "#bdbdbd"
|
||||
radius: 4
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
Text {
|
||||
id: labelNormal
|
||||
color: "#343434"
|
||||
text: name
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 24
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: delegateHighlighted
|
||||
width: 420
|
||||
height: 120
|
||||
visible: false
|
||||
color: "#8125eb29"
|
||||
radius: 4
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
Text {
|
||||
id: labelHighlighted
|
||||
color: "#efefef"
|
||||
text: name
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 52
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: delegate.ListView.view.currentIndex = index
|
||||
}
|
||||
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "Highlighted"
|
||||
|
||||
when: delegate.ListView.isCurrentItem
|
||||
PropertyChanges {
|
||||
target: delegateHighlighted
|
||||
visible: true
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: delegateNormal
|
||||
visible: false
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
82
tests/auto/qml/qmldesigner/data/merging/ListViewStyle.qml
Normal file
82
tests/auto/qml/qmldesigner/data/merging/ListViewStyle.qml
Normal file
@@ -0,0 +1,82 @@
|
||||
import QtQuick 2.12
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: artboard
|
||||
width: 800
|
||||
height: 600
|
||||
color: "#ee4040"
|
||||
|
||||
Rectangle {
|
||||
id: listViewBackground
|
||||
x: 19
|
||||
y: 34
|
||||
width: 420
|
||||
height: 420
|
||||
|
||||
color: "#69b5ec"
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: delegateNormal
|
||||
x: 19
|
||||
y: 51
|
||||
color: "#bdbdbd"
|
||||
|
||||
height: 120
|
||||
|
||||
width: 420
|
||||
|
||||
radius: 4
|
||||
Text {
|
||||
id: labelNormal //id required for binding preservation
|
||||
color: "#343434"
|
||||
text: "some text"
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
anchors.margins: 24
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: delegateHighlighted
|
||||
x: 19
|
||||
y: 177
|
||||
color: "#8125eb29"
|
||||
height: 120
|
||||
|
||||
width: 420
|
||||
|
||||
radius: 4
|
||||
Text {
|
||||
id: labelHighlighted //id required for binding preservation
|
||||
color: "#efefef"
|
||||
text: "some text"
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
anchors.margins: 52
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: listViewHighLight
|
||||
x: 19
|
||||
y: 323
|
||||
width: 420
|
||||
height: 120
|
||||
color: "#343434"
|
||||
radius: 4
|
||||
border.color: "#0d52a4"
|
||||
border.width: 8
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
133
tests/auto/qml/qmldesigner/data/merging/ListViewTemplate.qml
Normal file
133
tests/auto/qml/qmldesigner/data/merging/ListViewTemplate.qml
Normal file
@@ -0,0 +1,133 @@
|
||||
import QtQuick 2.10
|
||||
|
||||
ListView {
|
||||
id: view
|
||||
width: listViewBackground.width
|
||||
height: listViewBackground.height
|
||||
|
||||
highlightMoveDuration: 0
|
||||
|
||||
children: [
|
||||
Item {
|
||||
z: -1
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
id: listViewBackground
|
||||
width: 420
|
||||
height: 420
|
||||
|
||||
color: "#d80e0e"
|
||||
anchors.fill: parent // hsa to be preserved
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
model: ListModel {
|
||||
ListElement {
|
||||
name: "Music"
|
||||
}
|
||||
ListElement {
|
||||
name: "Movies"
|
||||
}
|
||||
ListElement {
|
||||
name: "Camera"
|
||||
}
|
||||
ListElement {
|
||||
name: "Map"
|
||||
}
|
||||
ListElement {
|
||||
name: "Calendar"
|
||||
}
|
||||
ListElement {
|
||||
name: "Messaging"
|
||||
}
|
||||
ListElement {
|
||||
name: "Todo List"
|
||||
}
|
||||
ListElement {
|
||||
name: "Contacts"
|
||||
}
|
||||
ListElement {
|
||||
name: "Settings"
|
||||
}
|
||||
}
|
||||
|
||||
highlight: Rectangle {
|
||||
id: listViewHighLight
|
||||
width: view.width // has to be preserved
|
||||
height: 120
|
||||
color: "#343434"
|
||||
radius: 4
|
||||
border.color: "#0d52a4"
|
||||
border.width: 8
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
id: delegate
|
||||
width: ListView.view.width
|
||||
height: delegateNormal.height
|
||||
|
||||
Rectangle {
|
||||
id: delegateNormal
|
||||
color: "#bdbdbd"
|
||||
anchors.fill: parent
|
||||
height: 140
|
||||
anchors.margins: 12
|
||||
visible: true
|
||||
radius: 4
|
||||
Text {
|
||||
id: labelNormal //id required for binding preservation
|
||||
color: "#343434"
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
text: name
|
||||
anchors.margins: 24
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: delegateHighlighted
|
||||
color: "#36bdbdbd"
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
visible: false
|
||||
radius: 4
|
||||
Text {
|
||||
id: labelHighlighted //id required for binding preservation
|
||||
color: "#efefef"
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
text: name
|
||||
anchors.margins: 32
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: delegate.ListView.view.currentIndex = index
|
||||
}
|
||||
states: [
|
||||
State {
|
||||
name: "Highlighted"
|
||||
|
||||
when: delegate.ListView.isCurrentItem
|
||||
PropertyChanges {
|
||||
target: delegateHighlighted
|
||||
visible: true
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: delegateNormal
|
||||
visible: false
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
import QtQuick 2.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
Rectangle {
|
||||
id: rectangle0
|
||||
Image {
|
||||
id: rectangle1
|
||||
x: 10
|
||||
y: 10
|
||||
width: 100
|
||||
height: 150
|
||||
source: "qt/icon.png"
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: rectangle4
|
||||
x: 10
|
||||
y: 10
|
||||
width: 100
|
||||
height: 150
|
||||
source: "qt/realcool.jpg"
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
import QtQuick 2.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
Rectangle {
|
||||
id: rectangle0
|
||||
Image {
|
||||
id: rectangle1
|
||||
x: 10
|
||||
y: 10
|
||||
height: 150
|
||||
width: 100
|
||||
source: "qt/icon.png"
|
||||
}
|
||||
}
|
||||
Image {
|
||||
id: rectangle4
|
||||
x: 10;
|
||||
y: 10;
|
||||
height: 150
|
||||
width: 100
|
||||
source: "qt/realcool.jpg"
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
import QtQuick 2.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
x: 10;
|
||||
y: 10;
|
||||
Rectangle {
|
||||
id: rectangle1
|
||||
x: 10;
|
||||
y: 10;
|
||||
height: 150
|
||||
width: 200
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle2
|
||||
x: 100;
|
||||
y: 100;
|
||||
anchors.fill: root
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle3
|
||||
x: 140;
|
||||
y: 180;
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "white"
|
||||
}
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
tests/auto/qml/qmldesigner/data/merging/SimpleExpected.qml
Normal file
38
tests/auto/qml/qmldesigner/data/merging/SimpleExpected.qml
Normal file
@@ -0,0 +1,38 @@
|
||||
import QtQuick 2.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
x: 10;
|
||||
y: 10;
|
||||
Image {
|
||||
id: rectangle1
|
||||
x: 10
|
||||
y: 10
|
||||
width: 100
|
||||
height: 150
|
||||
source: "qt/icon.png"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rectangle2
|
||||
x: 100;
|
||||
y: 100;
|
||||
anchors.fill: root
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle3
|
||||
x: 140;
|
||||
y: 180;
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "white"
|
||||
}
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
10
tests/auto/qml/qmldesigner/data/merging/SimpleStyle.qml
Normal file
10
tests/auto/qml/qmldesigner/data/merging/SimpleStyle.qml
Normal file
@@ -0,0 +1,10 @@
|
||||
import QtQuick 2.1
|
||||
|
||||
Image {
|
||||
id: rectangle1
|
||||
x: 10;
|
||||
y: 10;
|
||||
height: 150
|
||||
width: 100
|
||||
source: "qt/icon.png"
|
||||
}
|
38
tests/auto/qml/qmldesigner/data/merging/SimpleTemplate.qml
Normal file
38
tests/auto/qml/qmldesigner/data/merging/SimpleTemplate.qml
Normal file
@@ -0,0 +1,38 @@
|
||||
import QtQuick 2.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
x: 10;
|
||||
y: 10;
|
||||
Rectangle {
|
||||
id: rectangle1
|
||||
x: 10;
|
||||
y: 10;
|
||||
height: 150
|
||||
width: 200
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle2
|
||||
x: 100;
|
||||
y: 100;
|
||||
anchors.fill: root
|
||||
}
|
||||
Rectangle {
|
||||
id: rectangle3
|
||||
x: 140;
|
||||
y: 180;
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "white"
|
||||
}
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
68
tests/auto/qml/qmldesigner/data/merging/SliderExpected.qml
Normal file
68
tests/auto/qml/qmldesigner/data/merging/SliderExpected.qml
Normal file
@@ -0,0 +1,68 @@
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
Slider {
|
||||
id: control
|
||||
value: 0.5
|
||||
|
||||
background: Item {
|
||||
x: control.leftPadding
|
||||
y: control.topPadding + control.availableHeight / 2 - height / 2
|
||||
implicitWidth: sliderGroove.width
|
||||
implicitHeight: sliderGroove.height
|
||||
height: implicitHeight
|
||||
width: control.availableWidth
|
||||
|
||||
Rectangle {
|
||||
id: sliderGroove
|
||||
width: 200
|
||||
height: 6
|
||||
color: "#bdbebf"
|
||||
radius: 2
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Item {
|
||||
width: control.visualPosition * sliderGroove.width // should be preserved
|
||||
height: sliderGrooveLeft.height
|
||||
clip: true
|
||||
|
||||
Rectangle {
|
||||
id: sliderGrooveLeft
|
||||
width: 200
|
||||
height: 6
|
||||
color: "#21be2b"
|
||||
radius: 2
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handle: Item {
|
||||
x: control.leftPadding + control.visualPosition * (control.availableWidth - width)
|
||||
y: control.topPadding + control.availableHeight / 2 - height / 2
|
||||
|
||||
implicitWidth: handleNormal.width
|
||||
implicitHeight: handleNormal.height
|
||||
Rectangle {
|
||||
id: handleNormal
|
||||
width: 32
|
||||
height: 32
|
||||
visible: !control.pressed
|
||||
color: "#f6f6f6"
|
||||
radius: 13
|
||||
border.color: "#bdbebf"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: handlePressed
|
||||
width: 32
|
||||
height: 32
|
||||
visible: control.pressed
|
||||
color: "#221bdb"
|
||||
radius: 13
|
||||
border.color: "#bdbebf"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
65
tests/auto/qml/qmldesigner/data/merging/SliderStyle.qml
Normal file
65
tests/auto/qml/qmldesigner/data/merging/SliderStyle.qml
Normal file
@@ -0,0 +1,65 @@
|
||||
import QtQuick 2.12
|
||||
|
||||
|
||||
Item {
|
||||
id: artboard
|
||||
width: 640
|
||||
height: 480
|
||||
|
||||
Rectangle {
|
||||
id: sliderGroove
|
||||
x: 78
|
||||
y: 127
|
||||
width: 200
|
||||
height: 6
|
||||
color: "#bdbebf"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: sliderGrooveLeft
|
||||
x: 78
|
||||
y: 165
|
||||
width: 200
|
||||
height: 6
|
||||
color: "#21be2b"
|
||||
radius: 2
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: handleNormal
|
||||
x: 130
|
||||
y: 74
|
||||
width: 32
|
||||
height: 32
|
||||
radius: 13
|
||||
color: "#f6f6f6"
|
||||
border.color: "#bdbebf"
|
||||
}
|
||||
Rectangle {
|
||||
id: handlePressed
|
||||
x: 78
|
||||
y: 74
|
||||
width: 32
|
||||
height: 32
|
||||
radius: 13
|
||||
color: "#221bdb"
|
||||
border.color: "#bdbebf"
|
||||
}
|
||||
|
||||
Text {
|
||||
id: element
|
||||
x: 8
|
||||
y: 320
|
||||
color: "#eaeaea"
|
||||
text: qsTrId("Some stuff for reference that is thrown away")
|
||||
font.pixelSize: 32
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*##^##
|
||||
Designer {
|
||||
D{i:0;formeditorColor:"#000000"}
|
||||
}
|
||||
##^##*/
|
66
tests/auto/qml/qmldesigner/data/merging/SliderTemplate.qml
Normal file
66
tests/auto/qml/qmldesigner/data/merging/SliderTemplate.qml
Normal file
@@ -0,0 +1,66 @@
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
Slider {
|
||||
id: control
|
||||
value: 0.5
|
||||
|
||||
background: Item {
|
||||
x: control.leftPadding
|
||||
y: control.topPadding + control.availableHeight / 2 - height / 2
|
||||
implicitWidth: sliderGroove.width
|
||||
implicitHeight: sliderGroove.height
|
||||
height: implicitHeight
|
||||
width: control.availableWidth
|
||||
Rectangle {
|
||||
id: sliderGroove
|
||||
|
||||
width: 200
|
||||
height: 4
|
||||
|
||||
anchors.fill: parent // has to be preserved
|
||||
radius: 2
|
||||
color: "#bdbebf"
|
||||
}
|
||||
|
||||
Item {
|
||||
width: control.visualPosition * sliderGroove.width // should be preserved
|
||||
height: sliderGrooveLeft.height
|
||||
clip: true
|
||||
|
||||
Rectangle {
|
||||
id: sliderGrooveLeft
|
||||
width: 200
|
||||
height: 4
|
||||
color: "#21be2b"
|
||||
radius: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handle: Item {
|
||||
x: control.leftPadding + control.visualPosition * (control.availableWidth - width)
|
||||
y: control.topPadding + control.availableHeight / 2 - height / 2
|
||||
|
||||
implicitWidth: handleNormal.width
|
||||
implicitHeight: handleNormal.height
|
||||
Rectangle {
|
||||
id: handleNormal
|
||||
width: 26
|
||||
height: 26
|
||||
radius: 13
|
||||
color: "#f6f6f6"
|
||||
visible: !control.pressed //has to be preserved
|
||||
border.color: "#bdbebf"
|
||||
}
|
||||
Rectangle {
|
||||
id: handlePressed
|
||||
width: 26
|
||||
height: 26
|
||||
radius: 13
|
||||
visible: control.pressed //has to be preserved
|
||||
color: "#f0f0f0"
|
||||
border.color: "#bdbebf"
|
||||
}
|
||||
}
|
||||
}
|
111
tests/auto/qml/qmldesigner/data/merging/SwitchExpected.qml
Normal file
111
tests/auto/qml/qmldesigner/data/merging/SwitchExpected.qml
Normal file
@@ -0,0 +1,111 @@
|
||||
import QtQuick 2.10
|
||||
import QtQuick.Templates 2.1 as T
|
||||
import TemplateMerging 1.0
|
||||
|
||||
T.Switch {
|
||||
id: control
|
||||
|
||||
implicitWidth: background.implicitWidth
|
||||
implicitHeight: background.implicitHeight
|
||||
|
||||
text: "test"
|
||||
indicator: Rectangle {
|
||||
id: switchIndicator
|
||||
x: control.leftPadding
|
||||
y: 34
|
||||
width: 64
|
||||
height: 44
|
||||
color: "#e9e9e9"
|
||||
radius: 16
|
||||
border.color: "#dddddd"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Rectangle {
|
||||
id: switchHandle
|
||||
width: 31
|
||||
height: 44
|
||||
color: "#e9e9e9"
|
||||
radius: 16
|
||||
border.color: "#808080"
|
||||
}
|
||||
}
|
||||
|
||||
background: Item {
|
||||
implicitWidth: switchBackground.width
|
||||
implicitHeight: switchBackground.height
|
||||
|
||||
Rectangle {
|
||||
id: switchBackground
|
||||
width: 144
|
||||
height: 52
|
||||
color: "#c2c2c2"
|
||||
border.color: "#808080"
|
||||
anchors.fill: parent
|
||||
|
||||
Text {
|
||||
text: "background"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 12
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leftPadding: 4
|
||||
|
||||
contentItem: Item { //designer want to edit the label as part of background
|
||||
}
|
||||
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "off"
|
||||
when: !control.checked && !control.down
|
||||
},
|
||||
State {
|
||||
name: "on"
|
||||
when: control.checked && !control.down
|
||||
|
||||
PropertyChanges {
|
||||
target: switchIndicator
|
||||
color: "#1713de"
|
||||
border.color: "#1713de"
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: switchHandle
|
||||
x: parent.width - width
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "off_down"
|
||||
when: !control.checked && control.down
|
||||
|
||||
PropertyChanges {
|
||||
target: switchIndicator
|
||||
color: "#e9e9e9"
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: switchHandle
|
||||
color: "#d2d2d2"
|
||||
border.color: "#d2d2d2"
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "on_down"
|
||||
when: control.checked && control.down
|
||||
|
||||
PropertyChanges {
|
||||
target: switchHandle
|
||||
x: parent.width - width
|
||||
color: "#e9e9e9"
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: switchIndicator
|
||||
color: "#030381"
|
||||
border.color: "#030381"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
66
tests/auto/qml/qmldesigner/data/merging/SwitchStyle.qml
Normal file
66
tests/auto/qml/qmldesigner/data/merging/SwitchStyle.qml
Normal file
@@ -0,0 +1,66 @@
|
||||
import QtQuick 2.12
|
||||
|
||||
Item {
|
||||
width: 640
|
||||
height: 480
|
||||
|
||||
Rectangle {
|
||||
id: switchIndicator
|
||||
x: 219
|
||||
y: 34
|
||||
width: 64
|
||||
height: 44
|
||||
|
||||
color: "#e9e9e9"
|
||||
|
||||
radius: 16
|
||||
border.color: "#dddddd"
|
||||
|
||||
Rectangle {
|
||||
id: switchHandle //id is required for states
|
||||
|
||||
width: 31
|
||||
height: 44
|
||||
radius: 16
|
||||
color: "#e9e9e9"
|
||||
border.color: "#808080"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: switchBackground
|
||||
x: 346
|
||||
y: 27
|
||||
width: 144
|
||||
height: 52
|
||||
color: "#c2c2c2"
|
||||
border.color: "#808080"
|
||||
|
||||
Text {
|
||||
id: switchBackgroundText
|
||||
text: "background"
|
||||
anchors.right: parent.right
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.rightMargin: 12
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: element
|
||||
x: 1
|
||||
y: 362
|
||||
color: "#eaeaea"
|
||||
text: qsTrId("Some stuff for reference that is thrown away")
|
||||
font.pixelSize: 32
|
||||
}
|
||||
|
||||
Rectangle { //This is ignored when merging
|
||||
id: weirdStuff02
|
||||
x: 8
|
||||
y: 87
|
||||
width: 624
|
||||
height: 200
|
||||
color: "#ffffff"
|
||||
}
|
||||
}
|
120
tests/auto/qml/qmldesigner/data/merging/SwitchTemplate.qml
Normal file
120
tests/auto/qml/qmldesigner/data/merging/SwitchTemplate.qml
Normal file
@@ -0,0 +1,120 @@
|
||||
import QtQuick 2.10
|
||||
import QtQuick.Templates 2.1 as T
|
||||
import TemplateMerging 1.0
|
||||
|
||||
T.Switch {
|
||||
id: control
|
||||
|
||||
implicitWidth: background.implicitWidth
|
||||
implicitHeight: background.implicitHeight
|
||||
|
||||
text: "test"
|
||||
|
||||
background: Item {
|
||||
implicitWidth: switchBackground.width
|
||||
implicitHeight: switchBackground.height
|
||||
Rectangle {
|
||||
id: switchBackground
|
||||
color: "#ef1d1d"
|
||||
border.color: "#808080"
|
||||
width: 12 * 6.0
|
||||
height: 12 * 3.8
|
||||
anchors.fill: parent // has to be preserved
|
||||
Text {
|
||||
id: switchBackgroundText
|
||||
anchors.right: parent.right // does have to be preserved -- how to handle this? - anchors preference from style if not "root"?
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter // does have to be preserved -- how to handle this? - anchors preference from style if not "root"?
|
||||
text: control.text // has to be preserved
|
||||
anchors.rightMargin: 12 * 5
|
||||
}
|
||||
Rectangle {
|
||||
id: nonSenseRectangle
|
||||
width: 5 * 12.0
|
||||
height: 6 * 49.0
|
||||
color: "#ff0000"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leftPadding: 4
|
||||
|
||||
contentItem: Item { //designer want to edit the label as part of background
|
||||
}
|
||||
|
||||
|
||||
indicator: Rectangle {
|
||||
id: switchIndicator
|
||||
width: 58
|
||||
height: 31
|
||||
x: control.leftPadding // has to be preserved
|
||||
color: "#e9e9e9"
|
||||
anchors.verticalCenter: parent.verticalCenter // has to be preserved
|
||||
radius: 16
|
||||
border.color: "#dddddd"
|
||||
|
||||
Rectangle {
|
||||
id: switchHandle //id is required for states
|
||||
|
||||
width: 31
|
||||
height: 31
|
||||
radius: 16
|
||||
color: "#e9e9e9"
|
||||
border.color: "#808080"
|
||||
}
|
||||
}
|
||||
states: [
|
||||
State {
|
||||
name: "off"
|
||||
when: !control.checked && !control.down
|
||||
},
|
||||
State {
|
||||
name: "on"
|
||||
when: control.checked && !control.down
|
||||
|
||||
PropertyChanges {
|
||||
target: switchIndicator
|
||||
color: "#1713de"
|
||||
border.color: "#1713de"
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: switchHandle
|
||||
x: parent.width - width
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "off_down"
|
||||
when: !control.checked && control.down
|
||||
|
||||
PropertyChanges {
|
||||
target: switchIndicator
|
||||
color: "#e9e9e9"
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: switchHandle
|
||||
color: "#d2d2d2"
|
||||
border.color: "#d2d2d2"
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "on_down"
|
||||
when: control.checked && control.down
|
||||
|
||||
PropertyChanges {
|
||||
target: switchHandle
|
||||
x: parent.width - width
|
||||
color: "#e9e9e9"
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: switchIndicator
|
||||
color: "#030381"
|
||||
border.color: "#030381"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user