QmlDesigner: import only working imports

Change-Id: Ic7d74237eeb86e34925f1b048befa5da9420c278
Reviewed-by: Thomas Hartmann <Thomas.Hartmann@digia.com>
This commit is contained in:
Tim Jenssen
2014-09-25 12:57:57 +02:00
parent a56432b3b1
commit 2bd550f3fd
18 changed files with 162 additions and 122 deletions

View File

@@ -68,15 +68,8 @@ bool ComponentNodeInstance::hasContent() const
void ComponentNodeInstance::setNodeSource(const QString &source)
{
QByteArray importArray;
foreach (const QString &import, nodeInstanceServer()->imports()) {
importArray.append(import.toUtf8());
}
QByteArray data(source.toUtf8());
data.prepend(importArray);
data.append("\n");
QByteArray data(source.toUtf8() + "\n");
data.prepend(nodeInstanceServer()->importCode());
component()->setData(data, QUrl(nodeInstanceServer()->fileUrl().toString() +
QLatin1Char('_')+ id()));

View File

@@ -28,7 +28,9 @@
****************************************************************************/
#include "nodeinstanceserver.h"
#include <QDebug>
#include <QQmlEngine>
#include <QQmlApplicationEngine>
#include <QFileSystemWatcher>
#include <QUrl>
#include <QSet>
@@ -42,6 +44,7 @@
#include <private/qabstractanimation_p.h>
#include <QMutableVectorIterator>
#include <private/qquickview_p.h>
#include <designersupport.h>
#include "servernodeinstance.h"
#include "objectnodeinstance.h"
@@ -76,6 +79,26 @@
#include "dummycontextobject.h"
namespace {
bool testImportStatements(const QStringList &importStatementList, bool enableErrorOutput = false) {
static const QUrl localEmptyUrl(QUrl::fromLocalFile(""));
QQmlEngine engine;
QQmlComponent testImportComponent(&engine);
QByteArray testComponentCode = QStringList(importStatementList).join("\n").toUtf8();
testImportComponent.setData(testComponentCode.append("\nItem {}\n"), localEmptyUrl);
testImportComponent.create();
if (testImportComponent.errors().isEmpty()) {
return true;
} else {
if (enableErrorOutput)
qWarning() << "found not working imports: " << testImportComponent.errorString();
return false;
}
}
}
namespace QmlDesigner {
@@ -224,7 +247,7 @@ void NodeInstanceServer::stopRenderTimer()
void NodeInstanceServer::createScene(const CreateSceneCommand &command)
{
initializeView(command.imports());
initializeView();
QUnifiedTimer::instance()->setSlowdownFactor(0.00001);
QUnifiedTimer::instance()->setSlowModeEnabled(true);
@@ -348,6 +371,8 @@ void NodeInstanceServer::removeSharedMemory(const RemoveSharedMemoryCommand &/*c
void NodeInstanceServer::setupImports(const QVector<AddImportContainer> &containerVector)
{
Q_ASSERT(quickView());
QSet<QString> importStatementSet;
foreach (const AddImportContainer &container, containerVector) {
QString importStatement = QString("import ");
@@ -362,31 +387,53 @@ void NodeInstanceServer::setupImports(const QVector<AddImportContainer> &contain
if (!container.alias().isEmpty())
importStatement += " as " + container.alias();
importStatement.append('\n');
if (!m_importList.contains(importStatement))
m_importList.append(importStatement);
importStatementSet.insert(importStatement);
}
delete m_importComponent.data();
delete m_importComponentObject.data();
QStringList importStatementList(importStatementSet.toList());
QStringList workingImportStatementList;
QString componentString;
foreach (const QString &importStatement, m_importList)
componentString += QString("%1").arg(importStatement);
// check possible import statements combinations
bool enableErrorOutput(true);
componentString += QString("Item {}\n");
// maybe it just works
if (testImportStatements(importStatementList)) {
workingImportStatementList = importStatementList;
} else {
QString firstWorkingImportStatement; //usually this will be "import QtQuick x.x"
QStringList otherImportStatements;
foreach (const QString &importStatement, importStatementList) {
if (testImportStatements(QStringList(importStatement)))
firstWorkingImportStatement = importStatement;
else
otherImportStatements.append(importStatement);
}
// find the bad imports from otherImportStatements
foreach (const QString &importStatement, otherImportStatements) {
if (testImportStatements(QStringList(firstWorkingImportStatement) << importStatement, enableErrorOutput))
workingImportStatementList.append(importStatement);
}
workingImportStatementList.prepend(firstWorkingImportStatement);
}
setupOnlyWorkingImports(workingImportStatementList);
}
void NodeInstanceServer::setupOnlyWorkingImports(const QStringList &workingImportStatementList)
{
QByteArray componentCode = workingImportStatementList.join("\n").toUtf8();
m_importCode = componentCode;
m_importComponent = new QQmlComponent(engine(), quickView());
quickView()->setContent(fileUrl(), m_importComponent, quickView()->rootObject());
if (quickView())
quickView()->setContent(fileUrl(), m_importComponent, quickView()->rootObject());
m_importComponent->setData(componentString.toUtf8(), fileUrl());
m_importComponent->setData(componentCode.append("\nItem {}\n"), fileUrl());
m_importComponentObject = m_importComponent->create();
if (!m_importComponent->errorString().isEmpty())
qDebug() << "QmlDesigner.NodeInstances: import wrong: " << m_importComponent->errorString();
Q_ASSERT(m_importComponent && m_importComponentObject);
Q_ASSERT_X(m_importComponent->errors().isEmpty(), __FUNCTION__, m_importComponent->errorString().toLatin1());
}
void NodeInstanceServer::setupFileUrl(const QUrl &fileUrl)
@@ -1024,14 +1071,9 @@ ValuesChangedCommand NodeInstanceServer::createValuesChangedCommand(const QVecto
return ValuesChangedCommand(valueVector);
}
QStringList NodeInstanceServer::imports() const
QByteArray NodeInstanceServer::importCode() const
{
return m_importList;
}
void NodeInstanceServer::addImportString(const QString &import)
{
m_importList.append(import);
return m_importCode;
}
QObject *NodeInstanceServer::dummyContextObject() const

View File

@@ -120,7 +120,7 @@ public:
void notifyPropertyChange(qint32 instanceid, const PropertyName &propertyName);
QStringList imports() const;
QByteArray importCode() const;
QObject *dummyContextObject() const;
virtual QQmlView *declarativeView() const = 0;
@@ -136,7 +136,6 @@ public slots:
protected:
QList<ServerNodeInstance> createInstances(const QVector<InstanceContainer> &container);
void reparentInstances(const QVector<ReparentContainer> &containerVector);
void addImportString(const QString &import);
Internal::ChildrenChangeEventFilter *childrenChangeEventFilter();
void resetInstanceProperty(const PropertyAbstractContainer &propertyContainer);
@@ -170,7 +169,7 @@ protected:
int renderTimerInterval() const;
void setSlowRenderTimerInterval(int timerInterval);
virtual void initializeView(const QVector<AddImportContainer> &importVector) = 0;
virtual void initializeView() = 0;
virtual QList<ServerNodeInstance> setupScene(const CreateSceneCommand &command) = 0;
void loadDummyDataFiles(const QString& directory);
void loadDummyDataContext(const QString& directory);
@@ -203,6 +202,7 @@ protected:
virtual void resizeCanvasSizeToRootItemSize() = 0;
private:
void setupOnlyWorkingImports(const QStringList &workingImportStatementList);
ServerNodeInstance m_rootNodeInstance;
ServerNodeInstance m_activeStateInstance;
QHash<qint32, ServerNodeInstance> m_idInstanceHash;
@@ -219,7 +219,7 @@ private:
bool m_slowRenderTimer;
int m_slowRenderTimerInterval;
QVector<InstancePropertyPair> m_changedPropertyList;
QStringList m_importList;
QByteArray m_importCode;
QPointer<QObject> m_dummyContextObject;
QPointer<QQmlComponent> m_importComponent;
QPointer<QObject> m_importComponentObject;

View File

@@ -958,7 +958,7 @@ void tweakObjects(QObject *object)
}
}
QObject *ObjectNodeInstance::createComponentWrap(const QString &nodeSource, const QStringList &imports, QQmlContext *context)
QObject *ObjectNodeInstance::createComponentWrap(const QString &nodeSource, const QByteArray &importCode, QQmlContext *context)
{
ComponentCompleteDisabler disableComponentComplete;
@@ -966,16 +966,8 @@ QObject *ObjectNodeInstance::createComponentWrap(const QString &nodeSource, cons
QQmlComponent *component = new QQmlComponent(context->engine());
QByteArray importArray;
foreach (const QString &import, imports) {
importArray.append(import.toUtf8());
}
QByteArray data(nodeSource.toUtf8());
data.prepend(importArray);
data.prepend(importCode);
component->setData(data, context->baseUrl().resolved(QUrl("createComponent.qml")));
QObject *object = component;
@@ -1062,7 +1054,7 @@ QObject *ObjectNodeInstance::createComponent(const QUrl &componentUrl, QQmlConte
return object;
}
QObject *ObjectNodeInstance::createCustomParserObject(const QString &nodeSource, const QStringList &imports, QQmlContext *context)
QObject *ObjectNodeInstance::createCustomParserObject(const QString &nodeSource, const QByteArray &importCode, QQmlContext *context)
{
ComponentCompleteDisabler disableComponentComplete;
@@ -1070,15 +1062,8 @@ QObject *ObjectNodeInstance::createCustomParserObject(const QString &nodeSource,
QQmlComponent component(context->engine());
QByteArray importArray;
foreach (const QString &import, imports) {
importArray.append(import.toUtf8());
}
QByteArray data(nodeSource.toUtf8());
data.prepend(importArray);
data.prepend(importCode);
component.setData(data, context->baseUrl().resolved(QUrl("createCustomParserObject.qml")));
QObject *object = component.beginCreate(context);

View File

@@ -74,10 +74,10 @@ public:
static Pointer create(QObject *objectToBeWrapped);
static QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context);
static QObject *createCustomParserObject(const QString &nodeSource, const QStringList &imports, QQmlContext *context);
static QObject *createCustomParserObject(const QString &nodeSource, const QByteArray &importCode, QQmlContext *context);
static QObject *createComponent(const QString &componentPath, QQmlContext *context);
static QObject *createComponent(const QUrl &componentUrl, QQmlContext *context);
static QObject *createComponentWrap(const QString &nodeSource, const QStringList &imports, QQmlContext *context);
static QObject *createComponentWrap(const QString &nodeSource, const QByteArray &importCode, QQmlContext *context);
void setInstanceId(qint32 id);
qint32 instanceId() const;

View File

@@ -44,7 +44,6 @@ Qt5NodeInstanceServer::Qt5NodeInstanceServer(NodeInstanceClientInterface *nodeIn
: NodeInstanceServer(nodeInstanceClient),
m_designerSupport(new DesignerSupport)
{
addImportString("import QtQuick 2.0\n");
DesignerSupport::activateDesignerMode();
}
@@ -60,7 +59,7 @@ QQuickView *Qt5NodeInstanceServer::quickView() const
return m_quickView.data();
}
void Qt5NodeInstanceServer::initializeView(const QVector<AddImportContainer> &/*importVector*/)
void Qt5NodeInstanceServer::initializeView()
{
Q_ASSERT(!quickView());

View File

@@ -60,7 +60,7 @@ public:
void reparentInstances(const ReparentInstancesCommand &command) Q_DECL_OVERRIDE;
protected:
void initializeView(const QVector<AddImportContainer> &importVector) Q_DECL_OVERRIDE;
void initializeView() Q_DECL_OVERRIDE;
void resizeCanvasSizeToRootItemSize() Q_DECL_OVERRIDE;
void resetAllItems();
QList<ServerNodeInstance> setupScene(const CreateSceneCommand &command) Q_DECL_OVERRIDE;

View File

@@ -48,7 +48,7 @@ Qt5PreviewNodeInstanceServer::Qt5PreviewNodeInstanceServer(NodeInstanceClientInt
void Qt5PreviewNodeInstanceServer::createScene(const CreateSceneCommand &command)
{
initializeView(command.imports());
initializeView();
setupScene(command);
startRenderTimer();

View File

@@ -213,9 +213,9 @@ ServerNodeInstance ServerNodeInstance::create(NodeInstanceServer *nodeInstanceSe
QObject *object = 0;
if (componentWrap == WrapAsComponent) {
object = Internal::ObjectNodeInstance::createComponentWrap(instanceContainer.nodeSource(), nodeInstanceServer->imports(), nodeInstanceServer->context());
object = Internal::ObjectNodeInstance::createComponentWrap(instanceContainer.nodeSource(), nodeInstanceServer->importCode(), nodeInstanceServer->context());
} else if (!instanceContainer.nodeSource().isEmpty()) {
object = Internal::ObjectNodeInstance::createCustomParserObject(instanceContainer.nodeSource(), nodeInstanceServer->imports(), nodeInstanceServer->context());
object = Internal::ObjectNodeInstance::createCustomParserObject(instanceContainer.nodeSource(), nodeInstanceServer->importCode(), nodeInstanceServer->context());
if (object == 0)
nodeInstanceServer->sendDebugOutput(DebugOutputCommand::ErrorType, QLatin1String("Custom parser object could not be created."));
} else if (!instanceContainer.componentPath().isEmpty()) {