Commit 8fa642d8 authored by Thomas Hartmann's avatar Thomas Hartmann
Browse files

QuickDesigner.core: Allow any property to be a parent property

After this change, the parent properties of model nodes do not have
to be "data" or "children" anymore. Any node or node list property
can contain children.

original author: Joerg Schummer

I did some changes to the patch.
1.) Fix for NodeMetaInfo
2.) Remove changes to ObjectNodeInstance
3.) Adapt QmlObjectNode
parent c05bd6c7
......@@ -41,18 +41,22 @@ using namespace QmlDesigner::Internal;
using namespace QmlDesigner;
MoveObjectBeforeObjectVisitor::MoveObjectBeforeObjectVisitor(TextModifier &modifier,
quint32 movingObjectLocation):
quint32 movingObjectLocation,
bool inDefaultProperty):
QMLRewriter(modifier),
movingObjectLocation(movingObjectLocation),
inDefaultProperty(inDefaultProperty),
toEnd(true),
beforeObjectLocation(0)
{}
MoveObjectBeforeObjectVisitor::MoveObjectBeforeObjectVisitor(TextModifier &modifier,
quint32 movingObjectLocation,
quint32 beforeObjectLocation):
quint32 beforeObjectLocation,
bool inDefaultProperty):
QMLRewriter(modifier),
movingObjectLocation(movingObjectLocation),
inDefaultProperty(inDefaultProperty),
toEnd(false),
beforeObjectLocation(beforeObjectLocation)
{}
......@@ -108,12 +112,41 @@ void MoveObjectBeforeObjectVisitor::doMove()
Q_ASSERT(!movingObjectParents.isEmpty());
TextModifier::MoveInfo moveInfo;
Node *parent = movingObjectParent();
UiArrayMemberList *arrayMember = 0, *otherArrayMember;
QString separator;
if (!inDefaultProperty) {
UiArrayBinding *initializer = cast<UiArrayBinding*>(parent);
Q_ASSERT(initializer);
otherArrayMember = 0;
for (UiArrayMemberList *cur = initializer->members; cur; cur = cur->next) {
if (cur->member == movingObject) {
arrayMember = cur;
if (cur->next)
otherArrayMember = cur->next;
break;
}
otherArrayMember = cur;
}
Q_ASSERT(arrayMember && otherArrayMember);
separator = QLatin1String(",");
}
int start = movingObject->firstSourceLocation().offset;
int end = movingObject->lastSourceLocation().end();
moveInfo.objectStart = start;
moveInfo.objectEnd = end;
moveInfo.objectStart = movingObject->firstSourceLocation().offset;
moveInfo.objectEnd = movingObject->lastSourceLocation().end();
int start = moveInfo.objectStart;
int end = moveInfo.objectEnd;
if (!inDefaultProperty) {
if (arrayMember->commaToken.isValid()) {
start = arrayMember->commaToken.begin();
}
else {
end = otherArrayMember->commaToken.end();
}
}
includeSurroundingWhitespace(start, end);
moveInfo.leadingCharsToRemove = moveInfo.objectStart - start;
......@@ -125,7 +158,7 @@ void MoveObjectBeforeObjectVisitor::doMove()
includeSurroundingWhitespace(moveInfo.destination, dummy);
moveInfo.prefixToInsert = QString(moveInfo.leadingCharsToRemove, QLatin1Char(' '));
moveInfo.suffixToInsert = QLatin1String("\n\n");
moveInfo.suffixToInsert = separator + QLatin1String("\n\n");
} else {
const SourceLocation insertionPoint = lastParentLocation();
Q_ASSERT(insertionPoint.isValid());
......@@ -133,7 +166,7 @@ void MoveObjectBeforeObjectVisitor::doMove()
int dummy = -1;
includeSurroundingWhitespace(moveInfo.destination, dummy);
moveInfo.prefixToInsert = QString(moveInfo.leadingCharsToRemove, QLatin1Char(' '));
moveInfo.prefixToInsert = separator + QString(moveInfo.leadingCharsToRemove, QLatin1Char(' '));
moveInfo.suffixToInsert = QLatin1String("\n");
}
......@@ -141,18 +174,23 @@ void MoveObjectBeforeObjectVisitor::doMove()
setDidRewriting(true);
}
SourceLocation MoveObjectBeforeObjectVisitor::lastParentLocation() const
Node *MoveObjectBeforeObjectVisitor::movingObjectParent() const
{
dump(movingObjectParents);
Node *parent;
if (movingObjectParents.size() > 1)
parent = movingObjectParents.at(movingObjectParents.size() - 2);
return movingObjectParents.at(movingObjectParents.size() - 2);
else
parent = 0;
return 0;
}
SourceLocation MoveObjectBeforeObjectVisitor::lastParentLocation() const
{
dump(movingObjectParents);
Node *parent = movingObjectParent();
if (UiObjectInitializer *initializer = cast<UiObjectInitializer*>(parent))
return initializer->rbraceToken;
else if (UiArrayBinding *initializer = cast<UiArrayBinding*>(parent))
return initializer->rbracketToken;
else
return SourceLocation();
}
......@@ -41,10 +41,12 @@ class MoveObjectBeforeObjectVisitor: public QMLRewriter
{
public:
MoveObjectBeforeObjectVisitor(QmlDesigner::TextModifier &modifier,
quint32 movingObjectLocation);
quint32 movingObjectLocation,
bool inDefaultProperty);
MoveObjectBeforeObjectVisitor(QmlDesigner::TextModifier &modifier,
quint32 movingObjectLocation,
quint32 beforeObjectLocation);
quint32 beforeObjectLocation,
bool inDefaultProperty);
bool operator ()(QmlJS::AST::UiProgram *ast);
......@@ -60,11 +62,13 @@ private:
void doMove();
QmlJS::AST::Node *movingObjectParent() const;
QmlJS::AST::SourceLocation lastParentLocation() const;
private:
QStack<QmlJS::AST::Node *> parents;
quint32 movingObjectLocation;
bool inDefaultProperty;
bool toEnd;
quint32 beforeObjectLocation;
......
......@@ -128,6 +128,8 @@ private:
moveInfo.destination = ast->lbraceToken.end();
}
move(moveInfo);
setDidRewriting(true);
}
}
......@@ -145,7 +147,8 @@ private:
Q_ASSERT(!"Invalid QML: empty array found.");
moveInfo.destination = lastMember->lastSourceLocation().end();
moveInfo.suffixToInsert = QLatin1String(",\n");
moveInfo.prefixToInsert = QLatin1String(",\n");
moveInfo.suffixToInsert = QLatin1String("\n");
move(moveInfo);
}
......@@ -195,6 +198,7 @@ bool MoveObjectVisitor::visit(UiArrayBinding *ast)
if (currentMember) {
TextModifier::MoveInfo moveInfo;
moveInfo.objectStart = currentMember->member->firstSourceLocation().begin();
moveInfo.objectEnd = currentMember->member->lastSourceLocation().end();
if (currentMember == ast->members && !currentMember->next) {
......@@ -237,6 +241,7 @@ bool MoveObjectVisitor::visit(UiObjectBinding *ast)
if (ast->qualifiedTypeNameId->identifierToken.offset == objectLocation) {
TextModifier::MoveInfo moveInfo;
moveInfo.objectStart = objectLocation;
moveInfo.objectEnd = ast->lastSourceLocation().end();
// remove leading indentation and property name:
......
......@@ -138,16 +138,16 @@ bool QmlRefactoring::moveObject(int objectLocation, const QString &targetPropert
return visit(qmlDocument->qmlProgram());
}
bool QmlRefactoring::moveObjectBeforeObject(int movingObjectLocation, int beforeObjectLocation)
bool QmlRefactoring::moveObjectBeforeObject(int movingObjectLocation, int beforeObjectLocation, bool inDefaultProperty)
{
if (movingObjectLocation < 0 || beforeObjectLocation < -1)
return false;
if (beforeObjectLocation == -1) {
MoveObjectBeforeObjectVisitor visit(*textModifier, movingObjectLocation);
MoveObjectBeforeObjectVisitor visit(*textModifier, movingObjectLocation, inDefaultProperty);
return visit(qmlDocument->qmlProgram());
} else {
MoveObjectBeforeObjectVisitor visit(*textModifier, movingObjectLocation, beforeObjectLocation);
MoveObjectBeforeObjectVisitor visit(*textModifier, movingObjectLocation, beforeObjectLocation, inDefaultProperty);
return visit(qmlDocument->qmlProgram());
}
return false;
......
......@@ -65,7 +65,7 @@ public:
bool changeObjectType(int nodeLocation, const QString &newType);
bool moveObject(int objectLocation, const QString &targetPropertyName, bool targetIsArray, int targetParentObjectLocation);
bool moveObjectBeforeObject(int movingObjectLocation, int beforeObjectLocation);
bool moveObjectBeforeObject(int movingObjectLocation, int beforeObjectLocation, bool inDefaultProperty);
bool removeObject(int nodeLocation);
bool removeProperty(int parentLocation, const QString &name);
......
......@@ -56,6 +56,8 @@ public:
QmlModelStateGroup states() const;
QList<QmlItemNode> children() const;
QList<QmlObjectNode> resources() const;
QList<QmlObjectNode> defaultPropertyChildren() const;
QList<QmlObjectNode> allDirectSubNodes() const;
QmlAnchors anchors() const;
bool hasChildren() const;
......
......@@ -89,6 +89,9 @@ public:
bool isAncestorOf(const QmlObjectNode &objectNode) const;
bool hasDefaultProperty() const;
QString defaultProperty() const;
static QVariant instanceValue(const ModelNode &modelNode, const QString &name);
protected:
......
......@@ -503,7 +503,7 @@ bool NodeMetaInfo::hasDefaultProperty() const
return false;
}
return m_data->defaultProperty.isNull();
return !m_data->defaultProperty.isNull();
}
QString NodeMetaInfo::defaultProperty() const
......
......@@ -150,7 +150,7 @@ void ModelToTextMerger::nodeReparented(const ModelNode &node, const NodeAbstract
{
if (isInHierarchy(oldPropertyParent) && isInHierarchy(newPropertyParent)) { // the node is moved
schedule(new ReparentNodeRewriteAction(node,
oldPropertyParent.parentModelNode(),
oldPropertyParent,
newPropertyParent,
propertyType(newPropertyParent)));
} else if (isInHierarchy(oldPropertyParent) && !isInHierarchy(newPropertyParent)) { // the node is removed from hierarchy
......
......@@ -32,6 +32,7 @@
#include <QDeclarativeView>
#include "qmlchangeset.h"
#include "variantproperty.h"
#include "nodeproperty.h"
#include "nodelistproperty.h"
#include "nodeinstance.h"
#include "qmlanchors.h"
......@@ -123,6 +124,36 @@ QList<QmlObjectNode> QmlItemNode::resources() const
modelNodeList.append(modelNode().nodeListProperty("data").toModelNodeList());
}
foreach (const ModelNode &node, modelNodeList) {
if (!QmlObjectNode(node).isValid()) //if ModelNode is no FxItem
returnList.append(node);
}
}
return returnList;
}
QList<QmlObjectNode> QmlItemNode::defaultPropertyChildren() const
{
QList<QmlObjectNode> returnList;
if (isValid()) {
QList<ModelNode> modelNodeList;
if (modelNode().property(defaultProperty()).isNodeListProperty())
modelNodeList.append(modelNode().nodeListProperty(defaultProperty()).toModelNodeList());
foreach (const ModelNode &node, modelNodeList) {
if (!QmlObjectNode(node).isValid()) //if ModelNode is no FxItem
returnList.append(node);
}
}
return returnList;
}
QList<QmlObjectNode> QmlItemNode::allDirectSubNodes() const
{
QList<QmlObjectNode> returnList;
if (isValid()) {
QList<ModelNode> modelNodeList = modelNode().allDirectSubModelNodes();
foreach (const ModelNode &node, modelNodeList) {
if (!QmlItemNode(node).isValid()) //if ModelNode is no FxItem
returnList.append(node);
......
......@@ -196,7 +196,9 @@ QmlItemNode QmlModelView::createQmlItemNode(const ItemLibraryEntry &itemLibraryE
propertyPairList.append(qMakePair(property.name(), property.value()));
newNode = createQmlItemNode(itemLibraryEntry.typeName(), itemLibraryEntry.majorVersion(), itemLibraryEntry.minorVersion(), propertyPairList);
parentNode.nodeAbstractProperty("data").reparentHere(newNode);
if (parentNode.hasDefaultProperty()) {
parentNode.nodeAbstractProperty(parentNode.defaultProperty()).reparentHere(newNode);
}
Q_ASSERT(newNode.isValid());
......
......@@ -37,6 +37,7 @@
#include "qmlmodelview.h"
#include "nodeinstanceview.h"
#include "nodeinstance.h"
#include "nodemetainfo.h"
namespace QmlDesigner {
......@@ -432,10 +433,21 @@ QString QmlObjectNode::validId()
return modelNode().validId();
}
bool QmlObjectNode::hasDefaultProperty() const
{
return modelNode().metaInfo().hasDefaultProperty();
}
QString QmlObjectNode::defaultProperty() const
{
return modelNode().metaInfo().defaultProperty();
}
void QmlObjectNode::setParent(QmlObjectNode newParent)
{
newParent.modelNode().nodeListProperty("data").reparentHere(modelNode());
//TODO use metasystem for default Property
if (newParent.hasDefaultProperty()) {
newParent.modelNode().nodeAbstractProperty(newParent.defaultProperty()).reparentHere(modelNode());
}
}
QmlItemNode QmlObjectNode::toQmlItemNode() const
......
......@@ -31,6 +31,8 @@
#include "nodeabstractproperty.h"
#include "nodelistproperty.h"
#include "propertymetainfo.h"
#include "nodemetainfo.h"
#include "rewriteaction.h"
using namespace QmlDesigner;
......@@ -325,7 +327,9 @@ bool MoveNodeRewriteAction::execute(QmlRefactoring &refactoring,
const int newTrailingNodeLocation = m_newTrailingNode.isValid() ? positionStore.nodeOffset(m_newTrailingNode) : -1;
bool result = false;
result = refactoring.moveObjectBeforeObject(movingNodeLocation, newTrailingNodeLocation);
bool inDefaultProperty = (m_movingNode.parentProperty().parentModelNode().metaInfo().defaultProperty() == m_movingNode.parentProperty().name());
result = refactoring.moveObjectBeforeObject(movingNodeLocation, newTrailingNodeLocation, inDefaultProperty);
if (!result) {
qDebug() << "*** MoveNodeRewriteAction::execute failed in moveObjectBeforeObject("
<< movingNodeLocation << ','
......
......@@ -218,8 +218,8 @@ private:
class ReparentNodeRewriteAction: public RewriteAction
{
public:
ReparentNodeRewriteAction(const ModelNode &node, const ModelNode &oldParent, const AbstractProperty &targetProperty, QmlDesigner::QmlRefactoring::PropertyType propertyType):
m_node(node), m_oldParent(oldParent), m_targetProperty(targetProperty), m_propertyType(propertyType)
ReparentNodeRewriteAction(const ModelNode &node, const AbstractProperty &oldParentProperty, const AbstractProperty &targetProperty, QmlDesigner::QmlRefactoring::PropertyType propertyType):
m_node(node), m_oldParentProperty(oldParentProperty), m_targetProperty(targetProperty), m_propertyType(propertyType)
{}
virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
......@@ -230,11 +230,11 @@ public:
ModelNode reparentedNode() const
{ return m_node; }
ModelNode oldParent() const
{ return m_oldParent; }
void setOldParentProperty(const AbstractProperty &oldParentProperty)
{ m_oldParentProperty = oldParentProperty; }
void setOldParent(const ModelNode &oldParent)
{ m_oldParent = oldParent; }
AbstractProperty oldParentProperty() const
{ return m_oldParentProperty; }
AbstractProperty targetProperty() const
{ return m_targetProperty; }
......@@ -244,7 +244,7 @@ public:
private:
ModelNode m_node;
ModelNode m_oldParent;
AbstractProperty m_oldParentProperty;
AbstractProperty m_targetProperty;
QmlDesigner::QmlRefactoring::PropertyType m_propertyType;
};
......
......@@ -58,7 +58,7 @@ void RewriteActionCompressor::operator()(QList<RewriteAction *> &actions) const
{
compressImports(actions);
compressRereparentActions(actions);
compressReparentIntoSameParentActions(actions);
compressReparentIntoSamePropertyActions(actions);
compressPropertyActions(actions);
compressAddEditRemoveNodeActions(actions);
compressAddEditActions(actions);
......@@ -126,7 +126,7 @@ void RewriteActionCompressor::compressRereparentActions(QList<RewriteAction *> &
const ModelNode reparentedNode = reparentAction->reparentedNode();
if (ReparentNodeRewriteAction *otherAction = reparentedNodes.value(reparentedNode, 0)) {
otherAction->setOldParent(reparentAction->oldParent());
otherAction->setOldParentProperty(reparentAction->oldParentProperty());
actionsToRemove.append(action);
} else {
reparentedNodes.insert(reparentedNode, reparentAction);
......@@ -140,7 +140,7 @@ void RewriteActionCompressor::compressRereparentActions(QList<RewriteAction *> &
}
}
void RewriteActionCompressor::compressReparentIntoSameParentActions(QList<RewriteAction *> &actions) const
void RewriteActionCompressor::compressReparentIntoSamePropertyActions(QList<RewriteAction *> &actions) const
{
QList<RewriteAction *> actionsToRemove;
QMutableListIterator<RewriteAction *> iter(actions);
......@@ -149,9 +149,7 @@ void RewriteActionCompressor::compressReparentIntoSameParentActions(QList<Rewrit
RewriteAction *action = iter.previous();
if (ReparentNodeRewriteAction *reparentAction = action->asReparentNodeRewriteAction()) {
const ModelNode targetNode = reparentAction->targetProperty().parentModelNode();
const ModelNode oldParent = reparentAction->oldParent();
if (targetNode == oldParent)
if (reparentAction->targetProperty() == reparentAction->oldParentProperty())
actionsToRemove.append(action);
}
}
......
......@@ -48,7 +48,7 @@ private:
void compressImports(QList<RewriteAction *> &actions) const;
void compressRereparentActions(QList<RewriteAction *> &actions) const;
void compressReparentIntoSameParentActions(QList<RewriteAction *> &actions) const;
void compressReparentIntoSamePropertyActions(QList<RewriteAction *> &actions) const;
void compressAddEditRemoveNodeActions(QList<RewriteAction *> &actions) const;
void compressPropertyActions(QList<RewriteAction *> &actions) const;
void compressAddEditActions(QList<RewriteAction *> &actions) const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment