From 7d9056953e9aefad9a7cd3ddabfde21fd7651f67 Mon Sep 17 00:00:00 2001
From: Christiaan Janssen <christiaan.janssen@nokia.com>
Date: Thu, 26 Aug 2010 17:38:31 +0200
Subject: [PATCH] QmlInspector:  Added reparenting of items in the Qml Live
 Preview.  Reviewed by:  Lasse Holmstedt

---
 .../include/qdeclarativedesigndebugserver.h      |  1 +
 .../include/qdeclarativedesignview.h             |  1 +
 .../qdeclarativedesigndebugserver.cpp            |  4 ++++
 .../qmljsdebugger/qdeclarativedesignview.cpp     | 16 ++++++++++++++++
 .../qmljsdebugger/qdeclarativedesignview_p.h     |  1 +
 src/libs/qmljs/qmljsdelta.cpp                    | 13 ++++++++++++-
 src/libs/qmljs/qmljsdelta.h                      |  2 ++
 src/plugins/qmljsinspector/qmljsclientproxy.cpp  |  6 ++++++
 src/plugins/qmljsinspector/qmljsclientproxy.h    |  1 +
 .../qmljsinspector/qmljsdesigndebugclient.cpp    | 14 ++++++++++++++
 .../qmljsinspector/qmljsdesigndebugclient.h      |  1 +
 src/plugins/qmljsinspector/qmljsinspector.cpp    |  1 -
 .../qmljsinspector/qmljslivetextpreview.cpp      |  6 ++++++
 13 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/share/qtcreator/qmljsdebugger/include/qdeclarativedesigndebugserver.h b/share/qtcreator/qmljsdebugger/include/qdeclarativedesigndebugserver.h
index f93508194ac..174187d6e95 100644
--- a/share/qtcreator/qmljsdebugger/include/qdeclarativedesigndebugserver.h
+++ b/share/qtcreator/qmljsdebugger/include/qdeclarativedesigndebugserver.h
@@ -84,6 +84,7 @@ Q_SIGNALS:
 
     void objectCreationRequested(const QString &qml, QObject *parent,
                                  const QStringList &imports, const QString &filename = QString());
+    void objectReparentRequested(QObject *object, QObject *newParent);
 
     // 1 = normal speed,
     // 0 = paused,
diff --git a/share/qtcreator/qmljsdebugger/include/qdeclarativedesignview.h b/share/qtcreator/qmljsdebugger/include/qdeclarativedesignview.h
index 7ec687c2253..f06002dcd2a 100644
--- a/share/qtcreator/qmljsdebugger/include/qdeclarativedesignview.h
+++ b/share/qtcreator/qmljsdebugger/include/qdeclarativedesignview.h
@@ -105,6 +105,7 @@ private:
     Q_PRIVATE_SLOT(d_func(), void _q_onCurrentObjectsChanged(QList<QObject*>))
     Q_PRIVATE_SLOT(d_func(), void _q_applyChangesFromClient())
     Q_PRIVATE_SLOT(d_func(), void _q_createQmlObject(const QString &, QObject *, const QStringList &, const QString &))
+    Q_PRIVATE_SLOT(d_func(), void _q_reparentQmlObject(QObject *, QObject *))
     Q_PRIVATE_SLOT(d_func(), void _q_changeToSingleSelectTool())
     Q_PRIVATE_SLOT(d_func(), void _q_changeToMarqueeSelectTool())
     Q_PRIVATE_SLOT(d_func(), void _q_changeToZoomTool())
diff --git a/share/qtcreator/qmljsdebugger/qdeclarativedesigndebugserver.cpp b/share/qtcreator/qmljsdebugger/qdeclarativedesigndebugserver.cpp
index bf68d432ffc..a8bd60736ac 100644
--- a/share/qtcreator/qmljsdebugger/qdeclarativedesigndebugserver.cpp
+++ b/share/qtcreator/qmljsdebugger/qdeclarativedesigndebugserver.cpp
@@ -108,6 +108,10 @@ void QDeclarativeDesignDebugServer::messageReceived(const QByteArray &message)
         ds >> debugId;
         if (QObject* obj = objectForId(debugId))
             obj->deleteLater();
+    } else if (type == "MOVE_OBJECT") {
+       int debugId, newParent;
+       ds >> debugId >> newParent;
+       emit objectReparentRequested(objectForId(debugId), objectForId(newParent));
     } else if (type == "OBJECT_ID_LIST") {
         int itemCount;
         ds >> itemCount;
diff --git a/share/qtcreator/qmljsdebugger/qdeclarativedesignview.cpp b/share/qtcreator/qmljsdebugger/qdeclarativedesignview.cpp
index 90858d068a1..029f126b38e 100644
--- a/share/qtcreator/qmljsdebugger/qdeclarativedesignview.cpp
+++ b/share/qtcreator/qmljsdebugger/qdeclarativedesignview.cpp
@@ -98,6 +98,9 @@ QDeclarativeDesignView::QDeclarativeDesignView(QWidget *parent) :
     connect(qmlDesignDebugServer(),
             SIGNAL(objectCreationRequested(QString,QObject*,QStringList,QString)),
             SLOT(_q_createQmlObject(QString,QObject*,QStringList,QString)));
+    connect(qmlDesignDebugServer(),
+            SIGNAL(objectReparentRequested(QObject *, QObject *)),
+            SLOT(_q_reparentQmlObject(QObject *, QObject *)));
     connect(qmlDesignDebugServer(), SIGNAL(contextPathIndexChanged(int)), SLOT(_q_changeContextPathIndex(int)));
     connect(qmlDesignDebugServer(), SIGNAL(clearComponentCacheRequested()), SLOT(_q_clearComponentCache()));
     connect(this, SIGNAL(statusChanged(QDeclarativeView::Status)), SLOT(_q_onStatusChanged(QDeclarativeView::Status)));
@@ -277,6 +280,19 @@ void QDeclarativeDesignViewPrivate::_q_createQmlObject(const QString &qml, QObje
     }
 }
 
+void QDeclarativeDesignViewPrivate::_q_reparentQmlObject(QObject *object, QObject *newParent)
+{
+    if (!newParent)
+        return;
+
+    object->setParent(newParent);
+    QDeclarativeItem *newParentItem = qobject_cast<QDeclarativeItem*>(newParent);
+    QDeclarativeItem *item    = qobject_cast<QDeclarativeItem*>(object);
+    if (newParentItem && item) {
+        item->setParentItem(newParentItem);
+    }
+}
+
 void QDeclarativeDesignViewPrivate::_q_clearComponentCache()
 {
     q->engine()->clearComponentCache();
diff --git a/share/qtcreator/qmljsdebugger/qdeclarativedesignview_p.h b/share/qtcreator/qmljsdebugger/qdeclarativedesignview_p.h
index a3494e9582f..5166f60d23e 100644
--- a/share/qtcreator/qmljsdebugger/qdeclarativedesignview_p.h
+++ b/share/qtcreator/qmljsdebugger/qdeclarativedesignview_p.h
@@ -122,6 +122,7 @@ public:
     void _q_applyChangesFromClient();
     void _q_createQmlObject(const QString &qml, QObject *parent,
                             const QStringList &imports, const QString &filename = QString());
+    void _q_reparentQmlObject(QObject *, QObject *);
 
     void _q_changeToSingleSelectTool();
     void _q_changeToMarqueeSelectTool();
diff --git a/src/libs/qmljs/qmljsdelta.cpp b/src/libs/qmljs/qmljsdelta.cpp
index fa7af25c002..563f4494f20 100644
--- a/src/libs/qmljs/qmljsdelta.cpp
+++ b/src/libs/qmljs/qmljsdelta.cpp
@@ -432,6 +432,14 @@ void Delta::remove(const QList<DebugId>& debugReferences)
     }
 }
 
+void Delta::reparent(const QList <DebugId> &member, const QList<DebugId> &newParent)
+{
+    if (member.length() != newParent.length()) return;
+
+    for (int i=0; i<member.length(); i++)
+        reparentObject(member.at(i), newParent.at(i));
+}
+
 
 Delta::DebugIdMap Delta::operator()(const Document::Ptr &doc1, const Document::Ptr &doc2, const DebugIdMap &debugIds)
 {
@@ -478,7 +486,8 @@ Delta::DebugIdMap Delta::operator()(const Document::Ptr &doc1, const Document::P
 
         if (!M.contains(parents1.parent.value(x),parents2.parent.value(y))) {
             qDebug () << "Delta::operator():  move " << label(y, doc2) << " from " << label(parents1.parent.value(x), doc1)
-            << " to " << label(parents2.parent.value(y), doc2)  << " ### TODO";
+            << " to " << label(parents2.parent.value(y), doc2);
+            reparent(newDebuggIds.value(y), newDebuggIds.value(parents2.parent.value(y)));
             continue;
         }
     }
@@ -514,6 +523,8 @@ void Delta::createObject(const QString &, DebugId, const QStringList &, const QS
 {}
 void Delta::removeObject(int)
 {}
+void Delta::reparentObject(int, int)
+{}
 void Delta::resetBindingForObject(int, const QString &)
 {}
 void Delta::updateMethodBody(DebugId, UiObjectDefinition *, UiScriptBinding *, const QString &, const QString &)
diff --git a/src/libs/qmljs/qmljsdelta.h b/src/libs/qmljs/qmljsdelta.h
index 355b730574c..02d597b7bd3 100644
--- a/src/libs/qmljs/qmljsdelta.h
+++ b/src/libs/qmljs/qmljsdelta.h
@@ -54,6 +54,7 @@ private:
                 AST::UiObjectDefinition* newObject, const QmlJS::Document::Ptr& newDoc,
                 const QList<DebugId>& debugReferences);
     void remove(const QList<DebugId> &debugReferences);
+    void reparent(const QList <DebugId> &member, const QList<DebugId> &newParent);
 
 protected:
     virtual void updateScriptBinding(DebugId objectReference,
@@ -68,6 +69,7 @@ protected:
                             const QString &methodBody);
     virtual void resetBindingForObject(int debugId, const QString &propertyName);
     virtual void removeObject(int debugId);
+    virtual void reparentObject(int debugId, int newParent);
     virtual void createObject(const QString &qmlText, DebugId ref,
                               const QStringList &importList, const QString &filename);
 
diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.cpp b/src/plugins/qmljsinspector/qmljsclientproxy.cpp
index 2a81edac6e9..fd0100bd65f 100644
--- a/src/plugins/qmljsinspector/qmljsclientproxy.cpp
+++ b/src/plugins/qmljsinspector/qmljsclientproxy.cpp
@@ -393,6 +393,12 @@ void ClientProxy::destroyQmlObject(int debugId)
         m_designClient->destroyQmlObject(debugId);
 }
 
+void ClientProxy::reparentQmlObject(int debugId, int newParent)
+{
+    if (isDesignClientConnected())
+        m_designClient->reparentQmlObject(debugId, newParent);
+}
+
 void ClientProxy::setContextPathIndex(int contextIndex)
 {
     if (isDesignClientConnected())
diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.h b/src/plugins/qmljsinspector/qmljsclientproxy.h
index f7e617971da..a6e3b1cec63 100644
--- a/src/plugins/qmljsinspector/qmljsclientproxy.h
+++ b/src/plugins/qmljsinspector/qmljsclientproxy.h
@@ -113,6 +113,7 @@ public slots:
     void createQmlObject(const QString &qmlText, int parentDebugId,
                          const QStringList &imports, const QString &filename = QString());
     void destroyQmlObject(int debugId);
+    void reparentQmlObject(int debugId, int newParent);
     void setContextPathIndex(int contextIndex);
 
 private slots:
diff --git a/src/plugins/qmljsinspector/qmljsdesigndebugclient.cpp b/src/plugins/qmljsinspector/qmljsdesigndebugclient.cpp
index 5bc160b5200..ee02d3afc5f 100644
--- a/src/plugins/qmljsinspector/qmljsdesigndebugclient.cpp
+++ b/src/plugins/qmljsinspector/qmljsdesigndebugclient.cpp
@@ -313,6 +313,20 @@ void QmlJSDesignDebugClient::destroyQmlObject(int debugId)
     sendMessage(message);
 }
 
+void QmlJSDesignDebugClient::reparentQmlObject(int debugId, int newParent)
+{
+    if (!m_connection || !m_connection->isConnected())
+        return;
+    QByteArray message;
+    QDataStream ds(&message, QIODevice::WriteOnly);
+
+    ds << QByteArray("MOVE_OBJECT")
+       << debugId
+       << newParent;
+
+    sendMessage(message);
+}
+
 
 void QmlJSDesignDebugClient::applyChangesToQmlFile()
 {
diff --git a/src/plugins/qmljsinspector/qmljsdesigndebugclient.h b/src/plugins/qmljsinspector/qmljsdesigndebugclient.h
index 406495844bd..40c1654a44a 100644
--- a/src/plugins/qmljsinspector/qmljsdesigndebugclient.h
+++ b/src/plugins/qmljsinspector/qmljsdesigndebugclient.h
@@ -66,6 +66,7 @@ public:
     void createQmlObject(const QString &qmlText, int parentDebugId,
                          const QStringList &imports, const QString &filename);
     void destroyQmlObject(int debugId);
+    void reparentQmlObject(int debugId, int newParent);
 
     void applyChangesToQmlFile();
     void applyChangesFromQmlFile();
diff --git a/src/plugins/qmljsinspector/qmljsinspector.cpp b/src/plugins/qmljsinspector/qmljsinspector.cpp
index 90adca91918..79dbae1e5a7 100644
--- a/src/plugins/qmljsinspector/qmljsinspector.cpp
+++ b/src/plugins/qmljsinspector/qmljsinspector.cpp
@@ -40,7 +40,6 @@
 
 #include <qmljs/qmljsmodelmanagerinterface.h>
 #include <qmljs/qmljsdocument.h>
-#include <qmljs/qmljsdelta.h>
 
 #include <debugger/debuggerrunner.h>
 #include <debugger/debuggerconstants.h>
diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp
index ff6c7786191..e4f0dd496b5 100644
--- a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp
+++ b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp
@@ -514,6 +514,12 @@ protected:
         m_clientProxy->createQmlObject(qmlText, ref, importList, filename);
     }
 
+    virtual void reparentObject(int debugId, int newParent)
+    {
+        appliedChangesToViewer = true;
+        m_clientProxy->reparentQmlObject(debugId, newParent);
+    }
+
     void checkUnsyncronizableElementChanges(UiObjectDefinition *parentDefinition)
     {
         if (unsyncronizableChanges == QmlJSLiveTextPreview::NoUnsyncronizableChanges) {
-- 
GitLab