From a457d2eec3117b08d5dd27ec6605a9beab2b49cd Mon Sep 17 00:00:00 2001 From: Lasse Holmstedt <lasse.holmstedt@nokia.com> Date: Fri, 16 Jul 2010 09:41:56 +0200 Subject: [PATCH] Live preview: Creating objects dynamically --- .../qmljsinspector/qmljsclientproxy.cpp | 7 ++++ src/plugins/qmljsinspector/qmljsclientproxy.h | 2 ++ src/plugins/qmljsinspector/qmljsdelta.cpp | 32 ++++++++++++++++- src/plugins/qmljsinspector/qmljsdelta.h | 4 +++ .../qmljsinspector/qmljsdesigndebugclient.cpp | 18 ++++++++++ .../qmljsinspector/qmljsdesigndebugclient.h | 3 ++ .../qdeclarativedesigndebugserver.cpp | 8 +++++ .../qdeclarativedesigndebugserver.h | 3 ++ .../qmlobserver/qdeclarativedesignview.cpp | 34 ++++++++++++++++++- .../qml/qmlobserver/qdeclarativedesignview.h | 3 ++ 10 files changed, 112 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.cpp b/src/plugins/qmljsinspector/qmljsclientproxy.cpp index 9b01e49e3cd..9300cc6f3f4 100644 --- a/src/plugins/qmljsinspector/qmljsclientproxy.cpp +++ b/src/plugins/qmljsinspector/qmljsclientproxy.cpp @@ -408,6 +408,13 @@ void ClientProxy::changeToSelectMarqueeTool() m_designClient->changeToSelectMarqueeTool(); } +void ClientProxy::createQmlObject(const QString &qmlText, const QDeclarativeDebugObjectReference &parentRef, + const QStringList &imports, const QString &filename) +{ + if (isDesignClientConnected()) + m_designClient->createQmlObject(qmlText, parentRef, imports, filename); +} + bool ClientProxy::isDesignClientConnected() const { return (m_designClient && m_conn->isConnected()); diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.h b/src/plugins/qmljsinspector/qmljsclientproxy.h index 8aca0546365..85d002425db 100644 --- a/src/plugins/qmljsinspector/qmljsclientproxy.h +++ b/src/plugins/qmljsinspector/qmljsclientproxy.h @@ -102,6 +102,8 @@ public slots: void changeToZoomTool(); void changeToSelectTool(); void changeToSelectMarqueeTool(); + void createQmlObject(const QString &qmlText, const QDeclarativeDebugObjectReference &parent, + const QStringList &imports, const QString &filename = QString()); private slots: void contextChanged(); diff --git a/src/plugins/qmljsinspector/qmljsdelta.cpp b/src/plugins/qmljsinspector/qmljsdelta.cpp index 5a90b7fb344..5a304dc51de 100644 --- a/src/plugins/qmljsinspector/qmljsdelta.cpp +++ b/src/plugins/qmljsinspector/qmljsdelta.cpp @@ -98,6 +98,7 @@ static QString label(UiObjectMember *member, Document::Ptr doc) } else if(UiArrayBinding *foo = cast<UiArrayBinding *>(member)) { str = label(foo->qualifiedId) + QLatin1String("[]"); } else if(UiScriptBinding *foo = cast<UiScriptBinding *>(member)) { + Q_UNUSED(foo) } else { quint32 start = member->firstSourceLocation().begin(); quint32 end = member->lastSourceLocation().end(); @@ -277,6 +278,34 @@ static QString _methodName(UiSourceElement *source) } +void Delta::insert(UiObjectMember *member, UiObjectMember *parentMember, const QList<QDeclarativeDebugObjectReference > &debugReferences, const Document::Ptr &doc) +{ + if (!member || !parentMember) + return; + + // create new objects + if (UiObjectDefinition* uiObjectDef = cast<UiObjectDefinition *>(member)) { + unsigned begin = uiObjectDef->firstSourceLocation().begin(); + unsigned end = uiObjectDef->lastSourceLocation().end(); + QString qmlText = doc->source().mid(begin, end - begin); + QStringList importList; + for (UiImportList *it = doc->qmlProgram()->imports; it; it = it->next) { + if (!it->import) + continue; + unsigned importBegin = it->import->firstSourceLocation().begin(); + unsigned importEnd = it->import->lastSourceLocation().end(); + + importList << doc->source().mid(importBegin, importEnd - importBegin); + } + + foreach(const QDeclarativeDebugObjectReference &ref, debugReferences) { + if (ref.debugId() != -1) { + ClientProxy::instance()->createQmlObject(qmlText, ref, importList, doc->fileName()); + } + } + } +} + Delta::DebugIdMap Delta::operator()(const Document::Ptr &doc1, const Document::Ptr &doc2, const DebugIdMap &debugIds) { Q_ASSERT(doc1->qmlProgram()); @@ -297,13 +326,14 @@ Delta::DebugIdMap Delta::operator()(const Document::Ptr &doc1, const Document::P while(!todo.isEmpty()) { UiObjectMember *y = todo.takeFirst(); todo += children(y); + if (!M.way2.contains(y)) { + insert(y, parents2.parent.value(y), newDebuggIds.value(parents2.parent.value(y)), doc2); qDebug () << "insert " << label(y, doc2) << " to " << label(parents2.parent.value(y), doc2); continue; } UiObjectMember *x = M.way2[y]; - //--8<--------------------------------------------------------------------------------------- if (debugIds.contains(x)) { newDebuggIds[y] = debugIds[x]; diff --git a/src/plugins/qmljsinspector/qmljsdelta.h b/src/plugins/qmljsinspector/qmljsdelta.h index 38d99223783..0138e88031b 100644 --- a/src/plugins/qmljsinspector/qmljsdelta.h +++ b/src/plugins/qmljsinspector/qmljsdelta.h @@ -77,6 +77,10 @@ public: static bool compare(QmlJS::AST::UiQualifiedId *id, QmlJS::AST::UiQualifiedId *other); static QmlJS::AST::UiObjectMemberList *objectMembers(QmlJS::AST::UiObjectMember *object); +private: + void insert(UiObjectMember *member, UiObjectMember *parentMember, + const QList<QDeclarativeDebugObjectReference> &debugReferences, const Document::Ptr &doc); + private: QmlJS::Document::Ptr _doc; QmlJS::Document::Ptr _previousDoc; diff --git a/src/plugins/qmljsinspector/qmljsdesigndebugclient.cpp b/src/plugins/qmljsinspector/qmljsdesigndebugclient.cpp index 819336639c3..0e8a2c9a464 100644 --- a/src/plugins/qmljsinspector/qmljsdesigndebugclient.cpp +++ b/src/plugins/qmljsinspector/qmljsdesigndebugclient.cpp @@ -213,6 +213,24 @@ void QmlJSDesignDebugClient::changeToZoomTool() sendMessage(message); } +void QmlJSDesignDebugClient::createQmlObject(const QString &qmlText, const QDeclarativeDebugObjectReference &parentRef, + const QStringList &imports, const QString &filename) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("CREATE_OBJECT") + << qmlText + << parentRef.debugId() + << imports + << filename; + + sendMessage(message); +} + void QmlJSDesignDebugClient::applyChangesToQmlFile() { if (!m_connection || !m_connection->isConnected()) diff --git a/src/plugins/qmljsinspector/qmljsdesigndebugclient.h b/src/plugins/qmljsinspector/qmljsdesigndebugclient.h index f4124b1a815..32c0fcbf4a8 100644 --- a/src/plugins/qmljsinspector/qmljsdesigndebugclient.h +++ b/src/plugins/qmljsinspector/qmljsdesigndebugclient.h @@ -64,6 +64,9 @@ public: void changeToSelectMarqueeTool(); void changeToZoomTool(); + void createQmlObject(const QString &qmlText, const QDeclarativeDebugObjectReference &parentRef, + const QStringList &imports, const QString &filename); + void applyChangesToQmlFile(); void applyChangesFromQmlFile(); diff --git a/src/tools/qml/qmlobserver/qdeclarativedesigndebugserver.cpp b/src/tools/qml/qmlobserver/qdeclarativedesigndebugserver.cpp index d930753586c..8930e317994 100644 --- a/src/tools/qml/qmlobserver/qdeclarativedesigndebugserver.cpp +++ b/src/tools/qml/qmlobserver/qdeclarativedesigndebugserver.cpp @@ -1,4 +1,5 @@ #include "qdeclarativedesigndebugserver.h" +#include <QStringList> #include <QDebug> @@ -52,6 +53,13 @@ void QDeclarativeDesignDebugServer::messageReceived(const QByteArray &message) bool inDesignMode; ds >> inDesignMode; emit designModeBehaviorChanged(inDesignMode); + } else if (type == "CREATE_OBJECT") { + QString qml; + int parentId; + QString filename; + QStringList imports; + ds >> qml >> parentId >> imports >> filename; + emit objectCreationRequested(qml, objectForId(parentId), imports, filename); } } diff --git a/src/tools/qml/qmlobserver/qdeclarativedesigndebugserver.h b/src/tools/qml/qmlobserver/qdeclarativedesigndebugserver.h index 478dbfadaf4..301229ebb0a 100644 --- a/src/tools/qml/qmlobserver/qdeclarativedesigndebugserver.h +++ b/src/tools/qml/qmlobserver/qdeclarativedesigndebugserver.h @@ -72,6 +72,9 @@ Q_SIGNALS: void zoomToolRequested(); void colorPickerToolRequested(); + void objectCreationRequested(const QString &qml, QObject *parent, + const QStringList &imports, const QString &filename = QString()); + // 1 = normal speed, // 0 = paused, // 1 < x < 16 = slowdown by some factor diff --git a/src/tools/qml/qmlobserver/qdeclarativedesignview.cpp b/src/tools/qml/qmlobserver/qdeclarativedesignview.cpp index c8019f26537..cbb67dbf6ab 100644 --- a/src/tools/qml/qmlobserver/qdeclarativedesignview.cpp +++ b/src/tools/qml/qmlobserver/qdeclarativedesignview.cpp @@ -8,9 +8,12 @@ #include "subcomponenteditortool.h" #include "qmltoolbar.h" -#include <QMouseEvent> #include <QDeclarativeItem> +#include <QDeclarativeEngine> +#include <QDeclarativeContext> +#include <QDeclarativeExpression> #include <QWidget> +#include <QMouseEvent> #include <QGraphicsObject> #include <QApplication> @@ -48,6 +51,9 @@ QDeclarativeDesignView::QDeclarativeDesignView(QWidget *parent) : connect(qmlDesignDebugServer(), SIGNAL(selectMarqueeToolRequested()), SLOT(changeToMarqueeSelectTool())); connect(qmlDesignDebugServer(), SIGNAL(selectToolRequested()), SLOT(changeToSingleSelectTool())); connect(qmlDesignDebugServer(), SIGNAL(zoomToolRequested()), SLOT(changeToZoomTool())); + connect(qmlDesignDebugServer(), + SIGNAL(objectCreationRequested(QString,QObject*,QStringList,QString)), + SLOT(createQmlObject(QString,QObject*,QStringList,QString))); connect(this, SIGNAL(statusChanged(QDeclarativeView::Status)), SLOT(onStatusChanged(QDeclarativeView::Status))); @@ -178,6 +184,32 @@ void QDeclarativeDesignView::keyReleaseEvent(QKeyEvent *event) m_currentTool->keyReleaseEvent(event); } +void QDeclarativeDesignView::createQmlObject(const QString &qml, QObject *parent, const QStringList &importList, const QString &filename) +{ + if (!parent) + return; + + QString imports; + foreach(const QString &s, importList) { + imports += s + "\n"; + } + + QDeclarativeContext *parentContext = engine()->contextForObject(parent); + QDeclarativeComponent component(engine(), this); + QByteArray constructedQml = QString(imports + qml).toLatin1(); + + component.setData(constructedQml, filename); + QObject *newObject = component.create(parentContext); + if (newObject) { + newObject->setParent(parent); + QDeclarativeItem *parentItem = dynamic_cast<QDeclarativeItem*>(parent); + QDeclarativeItem *newItem = dynamic_cast<QDeclarativeItem*>(newObject); + if (parentItem && newItem) { + newItem->setParentItem(parentItem); + } + } +} + QGraphicsItem *QDeclarativeDesignView::currentRootItem() const { return m_subcomponentEditorTool->currentRootItem(); diff --git a/src/tools/qml/qmlobserver/qdeclarativedesignview.h b/src/tools/qml/qmlobserver/qdeclarativedesignview.h index 332d7f03fbd..961b1463647 100644 --- a/src/tools/qml/qmlobserver/qdeclarativedesignview.h +++ b/src/tools/qml/qmlobserver/qdeclarativedesignview.h @@ -93,6 +93,8 @@ private Q_SLOTS: void onStatusChanged(QDeclarativeView::Status status); void onCurrentObjectsChanged(QList<QObject*> objects); void applyChangesFromClient(); + void createQmlObject(const QString &qml, QObject *parent, + const QStringList &imports, const QString &filename = QString()); private: void clearEditorItems(); @@ -101,6 +103,7 @@ private: QList<QGraphicsItem*> filterForCurrentContext(QList<QGraphicsItem*> &itemlist) const; QList<QGraphicsItem*> filterForSelection(QList<QGraphicsItem*> &itemlist) const; + private: QPointF m_cursorPos; QList<QWeakPointer<QGraphicsObject> > m_currentSelection; -- GitLab