Commit faa59b75 authored by Thomas Hartmann's avatar Thomas Hartmann
Browse files

QmlDesigner.Model: add support for custom parser types

This patch enables us to create objects with custom parsers
like ListModel and XmlListModel.
parent 749d559a
......@@ -49,13 +49,14 @@ class InstanceContainer
public:
InstanceContainer();
InstanceContainer(qint32 instanceId, const QString &type, int majorNumber, int minorNumber, const QString &componentPath);
InstanceContainer(qint32 instanceId, const QString &type, int majorNumber, int minorNumber, const QString &componentPath, const QString &customParserSource);
qint32 instanceId() const;
QString type() const;
int majorNumber() const;
int minorNumber() const;
QString componentPath() const;
QString customParserSource() const;
private:
qint32 m_instanceId;
......@@ -63,6 +64,7 @@ private:
int m_majorNumber;
int m_minorNumber;
QString m_componentPath;
QString m_customParserSource;
};
} // namespace QmlDesigner
......
......@@ -17,6 +17,7 @@ HEADERS += $$PWD/addimportcommand.h
HEADERS += $$PWD/changebindingscommand.h
HEADERS += $$PWD/changefileurlcommand.h
HEADERS += $$PWD/changeidscommand.h
HEADERS += $$PWD/changecustomparsersourcecommand.h
HEADERS += $$PWD/changestatecommand.h
HEADERS += $$PWD/changevaluescommand.h
HEADERS += $$PWD/childrenchangeeventfilter.h
......@@ -66,6 +67,7 @@ SOURCES += $$PWD/addimportcommand.cpp
SOURCES += $$PWD/changebindingscommand.cpp
SOURCES += $$PWD/changefileurlcommand.cpp
SOURCES += $$PWD/changeidscommand.cpp
SOURCES += $$PWD/changecustomparsersourcecommand.cpp
SOURCES += $$PWD/changestatecommand.cpp
SOURCES += $$PWD/changevaluescommand.cpp
SOURCES += $$PWD/childrenchangeeventfilter.cpp
......
......@@ -67,6 +67,7 @@
#include "imagecontainer.h"
#include "statepreviewimagechangedcommand.h"
#include "componentcompletedcommand.h"
#include "changecustomparsersourcecommand.h"
namespace QmlDesigner {
......@@ -263,6 +264,11 @@ void NodeInstanceClientProxy::completeComponent(const CompleteComponentCommand &
nodeInstanceServer()->completeComponent(command);
}
void NodeInstanceClientProxy::changeCustomParserSource(ChangeCustomParserSourceCommand &command)
{
nodeInstanceServer()->changeCustomParserSource(command);
}
void NodeInstanceClientProxy::dispatchCommand(const QVariant &command)
{
static const int createInstancesCommandType = QMetaType::type("CreateInstancesCommand");
......@@ -279,6 +285,7 @@ void NodeInstanceClientProxy::dispatchCommand(const QVariant &command)
static const int addImportCommandType = QMetaType::type("AddImportCommand");
static const int completeComponentCommandType = QMetaType::type("CompleteComponentCommand");
static const int synchronizeCommandType = QMetaType::type("SynchronizeCommand");
static const int changeCustomParserSourceCommandType = QMetaType::type("ChangeCustomParserSourceCommand");
if (command.userType() == createInstancesCommandType) {
createInstances(command.value<CreateInstancesCommand>());
......@@ -306,6 +313,8 @@ void NodeInstanceClientProxy::dispatchCommand(const QVariant &command)
addImport(command.value<AddImportCommand>());
else if (command.userType() == completeComponentCommandType)
completeComponent(command.value<CompleteComponentCommand>());
else if (command.userType() == changeCustomParserSourceCommandType)
changeCustomParserSource(command.value<ChangeCustomParserSourceCommand>());
else if (command.userType() == synchronizeCommandType) {
SynchronizeCommand synchronizeCommand = command.value<SynchronizeCommand>();
m_synchronizeId = synchronizeCommand.synchronizeId();
......
......@@ -59,6 +59,7 @@ class RemovePropertiesCommand;
class AddImportCommand;
class CompleteComponentCommand;
class ChangeStateCommand;
class ChangeCustomParserSourceCommand;
class NodeInstanceClientProxy : public QObject, public NodeInstanceClientInterface
{
......@@ -72,7 +73,7 @@ public:
void pixmapChanged(const PixmapChangedCommand &command);
void childrenChanged(const ChildrenChangedCommand &command);
void statePreviewImagesChanged(const StatePreviewImageChangedCommand &command);
void componentCompleted(const ComponentCompletedCommand &command);
void componentCompleted(const ComponentCompletedCommand &command);
void flush();
void synchronizeWithClientProcess();
......@@ -96,6 +97,7 @@ protected:
void changeState(const ChangeStateCommand &command);
void addImport(const AddImportCommand &command);
void completeComponent(const CompleteComponentCommand &command);
void changeCustomParserSource(ChangeCustomParserSourceCommand &command);
private slots:
void readDataStream();
......
......@@ -76,6 +76,7 @@
#include "completecomponentcommand.h"
#include "componentcompletedcommand.h"
#include "createscenecommand.h"
#include "changecustomparsersourcecommand.h"
#include "dummycontextobject.h"
......@@ -345,6 +346,16 @@ void NodeInstanceServer::completeComponent(const CompleteComponentCommand &comma
startRenderTimer();
}
void NodeInstanceServer::changeCustomParserSource(ChangeCustomParserSourceCommand &command)
{
if (hasInstanceForId(command.instanceId())) {
ServerNodeInstance instance = instanceForId(command.instanceId());
;
}
startRenderTimer();
}
void NodeInstanceServer::addImports(const QVector<AddImportContainer> &containerVector)
{
foreach (const AddImportContainer &container, containerVector) {
......
......@@ -90,6 +90,7 @@ public:
void changeState(const ChangeStateCommand &command);
void addImport(const AddImportCommand &command);
void completeComponent(const CompleteComponentCommand &command);
void changeCustomParserSource(ChangeCustomParserSourceCommand &command);
ServerNodeInstance instanceForId(qint32 id) const;
bool hasInstanceForId(qint32 id) const;
......
......@@ -50,6 +50,7 @@
#include "changestatecommand.h"
#include "completecomponentcommand.h"
#include "addimportcontainer.h"
#include "changecustomparsersourcecommand.h"
#include "informationchangedcommand.h"
#include "pixmapchangedcommand.h"
......@@ -165,6 +166,10 @@ void NodeInstanceServerInterface::registerCommands()
qRegisterMetaType<SynchronizeCommand>("SynchronizeCommand");
qRegisterMetaTypeStreamOperators<SynchronizeCommand>("SynchronizeCommand");
qRegisterMetaType<ChangeCustomParserSourceCommand>("ChangeCustomParserSourceCommand");
qRegisterMetaTypeStreamOperators<ChangeCustomParserSourceCommand>("ChangeCustomParserSourceCommand");
}
}
......@@ -55,6 +55,7 @@
#include "changestatecommand.h"
#include "addimportcommand.h"
#include "completecomponentcommand.h"
#include "changecustomparsersourcecommand.h"
#include "informationchangedcommand.h"
#include "pixmapchangedcommand.h"
......@@ -451,4 +452,10 @@ void NodeInstanceServerProxy::completeComponent(const CompleteComponentCommand &
{
writeCommand(QVariant::fromValue(command));
}
void NodeInstanceServerProxy::changeCustomParserSource(ChangeCustomParserSourceCommand &command)
{
writeCommand(QVariant::fromValue(command));
}
} // namespace QmlDesigner
......@@ -70,6 +70,7 @@ public:
void changeState(const ChangeStateCommand &command);
void addImport(const AddImportCommand &command);
void completeComponent(const CompleteComponentCommand &command);
void changeCustomParserSource(ChangeCustomParserSourceCommand &command);
protected:
void writeCommand(const QVariant &command);
......
......@@ -66,6 +66,7 @@
#include "changevaluescommand.h"
#include "changebindingscommand.h"
#include "changeidscommand.h"
#include "changecustomparsersourcecommand.h"
#include "removeinstancescommand.h"
#include "removepropertiescommand.h"
#include "valueschangedcommand.h"
......@@ -515,6 +516,15 @@ void NodeInstanceView::customNotification(const AbstractView *view, const QStrin
restartProcess();
}
void NodeInstanceView::customParserSourceChanged(const ModelNode &node, const QString & newCustomParserSource)
{
if (hasInstanceForNode(node)) {
NodeInstance instance = instanceForNode(node);
ChangeCustomParserSourceCommand changeCustomParserSourceCommand(instance.instanceId(), newCustomParserSource);
nodeInstanceServer()->changeCustomParserSource(changeCustomParserSourceCommand);
}
}
void NodeInstanceView::rewriterBeginTransaction()
{
......@@ -738,7 +748,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
nodeList = filterNodesForSkipItems(nodeList);
QList<VariantProperty> variantPropertyList;
QList<BindingProperty> bindingPropertyList;
QList<BindingProperty> bindingPropertyList;
foreach (const ModelNode &node, nodeList) {
variantPropertyList.append(node.variantProperties());
......@@ -747,7 +757,9 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
QVector<InstanceContainer> instanceContainerList;
foreach(const NodeInstance &instance, instanceList) {
InstanceContainer container(instance.instanceId(), instance.modelNode().type(), instance.modelNode().majorVersion(), instance.modelNode().minorVersion(), instance.modelNode().metaInfo().componentFileName());
InstanceContainer container(instance.instanceId(), instance.modelNode().type(), instance.modelNode().majorVersion(),
instance.modelNode().minorVersion(), instance.modelNode().metaInfo().componentFileName(),
instance.modelNode().customParserSource());
instanceContainerList.append(container);
}
......@@ -858,7 +870,8 @@ CreateInstancesCommand NodeInstanceView::createCreateInstancesCommand(const QLis
{
QVector<InstanceContainer> containerList;
foreach(const NodeInstance &instance, instanceList) {
InstanceContainer container(instance.instanceId(), instance.modelNode().type(), instance.modelNode().majorVersion(), instance.modelNode().minorVersion(), instance.modelNode().metaInfo().componentFileName());
InstanceContainer container(instance.instanceId(), instance.modelNode().type(), instance.modelNode().majorVersion(), instance.modelNode().minorVersion(),
instance.modelNode().metaInfo().componentFileName(), instance.modelNode().customParserSource());
containerList.append(container);
}
......
......@@ -736,17 +736,46 @@ void tweakObjects(QObject *object)
}
QObject *createComponent(const QString &componentPath, QDeclarativeContext *context)
{
static QObject *createComponent(const QString &componentPath, QDeclarativeContext *context)
{
QDeclarativeComponent component(context->engine(), QUrl::fromLocalFile(componentPath));
QObject *object = component.beginCreate(context);
tweakObjects(object);
component.completeCreate();
if (component.isError()) {
qDebug() << componentPath;
foreach(const QDeclarativeError &error, component.errors())
qDebug() << error;
}
return object;
}
static QObject *createCustomParserObject(const QString &customParserSource, QStringList imports, QDeclarativeContext *context)
{
QDeclarativeComponent component(context->engine());
QByteArray importArray;
foreach(const QString &import, imports) {
importArray.append(import.toUtf8());
}
QByteArray data(customParserSource.toUtf8());
data.prepend(importArray);
component.setData(data, context->baseUrl().resolved(QUrl("createCustomParserObject.qml")));
QObject *object = component.beginCreate(context);
tweakObjects(object);
component.completeCreate();
return object;
}
QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QDeclarativeContext *context)
static QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QDeclarativeContext *context)
{
QObject *object = 0;
QDeclarativeType *type = QDeclarativeMetaType::qmlType(typeName.toUtf8(), majorNumber, minorNumber);
......@@ -770,11 +799,13 @@ QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumb
return object;
}
QObject* ObjectNodeInstance::createObject(const QString &typeName, int majorNumber, int minorNumber, const QString &componentPath, QDeclarativeContext *context)
QObject* ObjectNodeInstance::createObject(const QString &typeName, int majorNumber, int minorNumber, const QString &componentPath, const QString &customParserSource, NodeInstanceServer* nodeInstanceServer, QDeclarativeContext *context)
{
QObject *object = 0;
if (componentPath.isEmpty()) {
if (componentPath.isEmpty() && customParserSource.isEmpty()) {
object = createPrimitive(typeName, majorNumber, minorNumber, context);
} else if (componentPath.isEmpty()) {
object = createCustomParserObject(customParserSource, nodeInstanceServer->imports(), context);
} else {
object = createComponent(componentPath, context);
}
......
......@@ -77,7 +77,7 @@ public:
//void setModelNode(const ModelNode &node);
static Pointer create(QObject *objectToBeWrapped);
static QObject* createObject(const QString &typeName, int majorNumber, int minorNumber, const QString &componentPath, QDeclarativeContext *context);
static QObject* createObject(const QString &typeName, int majorNumber, int minorNumber, const QString &componentPath, const QString &customParserSource, NodeInstanceServer* nodeInstanceServer, QDeclarativeContext *context);
void setInstanceId(qint32 id);
qint32 instanceId() const;
......
......@@ -196,7 +196,9 @@ ServerNodeInstance ServerNodeInstance::create(NodeInstanceServer *nodeInstanceSe
QDeclarativeContext *context = nodeInstanceServer->context();
QObject *object = Internal::ObjectNodeInstance::createObject(instanceContainer.type(), instanceContainer.majorNumber(), instanceContainer.minorNumber(), instanceContainer.componentPath(), context);
QObject *object = Internal::ObjectNodeInstance::createObject(instanceContainer.type(), instanceContainer.majorNumber(),
instanceContainer.minorNumber(), instanceContainer.componentPath(),
instanceContainer.customParserSource(), nodeInstanceServer, context);
ServerNodeInstance instance(createInstance(object));
......
......@@ -999,6 +999,11 @@ QString NodeMetaInfo::componentFileName() const
return NodeMetaInfo::m_privateData->componentFileName();
}
bool NodeMetaInfo::hasCustomParser() const
{
return false;
}
bool NodeMetaInfo::availableInVersion(int majorVersion, int minorVersion) const
{
if (majorVersion == -1 && minorVersion == -1)
......
......@@ -80,9 +80,10 @@ RewriterTransaction AbstractView::beginRewriterTransaction()
ModelNode AbstractView::createModelNode(const QString &typeString,
int majorVersion,
int minorVersion,
const QList<QPair<QString, QVariant> > &propertyList)
const QList<QPair<QString, QVariant> > &propertyList,
const QString &customParserSource)
{
return ModelNode(model()->m_d->createNode(typeString, majorVersion, minorVersion, propertyList), model(), this);
return ModelNode(model()->m_d->createNode(typeString, majorVersion, minorVersion, propertyList, customParserSource), model(), this);
}
......
......@@ -342,5 +342,15 @@ qint32 InternalNode::internalId() const
return m_internalId;
}
void InternalNode::setCustomParserSource(const QString &customParserSource)
{
m_customParserSource = customParserSource;
}
QString InternalNode::customParserSource() const
{
return m_customParserSource;
}
}
}
......@@ -121,6 +121,9 @@ public:
qint32 internalId() const;
void setCustomParserSource(const QString&);
QString customParserSource() const;
protected:
Pointer internalPointer() const;
void setInternalWeakPointer(const Pointer &pointer);
......@@ -144,6 +147,8 @@ private:
QHash<QString, InternalPropertyPointer> m_namePropertyHash;
QStringList m_scriptFunctionList;
QString m_customParserSource;
};
uint qHash(const InternalNodePointer& node);
......
......@@ -94,7 +94,7 @@ ModelPrivate::ModelPrivate(Model *model) :
m_writeLock(false),
m_internalIdCounter(1)
{
m_rootInternalNode = createNode("QtQuick/Item", 1, 0, PropertyListType(), true);
m_rootInternalNode = createNode("QtQuick/Item", 1, 0, PropertyListType(), QString(), true);
}
ModelPrivate::~ModelPrivate()
......@@ -202,6 +202,7 @@ InternalNode::Pointer ModelPrivate::createNode(const QString &typeString,
int majorVersion,
int minorVersion,
const QList<QPair<QString, QVariant> > &propertyList,
const QString &customParserSource,
bool isRootNode)
{
if (typeString.isEmpty())
......@@ -224,6 +225,9 @@ InternalNode::Pointer ModelPrivate::createNode(const QString &typeString,
m_nodeSet.insert(newInternalNodePointer);
m_internalIdNodeHash.insert(newInternalNodePointer->internalId(), newInternalNodePointer);
if (!customParserSource.isNull())
newInternalNodePointer->setCustomParserSource(customParserSource);
notifyNodeCreated(newInternalNodePointer);
return newInternalNodePointer;
......@@ -355,6 +359,38 @@ void ModelPrivate::notifyAuxiliaryDataChanged(const InternalNodePointer &interna
}
}
void ModelPrivate::notifyCustomParserSourceChanged(const InternalNodePointer &internalNode, const QString &newCustomParserSource)
{
bool resetModel = false;
QString description;
try {
if (rewriterView()) {
ModelNode node(internalNode, model(), rewriterView());
rewriterView()->customParserSourceChanged(node, newCustomParserSource);
}
} catch (RewritingException &e) {
description = e.description();
resetModel = true;
}
foreach (const QWeakPointer<AbstractView> &view, m_viewList) {
Q_ASSERT(view != 0);
ModelNode node(internalNode, model(), view.data());
view->customParserSourceChanged(node, newCustomParserSource);
}
if (nodeInstanceView()) {
ModelNode node(internalNode, model(), nodeInstanceView());
nodeInstanceView()->customParserSourceChanged(node, newCustomParserSource);
}
if (resetModel) {
resetModelByRewriter(description);
}
}
void ModelPrivate::notifyRootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion)
{
bool resetModel = false;
......@@ -1456,6 +1492,12 @@ void ModelPrivate::setScriptFunctions(const InternalNode::Pointer &internalNode,
notifyScriptFunctionsChanged(internalNode, scriptFunctionList);
}
void ModelPrivate::setCustomParserSource(const InternalNodePointer &internalNode, const QString &customParserSource)
{
internalNode->setCustomParserSource(customParserSource);
notifyCustomParserSourceChanged(internalNode, customParserSource);
}
void ModelPrivate::changeNodeOrder(const InternalNode::Pointer &internalParentNode, const QString &listPropertyName, int from, int to)
{
InternalNodeListProperty::Pointer nodeList(internalParentNode->nodeListProperty(listPropertyName));
......
......@@ -105,6 +105,7 @@ public:
int majorVersion,
int minorVersion,
const QList<QPair<QString, QVariant> > &propertyList,
const QString &customParserSource,
bool isRootNode = false);
......@@ -142,6 +143,7 @@ public:
void notifyNodeOrderChanged(const InternalNodeListPropertyPointer &internalListPropertyPointer, const InternalNodePointer &internalNodePointer, int oldIndex);
void notifyAuxiliaryDataChanged(const InternalNodePointer &internalNode, const QString &name, const QVariant &data);
void notifyCustomParserSourceChanged(const InternalNodePointer &internalNode, const QString &newCustomParserSource);
void notifyRootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion);
......@@ -194,6 +196,7 @@ public:
void clearParent(const InternalNodePointer &internalNode);
void changeRootNodeType(const QString &type, int majorVersion, int minorVersion);
void setScriptFunctions(const InternalNodePointer &internalNode, const QStringList &scriptFunctionList);
void setCustomParserSource(const InternalNodePointer &internalNode, const QString &customParserSource);
InternalNodePointer nodeForId(const QString &id) const;
bool hasId(const QString &id) const;
......
......@@ -51,6 +51,7 @@
#include "nodeabstractproperty.h"
#include "nodelistproperty.h"
#include "nodeproperty.h"
#include <rewriterview.h>
namespace QmlDesigner {
using namespace QmlDesigner::Internal;
......@@ -935,4 +936,28 @@ qint32 ModelNode::internalId() const
return m_internalNode->internalId();
}
void ModelNode::setCustomParserSource(const QString &newCustomParserSource)
{
Internal::WriteLocker locker(m_model.data());
if (!isValid()) {
Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
}
if (internalNode()->customParserSource() == newCustomParserSource)
return;
m_model.data()->m_d->setCustomParserSource(internalNode(), newCustomParserSource);
}
QString ModelNode::customParserSource() const
{
if (!isValid()) {
throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
}
return internalNode()->customParserSource();
}
}
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