qml debugger: Create abstraction for State management
authorKent Hansen <kent.hansen@nokia.com>
Wed, 23 Nov 2011 11:09:15 +0000 (12:09 +0100)
committerQt by Nokia <qt-info@nokia.com>
Mon, 28 Nov 2011 06:45:43 +0000 (07:45 +0100)
State and PropertyChanges aren't part of the core qml types. The
(general-purpose) qml debugger shouldn't have to know those types;
they are only relevant when QtQuick (2.0) has been imported.

Introduce a delegate interface that performs State processing.
Implement a delegate for QtQuick 2, and install it when the QtQuick 2
module is imported.

Change-Id: I8af1157346ca9365eb0f7b99ccb71744d17fcebc
Reviewed-by: Aurindam Jana <aurindam.jana@nokia.com>

src/declarative/debugger/debugger.pri
src/declarative/debugger/qdeclarativedebugstatesdelegate_p.h [new file with mode: 0644]
src/declarative/debugger/qdeclarativeenginedebugservice.cpp
src/declarative/debugger/qdeclarativeenginedebugservice_p.h
src/declarative/qtquick2.cpp

index 4128771..e5508a2 100644 (file)
@@ -21,6 +21,7 @@ HEADERS += \
     $$PWD/qdeclarativedebughelper_p.h \
     $$PWD/qdeclarativedebugserver_p.h \
     $$PWD/qdeclarativedebugserverconnection_p.h \
+    $$PWD/qdeclarativedebugstatesdelegate_p.h \
     $$PWD/qdeclarativeinspectorservice_p.h \
     $$PWD/qdeclarativeinspectorinterface_p.h \
     $$PWD/qv8debugservice_p.h \
diff --git a/src/declarative/debugger/qdeclarativedebugstatesdelegate_p.h b/src/declarative/debugger/qdeclarativedebugstatesdelegate_p.h
new file mode 100644 (file)
index 0000000..0d70aa3
--- /dev/null
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEDEBUGSTATESDELEGATE_P_H
+#define QDECLARATIVEDEBUGSTATESDELEGATE_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeContext;
+class QDeclarativeProperty;
+class QObject;
+class QString;
+class QVariant;
+
+class QDeclarativeDebugStatesDelegate
+{
+protected:
+    QDeclarativeDebugStatesDelegate() {}
+
+public:
+    virtual ~QDeclarativeDebugStatesDelegate() {}
+
+    virtual void buildStatesList(QDeclarativeContext *ctxt, bool cleanList) = 0;
+    virtual void updateBinding(QDeclarativeContext *context,
+                               const QDeclarativeProperty &property,
+                               const QVariant &expression, bool isLiteralValue,
+                               const QString &fileName, int line,
+                               bool *inBaseState) = 0;
+    virtual bool setBindingForInvalidProperty(QObject *object,
+                                              const QString &propertyName,
+                                              const QVariant &expression,
+                                              bool isLiteralValue) = 0;
+    virtual void resetBindingForInvalidProperty(QObject *object,
+                                                const QString &propertyName) = 0;
+
+private:
+    Q_DISABLE_COPY(QDeclarativeDebugStatesDelegate)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEDEBUGSTATESDELEGATE_P_H
index 501e600..f831929 100644 (file)
@@ -41,6 +41,7 @@
 
 #include "qdeclarativeenginedebugservice_p.h"
 
+#include "qdeclarativedebugstatesdelegate_p.h"
 #include <private/qdeclarativeboundsignal_p.h>
 #include <qdeclarativeengine.h>
 #include <private/qdeclarativemetatype_p.h>
@@ -52,7 +53,6 @@
 #include <private/qdeclarativevaluetype_p.h>
 #include <private/qdeclarativevmemetaobject_p.h>
 #include <private/qdeclarativeexpression_p.h>
-#include <private/qdeclarativepropertychanges_p.h>
 
 #include <QtCore/qdebug.h>
 #include <QtCore/qmetaobject.h>
@@ -68,7 +68,8 @@ QDeclarativeEngineDebugService *QDeclarativeEngineDebugService::instance()
 
 QDeclarativeEngineDebugService::QDeclarativeEngineDebugService(QObject *parent)
     : QDeclarativeDebugService(QLatin1String("QDeclarativeEngine"), parent),
-      m_watch(new QDeclarativeWatcher(this))
+      m_watch(new QDeclarativeWatcher(this)),
+      m_statesDelegate(0)
 {
     QObject::connect(m_watch, SIGNAL(propertyChanged(int,int,QMetaProperty,QVariant)),
                      this, SLOT(propertyChanged(int,int,QMetaProperty,QVariant)));
@@ -76,6 +77,11 @@ QDeclarativeEngineDebugService::QDeclarativeEngineDebugService(QObject *parent)
     registerService();
 }
 
+QDeclarativeEngineDebugService::~QDeclarativeEngineDebugService()
+{
+    delete m_statesDelegate;
+}
+
 QDataStream &operator<<(QDataStream &ds, 
                         const QDeclarativeEngineDebugService::QDeclarativeObjectData &data)
 {
@@ -318,33 +324,10 @@ void QDeclarativeEngineDebugService::buildObjectList(QDataStream &message, QDecl
     }
 }
 
-void QDeclarativeEngineDebugService::buildStatesList(QDeclarativeContext *ctxt, bool cleanList=false)
+void QDeclarativeEngineDebugService::buildStatesList(QDeclarativeContext *ctxt, bool cleanList)
 {
-    if (cleanList)
-        m_allStates.clear();
-
-    QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(ctxt);
-    for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
-        buildStatesList(ctxtPriv->instances.at(ii));
-    }
-
-    QDeclarativeContextData *child = QDeclarativeContextData::get(ctxt)->childContexts;
-    while (child) {
-        buildStatesList(child->asQDeclarativeContext());
-        child = child->nextChild;
-    }
-}
-
-void QDeclarativeEngineDebugService::buildStatesList(QObject *obj)
-{
-    if (QDeclarativeState *state = qobject_cast<QDeclarativeState *>(obj)) {
-        m_allStates.append(state);
-    }
-
-    QObjectList children = obj->children();
-    for (int ii = 0; ii < children.count(); ++ii) {
-        buildStatesList(children.at(ii));
-    }
+    if (m_statesDelegate)
+        m_statesDelegate->buildStatesList(ctxt, cleanList);
 }
 
 QDeclarativeEngineDebugService::QDeclarativeObjectData
@@ -567,27 +550,9 @@ void QDeclarativeEngineDebugService::setBinding(int objectId,
         if (property.isValid()) {
 
             bool inBaseState = true;
-
-            foreach(QWeakPointer<QDeclarativeState> statePointer, m_allStates) {
-                if (QDeclarativeState *state = statePointer.data()) {
-                    // here we assume that the revert list on itself defines the base state
-                    if (state->isStateActive() && state->containsPropertyInRevertList(object, propertyName)) {
-                        inBaseState = false;
-
-                        QDeclarativeBinding *newBinding = 0;
-                        if (!isLiteralValue) {
-                            newBinding = new QDeclarativeBinding(expression.toString(), object, context);
-                            newBinding->setTarget(property);
-                            newBinding->setNotifyOnValueChanged(true);
-                            newBinding->setSourceLocation(filename, line);
-                        }
-
-                        state->changeBindingInRevertList(object, propertyName, newBinding);
-
-                        if (isLiteralValue)
-                            state->changeValueInRevertList(object, propertyName, expression);
-                    }
-                }
+            if (m_statesDelegate) {
+                m_statesDelegate->updateBinding(context, property, expression, isLiteralValue,
+                                                filename, line, &inBaseState);
             }
 
             if (inBaseState) {
@@ -613,15 +578,11 @@ void QDeclarativeEngineDebugService::setBinding(int objectId,
 
         } else {
             // not a valid property
-            if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
-                if (isLiteralValue) {
-                    propertyChanges->changeValue(propertyName, expression);
-                } else {
-                    propertyChanges->changeExpression(propertyName, expression.toString());
-                }
-            } else {
+            bool ok = false;
+            if (m_statesDelegate)
+                ok = m_statesDelegate->setBindingForInvalidProperty(object, propertyName, expression, isLiteralValue);
+            if (!ok)
                 qWarning() << "QDeclarativeEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
-            }
         }
     }
 }
@@ -664,9 +625,8 @@ void QDeclarativeEngineDebugService::resetBinding(int objectId, const QString &p
             QDeclarativeProperty property(object, propertyName, context);
             QDeclarativePropertyPrivate::setSignalExpression(property, 0);
         } else {
-            if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
-                propertyChanges->removeProperty(propertyName);
-            }
+            if (m_statesDelegate)
+                m_statesDelegate->resetBindingForInvalidProperty(object, propertyName);
         }
     }
 }
@@ -751,4 +711,9 @@ void QDeclarativeEngineDebugService::objectCreated(QDeclarativeEngine *engine, Q
     sendMessage(reply);
 }
 
+void QDeclarativeEngineDebugService::setStatesDelegate(QDeclarativeDebugStatesDelegate *delegate)
+{
+    m_statesDelegate = delegate;
+}
+
 QT_END_NAMESPACE
index d3e5c79..7c74c63 100644 (file)
@@ -57,7 +57,6 @@
 
 #include <QtCore/qurl.h>
 #include <QtCore/qvariant.h>
-#include <QWeakPointer>
 
 QT_BEGIN_NAMESPACE
 
@@ -65,13 +64,14 @@ class QDeclarativeEngine;
 class QDeclarativeContext;
 class QDeclarativeWatcher;
 class QDataStream;
-class QDeclarativeState;
+class QDeclarativeDebugStatesDelegate;
 
 class QDeclarativeEngineDebugService : public QDeclarativeDebugService
 {
     Q_OBJECT
 public:
     QDeclarativeEngineDebugService(QObject * = 0);
+    ~QDeclarativeEngineDebugService();
 
     struct QDeclarativeObjectData {
         QUrl url;
@@ -98,6 +98,8 @@ public:
     void remEngine(QDeclarativeEngine *);
     void objectCreated(QDeclarativeEngine *, QObject *);
 
+    void setStatesDelegate(QDeclarativeDebugStatesDelegate *);
+
     static QDeclarativeEngineDebugService *instance();
 
 protected:
@@ -112,7 +114,6 @@ private:
     void buildObjectList(QDataStream &, QDeclarativeContext *);
     void buildObjectDump(QDataStream &, QObject *, bool, bool);
     void buildStatesList(QDeclarativeContext *, bool);
-    void buildStatesList(QObject *obj);
     QDeclarativeObjectData objectData(QObject *);
     QDeclarativeObjectProperty propertyData(QObject *, int);
     QVariant valueContents(const QVariant &defaultValue) const;
@@ -122,7 +123,7 @@ private:
 
     QList<QDeclarativeEngine *> m_engines;
     QDeclarativeWatcher *m_watch;
-    QList<QWeakPointer<QDeclarativeState> > m_allStates;
+    QDeclarativeDebugStatesDelegate *m_statesDelegate;
 };
 Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugService::QDeclarativeObjectData &);
 Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugService::QDeclarativeObjectData &);
index 64739b3..72e3251 100644 (file)
 #include <private/qquickitemsmodule_p.h>
 #include <private/qquickparticlesmodule_p.h>
 
+#include <private/qdeclarativeenginedebugservice_p.h>
+#include <private/qdeclarativedebugstatesdelegate_p.h>
+#include <private/qdeclarativebinding_p.h>
+#include <private/qdeclarativecontext_p.h>
+#include <private/qdeclarativepropertychanges_p.h>
+#include <private/qdeclarativestate_p.h>
+#include <qdeclarativeproperty.h>
+#include <QtCore/QWeakPointer>
+
 QT_BEGIN_NAMESPACE
 
+class QDeclarativeQtQuick2DebugStatesDelegate : public QDeclarativeDebugStatesDelegate
+{
+public:
+    QDeclarativeQtQuick2DebugStatesDelegate();
+    virtual ~QDeclarativeQtQuick2DebugStatesDelegate();
+    virtual void buildStatesList(QDeclarativeContext *ctxt, bool cleanList);
+    virtual void updateBinding(QDeclarativeContext *context,
+                               const QDeclarativeProperty &property,
+                               const QVariant &expression, bool isLiteralValue,
+                               const QString &fileName, int line,
+                               bool *isBaseState);
+    virtual bool setBindingForInvalidProperty(QObject *object,
+                                              const QString &propertyName,
+                                              const QVariant &expression,
+                                              bool isLiteralValue);
+    virtual void resetBindingForInvalidProperty(QObject *object,
+                                                const QString &propertyName);
+
+private:
+    void buildStatesList(QObject *obj);
+
+    QList<QWeakPointer<QDeclarativeState> > m_allStates;
+};
+
+QDeclarativeQtQuick2DebugStatesDelegate::QDeclarativeQtQuick2DebugStatesDelegate()
+{
+}
+
+QDeclarativeQtQuick2DebugStatesDelegate::~QDeclarativeQtQuick2DebugStatesDelegate()
+{
+}
+
+void QDeclarativeQtQuick2DebugStatesDelegate::buildStatesList(QDeclarativeContext *ctxt, bool cleanList)
+{
+    if (cleanList)
+        m_allStates.clear();
+
+    QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(ctxt);
+    for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
+        buildStatesList(ctxtPriv->instances.at(ii));
+    }
+
+    QDeclarativeContextData *child = QDeclarativeContextData::get(ctxt)->childContexts;
+    while (child) {
+        buildStatesList(child->asQDeclarativeContext());
+        child = child->nextChild;
+    }
+}
+
+void QDeclarativeQtQuick2DebugStatesDelegate::buildStatesList(QObject *obj)
+{
+    if (QDeclarativeState *state = qobject_cast<QDeclarativeState *>(obj)) {
+        m_allStates.append(state);
+    }
+
+    QObjectList children = obj->children();
+    for (int ii = 0; ii < children.count(); ++ii) {
+        buildStatesList(children.at(ii));
+    }
+}
+
+void QDeclarativeQtQuick2DebugStatesDelegate::updateBinding(QDeclarativeContext *context,
+                                                            const QDeclarativeProperty &property,
+                                                            const QVariant &expression, bool isLiteralValue,
+                                                            const QString &fileName, int line,
+                                                            bool *inBaseState)
+{
+    QObject *object = property.object();
+    QString propertyName = property.name();
+    foreach (QWeakPointer<QDeclarativeState> statePointer, m_allStates) {
+        if (QDeclarativeState *state = statePointer.data()) {
+            // here we assume that the revert list on itself defines the base state
+            if (state->isStateActive() && state->containsPropertyInRevertList(object, propertyName)) {
+                *inBaseState = false;
+
+                QDeclarativeBinding *newBinding = 0;
+                if (!isLiteralValue) {
+                    newBinding = new QDeclarativeBinding(expression.toString(), object, context);
+                    newBinding->setTarget(property);
+                    newBinding->setNotifyOnValueChanged(true);
+                    newBinding->setSourceLocation(fileName, line);
+                }
+
+                state->changeBindingInRevertList(object, propertyName, newBinding);
+
+                if (isLiteralValue)
+                    state->changeValueInRevertList(object, propertyName, expression);
+            }
+        }
+    }
+}
+
+bool QDeclarativeQtQuick2DebugStatesDelegate::setBindingForInvalidProperty(QObject *object,
+                                                                           const QString &propertyName,
+                                                                           const QVariant &expression,
+                                                                           bool isLiteralValue)
+{
+    if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
+        if (isLiteralValue)
+            propertyChanges->changeValue(propertyName, expression);
+        else
+            propertyChanges->changeExpression(propertyName, expression.toString());
+        return true;
+    } else {
+        return false;
+    }
+}
+
+void QDeclarativeQtQuick2DebugStatesDelegate::resetBindingForInvalidProperty(QObject *object, const QString &propertyName)
+{
+    if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
+        propertyChanges->removeProperty(propertyName);
+    }
+}
+
+
 void QDeclarativeQtQuick2Module::defineModule()
 {
     QDeclarativeUtilModule::defineModule();
@@ -55,6 +180,11 @@ void QDeclarativeQtQuick2Module::defineModule()
     QQuickItemsModule::defineModule();
     QQuickParticlesModule::defineModule();
     QDeclarativeValueTypeFactory::registerValueTypes();
+
+    if (QDeclarativeEngineDebugService::isDebuggingEnabled()) {
+        QDeclarativeEngineDebugService::instance()->setStatesDelegate(
+                    new QDeclarativeQtQuick2DebugStatesDelegate);
+    }
 }
 
 QT_END_NAMESPACE