summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2011-05-12 07:15:00 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2011-05-12 07:15:00 (GMT)
commit51684a152f380ed86bb45303871c0881f138d6d9 (patch)
tree9afce594ecbf1685863f13f342b1c5608c49c7fa
parentb80c3b1b04c35ae1fa6d7119b6f7dac06ee6494b (diff)
parent5c830ed2a612b940c377fb4e8a2372655f175707 (diff)
downloadQt-51684a152f380ed86bb45303871c0881f138d6d9.zip
Qt-51684a152f380ed86bb45303871c0881f138d6d9.tar.gz
Qt-51684a152f380ed86bb45303871c0881f138d6d9.tar.bz2
Merge branch 'master' of scm.dev.nokia.troll.no:qt/qt-qml-staging into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/qt-qml-staging: QmlDebug: Fix QmlOstPlugin compilation failure QmlDebug: Fix QmlOstPlugin compilation failure Enable performance monitoring at application startup. Augment documentation QmlDebugger: removing slots in Live Preview QmlDebugger: adding slots to items in Live Preview Fixed license header Fixed compile on Windows Added forgotten file qdeclarativeobserverinterface_p.h Removed some trailing whitespace Introduced a CONFIG option that enables declarative debug services Moved the QML Observer Service and related functionality into Qt QDeclarativeDebugServer: Send hello answer before any service messages Removed some superfluous semicolons
-rw-r--r--mkspecs/features/declarative_debug.prf1
-rw-r--r--src/declarative/debugger/debugger.pri11
-rw-r--r--src/declarative/debugger/qdeclarativedebugserver.cpp69
-rw-r--r--src/declarative/debugger/qdeclarativedebugserver_p.h3
-rw-r--r--src/declarative/debugger/qdeclarativedebugserverconnection_p.h1
-rw-r--r--src/declarative/debugger/qdeclarativedebugservice.cpp10
-rw-r--r--src/declarative/debugger/qdeclarativedebugservice_p.h2
-rw-r--r--src/declarative/debugger/qdeclarativedebugtrace.cpp9
-rw-r--r--src/declarative/debugger/qdeclarativedebugtrace_p.h1
-rw-r--r--src/declarative/debugger/qdeclarativeobserverinterface_p.h69
-rw-r--r--src/declarative/debugger/qdeclarativeobserverservice.cpp137
-rw-r--r--src/declarative/debugger/qdeclarativeobserverservice_p.h91
-rw-r--r--src/declarative/debugger/qjsdebuggeragent.cpp576
-rw-r--r--src/declarative/debugger/qjsdebuggeragent_p.h204
-rw-r--r--src/declarative/debugger/qjsdebugservice.cpp198
-rw-r--r--src/declarative/debugger/qjsdebugservice_p.h99
-rw-r--r--src/declarative/debugger/qpacketprotocol.cpp49
-rw-r--r--src/declarative/debugger/qpacketprotocol_p.h2
-rw-r--r--src/declarative/qml/qdeclarative.h11
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp53
-rw-r--r--src/declarative/qml/qdeclarativeengine_p.h11
-rw-r--r--src/declarative/qml/qdeclarativeenginedebug.cpp22
-rw-r--r--src/declarative/qml/qdeclarativeenginedebug_p.h2
-rw-r--r--src/declarative/util/qdeclarativeview.cpp5
-rw-r--r--src/plugins/qmltooling/declarativeobserver/declarativeobserver.pro53
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool.cpp200
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool_p.h121
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter.cpp284
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter_p.h126
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/colorpickertool.cpp131
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/colorpickertool_p.h99
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/editor.qrc24
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-24.pngbin0 -> 3440 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-hicontrast.pngbin0 -> 3192 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/color-picker.pngbin0 -> 3173 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/from-qml-24.pngbin0 -> 3395 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/from-qml.pngbin0 -> 3205 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/observermode-24.pngbin0 -> 1283 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/observermode.pngbin0 -> 3539 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/pause-24.pngbin0 -> 3307 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/pause.pngbin0 -> 3097 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/play-24.pngbin0 -> 3655 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/play.pngbin0 -> 3363 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/reload.pngbin0 -> 3418 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/resize_handle.pngbin0 -> 160 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/select-24.pngbin0 -> 3510 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee-24.pngbin0 -> 2891 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee.pngbin0 -> 2871 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/select.pngbin0 -> 3308 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/to-qml-24.pngbin0 -> 3407 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/to-qml.pngbin0 -> 3227 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/zoom-24.pngbin0 -> 3566 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/images/zoom.pngbin0 -> 3347 bytes
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/livelayeritem.cpp92
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/livelayeritem_p.h73
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator.cpp165
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator_p.h102
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator.cpp148
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator_p.h90
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle.cpp113
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle_p.h83
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool.cpp442
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool_p.h126
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator.cpp151
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator_p.h95
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar.cpp328
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar_p.h138
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool.cpp364
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool_p.h131
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem.cpp124
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem_p.h77
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox.cpp134
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox_p.h87
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/zoomtool.cpp336
-rw-r--r--src/plugins/qmltooling/declarativeobserver/editor/zoomtool_p.h113
-rw-r--r--src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.cpp81
-rw-r--r--src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.h71
-rw-r--r--src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverprotocol.h145
-rw-r--r--src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver.cpp1167
-rw-r--r--src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p.h154
-rw-r--r--src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p_p.h165
-rw-r--r--src/plugins/qmltooling/declarativeobserver/qmlobserverconstants_p.h90
-rw-r--r--src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp6
-rw-r--r--src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h1
-rw-r--r--src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp42
-rw-r--r--src/plugins/qmltooling/qmldbg_ost/qostdevice.h4
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp15
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h2
-rw-r--r--src/plugins/qmltooling/qmltooling.pro2
-rw-r--r--src/script/api/qscriptengineagent_p.h18
-rw-r--r--tools/qml/main.cpp3
-rw-r--r--tools/qml/qml.pro2
92 files changed, 8086 insertions, 68 deletions
diff --git a/mkspecs/features/declarative_debug.prf b/mkspecs/features/declarative_debug.prf
new file mode 100644
index 0000000..b0248f0
--- /dev/null
+++ b/mkspecs/features/declarative_debug.prf
@@ -0,0 +1 @@
+contains(QT, declarative):DEFINES += QT_DECLARATIVE_DEBUG
diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri
index 75287b4..044db3c 100644
--- a/src/declarative/debugger/debugger.pri
+++ b/src/declarative/debugger/debugger.pri
@@ -8,7 +8,10 @@ SOURCES += \
$$PWD/qdeclarativedebug.cpp \
$$PWD/qdeclarativedebugtrace.cpp \
$$PWD/qdeclarativedebughelper.cpp \
- $$PWD/qdeclarativedebugserver.cpp
+ $$PWD/qdeclarativedebugserver.cpp \
+ $$PWD/qdeclarativeobserverservice.cpp \
+ $$PWD/qjsdebuggeragent.cpp \
+ $$PWD/qjsdebugservice.cpp
HEADERS += \
$$PWD/qdeclarativedebuggerstatus_p.h \
@@ -20,4 +23,8 @@ HEADERS += \
$$PWD/qdeclarativedebugtrace_p.h \
$$PWD/qdeclarativedebughelper_p.h \
$$PWD/qdeclarativedebugserver_p.h \
- debugger/qdeclarativedebugserverconnection_p.h
+ $$PWD/qdeclarativedebugserverconnection_p.h \
+ $$PWD/qdeclarativeobserverservice_p.h \
+ $$PWD/qdeclarativeobserverinterface_p.h \
+ $$PWD/qjsdebuggeragent_p.h \
+ $$PWD/qjsdebugservice_p.h
diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp
index 5112af0..4343870 100644
--- a/src/declarative/debugger/qdeclarativedebugserver.cpp
+++ b/src/declarative/debugger/qdeclarativedebugserver.cpp
@@ -90,7 +90,11 @@ public:
QHash<QString, QDeclarativeDebugService *> plugins;
QStringList clientPlugins;
bool gotHello;
+ QString waitingForMsgFromService;
+private:
+ // private slot
+ void _q_deliverMessage(const QString &serviceName, const QByteArray &message);
static QDeclarativeDebugServerConnection *loadConnectionPlugin(const QString &pluginName);
};
@@ -237,7 +241,6 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
QDataStream in(message);
if (!d->gotHello) {
-
QString name;
int op;
in >> name >> op;
@@ -252,6 +255,17 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
int version;
in >> version >> d->clientPlugins;
+ // Send the hello answer immediately, since it needs to arrive before
+ // the plugins below start sending messages.
+ QByteArray helloAnswer;
+ {
+ QDataStream out(&helloAnswer, QIODevice::WriteOnly);
+ out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys();
+ }
+ d->connection->send(helloAnswer);
+
+ d->gotHello = true;
+
QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
for (; iter != d->plugins.end(); ++iter) {
QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
@@ -261,14 +275,6 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
iter.value()->statusChanged(newStatus);
}
- QByteArray helloAnswer;
- {
- QDataStream out(&helloAnswer, QIODevice::WriteOnly);
- out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys();
- }
- d->connection->send(helloAnswer);
-
- d->gotHello = true;
qWarning("QDeclarativeDebugServer: Connection established");
} else {
@@ -306,17 +312,33 @@ void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
QByteArray message;
in >> message;
- QHash<QString, QDeclarativeDebugService *>::Iterator iter =
- d->plugins.find(name);
- if (iter == d->plugins.end()) {
- qWarning() << "QDeclarativeDebugServer: Message received for missing plugin" << name;
+ if (d->waitingForMsgFromService == name) {
+ // deliver directly so that it is delivered before waitForMessage is returning.
+ d->_q_deliverMessage(name, message);
+ d->waitingForMsgFromService.clear();
} else {
- (*iter)->messageReceived(message);
+ // deliver message in next event loop run.
+ // Fixes the case that the service does start it's own event loop ...,
+ // but the networking code doesn't deliver any new messages because readyRead
+ // hasn't returned.
+ QMetaObject::invokeMethod(this, "_q_deliverMessage", Qt::QueuedConnection,
+ Q_ARG(QString, name),
+ Q_ARG(QByteArray, message));
}
}
}
}
+void QDeclarativeDebugServerPrivate::_q_deliverMessage(const QString &serviceName, const QByteArray &message)
+{
+ QHash<QString, QDeclarativeDebugService *>::Iterator iter = plugins.find(serviceName);
+ if (iter == plugins.end()) {
+ qWarning() << "QDeclarativeDebugServer: Message received for missing plugin" << serviceName;
+ } else {
+ (*iter)->messageReceived(message);
+ }
+}
+
QList<QDeclarativeDebugService*> QDeclarativeDebugServer::services() const
{
const Q_D(QDeclarativeDebugServer);
@@ -374,4 +396,23 @@ void QDeclarativeDebugServer::sendMessage(QDeclarativeDebugService *service,
d->connection->send(msg);
}
+bool QDeclarativeDebugServer::waitForMessage(QDeclarativeDebugService *service)
+{
+ Q_D(QDeclarativeDebugServer);
+
+ if (!service
+ || !d->plugins.contains(service->name())
+ || !d->waitingForMsgFromService.isEmpty())
+ return false;
+
+ d->waitingForMsgFromService = service->name();
+
+ do {
+ d->connection->waitForMessage();
+ } while (!d->waitingForMsgFromService.isEmpty());
+ return true;
+}
+
QT_END_NAMESPACE
+
+#include "moc_qdeclarativedebugserver_p.cpp"
diff --git a/src/declarative/debugger/qdeclarativedebugserver_p.h b/src/declarative/debugger/qdeclarativedebugserver_p.h
index 68ea4d8..72c664c 100644
--- a/src/declarative/debugger/qdeclarativedebugserver_p.h
+++ b/src/declarative/debugger/qdeclarativedebugserver_p.h
@@ -75,10 +75,13 @@ public:
void sendMessage(QDeclarativeDebugService *service, const QByteArray &message);
void receiveMessage(const QByteArray &message);
+ bool waitForMessage(QDeclarativeDebugService *service);
+
private:
friend class QDeclarativeDebugService;
friend class QDeclarativeDebugServicePrivate;
QDeclarativeDebugServer();
+ Q_PRIVATE_SLOT(d_func(), void _q_deliverMessage(QString, QByteArray))
};
QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativedebugserverconnection_p.h b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h
index 0c2bdb4..ca267e0 100644
--- a/src/declarative/debugger/qdeclarativedebugserverconnection_p.h
+++ b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h
@@ -62,6 +62,7 @@ public:
virtual bool isConnected() const = 0;
virtual void send(const QByteArray &message) = 0;
virtual void disconnect() = 0;
+ virtual bool waitForMessage() = 0;
};
Q_DECLARE_INTERFACE(QDeclarativeDebugServerConnection, "com.trolltech.Qt.QDeclarativeDebugServerConnection/1.0")
diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp
index 1b39f1c..c7e6615 100644
--- a/src/declarative/debugger/qdeclarativedebugservice.cpp
+++ b/src/declarative/debugger/qdeclarativedebugservice.cpp
@@ -209,6 +209,16 @@ void QDeclarativeDebugService::sendMessage(const QByteArray &message)
d->server->sendMessage(this, message);
}
+bool QDeclarativeDebugService::waitForMessage()
+{
+ Q_D(QDeclarativeDebugService);
+
+ if (status() != Enabled)
+ return false;
+
+ return d->server->waitForMessage(this);
+}
+
void QDeclarativeDebugService::statusChanged(Status)
{
}
diff --git a/src/declarative/debugger/qdeclarativedebugservice_p.h b/src/declarative/debugger/qdeclarativedebugservice_p.h
index 5e30350..f3d1919 100644
--- a/src/declarative/debugger/qdeclarativedebugservice_p.h
+++ b/src/declarative/debugger/qdeclarativedebugservice_p.h
@@ -69,6 +69,7 @@ public:
Status status() const;
void sendMessage(const QByteArray &);
+ bool waitForMessage();
static int idForObject(QObject *);
static QObject *objectForId(int);
@@ -84,6 +85,7 @@ protected:
private:
friend class QDeclarativeDebugServer;
+ friend class QDeclarativeDebugServerPrivate;
};
QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp
index 6f28736..edbbe78 100644
--- a/src/declarative/debugger/qdeclarativedebugtrace.cpp
+++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp
@@ -65,9 +65,14 @@ QByteArray QDeclarativeDebugData::toByteArray() const
QDeclarativeDebugTrace::QDeclarativeDebugTrace()
: QDeclarativeDebugService(QLatin1String("CanvasFrameRate")),
- m_enabled(false), m_deferredSend(true)
+ m_enabled(false), m_deferredSend(true), m_messageReceived(false)
{
m_timer.start();
+ if (status() == Enabled) {
+ // wait for first message indicating whether to trace or not
+ while (!m_messageReceived)
+ waitForMessage();
+ }
}
void QDeclarativeDebugTrace::addEvent(EventType t)
@@ -213,6 +218,8 @@ void QDeclarativeDebugTrace::messageReceived(const QByteArray &message)
stream >> m_enabled;
+ m_messageReceived = true;
+
if (!m_enabled)
sendMessages();
}
diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h
index ae0653e..c74cbe0 100644
--- a/src/declarative/debugger/qdeclarativedebugtrace_p.h
+++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h
@@ -120,6 +120,7 @@ private:
QPerformanceTimer m_timer;
bool m_enabled;
bool m_deferredSend;
+ bool m_messageReceived;
QList<QDeclarativeDebugData> m_data;
};
diff --git a/src/declarative/debugger/qdeclarativeobserverinterface_p.h b/src/declarative/debugger/qdeclarativeobserverinterface_p.h
new file mode 100644
index 0000000..501c132
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeobserverinterface_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEOBSERVERINTERFACE_H
+#define QDECLARATIVEOBSERVERINTERFACE_H
+
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QDeclarativeObserverInterface
+{
+public:
+ QDeclarativeObserverInterface() {}
+ virtual ~QDeclarativeObserverInterface() {}
+
+ virtual void activate() = 0;
+ virtual void deactivate() = 0;
+};
+
+Q_DECLARE_INTERFACE(QDeclarativeObserverInterface, "com.trolltech.Qt.QDeclarativeObserverInterface/1.0")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEOBSERVERINTERFACE_H
diff --git a/src/declarative/debugger/qdeclarativeobserverservice.cpp b/src/declarative/debugger/qdeclarativeobserverservice.cpp
new file mode 100644
index 0000000..a623c55
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeobserverservice.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qdeclarativeobserverservice_p.h"
+#include "private/qdeclarativeobserverinterface_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QPluginLoader>
+
+#include <QtDeclarative/QDeclarativeView>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QDeclarativeObserverService, serviceInstance)
+
+QDeclarativeObserverService::QDeclarativeObserverService()
+ : QDeclarativeDebugService(QLatin1String("QDeclarativeObserverMode"))
+ , m_observer(0)
+{
+}
+
+QDeclarativeObserverService *QDeclarativeObserverService::instance()
+{
+ return serviceInstance();
+}
+
+void QDeclarativeObserverService::addView(QDeclarativeView *view)
+{
+ m_views.append(view);
+}
+
+void QDeclarativeObserverService::removeView(QDeclarativeView *view)
+{
+ m_views.removeAll(view);
+}
+
+void QDeclarativeObserverService::sendMessage(const QByteArray &message)
+{
+ if (status() != Enabled)
+ return;
+
+ QDeclarativeDebugService::sendMessage(message);
+}
+
+void QDeclarativeObserverService::statusChanged(Status status)
+{
+ if (m_views.isEmpty())
+ return;
+
+ if (status == Enabled) {
+ if (!m_observer)
+ m_observer = loadObserverPlugin();
+
+ if (!m_observer) {
+ qWarning() << "Error while loading observer plugin";
+ return;
+ }
+
+ m_observer->activate();
+ } else {
+ if (m_observer)
+ m_observer->deactivate();
+ }
+}
+
+void QDeclarativeObserverService::messageReceived(const QByteArray &message)
+{
+ emit gotMessage(message);
+}
+
+QDeclarativeObserverInterface *QDeclarativeObserverService::loadObserverPlugin()
+{
+ QStringList pluginCandidates;
+ const QStringList paths = QCoreApplication::libraryPaths();
+ foreach (const QString &libPath, paths) {
+ const QDir dir(libPath + QLatin1String("/qmltooling"));
+ if (dir.exists())
+ foreach (const QString &pluginPath, dir.entryList(QDir::Files))
+ pluginCandidates << dir.absoluteFilePath(pluginPath);
+ }
+
+ foreach (const QString &pluginPath, pluginCandidates) {
+ QPluginLoader loader(pluginPath);
+ if (!loader.load())
+ continue;
+
+ QDeclarativeObserverInterface *observer =
+ qobject_cast<QDeclarativeObserverInterface*>(loader.instance());
+
+ if (observer)
+ return observer;
+ loader.unload();
+ }
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativeobserverservice_p.h b/src/declarative/debugger/qdeclarativeobserverservice_p.h
new file mode 100644
index 0000000..36f31dc
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeobserverservice_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEOBSERVERSERVICE_H
+#define QDECLARATIVEOBSERVERSERVICE_H
+
+#include "private/qdeclarativedebugservice_p.h"
+#include <private/qdeclarativeglobal_p.h>
+
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeView;
+class QDeclarativeObserverInterface;
+
+class Q_DECLARATIVE_EXPORT QDeclarativeObserverService : public QDeclarativeDebugService
+{
+ Q_OBJECT
+
+public:
+ QDeclarativeObserverService();
+ static QDeclarativeObserverService *instance();
+
+ void addView(QDeclarativeView *);
+ void removeView(QDeclarativeView *);
+ QList<QDeclarativeView*> views() const { return m_views; }
+
+ void sendMessage(const QByteArray &message);
+
+Q_SIGNALS:
+ void gotMessage(const QByteArray &message);
+
+protected:
+ virtual void statusChanged(Status status);
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ static QDeclarativeObserverInterface *loadObserverPlugin();
+
+ QList<QDeclarativeView*> m_views;
+ QDeclarativeObserverInterface *m_observer;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEOBSERVERSERVICE_H
diff --git a/src/declarative/debugger/qjsdebuggeragent.cpp b/src/declarative/debugger/qjsdebuggeragent.cpp
new file mode 100644
index 0000000..601c8c8
--- /dev/null
+++ b/src/declarative/debugger/qjsdebuggeragent.cpp
@@ -0,0 +1,576 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qjsdebuggeragent_p.h"
+#include "private/qdeclarativedebughelper_p.h"
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qset.h>
+#include <QtCore/qurl.h>
+#include <QtScript/qscriptcontextinfo.h>
+#include <QtScript/qscriptengine.h>
+#include <QtScript/qscriptvalueiterator.h>
+
+QT_BEGIN_NAMESPACE
+
+class QJSDebuggerAgentPrivate
+{
+public:
+ QJSDebuggerAgentPrivate(QJSDebuggerAgent *q)
+ : q(q), state(NoState)
+ {}
+
+ void continueExec();
+ void recordKnownObjects(const QList<JSAgentWatchData> &);
+ QList<JSAgentWatchData> getLocals(QScriptContext *);
+ void positionChange(qint64 scriptId, int lineNumber, int columnNumber);
+ QScriptEngine *engine() { return q->engine(); }
+ void stopped();
+
+public:
+ QJSDebuggerAgent *q;
+ JSDebuggerState state;
+ int stepDepth;
+ int stepCount;
+
+ QEventLoop loop;
+ QHash<qint64, QString> filenames;
+ JSAgentBreakpoints breakpoints;
+ // breakpoints by filename (without path)
+ QHash<QString, JSAgentBreakpointData> fileNameToBreakpoints;
+ QStringList watchExpressions;
+ QSet<qint64> knownObjectIds;
+};
+
+namespace {
+
+class SetupExecEnv
+{
+public:
+ SetupExecEnv(QJSDebuggerAgentPrivate *a)
+ : agent(a),
+ previousState(a->state),
+ hadException(a->engine()->hasUncaughtException())
+ {
+ agent->state = StoppedState;
+ }
+
+ ~SetupExecEnv()
+ {
+ if (!hadException && agent->engine()->hasUncaughtException())
+ agent->engine()->clearExceptions();
+ agent->state = previousState;
+ }
+
+private:
+ QJSDebuggerAgentPrivate *agent;
+ JSDebuggerState previousState;
+ bool hadException;
+};
+
+} // anonymous namespace
+
+static JSAgentWatchData fromScriptValue(const QString &expression,
+ const QScriptValue &value)
+{
+ static const QString arrayStr = QCoreApplication::translate
+ ("Debugger::JSAgentWatchData", "[Array of length %1]");
+ static const QString undefinedStr = QCoreApplication::translate
+ ("Debugger::JSAgentWatchData", "<undefined>");
+
+ JSAgentWatchData data;
+ data.exp = expression.toUtf8();
+ data.name = data.exp;
+ data.hasChildren = false;
+ data.value = value.toString().toUtf8();
+ data.objectId = value.objectId();
+ if (value.isArray()) {
+ data.type = "Array";
+ data.value = arrayStr.arg(value.property(QLatin1String("length")).toString()).toUtf8();
+ data.hasChildren = true;
+ } else if (value.isBool()) {
+ data.type = "Bool";
+ // data.value = value.toBool() ? "true" : "false";
+ } else if (value.isDate()) {
+ data.type = "Date";
+ data.value = value.toDateTime().toString().toUtf8();
+ } else if (value.isError()) {
+ data.type = "Error";
+ } else if (value.isFunction()) {
+ data.type = "Function";
+ } else if (value.isUndefined()) {
+ data.type = undefinedStr.toUtf8();
+ } else if (value.isNumber()) {
+ data.type = "Number";
+ } else if (value.isRegExp()) {
+ data.type = "RegExp";
+ } else if (value.isString()) {
+ data.type = "String";
+ } else if (value.isVariant()) {
+ data.type = "Variant";
+ } else if (value.isQObject()) {
+ const QObject *obj = value.toQObject();
+ data.type = "Object";
+ data.value += '[';
+ data.value += obj->metaObject()->className();
+ data.value += ']';
+ data.hasChildren = true;
+ } else if (value.isObject()) {
+ data.type = "Object";
+ data.hasChildren = true;
+ data.value = "[Object]";
+ } else if (value.isNull()) {
+ data.type = "<null>";
+ } else {
+ data.type = "<unknown>";
+ }
+ return data;
+}
+
+static QList<JSAgentWatchData> expandObject(const QScriptValue &object)
+{
+ QList<JSAgentWatchData> result;
+ QScriptValueIterator it(object);
+ while (it.hasNext()) {
+ it.next();
+ if (it.flags() & QScriptValue::SkipInEnumeration)
+ continue;
+ if (/*object.isQObject() &&*/ it.value().isFunction()) {
+ // Cosmetics: skip all functions and slot, there are too many of them,
+ // and it is not useful information in the debugger.
+ continue;
+ }
+ JSAgentWatchData data = fromScriptValue(it.name(), it.value());
+ result.append(data);
+ }
+ if (result.isEmpty()) {
+ JSAgentWatchData data;
+ data.name = "<no initialized data>";
+ data.hasChildren = false;
+ data.value = " ";
+ data.objectId = 0;
+ result.append(data);
+ }
+ return result;
+}
+
+static QString fileName(const QString &fileUrl)
+{
+ int lastDelimiterPos = fileUrl.lastIndexOf(QLatin1Char('/'));
+ return fileUrl.mid(lastDelimiterPos, fileUrl.size() - lastDelimiterPos);
+}
+
+void QJSDebuggerAgentPrivate::recordKnownObjects(const QList<JSAgentWatchData>& list)
+{
+ foreach (const JSAgentWatchData &data, list)
+ knownObjectIds << data.objectId;
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgentPrivate::getLocals(QScriptContext *ctx)
+{
+ QList<JSAgentWatchData> locals;
+ if (ctx) {
+ QScriptValue activationObject = ctx->activationObject();
+ QScriptValue thisObject = ctx->thisObject();
+ locals = expandObject(activationObject);
+ if (thisObject.isObject()
+ && thisObject.objectId() != engine()->globalObject().objectId()
+ && QScriptValueIterator(thisObject).hasNext())
+ locals.prepend(fromScriptValue(QLatin1String("this"), thisObject));
+ recordKnownObjects(locals);
+ knownObjectIds << activationObject.objectId();
+ }
+ return locals;
+}
+
+/*!
+ Constructs a new agent for the given \a engine. The agent will
+ report debugging-related events (e.g. step completion) to the given
+ \a backend.
+*/
+QJSDebuggerAgent::QJSDebuggerAgent(QScriptEngine *engine, QObject *parent)
+ : QObject(parent)
+ , QScriptEngineAgent(engine)
+ , d(new QJSDebuggerAgentPrivate(this))
+{
+ QJSDebuggerAgent::engine()->setAgent(this);
+}
+
+QJSDebuggerAgent::QJSDebuggerAgent(QDeclarativeEngine *engine, QObject *parent)
+ : QObject(parent)
+ , QScriptEngineAgent(QDeclarativeDebugHelper::getScriptEngine(engine))
+ , d(new QJSDebuggerAgentPrivate(this))
+{
+ QJSDebuggerAgent::engine()->setAgent(this);
+}
+
+/*!
+ Destroys this QJSDebuggerAgent.
+*/
+QJSDebuggerAgent::~QJSDebuggerAgent()
+{
+ engine()->setAgent(0);
+ delete d;
+}
+
+void QJSDebuggerAgent::setBreakpoints(const JSAgentBreakpoints &breakpoints)
+{
+ d->breakpoints = breakpoints;
+
+ d->fileNameToBreakpoints.clear();
+ foreach (const JSAgentBreakpointData &bp, breakpoints)
+ d->fileNameToBreakpoints.insertMulti(fileName(QString::fromUtf8(bp.fileUrl)), bp);
+}
+
+void QJSDebuggerAgent::setWatchExpressions(const QStringList &watchExpressions)
+{
+ d->watchExpressions = watchExpressions;
+}
+
+void QJSDebuggerAgent::stepOver()
+{
+ d->stepDepth = 0;
+ d->state = SteppingOverState;
+ d->continueExec();
+}
+
+void QJSDebuggerAgent::stepInto()
+{
+ d->stepDepth = 0;
+ d->state = SteppingIntoState;
+ d->continueExec();
+}
+
+void QJSDebuggerAgent::stepOut()
+{
+ d->stepDepth = 0;
+ d->state = SteppingOutState;
+ d->continueExec();
+}
+
+void QJSDebuggerAgent::continueExecution()
+{
+ d->state = NoState;
+ d->continueExec();
+}
+
+JSAgentWatchData QJSDebuggerAgent::executeExpression(const QString &expr)
+{
+ SetupExecEnv execEnv(d);
+
+ JSAgentWatchData data = fromScriptValue(expr, engine()->evaluate(expr));
+ d->knownObjectIds << data.objectId;
+ return data;
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgent::expandObjectById(quint64 objectId)
+{
+ SetupExecEnv execEnv(d);
+
+ QScriptValue v;
+ if (d->knownObjectIds.contains(objectId))
+ v = engine()->objectById(objectId);
+
+ QList<JSAgentWatchData> result = expandObject(v);
+ d->recordKnownObjects(result);
+ return result;
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgent::locals()
+{
+ SetupExecEnv execEnv(d);
+ return d->getLocals(engine()->currentContext());
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgent::localsAtFrame(int frameId)
+{
+ SetupExecEnv execEnv(d);
+
+ int deep = 0;
+ QScriptContext *ctx = engine()->currentContext();
+ while (ctx && deep < frameId) {
+ ctx = ctx->parentContext();
+ deep++;
+ }
+
+ return d->getLocals(ctx);
+}
+
+QList<JSAgentStackData> QJSDebuggerAgent::backtrace()
+{
+ SetupExecEnv execEnv(d);
+
+ QList<JSAgentStackData> backtrace;
+
+ for (QScriptContext *ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
+ QScriptContextInfo info(ctx);
+
+ JSAgentStackData frame;
+ frame.functionName = info.functionName().toUtf8();
+ if (frame.functionName.isEmpty()) {
+ if (ctx->parentContext()) {
+ switch (info.functionType()) {
+ case QScriptContextInfo::ScriptFunction:
+ frame.functionName = "<anonymous>";
+ break;
+ case QScriptContextInfo::NativeFunction:
+ frame.functionName = "<native>";
+ break;
+ case QScriptContextInfo::QtFunction:
+ case QScriptContextInfo::QtPropertyFunction:
+ frame.functionName = "<native slot>";
+ break;
+ }
+ } else {
+ frame.functionName = "<global>";
+ }
+ }
+ frame.lineNumber = info.lineNumber();
+ // if the line number is unknown, fallback to the function line number
+ if (frame.lineNumber == -1)
+ frame.lineNumber = info.functionStartLineNumber();
+
+ frame.fileUrl = info.fileName().toUtf8();
+ backtrace.append(frame);
+ }
+
+ return backtrace;
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgent::watches()
+{
+ SetupExecEnv execEnv(d);
+
+ QList<JSAgentWatchData> watches;
+ foreach (const QString &expr, d->watchExpressions)
+ watches << fromScriptValue(expr, engine()->evaluate(expr));
+ d->recordKnownObjects(watches);
+ return watches;
+}
+
+void QJSDebuggerAgent::setProperty(qint64 objectId,
+ const QString &property,
+ const QString &value)
+{
+ SetupExecEnv execEnv(d);
+
+ if (d->knownObjectIds.contains(objectId)) {
+ QScriptValue object = engine()->objectById(objectId);
+ if (object.isObject()) {
+ QScriptValue result = engine()->evaluate(value);
+ object.setProperty(property, result);
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::scriptLoad(qint64 id, const QString &program,
+ const QString &fileName, int)
+{
+ Q_UNUSED(program);
+ d->filenames.insert(id, fileName);
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::scriptUnload(qint64 id)
+{
+ d->filenames.remove(id);
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::contextPush()
+{
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::contextPop()
+{
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::functionEntry(qint64 scriptId)
+{
+ Q_UNUSED(scriptId);
+ d->stepDepth++;
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue)
+{
+ Q_UNUSED(scriptId);
+ Q_UNUSED(returnValue);
+ d->stepDepth--;
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
+{
+ d->positionChange(scriptId, lineNumber, columnNumber);
+}
+
+void QJSDebuggerAgentPrivate::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
+{
+ Q_UNUSED(columnNumber);
+
+ if (state == StoppedState)
+ return; //no re-entrency
+
+ // check breakpoints
+ if (!breakpoints.isEmpty()) {
+ QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
+ QScriptContext *ctx = engine()->currentContext();
+ QScriptContextInfo info(ctx);
+ if (it == filenames.constEnd()) {
+ // It is possible that the scripts are loaded before the agent is attached
+ QString filename = info.fileName();
+
+ JSAgentStackData frame;
+ frame.functionName = info.functionName().toUtf8();
+
+ QPair<QString, qint32> key = qMakePair(filename, lineNumber);
+ it = filenames.insert(scriptId, filename);
+ }
+
+ const QString filePath = it.value();
+ JSAgentBreakpoints bps = fileNameToBreakpoints.values(fileName(filePath)).toSet();
+
+ foreach (const JSAgentBreakpointData &bp, bps) {
+ if (bp.lineNumber == lineNumber) {
+ stopped();
+ return;
+ }
+ }
+ }
+
+ switch (state) {
+ case NoState:
+ case StoppedState:
+ // Do nothing
+ break;
+ case SteppingOutState:
+ if (stepDepth >= 0)
+ break;
+ //fallthough
+ case SteppingOverState:
+ if (stepDepth > 0)
+ break;
+ //fallthough
+ case SteppingIntoState:
+ stopped();
+ break;
+ }
+
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::exceptionThrow(qint64 scriptId,
+ const QScriptValue &exception,
+ bool hasHandler)
+{
+ Q_UNUSED(scriptId);
+ Q_UNUSED(exception);
+ Q_UNUSED(hasHandler);
+// qDebug() << Q_FUNC_INFO << exception.toString() << hasHandler;
+#if 0 //sometimes, we get exceptions that we should just ignore.
+ if (!hasHandler && state != StoppedState)
+ stopped(true, exception);
+#endif
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::exceptionCatch(qint64 scriptId, const QScriptValue &exception)
+{
+ Q_UNUSED(scriptId);
+ Q_UNUSED(exception);
+}
+
+bool QJSDebuggerAgent::supportsExtension(Extension extension) const
+{
+ return extension == QScriptEngineAgent::DebuggerInvocationRequest;
+}
+
+QVariant QJSDebuggerAgent::extension(Extension extension, const QVariant &argument)
+{
+ if (extension == QScriptEngineAgent::DebuggerInvocationRequest) {
+ d->stopped();
+ return QVariant();
+ }
+ return QScriptEngineAgent::extension(extension, argument);
+}
+
+void QJSDebuggerAgentPrivate::stopped()
+{
+ bool becauseOfException = false;
+ const QScriptValue &exception = QScriptValue();
+
+ knownObjectIds.clear();
+ state = StoppedState;
+
+ emit q->stopped(becauseOfException, exception.toString());
+
+ loop.exec(QEventLoop::ExcludeUserInputEvents);
+}
+
+void QJSDebuggerAgentPrivate::continueExec()
+{
+ loop.quit();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qjsdebuggeragent_p.h b/src/declarative/debugger/qjsdebuggeragent_p.h
new file mode 100644
index 0000000..ce5a044
--- /dev/null
+++ b/src/declarative/debugger/qjsdebuggeragent_p.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QJSDEBUGGERAGENT_P_H
+#define QJSDEBUGGERAGENT_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 <QtScript/qscriptengineagent.h>
+#include <QtCore/qset.h>
+
+QT_BEGIN_NAMESPACE
+class QScriptValue;
+class QDeclarativeEngine;
+QT_END_NAMESPACE
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QJSDebuggerAgentPrivate;
+
+enum JSDebuggerState
+{
+ NoState,
+ SteppingIntoState,
+ SteppingOverState,
+ SteppingOutState,
+ StoppedState
+};
+
+struct JSAgentWatchData
+{
+ QByteArray exp;
+ QByteArray name;
+ QByteArray value;
+ QByteArray type;
+ bool hasChildren;
+ quint64 objectId;
+};
+
+inline QDataStream &operator<<(QDataStream &s, const JSAgentWatchData &data)
+{
+ return s << data.exp << data.name << data.value
+ << data.type << data.hasChildren << data.objectId;
+}
+
+struct JSAgentStackData
+{
+ QByteArray functionName;
+ QByteArray fileUrl;
+ qint32 lineNumber;
+};
+
+inline QDataStream &operator<<(QDataStream &s, const JSAgentStackData &data)
+{
+ return s << data.functionName << data.fileUrl << data.lineNumber;
+}
+
+struct JSAgentBreakpointData
+{
+ QByteArray functionName;
+ QByteArray fileUrl;
+ qint32 lineNumber;
+};
+
+typedef QSet<JSAgentBreakpointData> JSAgentBreakpoints;
+
+inline QDataStream &operator<<(QDataStream &s, const JSAgentBreakpointData &data)
+{
+ return s << data.functionName << data.fileUrl << data.lineNumber;
+}
+
+inline QDataStream &operator>>(QDataStream &s, JSAgentBreakpointData &data)
+{
+ return s >> data.functionName >> data.fileUrl >> data.lineNumber;
+}
+
+inline bool operator==(const JSAgentBreakpointData &b1, const JSAgentBreakpointData &b2)
+{
+ return b1.lineNumber == b2.lineNumber && b1.fileUrl == b2.fileUrl;
+}
+
+inline uint qHash(const JSAgentBreakpointData &b)
+{
+ return b.lineNumber ^ qHash(b.fileUrl);
+}
+
+
+class QJSDebuggerAgent : public QObject, public QScriptEngineAgent
+{
+ Q_OBJECT
+
+public:
+ QJSDebuggerAgent(QScriptEngine *engine, QObject *parent = 0);
+ QJSDebuggerAgent(QDeclarativeEngine *engine, QObject *parent = 0);
+ ~QJSDebuggerAgent();
+
+ void setBreakpoints(const JSAgentBreakpoints &);
+ void setWatchExpressions(const QStringList &);
+
+ void stepOver();
+ void stepInto();
+ void stepOut();
+ void continueExecution();
+
+ JSAgentWatchData executeExpression(const QString &expr);
+ QList<JSAgentWatchData> expandObjectById(quint64 objectId);
+ QList<JSAgentWatchData> locals();
+ QList<JSAgentWatchData> localsAtFrame(int frameId);
+ QList<JSAgentStackData> backtrace();
+ QList<JSAgentWatchData> watches();
+ void setProperty(qint64 objectId,
+ const QString &property,
+ const QString &value);
+
+ // reimplemented
+ void scriptLoad(qint64 id, const QString &program,
+ const QString &fileName, int baseLineNumber);
+ void scriptUnload(qint64 id);
+
+ void contextPush();
+ void contextPop();
+
+ void functionEntry(qint64 scriptId);
+ void functionExit(qint64 scriptId,
+ const QScriptValue &returnValue);
+
+ void positionChange(qint64 scriptId,
+ int lineNumber, int columnNumber);
+
+ void exceptionThrow(qint64 scriptId,
+ const QScriptValue &exception,
+ bool hasHandler);
+ void exceptionCatch(qint64 scriptId,
+ const QScriptValue &exception);
+
+ bool supportsExtension(Extension extension) const;
+ QVariant extension(Extension extension,
+ const QVariant &argument = QVariant());
+
+Q_SIGNALS:
+ void stopped(bool becauseOfException,
+ const QString &exception);
+
+private:
+ friend class QJSDebuggerAgentPrivate;
+ QJSDebuggerAgentPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QJSDEBUGGERAGENT_P_H
diff --git a/src/declarative/debugger/qjsdebugservice.cpp b/src/declarative/debugger/qjsdebugservice.cpp
new file mode 100644
index 0000000..f8cd095
--- /dev/null
+++ b/src/declarative/debugger/qjsdebugservice.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qjsdebugservice_p.h"
+#include "private/qjsdebuggeragent_p.h"
+
+#include <QtCore/qdatastream.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+
+Q_GLOBAL_STATIC(QJSDebugService, serviceInstance)
+
+QJSDebugService::QJSDebugService(QObject *parent)
+ : QDeclarativeDebugService(QLatin1String("JSDebugger"), parent)
+ , m_agent(0)
+{
+}
+
+QJSDebugService::~QJSDebugService()
+{
+ delete m_agent;
+}
+
+QJSDebugService *QJSDebugService::instance()
+{
+ return serviceInstance();
+}
+
+void QJSDebugService::addEngine(QDeclarativeEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(!m_engines.contains(engine));
+
+ m_engines.append(engine);
+}
+
+void QJSDebugService::removeEngine(QDeclarativeEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(m_engines.contains(engine));
+
+ m_engines.removeAll(engine);
+}
+
+void QJSDebugService::statusChanged(Status status)
+{
+ if (status == Enabled && !m_engines.isEmpty() && !m_agent) {
+ // Multiple engines are currently unsupported
+ QDeclarativeEngine *engine = m_engines.first();
+ m_agent = new QJSDebuggerAgent(engine, engine);
+
+ connect(m_agent, SIGNAL(stopped(bool,QString)),
+ this, SLOT(executionStopped(bool,QString)));
+
+ } else if (status != Enabled && m_agent) {
+ delete m_agent;
+ m_agent = 0;
+ }
+}
+
+void QJSDebugService::messageReceived(const QByteArray &message)
+{
+ if (!m_agent) {
+ qWarning() << "QJSDebugService::messageReceived: No QJSDebuggerAgent available";
+ return;
+ }
+
+ QDataStream ds(message);
+ QByteArray command;
+ ds >> command;
+ if (command == "BREAKPOINTS") {
+ JSAgentBreakpoints breakpoints;
+ ds >> breakpoints;
+ m_agent->setBreakpoints(breakpoints);
+
+ //qDebug() << "BREAKPOINTS";
+ //foreach (const JSAgentBreakpointData &bp, breakpoints)
+ // qDebug() << "BREAKPOINT: " << bp.fileUrl << bp.lineNumber;
+ } else if (command == "WATCH_EXPRESSIONS") {
+ QStringList watchExpressions;
+ ds >> watchExpressions;
+ m_agent->setWatchExpressions(watchExpressions);
+ } else if (command == "STEPOVER") {
+ m_agent->stepOver();
+ } else if (command == "STEPINTO" || command == "INTERRUPT") {
+ m_agent->stepInto();
+ } else if (command == "STEPOUT") {
+ m_agent->stepOut();
+ } else if (command == "CONTINUE") {
+ m_agent->continueExecution();
+ } else if (command == "EXEC") {
+ QByteArray id;
+ QString expr;
+ ds >> id >> expr;
+
+ JSAgentWatchData data = m_agent->executeExpression(expr);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("RESULT") << id << data;
+ sendMessage(reply);
+ } else if (command == "EXPAND") {
+ QByteArray requestId;
+ quint64 objectId;
+ ds >> requestId >> objectId;
+
+ QList<JSAgentWatchData> result = m_agent->expandObjectById(objectId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("EXPANDED") << requestId << result;
+ sendMessage(reply);
+ } else if (command == "ACTIVATE_FRAME") {
+ int frameId;
+ ds >> frameId;
+
+ QList<JSAgentWatchData> locals = m_agent->localsAtFrame(frameId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("LOCALS") << frameId << locals;
+ sendMessage(reply);
+ } else if (command == "SET_PROPERTY") {
+ QByteArray id;
+ qint64 objectId;
+ QString property;
+ QString value;
+ ds >> id >> objectId >> property >> value;
+
+ m_agent->setProperty(objectId, property, value);
+
+ //TODO: feedback
+ } else if (command == "PING") {
+ int ping;
+ ds >> ping;
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("PONG") << ping;
+ sendMessage(reply);
+ } else {
+ qDebug() << Q_FUNC_INFO << "Unknown command" << command;
+ }
+
+ QDeclarativeDebugService::messageReceived(message);
+}
+
+void QJSDebugService::executionStopped(bool becauseOfException,
+ const QString &exception)
+{
+ const QList<JSAgentStackData> backtrace = m_agent->backtrace();
+ const QList<JSAgentWatchData> watches = m_agent->watches();
+ const QList<JSAgentWatchData> locals = m_agent->locals();
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("STOPPED") << backtrace << watches << locals
+ << becauseOfException << exception;
+ sendMessage(reply);
+}
diff --git a/src/declarative/debugger/qjsdebugservice_p.h b/src/declarative/debugger/qjsdebugservice_p.h
new file mode 100644
index 0000000..6839ca8
--- /dev/null
+++ b/src/declarative/debugger/qjsdebugservice_p.h
@@ -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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QJSDEBUGSERVICE_P_H
+#define QJSDEBUGSERVICE_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 <QtCore/QPointer>
+
+#include "private/qdeclarativedebugservice_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeEngine;
+class QJSDebuggerAgent;
+
+class QJSDebugService : public QDeclarativeDebugService
+{
+ Q_OBJECT
+
+public:
+ QJSDebugService(QObject *parent = 0);
+ ~QJSDebugService();
+
+ static QJSDebugService *instance();
+
+ void addEngine(QDeclarativeEngine *);
+ void removeEngine(QDeclarativeEngine *);
+
+protected:
+ void statusChanged(Status status);
+ void messageReceived(const QByteArray &);
+
+private Q_SLOTS:
+ void executionStopped(bool becauseOfException,
+ const QString &exception);
+
+private:
+ QList<QDeclarativeEngine *> m_engines;
+ QPointer<QJSDebuggerAgent> m_agent;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QJSDEBUGSERVICE_P_H
diff --git a/src/declarative/debugger/qpacketprotocol.cpp b/src/declarative/debugger/qpacketprotocol.cpp
index 15a14cf..c1034a7 100644
--- a/src/declarative/debugger/qpacketprotocol.cpp
+++ b/src/declarative/debugger/qpacketprotocol.cpp
@@ -42,6 +42,7 @@
#include "private/qpacketprotocol_p.h"
#include <QBuffer>
+#include <QElapsedTimer>
QT_BEGIN_NAMESPACE
@@ -114,7 +115,7 @@ Q_OBJECT
public:
QPacketProtocolPrivate(QPacketProtocol * parent, QIODevice * _dev)
: QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
- dev(_dev)
+ waitingForPacket(false), dev(_dev)
{
Q_ASSERT(4 == sizeof(qint32));
@@ -125,7 +126,7 @@ public:
QObject::connect(this, SIGNAL(invalidPacket()),
parent, SIGNAL(invalidPacket()));
QObject::connect(dev, SIGNAL(readyRead()),
- this, SLOT(readyToRead()), Qt::QueuedConnection);
+ this, SLOT(readyToRead()));
QObject::connect(dev, SIGNAL(aboutToClose()),
this, SLOT(aboutToClose()));
QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
@@ -200,6 +201,7 @@ public Q_SLOTS:
inProgress.clear();
emit readyRead();
+ waitingForPacket = false;
// Need to get trailing data
readyToRead();
@@ -213,6 +215,7 @@ public:
QByteArray inProgress;
qint32 inProgressSize;
qint32 maxPacketSize;
+ bool waitingForPacket;
QIODevice * dev;
};
@@ -324,6 +327,48 @@ QPacket QPacketProtocol::read()
return rv;
}
+/*
+ Returns the difference between msecs and elapsed. If msecs is -1,
+ however, -1 is returned.
+*/
+static int qt_timeout_value(int msecs, int elapsed)
+{
+ if (msecs == -1)
+ return -1;
+
+ int timeout = msecs - elapsed;
+ return timeout < 0 ? 0 : timeout;
+}
+
+/*!
+ This function locks until a new packet is available for reading and the
+ \l{QIODevice::}{readyRead()} signal has been emitted. The function
+ will timeout after \a msecs milliseconds; the default timeout is
+ 30000 milliseconds.
+
+ The function returns true if the readyRead() signal is emitted and
+ there is new data available for reading; otherwise it returns false
+ (if an error occurred or the operation timed out).
+ */
+
+bool QPacketProtocol::waitForReadyRead(int msecs)
+{
+ if (!d->packets.isEmpty())
+ return true;
+
+ QElapsedTimer stopWatch;
+ stopWatch.start();
+
+ d->waitingForPacket = true;
+ do {
+ if (!d->dev->waitForReadyRead(msecs))
+ return false;
+ if (!d->waitingForPacket)
+ return true;
+ msecs = qt_timeout_value(msecs, stopWatch.elapsed());
+ } while (true);
+}
+
/*!
Return the QIODevice passed to the QPacketProtocol constructor.
*/
diff --git a/src/declarative/debugger/qpacketprotocol_p.h b/src/declarative/debugger/qpacketprotocol_p.h
index accb8ef..22bc3c2 100644
--- a/src/declarative/debugger/qpacketprotocol_p.h
+++ b/src/declarative/debugger/qpacketprotocol_p.h
@@ -75,6 +75,8 @@ public:
qint64 packetsAvailable() const;
QPacket read();
+ bool waitForReadyRead(int msecs = 3000);
+
void clear();
QIODevice * device();
diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h
index 5da7901..28a6be4 100644
--- a/src/declarative/qml/qdeclarative.h
+++ b/src/declarative/qml/qdeclarative.h
@@ -405,6 +405,17 @@ QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true)
return qmlAttachedPropertiesObject(&idx, obj, &T::staticMetaObject, create);
}
+// Enable debugging before any QDeclarativeEngine is created
+struct Q_DECLARATIVE_EXPORT QDeclarativeDebuggingEnabler
+{
+ QDeclarativeDebuggingEnabler();
+};
+
+// Execute code in constructor before first QDeclarativeEngine is instantiated
+#if defined(QT_DECLARATIVE_DEBUG)
+static QDeclarativeDebuggingEnabler qmlEnableDebuggingHelper;
+#endif
+
QT_END_NAMESPACE
QML_DECLARE_TYPE(QObject)
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 9fde18c..aa4bcd4 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -71,6 +71,7 @@
#include "private/qdeclarativenotifier_p.h"
#include "private/qdeclarativedebugtrace_p.h"
#include "private/qdeclarativeapplication_p.h"
+#include "private/qjsdebugservice_p.h"
#include <QtCore/qmetaobject.h>
#include <QScriptClass>
@@ -123,7 +124,7 @@ QT_BEGIN_NAMESPACE
\brief The QtObject element is the most basic element in QML.
The QtObject element is a non-visual element which contains only the
- objectName property.
+ objectName property.
It can be useful to create a QtObject if you need an extremely
lightweight element to enclose a set of custom properties:
@@ -138,7 +139,7 @@ QT_BEGIN_NAMESPACE
This property holds the QObject::objectName for this specific object instance.
This allows a C++ application to locate an item within a QML component
- using the QObject::findChild() method. For example, the following C++
+ using the QObject::findChild() method. For example, the following C++
application locates the child \l Rectangle item and dynamically changes its
\c color value:
@@ -152,7 +153,7 @@ QT_BEGIN_NAMESPACE
Rectangle {
anchors.fill: parent
- color: "red"
+ color: "red"
objectName: "myRect"
}
}
@@ -166,7 +167,7 @@ QT_BEGIN_NAMESPACE
view.show();
QDeclarativeItem *item = view.rootObject()->findChild<QDeclarativeItem*>("myRect");
- if (item)
+ if (item)
item->setProperty("color", QColor(Qt::yellow));
\endcode
*/
@@ -202,7 +203,7 @@ void QDeclarativeEnginePrivate::defineModule()
\keyword QmlGlobalQtObject
-\brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
+\brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
The \c Qt object is a global object with utility functions, properties and enums.
@@ -583,6 +584,7 @@ void QDeclarativeEnginePrivate::init()
QDeclarativeEngineDebugServer::isDebuggingEnabled()) {
isDebugging = true;
QDeclarativeEngineDebugServer::instance()->addEngine(q);
+ QJSDebugService::instance()->addEngine(q);
}
}
@@ -645,8 +647,10 @@ QDeclarativeEngine::QDeclarativeEngine(QObject *parent)
QDeclarativeEngine::~QDeclarativeEngine()
{
Q_D(QDeclarativeEngine);
- if (d->isDebugging)
+ if (d->isDebugging) {
QDeclarativeEngineDebugServer::instance()->remEngine(this);
+ QJSDebugService::instance()->removeEngine(this);
+ }
}
/*! \fn void QDeclarativeEngine::quit()
@@ -757,7 +761,7 @@ QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
/*!
Sets the \a provider to use for images requested via the \e
- image: url scheme, with host \a providerId. The QDeclarativeEngine
+ image: url scheme, with host \a providerId. The QDeclarativeEngine
takes ownership of \a provider.
Image providers enable support for pixmap and threaded image
@@ -1066,7 +1070,7 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre
rv = pf(const_cast<QObject *>(object));
- if (rv)
+ if (rv)
data->attachedProperties()->insert(id, rv);
return rv;
@@ -1084,6 +1088,17 @@ QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
return qmlAttachedPropertiesObjectById(*idCache, object, create);
}
+QDeclarativeDebuggingEnabler::QDeclarativeDebuggingEnabler()
+{
+#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
+ if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
+ qWarning("Qml debugging is enabled. Only use this in a safe environment!");
+ }
+ QDeclarativeEnginePrivate::qml_debugging_enabled = true;
+#endif
+}
+
+
class QDeclarativeDataExtended {
public:
QDeclarativeDataExtended();
@@ -1258,7 +1273,7 @@ Returns a \l Component object created using the QML file at the specified \a url
or \c null if an empty string was given.
The returned component's \l Component::status property indicates whether the
-component was successfully created. If the status is \c Component.Error,
+component was successfully created. If the status is \c Component.Error,
see \l Component::errorString() for an error description.
Call \l {Component::createObject()}{Component.createObject()} on the returned
@@ -1311,6 +1326,8 @@ Example (where \c parentItem is the id of an existing QML item):
In the case of an error, a QtScript Error object is thrown. This object has an additional property,
\c qmlErrors, which is an array of the errors encountered.
Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message.
+For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following:
+{ "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}.
Note that this function returns immediately, and therefore may not work if
the \a qml string loads new components (that is, external QML files that have not yet been loaded).
@@ -1618,7 +1635,7 @@ QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScr
return engine->newVariant(QVariant::fromValue(date.toString(format)));
} else if (formatArg.isNumber()) {
enumFormat = Qt::DateFormat(formatArg.toUInt32());
- } else {
+ } else {
return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid datetime format"));
}
}
@@ -1683,7 +1700,7 @@ QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine
}
/*!
-\qmlmethod rect Qt::rect(int x, int y, int width, int height)
+\qmlmethod rect Qt::rect(int x, int y, int width, int height)
Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
@@ -1855,7 +1872,7 @@ Binary to ASCII - this function returns a base64 encoding of \c data.
*/
QScriptValue QDeclarativeEnginePrivate::btoa(QScriptContext *ctxt, QScriptEngine *)
{
- if (ctxt->argumentCount() != 1)
+ if (ctxt->argumentCount() != 1)
return ctxt->throwError(QLatin1String("Qt.btoa(): Invalid arguments"));
QByteArray data = ctxt->argument(0).toString().toUtf8();
@@ -1870,7 +1887,7 @@ ASCII to binary - this function returns a base64 decoding of \c data.
QScriptValue QDeclarativeEnginePrivate::atob(QScriptContext *ctxt, QScriptEngine *)
{
- if (ctxt->argumentCount() != 1)
+ if (ctxt->argumentCount() != 1)
return ctxt->throwError(QLatin1String("Qt.atob(): Invalid arguments"));
QByteArray data = ctxt->argument(0).toString().toUtf8();
@@ -2289,7 +2306,7 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObj
}
}
-QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
+QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
QDeclarativeError &error)
{
QList<QDeclarativeType *> types;
@@ -2298,7 +2315,7 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeTy
const QMetaObject *metaObject = type->metaObject();
while (metaObject) {
- QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
+ QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
type->majorVersion(), minorVersion);
if (t) {
maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
@@ -2342,7 +2359,7 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeTy
// Signals override:
// * other signals and methods of the same name.
- // * properties named on<Signal Name>
+ // * properties named on<Signal Name>
// * automatic <property name>Changed notify signals
// Methods override:
@@ -2367,7 +2384,7 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeTy
QDeclarativePropertyCache::Data *current = d;
while (!overloadError && current) {
current = d->overrideData(current);
- if (current && raw->isAllowedInRevision(current))
+ if (current && raw->isAllowedInRevision(current))
overloadError = true;
}
}
@@ -2375,7 +2392,7 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeTy
if (overloadError) {
if (hasCopied) raw->release();
-
+
error.setDescription(QLatin1String("Type ") + QString::fromUtf8(type->qmlTypeName()) + QLatin1String(" ") + QString::number(type->majorVersion()) + QLatin1String(".") + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation."));
return 0;
}
diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h
index 88b4e80..fd851f7 100644
--- a/src/declarative/qml/qdeclarativeengine_p.h
+++ b/src/declarative/qml/qdeclarativeengine_p.h
@@ -95,7 +95,6 @@ class QDeclarativeImportDatabase;
class QDeclarativeObjectScriptClass;
class QDeclarativeTypeNameScriptClass;
class QDeclarativeValueTypeScriptClass;
-class QScriptEngineDebugger;
class QNetworkReply;
class QNetworkAccessManager;
class QDeclarativeNetworkAccessManagerFactory;
@@ -332,14 +331,14 @@ public:
/*!
Returns a QDeclarativePropertyCache for \a obj if one is available.
-If \a obj is null, being deleted or contains a dynamic meta object 0
+If \a obj is null, being deleted or contains a dynamic meta object 0
is returned.
The returned cache is not referenced, so if it is to be stored, call addref().
*/
-QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QObject *obj)
+QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QObject *obj)
{
- if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
+ if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
return 0;
const QMetaObject *mo = obj->metaObject();
@@ -349,10 +348,10 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QObject *obj)
}
/*!
-Returns a QDeclarativePropertyCache for \a metaObject.
+Returns a QDeclarativePropertyCache for \a metaObject.
As the cache is persisted for the life of the engine, \a metaObject must be
-a static "compile time" meta-object, or a meta-object that is otherwise known to
+a static "compile time" meta-object, or a meta-object that is otherwise known to
exist for the lifetime of the QDeclarativeEngine.
The returned cache is not referenced, so if it is to be stored, call addref().
diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp
index b2a05c3..b7b88c9 100644
--- a/src/declarative/qml/qdeclarativeenginedebug.cpp
+++ b/src/declarative/qml/qdeclarativeenginedebug.cpp
@@ -524,8 +524,13 @@ void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message)
QString propertyName;
QVariant expr;
bool isLiteralValue;
+ QString filename;
+ int line;
ds >> objectId >> propertyName >> expr >> isLiteralValue;
- setBinding(objectId, propertyName, expr, isLiteralValue);
+ if (!ds.atEnd()) { // backward compatibility from 2.1, 2.2
+ ds >> filename >> line;
+ }
+ setBinding(objectId, propertyName, expr, isLiteralValue, filename, line);
} else if (type == "RESET_BINDING") {
int objectId;
QString propertyName;
@@ -543,7 +548,9 @@ void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message)
void QDeclarativeEngineDebugServer::setBinding(int objectId,
const QString &propertyName,
const QVariant &expression,
- bool isLiteralValue)
+ bool isLiteralValue,
+ QString filename,
+ int line)
{
QObject *object = objectForId(objectId);
QDeclarativeContext *context = qmlContext(object);
@@ -565,6 +572,7 @@ void QDeclarativeEngineDebugServer::setBinding(int objectId,
newBinding = new QDeclarativeBinding(expression.toString(), object, context);
newBinding->setTarget(property);
newBinding->setNotifyOnValueChanged(true);
+ newBinding->setSourceLocation(filename, line);
}
state->changeBindingInRevertList(object, propertyName, newBinding);
@@ -580,11 +588,12 @@ void QDeclarativeEngineDebugServer::setBinding(int objectId,
property.write(expression);
} else if (hasValidSignal(object, propertyName)) {
QDeclarativeExpression *declarativeExpression = new QDeclarativeExpression(context, object, expression.toString());
- QDeclarativeExpression *oldExpression = QDeclarativePropertyPrivate::setSignalExpression(property, declarativeExpression);
- declarativeExpression->setSourceLocation(oldExpression->sourceFile(), oldExpression->lineNumber());
+ QDeclarativePropertyPrivate::setSignalExpression(property, declarativeExpression);
+ declarativeExpression->setSourceLocation(filename, line);
} else if (property.isProperty()) {
QDeclarativeBinding *binding = new QDeclarativeBinding(expression.toString(), object, context);
binding->setTarget(property);
+ binding->setSourceLocation(filename, line);
binding->setNotifyOnValueChanged(true);
QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, binding);
if (oldBinding)
@@ -644,7 +653,10 @@ void QDeclarativeEngineDebugServer::resetBinding(int objectId, const QString &pr
}
}
}
- } else {
+ } else if (hasValidSignal(object, propertyName)) {
+ QDeclarativeProperty property(object, propertyName, context);
+ QDeclarativePropertyPrivate::setSignalExpression(property, 0);
+ } else {
if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
propertyChanges->removeProperty(propertyName);
}
diff --git a/src/declarative/qml/qdeclarativeenginedebug_p.h b/src/declarative/qml/qdeclarativeenginedebug_p.h
index e95676c..64b2724 100644
--- a/src/declarative/qml/qdeclarativeenginedebug_p.h
+++ b/src/declarative/qml/qdeclarativeenginedebug_p.h
@@ -115,7 +115,7 @@ private:
QDeclarativeObjectData objectData(QObject *);
QDeclarativeObjectProperty propertyData(QObject *, int);
QVariant valueContents(const QVariant &defaultValue) const;
- void setBinding(int objectId, const QString &propertyName, const QVariant &expression, bool isLiteralValue);
+ void setBinding(int objectId, const QString &propertyName, const QVariant &expression, bool isLiteralValue, QString filename = QString(), int line = -1);
void resetBinding(int objectId, const QString &propertyName);
void setMethodBody(int objectId, const QString &method, const QString &body);
diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp
index e24f80f..628c82c 100644
--- a/src/declarative/util/qdeclarativeview.cpp
+++ b/src/declarative/util/qdeclarativeview.cpp
@@ -49,6 +49,7 @@
#include <qdeclarativeguard_p.h>
#include <private/qdeclarativedebugtrace_p.h>
+#include <private/qdeclarativeobserverservice_p.h>
#include <qscriptvalueiterator.h>
#include <qdebug.h>
@@ -299,6 +300,8 @@ void QDeclarativeViewPrivate::init()
q->viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
q->viewport()->setAttribute(Qt::WA_NoSystemBackground);
#endif
+
+ QDeclarativeObserverService::instance()->addView(q);
}
/*!
@@ -306,6 +309,7 @@ void QDeclarativeViewPrivate::init()
*/
QDeclarativeView::~QDeclarativeView()
{
+ QDeclarativeObserverService::instance()->removeView(this);
}
/*! \property QDeclarativeView::source
@@ -558,7 +562,6 @@ void QDeclarativeView::continueExecute()
emit statusChanged(status());
}
-
/*!
\internal
*/
diff --git a/src/plugins/qmltooling/declarativeobserver/declarativeobserver.pro b/src/plugins/qmltooling/declarativeobserver/declarativeobserver.pro
new file mode 100644
index 0000000..bccabcb
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/declarativeobserver.pro
@@ -0,0 +1,53 @@
+TARGET = declarativeobserver
+QT += declarative
+
+include(../../qpluginbase.pri)
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/qmltooling
+QTDIR_build:REQUIRES += "contains(QT_CONFIG, declarative)"
+
+SOURCES += \
+ qdeclarativeobserverplugin.cpp \
+ qdeclarativeviewobserver.cpp \
+ editor/abstractliveedittool.cpp \
+ editor/liveselectiontool.cpp \
+ editor/livelayeritem.cpp \
+ editor/livesingleselectionmanipulator.cpp \
+ editor/liverubberbandselectionmanipulator.cpp \
+ editor/liveselectionrectangle.cpp \
+ editor/liveselectionindicator.cpp \
+ editor/boundingrecthighlighter.cpp \
+ editor/subcomponenteditortool.cpp \
+ editor/subcomponentmasklayeritem.cpp \
+ editor/zoomtool.cpp \
+ editor/colorpickertool.cpp \
+ editor/qmltoolbar.cpp \
+ editor/toolbarcolorbox.cpp
+
+HEADERS += \
+ qdeclarativeobserverplugin.h \
+ qdeclarativeobserverprotocol.h \
+ qdeclarativeviewobserver_p.h \
+ qdeclarativeviewobserver_p_p.h \
+ qmlobserverconstants_p.h \
+ editor/abstractliveedittool_p.h \
+ editor/liveselectiontool_p.h \
+ editor/livelayeritem_p.h \
+ editor/livesingleselectionmanipulator_p.h \
+ editor/liverubberbandselectionmanipulator_p.h \
+ editor/liveselectionrectangle_p.h \
+ editor/liveselectionindicator_p.h \
+ editor/boundingrecthighlighter_p.h \
+ editor/subcomponenteditortool_p.h \
+ editor/subcomponentmasklayeritem_p.h \
+ editor/zoomtool_p.h \
+ editor/colorpickertool_p.h \
+ editor/qmltoolbar_p.h \
+ editor/toolbarcolorbox_p.h
+
+RESOURCES += editor/editor.qrc
+
+target.path += $$[QT_INSTALL_PLUGINS]/qmltooling
+INSTALLS += target
+
+symbian:TARGET.UID3=0x20031E90
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool.cpp b/src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool.cpp
new file mode 100644
index 0000000..b3ed22e
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractliveedittool_p.h"
+#include "../qdeclarativeviewobserver_p_p.h"
+
+#include <QDeclarativeEngine>
+
+#include <QtDebug>
+#include <QGraphicsItem>
+#include <QDeclarativeItem>
+
+QT_BEGIN_NAMESPACE
+
+AbstractLiveEditTool::AbstractLiveEditTool(QDeclarativeViewObserver *editorView)
+ : QObject(editorView), m_observer(editorView)
+{
+}
+
+
+AbstractLiveEditTool::~AbstractLiveEditTool()
+{
+}
+
+QDeclarativeViewObserver *AbstractLiveEditTool::observer() const
+{
+ return m_observer;
+}
+
+QDeclarativeView *AbstractLiveEditTool::view() const
+{
+ return m_observer->declarativeView();
+}
+
+QGraphicsScene* AbstractLiveEditTool::scene() const
+{
+ return view()->scene();
+}
+
+void AbstractLiveEditTool::updateSelectedItems()
+{
+ selectedItemsChanged(items());
+}
+
+QList<QGraphicsItem*> AbstractLiveEditTool::items() const
+{
+ return observer()->selectedItems();
+}
+
+void AbstractLiveEditTool::enterContext(QGraphicsItem *itemToEnter)
+{
+ observer()->data->enterContext(itemToEnter);
+}
+
+bool AbstractLiveEditTool::topItemIsMovable(const QList<QGraphicsItem*> & itemList)
+{
+ QGraphicsItem *firstSelectableItem = topMovableGraphicsItem(itemList);
+ if (firstSelectableItem == 0)
+ return false;
+ if (toQDeclarativeItem(firstSelectableItem) != 0)
+ return true;
+
+ return false;
+
+}
+
+bool AbstractLiveEditTool::topSelectedItemIsMovable(const QList<QGraphicsItem*> &itemList)
+{
+ QList<QGraphicsItem*> selectedItems = observer()->selectedItems();
+
+ foreach (QGraphicsItem *item, itemList) {
+ QDeclarativeItem *declarativeItem = toQDeclarativeItem(item);
+ if (declarativeItem
+ && selectedItems.contains(declarativeItem)
+ /*&& (declarativeItem->qmlItemNode().hasShowContent() || selectNonContentItems)*/)
+ return true;
+ }
+
+ return false;
+
+}
+
+bool AbstractLiveEditTool::topItemIsResizeHandle(const QList<QGraphicsItem*> &/*itemList*/)
+{
+ return false;
+}
+
+QDeclarativeItem *AbstractLiveEditTool::toQDeclarativeItem(QGraphicsItem *item)
+{
+ return qobject_cast<QDeclarativeItem*>(item->toGraphicsObject());
+}
+
+QGraphicsItem *AbstractLiveEditTool::topMovableGraphicsItem(const QList<QGraphicsItem*> &itemList)
+{
+ foreach (QGraphicsItem *item, itemList) {
+ if (item->flags().testFlag(QGraphicsItem::ItemIsMovable))
+ return item;
+ }
+ return 0;
+}
+
+QDeclarativeItem *AbstractLiveEditTool::topMovableDeclarativeItem(const QList<QGraphicsItem*>
+ &itemList)
+{
+ foreach (QGraphicsItem *item, itemList) {
+ QDeclarativeItem *declarativeItem = toQDeclarativeItem(item);
+ if (declarativeItem /*&& (declarativeItem->qmlItemNode().hasShowContent())*/)
+ return declarativeItem;
+ }
+
+ return 0;
+}
+
+QList<QGraphicsObject*> AbstractLiveEditTool::toGraphicsObjectList(const QList<QGraphicsItem*>
+ &itemList)
+{
+ QList<QGraphicsObject*> gfxObjects;
+ foreach (QGraphicsItem *item, itemList) {
+ QGraphicsObject *obj = item->toGraphicsObject();
+ if (obj)
+ gfxObjects << obj;
+ }
+
+ return gfxObjects;
+}
+
+QString AbstractLiveEditTool::titleForItem(QGraphicsItem *item)
+{
+ QString className(QLatin1String("QGraphicsItem"));
+ QString objectStringId;
+
+ QString constructedName;
+
+ QGraphicsObject *gfxObject = item->toGraphicsObject();
+ if (gfxObject) {
+ className = QLatin1String(gfxObject->metaObject()->className());
+
+ className.remove(QRegExp(QLatin1String("_QMLTYPE_\\d+")));
+ className.remove(QRegExp(QLatin1String("_QML_\\d+")));
+ if (className.startsWith(QLatin1String("QDeclarative")))
+ className = className.remove(QLatin1String("QDeclarative"));
+
+ QDeclarativeItem *declarativeItem = qobject_cast<QDeclarativeItem*>(gfxObject);
+ if (declarativeItem) {
+ objectStringId = m_observer->idStringForObject(declarativeItem);
+ }
+
+ if (!objectStringId.isEmpty()) {
+ constructedName = objectStringId + QLatin1String(" (") + className + QLatin1Char(')');
+ } else {
+ if (!gfxObject->objectName().isEmpty()) {
+ constructedName = gfxObject->objectName() + QLatin1String(" (") + className + QLatin1Char(')');
+ } else {
+ constructedName = className;
+ }
+ }
+ }
+
+ return constructedName;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool_p.h b/src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool_p.h
new file mode 100644
index 0000000..1dbc323
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/abstractliveedittool_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTLIVEEDITTOOL_H
+#define ABSTRACTLIVEEDITTOOL_H
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+class QMouseEvent;
+class QGraphicsItem;
+class QDeclarativeItem;
+class QKeyEvent;
+class QGraphicsScene;
+class QGraphicsObject;
+class QWheelEvent;
+class QDeclarativeView;
+QT_END_NAMESPACE
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+
+class AbstractLiveEditTool : public QObject
+{
+ Q_OBJECT
+public:
+ AbstractLiveEditTool(QDeclarativeViewObserver *observer);
+
+ virtual ~AbstractLiveEditTool();
+
+ virtual void mousePressEvent(QMouseEvent *event) = 0;
+ virtual void mouseMoveEvent(QMouseEvent *event) = 0;
+ virtual void mouseReleaseEvent(QMouseEvent *event) = 0;
+ virtual void mouseDoubleClickEvent(QMouseEvent *event) = 0;
+
+ virtual void hoverMoveEvent(QMouseEvent *event) = 0;
+ virtual void wheelEvent(QWheelEvent *event) = 0;
+
+ virtual void keyPressEvent(QKeyEvent *event) = 0;
+ virtual void keyReleaseEvent(QKeyEvent *keyEvent) = 0;
+ virtual void itemsAboutToRemoved(const QList<QGraphicsItem*> &itemList) = 0;
+
+ virtual void clear() = 0;
+
+ void updateSelectedItems();
+ QList<QGraphicsItem*> items() const;
+
+ void enterContext(QGraphicsItem *itemToEnter);
+
+ bool topItemIsMovable(const QList<QGraphicsItem*> &itemList);
+ bool topItemIsResizeHandle(const QList<QGraphicsItem*> &itemList);
+ bool topSelectedItemIsMovable(const QList<QGraphicsItem*> &itemList);
+
+ QString titleForItem(QGraphicsItem *item);
+
+ static QList<QGraphicsObject*> toGraphicsObjectList(const QList<QGraphicsItem*> &itemList);
+ static QGraphicsItem* topMovableGraphicsItem(const QList<QGraphicsItem*> &itemList);
+ static QDeclarativeItem* topMovableDeclarativeItem(const QList<QGraphicsItem*> &itemList);
+ static QDeclarativeItem *toQDeclarativeItem(QGraphicsItem *item);
+
+protected:
+ virtual void selectedItemsChanged(const QList<QGraphicsItem*> &objectList) = 0;
+
+ QDeclarativeViewObserver *observer() const;
+ QDeclarativeView *view() const;
+ QGraphicsScene *scene() const;
+
+private:
+ QDeclarativeViewObserver *m_observer;
+ QList<QGraphicsItem*> m_itemList;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTLIVEEDITTOOL_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter.cpp b/src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter.cpp
new file mode 100644
index 0000000..98dbc4f
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter.cpp
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "boundingrecthighlighter_p.h"
+
+#include "../qdeclarativeviewobserver_p.h"
+#include "../qmlobserverconstants_p.h"
+
+#include <QtGui/QGraphicsPolygonItem>
+
+#include <QtCore/QTimer>
+#include <QtCore/QObject>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+const qreal AnimDelta = 0.025f;
+const int AnimInterval = 30;
+const int AnimFrames = 10;
+
+BoundingBox::BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem,
+ QObject *parent)
+ : QObject(parent),
+ highlightedObject(itemToHighlight),
+ highlightPolygon(0),
+ highlightPolygonEdge(0)
+{
+ highlightPolygon = new BoundingBoxPolygonItem(parentItem);
+ highlightPolygonEdge = new BoundingBoxPolygonItem(parentItem);
+
+ highlightPolygon->setPen(QPen(QColor(0, 22, 159)));
+ highlightPolygonEdge->setPen(QPen(QColor(158, 199, 255)));
+
+ highlightPolygon->setFlag(QGraphicsItem::ItemIsSelectable, false);
+ highlightPolygonEdge->setFlag(QGraphicsItem::ItemIsSelectable, false);
+}
+
+BoundingBox::~BoundingBox()
+{
+ highlightedObject.clear();
+}
+
+BoundingBoxPolygonItem::BoundingBoxPolygonItem(QGraphicsItem *item) : QGraphicsPolygonItem(item)
+{
+ QPen pen;
+ pen.setColor(QColor(108, 141, 221));
+ pen.setWidth(1);
+ setPen(pen);
+}
+
+int BoundingBoxPolygonItem::type() const
+{
+ return Constants::EditorItemType;
+}
+
+BoundingRectHighlighter::BoundingRectHighlighter(QDeclarativeViewObserver *view) :
+ LiveLayerItem(view->declarativeView()->scene()),
+ m_view(view),
+ m_animFrame(0)
+{
+ m_animTimer = new QTimer(this);
+ m_animTimer->setInterval(AnimInterval);
+ connect(m_animTimer, SIGNAL(timeout()), SLOT(animTimeout()));
+}
+
+BoundingRectHighlighter::~BoundingRectHighlighter()
+{
+
+}
+
+void BoundingRectHighlighter::animTimeout()
+{
+ ++m_animFrame;
+ if (m_animFrame == AnimFrames) {
+ m_animTimer->stop();
+ }
+
+ qreal alpha = m_animFrame / float(AnimFrames);
+
+ foreach (BoundingBox *box, m_boxes) {
+ box->highlightPolygonEdge->setOpacity(alpha);
+ }
+}
+
+void BoundingRectHighlighter::clear()
+{
+ if (m_boxes.length()) {
+ m_animTimer->stop();
+
+ foreach (BoundingBox *box, m_boxes) {
+ freeBoundingBox(box);
+ }
+ }
+}
+
+BoundingBox *BoundingRectHighlighter::boxFor(QGraphicsObject *item) const
+{
+ foreach (BoundingBox *box, m_boxes) {
+ if (box->highlightedObject.data() == item) {
+ return box;
+ }
+ }
+ return 0;
+}
+
+void BoundingRectHighlighter::highlight(QList<QGraphicsObject*> items)
+{
+ if (items.isEmpty())
+ return;
+
+ bool animate = false;
+
+ QList<BoundingBox *> newBoxes;
+ foreach (QGraphicsObject *itemToHighlight, items) {
+ BoundingBox *box = boxFor(itemToHighlight);
+ if (!box) {
+ box = createBoundingBox(itemToHighlight);
+ animate = true;
+ }
+
+ newBoxes << box;
+ }
+ qSort(newBoxes);
+
+ if (newBoxes != m_boxes) {
+ clear();
+ m_boxes << newBoxes;
+ }
+
+ highlightAll(animate);
+}
+
+void BoundingRectHighlighter::highlight(QGraphicsObject* itemToHighlight)
+{
+ if (!itemToHighlight)
+ return;
+
+ bool animate = false;
+
+ BoundingBox *box = boxFor(itemToHighlight);
+ if (!box) {
+ box = createBoundingBox(itemToHighlight);
+ m_boxes << box;
+ animate = true;
+ qSort(m_boxes);
+ }
+
+ highlightAll(animate);
+}
+
+BoundingBox *BoundingRectHighlighter::createBoundingBox(QGraphicsObject *itemToHighlight)
+{
+ if (!m_freeBoxes.isEmpty()) {
+ BoundingBox *box = m_freeBoxes.last();
+ if (box->highlightedObject.isNull()) {
+ box->highlightedObject = itemToHighlight;
+ box->highlightPolygon->show();
+ box->highlightPolygonEdge->show();
+ m_freeBoxes.removeLast();
+ return box;
+ }
+ }
+
+ BoundingBox *box = new BoundingBox(itemToHighlight, this, this);
+
+ connect(itemToHighlight, SIGNAL(xChanged()), this, SLOT(refresh()));
+ connect(itemToHighlight, SIGNAL(yChanged()), this, SLOT(refresh()));
+ connect(itemToHighlight, SIGNAL(widthChanged()), this, SLOT(refresh()));
+ connect(itemToHighlight, SIGNAL(heightChanged()), this, SLOT(refresh()));
+ connect(itemToHighlight, SIGNAL(rotationChanged()), this, SLOT(refresh()));
+ connect(itemToHighlight, SIGNAL(destroyed(QObject*)), this, SLOT(itemDestroyed(QObject*)));
+
+ return box;
+}
+
+void BoundingRectHighlighter::removeBoundingBox(BoundingBox *box)
+{
+ delete box;
+ box = 0;
+}
+
+void BoundingRectHighlighter::freeBoundingBox(BoundingBox *box)
+{
+ if (!box->highlightedObject.isNull()) {
+ disconnect(box->highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh()));
+ disconnect(box->highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh()));
+ disconnect(box->highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh()));
+ disconnect(box->highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh()));
+ disconnect(box->highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh()));
+ }
+
+ box->highlightedObject.clear();
+ box->highlightPolygon->hide();
+ box->highlightPolygonEdge->hide();
+ m_boxes.removeOne(box);
+ m_freeBoxes << box;
+}
+
+void BoundingRectHighlighter::itemDestroyed(QObject *obj)
+{
+ foreach (BoundingBox *box, m_boxes) {
+ if (box->highlightedObject.data() == obj) {
+ freeBoundingBox(box);
+ break;
+ }
+ }
+}
+
+void BoundingRectHighlighter::highlightAll(bool animate)
+{
+ foreach (BoundingBox *box, m_boxes) {
+ if (box && box->highlightedObject.isNull()) {
+ // clear all highlights
+ clear();
+ return;
+ }
+ QGraphicsObject *item = box->highlightedObject.data();
+ QRectF itemAndChildRect = item->boundingRect() | item->childrenBoundingRect();
+
+ QPolygonF boundingRectInSceneSpace(item->mapToScene(itemAndChildRect));
+ QPolygonF boundingRectInLayerItemSpace = mapFromScene(boundingRectInSceneSpace);
+ QRectF bboxRect
+ = m_view->adjustToScreenBoundaries(boundingRectInLayerItemSpace.boundingRect());
+ QRectF edgeRect = bboxRect;
+ edgeRect.adjust(-1, -1, 1, 1);
+
+ box->highlightPolygon->setPolygon(QPolygonF(bboxRect));
+ box->highlightPolygonEdge->setPolygon(QPolygonF(edgeRect));
+
+ if (animate)
+ box->highlightPolygonEdge->setOpacity(0);
+ }
+
+ if (animate) {
+ m_animFrame = 0;
+ m_animTimer->start();
+ }
+}
+
+void BoundingRectHighlighter::refresh()
+{
+ if (!m_boxes.isEmpty())
+ highlightAll(true);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter_p.h b/src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter_p.h
new file mode 100644
index 0000000..c1beed8
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/boundingrecthighlighter_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BOUNDINGRECTHIGHLIGHTER_H
+#define BOUNDINGRECTHIGHLIGHTER_H
+
+#include "livelayeritem_p.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QWeakPointer>
+
+QT_FORWARD_DECLARE_CLASS(QGraphicsItem)
+QT_FORWARD_DECLARE_CLASS(QPainter)
+QT_FORWARD_DECLARE_CLASS(QWidget)
+QT_FORWARD_DECLARE_CLASS(QStyleOptionGraphicsItem)
+QT_FORWARD_DECLARE_CLASS(QTimer)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+class BoundingBox;
+
+class BoundingRectHighlighter : public LiveLayerItem
+{
+ Q_OBJECT
+public:
+ explicit BoundingRectHighlighter(QDeclarativeViewObserver *view);
+ ~BoundingRectHighlighter();
+ void clear();
+ void highlight(QList<QGraphicsObject*> items);
+ void highlight(QGraphicsObject* item);
+
+private slots:
+ void refresh();
+ void animTimeout();
+ void itemDestroyed(QObject *);
+
+private:
+ BoundingBox *boxFor(QGraphicsObject *item) const;
+ void highlightAll(bool animate);
+ BoundingBox *createBoundingBox(QGraphicsObject *itemToHighlight);
+ void removeBoundingBox(BoundingBox *box);
+ void freeBoundingBox(BoundingBox *box);
+
+private:
+ Q_DISABLE_COPY(BoundingRectHighlighter)
+
+ QDeclarativeViewObserver *m_view;
+ QList<BoundingBox* > m_boxes;
+ QList<BoundingBox* > m_freeBoxes;
+ QTimer *m_animTimer;
+ qreal m_animScale;
+ int m_animFrame;
+
+};
+
+class BoundingBox : public QObject
+{
+ Q_OBJECT
+public:
+ explicit BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem,
+ QObject *parent = 0);
+ ~BoundingBox();
+ QWeakPointer<QGraphicsObject> highlightedObject;
+ QGraphicsPolygonItem *highlightPolygon;
+ QGraphicsPolygonItem *highlightPolygonEdge;
+
+private:
+ Q_DISABLE_COPY(BoundingBox)
+
+};
+
+class BoundingBoxPolygonItem : public QGraphicsPolygonItem
+{
+public:
+ explicit BoundingBoxPolygonItem(QGraphicsItem *item);
+ int type() const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // BOUNDINGRECTHIGHLIGHTER_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/colorpickertool.cpp b/src/plugins/qmltooling/declarativeobserver/editor/colorpickertool.cpp
new file mode 100644
index 0000000..a71e408
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/colorpickertool.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "colorpickertool_p.h"
+
+#include "../qdeclarativeviewobserver_p.h"
+
+#include <QtGui/QMouseEvent>
+#include <QtGui/QKeyEvent>
+#include <QtCore/QRectF>
+#include <QtGui/QRgb>
+#include <QtGui/QImage>
+#include <QtGui/QApplication>
+#include <QtGui/QPalette>
+
+QT_BEGIN_NAMESPACE
+
+ColorPickerTool::ColorPickerTool(QDeclarativeViewObserver *view) :
+ AbstractLiveEditTool(view)
+{
+ m_selectedColor.setRgb(0,0,0);
+}
+
+ColorPickerTool::~ColorPickerTool()
+{
+
+}
+
+void ColorPickerTool::mousePressEvent(QMouseEvent * /*event*/)
+{
+}
+
+void ColorPickerTool::mouseMoveEvent(QMouseEvent *event)
+{
+ pickColor(event->pos());
+}
+
+void ColorPickerTool::mouseReleaseEvent(QMouseEvent *event)
+{
+ pickColor(event->pos());
+}
+
+void ColorPickerTool::mouseDoubleClickEvent(QMouseEvent * /*event*/)
+{
+}
+
+
+void ColorPickerTool::hoverMoveEvent(QMouseEvent * /*event*/)
+{
+}
+
+void ColorPickerTool::keyPressEvent(QKeyEvent * /*event*/)
+{
+}
+
+void ColorPickerTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
+{
+}
+void ColorPickerTool::wheelEvent(QWheelEvent * /*event*/)
+{
+}
+
+void ColorPickerTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
+{
+}
+
+void ColorPickerTool::clear()
+{
+ view()->setCursor(Qt::CrossCursor);
+}
+
+void ColorPickerTool::selectedItemsChanged(const QList<QGraphicsItem*> &/*itemList*/)
+{
+}
+
+void ColorPickerTool::pickColor(const QPoint &pos)
+{
+ QRgb fillColor = view()->backgroundBrush().color().rgb();
+ if (view()->backgroundBrush().style() == Qt::NoBrush)
+ fillColor = view()->palette().color(QPalette::Base).rgb();
+
+ QRectF target(0,0, 1, 1);
+ QRect source(pos.x(), pos.y(), 1, 1);
+ QImage img(1, 1, QImage::Format_ARGB32);
+ img.fill(fillColor);
+ QPainter painter(&img);
+ view()->render(&painter, target, source);
+ m_selectedColor = QColor::fromRgb(img.pixel(0, 0));
+
+ emit selectedColorChanged(m_selectedColor);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/colorpickertool_p.h b/src/plugins/qmltooling/declarativeobserver/editor/colorpickertool_p.h
new file mode 100644
index 0000000..86a8893
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/colorpickertool_p.h
@@ -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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef COLORPICKERTOOL_H
+#define COLORPICKERTOOL_H
+
+#include "abstractliveedittool_p.h"
+
+#include <QtGui/QColor>
+
+QT_FORWARD_DECLARE_CLASS(QPoint)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class ColorPickerTool : public AbstractLiveEditTool
+{
+ Q_OBJECT
+public:
+ explicit ColorPickerTool(QDeclarativeViewObserver *view);
+
+ virtual ~ColorPickerTool();
+
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+
+ void hoverMoveEvent(QMouseEvent *event);
+
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *keyEvent);
+
+ void wheelEvent(QWheelEvent *event);
+
+ void itemsAboutToRemoved(const QList<QGraphicsItem*> &itemList);
+
+ void clear();
+
+signals:
+ void selectedColorChanged(const QColor &color);
+
+protected:
+
+ void selectedItemsChanged(const QList<QGraphicsItem*> &itemList);
+
+private:
+ void pickColor(const QPoint &pos);
+
+private:
+ QColor m_selectedColor;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // COLORPICKERTOOL_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/editor.qrc b/src/plugins/qmltooling/declarativeobserver/editor/editor.qrc
new file mode 100644
index 0000000..77744d5
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/editor.qrc
@@ -0,0 +1,24 @@
+<RCC>
+ <qresource prefix="/qml">
+ <file>images/resize_handle.png</file>
+ <file>images/select.png</file>
+ <file>images/select-marquee.png</file>
+ <file>images/color-picker.png</file>
+ <file>images/play.png</file>
+ <file>images/pause.png</file>
+ <file>images/from-qml.png</file>
+ <file>images/to-qml.png</file>
+ <file>images/color-picker-hicontrast.png</file>
+ <file>images/zoom.png</file>
+ <file>images/color-picker-24.png</file>
+ <file>images/from-qml-24.png</file>
+ <file>images/pause-24.png</file>
+ <file>images/play-24.png</file>
+ <file>images/to-qml-24.png</file>
+ <file>images/zoom-24.png</file>
+ <file>images/select-24.png</file>
+ <file>images/select-marquee-24.png</file>
+ <file>images/observermode.png</file>
+ <file>images/observermode-24.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-24.png
new file mode 100644
index 0000000..cff4721
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-24.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-hicontrast.png b/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-hicontrast.png
new file mode 100644
index 0000000..b953d08
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker-hicontrast.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker.png b/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker.png
new file mode 100644
index 0000000..026c31b
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/color-picker.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/from-qml-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/from-qml-24.png
new file mode 100644
index 0000000..0ad21f3
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/from-qml-24.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/from-qml.png b/src/plugins/qmltooling/declarativeobserver/editor/images/from-qml.png
new file mode 100644
index 0000000..666382c
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/from-qml.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/observermode-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/observermode-24.png
new file mode 100644
index 0000000..5e74d86
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/observermode-24.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/observermode.png b/src/plugins/qmltooling/declarativeobserver/editor/images/observermode.png
new file mode 100644
index 0000000..daed21c
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/observermode.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/pause-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/pause-24.png
new file mode 100644
index 0000000..d9a2f6f
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/pause-24.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/pause.png b/src/plugins/qmltooling/declarativeobserver/editor/images/pause.png
new file mode 100644
index 0000000..114d89b
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/pause.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/play-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/play-24.png
new file mode 100644
index 0000000..e2b9fbc
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/play-24.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/play.png b/src/plugins/qmltooling/declarativeobserver/editor/images/play.png
new file mode 100644
index 0000000..011598a
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/play.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/reload.png b/src/plugins/qmltooling/declarativeobserver/editor/images/reload.png
new file mode 100644
index 0000000..7042bec
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/reload.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/resize_handle.png b/src/plugins/qmltooling/declarativeobserver/editor/images/resize_handle.png
new file mode 100644
index 0000000..2934f25
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/resize_handle.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/select-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/select-24.png
new file mode 100644
index 0000000..5388a9d
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/select-24.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee-24.png
new file mode 100644
index 0000000..0111dda
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee-24.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee.png b/src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee.png
new file mode 100644
index 0000000..92fe40d
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/select-marquee.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/select.png b/src/plugins/qmltooling/declarativeobserver/editor/images/select.png
new file mode 100644
index 0000000..6722855
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/select.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/to-qml-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/to-qml-24.png
new file mode 100644
index 0000000..b72450d
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/to-qml-24.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/to-qml.png b/src/plugins/qmltooling/declarativeobserver/editor/images/to-qml.png
new file mode 100644
index 0000000..2ab951f
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/to-qml.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/zoom-24.png b/src/plugins/qmltooling/declarativeobserver/editor/images/zoom-24.png
new file mode 100644
index 0000000..0346200
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/zoom-24.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/images/zoom.png b/src/plugins/qmltooling/declarativeobserver/editor/images/zoom.png
new file mode 100644
index 0000000..17f0da6
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/images/zoom.png
Binary files differ
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/livelayeritem.cpp b/src/plugins/qmltooling/declarativeobserver/editor/livelayeritem.cpp
new file mode 100644
index 0000000..7b508a4
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/livelayeritem.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "livelayeritem_p.h"
+
+#include "../qmlobserverconstants_p.h"
+
+#include <QGraphicsScene>
+
+QT_BEGIN_NAMESPACE
+
+LiveLayerItem::LiveLayerItem(QGraphicsScene* scene)
+ : QGraphicsObject()
+{
+ scene->addItem(this);
+ setZValue(1);
+ setFlag(QGraphicsItem::ItemIsMovable, false);
+}
+
+LiveLayerItem::~LiveLayerItem()
+{
+}
+
+void LiveLayerItem::paint(QPainter * /*painter*/, const QStyleOptionGraphicsItem * /*option*/,
+ QWidget * /*widget*/)
+{
+}
+
+int LiveLayerItem::type() const
+{
+ return Constants::EditorItemType;
+}
+
+QRectF LiveLayerItem::boundingRect() const
+{
+ return childrenBoundingRect();
+}
+
+QList<QGraphicsItem*> LiveLayerItem::findAllChildItems() const
+{
+ return findAllChildItems(this);
+}
+
+QList<QGraphicsItem*> LiveLayerItem::findAllChildItems(const QGraphicsItem *item) const
+{
+ QList<QGraphicsItem*> itemList(item->childItems());
+
+ foreach (QGraphicsItem *childItem, item->childItems())
+ itemList += findAllChildItems(childItem);
+
+ return itemList;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/livelayeritem_p.h b/src/plugins/qmltooling/declarativeobserver/editor/livelayeritem_p.h
new file mode 100644
index 0000000..242e365
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/livelayeritem_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LIVELAYERITEM_H
+#define LIVELAYERITEM_H
+
+#include <QtGui/QGraphicsObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class LiveLayerItem : public QGraphicsObject
+{
+public:
+ LiveLayerItem(QGraphicsScene *scene);
+ ~LiveLayerItem();
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+ QWidget *widget = 0);
+ QRectF boundingRect() const;
+ int type() const;
+
+ QList<QGraphicsItem*> findAllChildItems() const;
+
+protected:
+ QList<QGraphicsItem*> findAllChildItems(const QGraphicsItem *item) const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // LIVELAYERITEM_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator.cpp b/src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator.cpp
new file mode 100644
index 0000000..6c37ba5
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "liverubberbandselectionmanipulator_p.h"
+
+#include "../qdeclarativeviewobserver_p_p.h"
+
+#include <QtGui/QGraphicsItem>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+LiveRubberBandSelectionManipulator::LiveRubberBandSelectionManipulator(QGraphicsObject *layerItem,
+ QDeclarativeViewObserver *editorView)
+ : m_selectionRectangleElement(layerItem),
+ m_editorView(editorView),
+ m_beginFormEditorItem(0),
+ m_isActive(false)
+{
+ m_selectionRectangleElement.hide();
+}
+
+void LiveRubberBandSelectionManipulator::clear()
+{
+ m_selectionRectangleElement.clear();
+ m_isActive = false;
+ m_beginPoint = QPointF();
+ m_itemList.clear();
+ m_oldSelectionList.clear();
+}
+
+QGraphicsItem *LiveRubberBandSelectionManipulator::topFormEditorItem(const QList<QGraphicsItem*>
+ &itemList)
+{
+ if (itemList.isEmpty())
+ return 0;
+
+ return itemList.first();
+}
+
+void LiveRubberBandSelectionManipulator::begin(const QPointF &beginPoint)
+{
+ m_beginPoint = beginPoint;
+ m_selectionRectangleElement.setRect(m_beginPoint, m_beginPoint);
+ m_selectionRectangleElement.show();
+ m_isActive = true;
+ QDeclarativeViewObserverPrivate *observerPrivate
+ = QDeclarativeViewObserverPrivate::get(m_editorView);
+ m_beginFormEditorItem = topFormEditorItem(observerPrivate->selectableItems(beginPoint));
+ m_oldSelectionList = m_editorView->selectedItems();
+}
+
+void LiveRubberBandSelectionManipulator::update(const QPointF &updatePoint)
+{
+ m_selectionRectangleElement.setRect(m_beginPoint, updatePoint);
+}
+
+void LiveRubberBandSelectionManipulator::end()
+{
+ m_oldSelectionList.clear();
+ m_selectionRectangleElement.hide();
+ m_isActive = false;
+}
+
+void LiveRubberBandSelectionManipulator::select(SelectionType selectionType)
+{
+ QDeclarativeViewObserverPrivate *observerPrivate
+ = QDeclarativeViewObserverPrivate::get(m_editorView);
+ QList<QGraphicsItem*> itemList
+ = observerPrivate->selectableItems(m_selectionRectangleElement.rect(),
+ Qt::IntersectsItemShape);
+ QList<QGraphicsItem*> newSelectionList;
+
+ foreach (QGraphicsItem* item, itemList) {
+ if (item
+ && item->parentItem()
+ && !newSelectionList.contains(item)
+ //&& m_beginFormEditorItem->childItems().contains(item) // TODO activate this test
+ )
+ {
+ newSelectionList.append(item);
+ }
+ }
+
+ if (newSelectionList.isEmpty() && m_beginFormEditorItem)
+ newSelectionList.append(m_beginFormEditorItem);
+
+ QList<QGraphicsItem*> resultList;
+
+ switch (selectionType) {
+ case AddToSelection: {
+ resultList.append(m_oldSelectionList);
+ resultList.append(newSelectionList);
+ }
+ break;
+ case ReplaceSelection: {
+ resultList.append(newSelectionList);
+ }
+ break;
+ case RemoveFromSelection: {
+ QSet<QGraphicsItem*> oldSelectionSet(m_oldSelectionList.toSet());
+ QSet<QGraphicsItem*> newSelectionSet(newSelectionList.toSet());
+ resultList.append(oldSelectionSet.subtract(newSelectionSet).toList());
+ }
+ }
+
+ m_editorView->setSelectedItems(resultList);
+}
+
+
+void LiveRubberBandSelectionManipulator::setItems(const QList<QGraphicsItem*> &itemList)
+{
+ m_itemList = itemList;
+}
+
+QPointF LiveRubberBandSelectionManipulator::beginPoint() const
+{
+ return m_beginPoint;
+}
+
+bool LiveRubberBandSelectionManipulator::isActive() const
+{
+ return m_isActive;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator_p.h b/src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator_p.h
new file mode 100644
index 0000000..8d15288
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liverubberbandselectionmanipulator_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RUBBERBANDSELECTIONMANIPULATOR_H
+#define RUBBERBANDSELECTIONMANIPULATOR_H
+
+#include "liveselectionrectangle_p.h"
+
+#include <QtCore/QPointF>
+
+QT_FORWARD_DECLARE_CLASS(QGraphicsItem)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+
+class LiveRubberBandSelectionManipulator
+{
+public:
+ enum SelectionType {
+ ReplaceSelection,
+ AddToSelection,
+ RemoveFromSelection
+ };
+
+ LiveRubberBandSelectionManipulator(QGraphicsObject *layerItem,
+ QDeclarativeViewObserver *editorView);
+
+ void setItems(const QList<QGraphicsItem*> &itemList);
+
+ void begin(const QPointF& beginPoint);
+ void update(const QPointF& updatePoint);
+ void end();
+
+ void clear();
+
+ void select(SelectionType selectionType);
+
+ QPointF beginPoint() const;
+
+ bool isActive() const;
+
+protected:
+ QGraphicsItem *topFormEditorItem(const QList<QGraphicsItem*> &itemList);
+
+private:
+ QList<QGraphicsItem*> m_itemList;
+ QList<QGraphicsItem*> m_oldSelectionList;
+ LiveSelectionRectangle m_selectionRectangleElement;
+ QPointF m_beginPoint;
+ QDeclarativeViewObserver *m_editorView;
+ QGraphicsItem *m_beginFormEditorItem;
+ bool m_isActive;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // RUBBERBANDSELECTIONMANIPULATOR_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator.cpp b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator.cpp
new file mode 100644
index 0000000..96e9dbf
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "liveselectionindicator_p.h"
+
+#include "../qdeclarativeviewobserver_p_p.h"
+#include "../qmlobserverconstants_p.h"
+
+#include <QtCore/QDebug>
+
+#include <QtGui/QGraphicsPolygonItem>
+#include <QtGui/QGraphicsObject>
+#include <QtGui/QGraphicsScene>
+#include <QtGui/QPen>
+
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+LiveSelectionIndicator::LiveSelectionIndicator(QDeclarativeViewObserver *editorView,
+ QGraphicsObject *layerItem)
+ : m_layerItem(layerItem), m_view(editorView)
+{
+}
+
+LiveSelectionIndicator::~LiveSelectionIndicator()
+{
+ clear();
+}
+
+void LiveSelectionIndicator::show()
+{
+ foreach (QGraphicsPolygonItem *item, m_indicatorShapeHash.values())
+ item->show();
+}
+
+void LiveSelectionIndicator::hide()
+{
+ foreach (QGraphicsPolygonItem *item, m_indicatorShapeHash.values())
+ item->hide();
+}
+
+void LiveSelectionIndicator::clear()
+{
+ if (!m_layerItem.isNull()) {
+ QHashIterator<QGraphicsItem*, QGraphicsPolygonItem *> iter(m_indicatorShapeHash);
+ while (iter.hasNext()) {
+ iter.next();
+ m_layerItem.data()->scene()->removeItem(iter.value());
+ delete iter.value();
+ }
+ }
+
+ m_indicatorShapeHash.clear();
+
+}
+
+QPolygonF LiveSelectionIndicator::addBoundingRectToPolygon(QGraphicsItem *item, QPolygonF &polygon)
+{
+ // ### remove this if statement when QTBUG-12172 gets fixed
+ if (item->boundingRect() != QRectF(0,0,0,0)) {
+ QPolygonF bounding = item->mapToScene(item->boundingRect());
+ if (bounding.isClosed()) //avoid crashes if there is an infinite scale.
+ polygon = polygon.united(bounding);
+ }
+
+ foreach (QGraphicsItem *child, item->childItems()) {
+ if (!QDeclarativeViewObserverPrivate::get(m_view)->isEditorItem(child))
+ addBoundingRectToPolygon(child, polygon);
+ }
+ return polygon;
+}
+
+void LiveSelectionIndicator::setItems(const QList<QWeakPointer<QGraphicsObject> > &itemList)
+{
+ clear();
+
+ // set selections to also all children if they are not editor items
+
+ foreach (const QWeakPointer<QGraphicsObject> &object, itemList) {
+ if (object.isNull())
+ continue;
+
+ QGraphicsItem *item = object.data();
+
+ QGraphicsPolygonItem *newSelectionIndicatorGraphicsItem
+ = new QGraphicsPolygonItem(m_layerItem.data());
+ if (!m_indicatorShapeHash.contains(item)) {
+ m_indicatorShapeHash.insert(item, newSelectionIndicatorGraphicsItem);
+
+ QPolygonF boundingShapeInSceneSpace;
+ addBoundingRectToPolygon(item, boundingShapeInSceneSpace);
+
+ QRectF boundingRect
+ = m_view->adjustToScreenBoundaries(boundingShapeInSceneSpace.boundingRect());
+ QPolygonF boundingRectInLayerItemSpace = m_layerItem.data()->mapFromScene(boundingRect);
+
+ QPen pen;
+ pen.setColor(QColor(108, 141, 221));
+ newSelectionIndicatorGraphicsItem->setData(Constants::EditorItemDataKey,
+ QVariant(true));
+ newSelectionIndicatorGraphicsItem->setFlag(QGraphicsItem::ItemIsSelectable, false);
+ newSelectionIndicatorGraphicsItem->setPolygon(boundingRectInLayerItemSpace);
+ newSelectionIndicatorGraphicsItem->setPen(pen);
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator_p.h b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator_p.h
new file mode 100644
index 0000000..da95955
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionindicator_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LIVESELECTIONINDICATOR_H
+#define LIVESELECTIONINDICATOR_H
+
+#include <QtCore/QWeakPointer>
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+class QGraphicsObject;
+class QGraphicsPolygonItem;
+class QGraphicsItem;
+class QPolygonF;
+QT_END_NAMESPACE
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+
+class LiveSelectionIndicator
+{
+public:
+ LiveSelectionIndicator(QDeclarativeViewObserver* editorView, QGraphicsObject *layerItem);
+ ~LiveSelectionIndicator();
+
+ void show();
+ void hide();
+
+ void clear();
+
+ void setItems(const QList<QWeakPointer<QGraphicsObject> > &itemList);
+
+private:
+ QPolygonF addBoundingRectToPolygon(QGraphicsItem *item, QPolygonF &polygon);
+
+private:
+ QHash<QGraphicsItem*, QGraphicsPolygonItem *> m_indicatorShapeHash;
+ QWeakPointer<QGraphicsObject> m_layerItem;
+ QDeclarativeViewObserver *m_view;
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // LIVESELECTIONINDICATOR_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle.cpp b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle.cpp
new file mode 100644
index 0000000..2a1d393
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "liveselectionrectangle_p.h"
+
+#include "../qmlobserverconstants_p.h"
+
+#include <QtGui/QPen>
+#include <QtGui/QGraphicsRectItem>
+#include <QtGui/QGraphicsObject>
+#include <QtGui/QGraphicsScene>
+
+#include <QtCore/QtDebug>
+
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+class SelectionRectShape : public QGraphicsRectItem
+{
+public:
+ SelectionRectShape(QGraphicsItem *parent = 0) : QGraphicsRectItem(parent) {}
+ int type() const { return Constants::EditorItemType; }
+};
+
+LiveSelectionRectangle::LiveSelectionRectangle(QGraphicsObject *layerItem)
+ : m_controlShape(new SelectionRectShape(layerItem)),
+ m_layerItem(layerItem)
+{
+ m_controlShape->setPen(QPen(Qt::black));
+ m_controlShape->setBrush(QColor(128, 128, 128, 50));
+}
+
+LiveSelectionRectangle::~LiveSelectionRectangle()
+{
+ if (m_layerItem)
+ m_layerItem.data()->scene()->removeItem(m_controlShape);
+}
+
+void LiveSelectionRectangle::clear()
+{
+ hide();
+}
+void LiveSelectionRectangle::show()
+{
+ m_controlShape->show();
+}
+
+void LiveSelectionRectangle::hide()
+{
+ m_controlShape->hide();
+}
+
+QRectF LiveSelectionRectangle::rect() const
+{
+ return m_controlShape->mapFromScene(m_controlShape->rect()).boundingRect();
+}
+
+void LiveSelectionRectangle::setRect(const QPointF &firstPoint,
+ const QPointF &secondPoint)
+{
+ double firstX = std::floor(firstPoint.x()) + 0.5;
+ double firstY = std::floor(firstPoint.y()) + 0.5;
+ double secondX = std::floor(secondPoint.x()) + 0.5;
+ double secondY = std::floor(secondPoint.y()) + 0.5;
+ QPointF topLeftPoint(firstX < secondX ? firstX : secondX,
+ firstY < secondY ? firstY : secondY);
+ QPointF bottomRightPoint(firstX > secondX ? firstX : secondX,
+ firstY > secondY ? firstY : secondY);
+
+ QRectF rect(topLeftPoint, bottomRightPoint);
+ m_controlShape->setRect(rect);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle_p.h b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle_p.h
new file mode 100644
index 0000000..d1bed72
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liveselectionrectangle_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LIVESELECTIONRECTANGLE_H
+#define LIVESELECTIONRECTANGLE_H
+
+#include <QtCore/QWeakPointer>
+
+QT_FORWARD_DECLARE_CLASS(QGraphicsObject)
+QT_FORWARD_DECLARE_CLASS(QGraphicsRectItem)
+QT_FORWARD_DECLARE_CLASS(QPointF)
+QT_FORWARD_DECLARE_CLASS(QRectF)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class LiveSelectionRectangle
+{
+public:
+ LiveSelectionRectangle(QGraphicsObject *layerItem);
+ ~LiveSelectionRectangle();
+
+ void show();
+ void hide();
+
+ void clear();
+
+ void setRect(const QPointF &firstPoint,
+ const QPointF &secondPoint);
+
+ QRectF rect() const;
+
+private:
+ QGraphicsRectItem *m_controlShape;
+ QWeakPointer<QGraphicsObject> m_layerItem;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // LIVESELECTIONRECTANGLE_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool.cpp b/src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool.cpp
new file mode 100644
index 0000000..d85926e
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool.cpp
@@ -0,0 +1,442 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "liveselectiontool_p.h"
+#include "livelayeritem_p.h"
+
+#include "../qdeclarativeviewobserver_p_p.h"
+
+#include <QtGui/QApplication>
+#include <QtGui/QWheelEvent>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QClipboard>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+#include <QtGui/QGraphicsObject>
+
+#include <QtDeclarative/QDeclarativeItem>
+#include <QtDeclarative/QDeclarativeEngine>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+LiveSelectionTool::LiveSelectionTool(QDeclarativeViewObserver *editorView) :
+ AbstractLiveEditTool(editorView),
+ m_rubberbandSelectionMode(false),
+ m_rubberbandSelectionManipulator(
+ QDeclarativeViewObserverPrivate::get(editorView)->manipulatorLayer, editorView),
+ m_singleSelectionManipulator(editorView),
+ m_selectionIndicator(editorView,
+ QDeclarativeViewObserverPrivate::get(editorView)->manipulatorLayer),
+ //m_resizeIndicator(editorView->manipulatorLayer()),
+ m_selectOnlyContentItems(true)
+{
+
+}
+
+LiveSelectionTool::~LiveSelectionTool()
+{
+}
+
+void LiveSelectionTool::setRubberbandSelectionMode(bool value)
+{
+ m_rubberbandSelectionMode = value;
+}
+
+LiveSingleSelectionManipulator::SelectionType LiveSelectionTool::getSelectionType(Qt::KeyboardModifiers
+ modifiers)
+{
+ LiveSingleSelectionManipulator::SelectionType selectionType
+ = LiveSingleSelectionManipulator::ReplaceSelection;
+ if (modifiers.testFlag(Qt::ControlModifier)) {
+ selectionType = LiveSingleSelectionManipulator::RemoveFromSelection;
+ } else if (modifiers.testFlag(Qt::ShiftModifier)) {
+ selectionType = LiveSingleSelectionManipulator::AddToSelection;
+ }
+ return selectionType;
+}
+
+bool LiveSelectionTool::alreadySelected(const QList<QGraphicsItem*> &itemList) const
+{
+ QDeclarativeViewObserverPrivate *observerPrivate
+ = QDeclarativeViewObserverPrivate::get(observer());
+ const QList<QGraphicsItem*> selectedItems = observerPrivate->selectedItems();
+
+ if (selectedItems.isEmpty())
+ return false;
+
+ foreach (QGraphicsItem *item, itemList)
+ if (selectedItems.contains(item))
+ return true;
+
+ return false;
+}
+
+void LiveSelectionTool::mousePressEvent(QMouseEvent *event)
+{
+ QDeclarativeViewObserverPrivate *observerPrivate
+ = QDeclarativeViewObserverPrivate::get(observer());
+ QList<QGraphicsItem*> itemList = observerPrivate->selectableItems(event->pos());
+ LiveSingleSelectionManipulator::SelectionType selectionType = getSelectionType(event->modifiers());
+
+ if (event->buttons() & Qt::LeftButton) {
+ m_mousePressTimer.start();
+
+ if (m_rubberbandSelectionMode) {
+ m_rubberbandSelectionManipulator.begin(event->pos());
+ } else {
+ m_singleSelectionManipulator.begin(event->pos());
+ m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
+ }
+ } else if (event->buttons() & Qt::RightButton) {
+ createContextMenu(itemList, event->globalPos());
+ }
+}
+
+void LiveSelectionTool::createContextMenu(QList<QGraphicsItem*> itemList, QPoint globalPos)
+{
+ if (!QDeclarativeViewObserverPrivate::get(observer())->mouseInsideContextItem())
+ return;
+
+ QMenu contextMenu;
+ connect(&contextMenu, SIGNAL(hovered(QAction*)),
+ this, SLOT(contextMenuElementHovered(QAction*)));
+
+ m_contextMenuItemList = itemList;
+
+ contextMenu.addAction(tr("Items"));
+ contextMenu.addSeparator();
+ int shortcutKey = Qt::Key_1;
+ bool addKeySequence = true;
+ int i = 0;
+
+ foreach (QGraphicsItem * const item, itemList) {
+ QString itemTitle = titleForItem(item);
+ QAction *elementAction = contextMenu.addAction(itemTitle, this,
+ SLOT(contextMenuElementSelected()));
+
+ if (observer()->selectedItems().contains(item)) {
+ QFont boldFont = elementAction->font();
+ boldFont.setBold(true);
+ elementAction->setFont(boldFont);
+ }
+
+ elementAction->setData(i);
+ if (addKeySequence)
+ elementAction->setShortcut(QKeySequence(shortcutKey));
+
+ shortcutKey++;
+ if (shortcutKey > Qt::Key_9)
+ addKeySequence = false;
+
+ ++i;
+ }
+ // add root item separately
+ // QString itemTitle = QString(tr("%1")).arg(titleForItem(view()->currentRootItem()));
+ // contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected()));
+ // m_contextMenuItemList.append(view()->currentRootItem());
+
+ contextMenu.exec(globalPos);
+ m_contextMenuItemList.clear();
+}
+
+void LiveSelectionTool::contextMenuElementSelected()
+{
+ QAction *senderAction = static_cast<QAction*>(sender());
+ int itemListIndex = senderAction->data().toInt();
+ if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {
+
+ QPointF updatePt(0, 0);
+ QGraphicsItem *item = m_contextMenuItemList.at(itemListIndex);
+ m_singleSelectionManipulator.begin(updatePt);
+ m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::InvertSelection,
+ QList<QGraphicsItem*>() << item,
+ false);
+ m_singleSelectionManipulator.end(updatePt);
+ enterContext(item);
+ }
+}
+
+void LiveSelectionTool::contextMenuElementHovered(QAction *action)
+{
+ int itemListIndex = action->data().toInt();
+ if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {
+ QGraphicsObject *item = m_contextMenuItemList.at(itemListIndex)->toGraphicsObject();
+ QDeclarativeViewObserverPrivate::get(observer())->highlight(item);
+ }
+}
+
+void LiveSelectionTool::mouseMoveEvent(QMouseEvent *event)
+{
+ if (m_singleSelectionManipulator.isActive()) {
+ QPointF mouseMovementVector = m_singleSelectionManipulator.beginPoint() - event->pos();
+
+ if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
+ && (m_mousePressTimer.elapsed() > Constants::DragStartTime))
+ {
+ m_singleSelectionManipulator.end(event->pos());
+ //view()->changeToMoveTool(m_singleSelectionManipulator.beginPoint());
+ return;
+ }
+ } else if (m_rubberbandSelectionManipulator.isActive()) {
+ QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();
+
+ if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
+ && (m_mousePressTimer.elapsed() > Constants::DragStartTime)) {
+ m_rubberbandSelectionManipulator.update(event->pos());
+
+ if (event->modifiers().testFlag(Qt::ControlModifier))
+ m_rubberbandSelectionManipulator.select(
+ LiveRubberBandSelectionManipulator::RemoveFromSelection);
+ else if (event->modifiers().testFlag(Qt::ShiftModifier))
+ m_rubberbandSelectionManipulator.select(
+ LiveRubberBandSelectionManipulator::AddToSelection);
+ else
+ m_rubberbandSelectionManipulator.select(
+ LiveRubberBandSelectionManipulator::ReplaceSelection);
+ }
+ }
+}
+
+void LiveSelectionTool::hoverMoveEvent(QMouseEvent * event)
+{
+// ### commented out until move tool is re-enabled
+// QList<QGraphicsItem*> itemList = view()->items(event->pos());
+// if (!itemList.isEmpty() && !m_rubberbandSelectionMode) {
+//
+// foreach (QGraphicsItem *item, itemList) {
+// if (item->type() == Constants::ResizeHandleItemType) {
+// ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(item);
+// if (resizeHandle)
+// view()->changeTool(Constants::ResizeToolMode);
+// return;
+// }
+// }
+// if (topSelectedItemIsMovable(itemList))
+// view()->changeTool(Constants::MoveToolMode);
+// }
+ QDeclarativeViewObserverPrivate *observerPrivate
+ = QDeclarativeViewObserverPrivate::get(observer());
+
+ QList<QGraphicsItem*> selectableItemList = observerPrivate->selectableItems(event->pos());
+ if (!selectableItemList.isEmpty()) {
+ QGraphicsObject *item = selectableItemList.first()->toGraphicsObject();
+ if (item)
+ QDeclarativeViewObserverPrivate::get(observer())->highlight(item);
+
+ return;
+ }
+
+ QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
+}
+
+void LiveSelectionTool::mouseReleaseEvent(QMouseEvent *event)
+{
+ if (m_singleSelectionManipulator.isActive()) {
+ m_singleSelectionManipulator.end(event->pos());
+ }
+ else if (m_rubberbandSelectionManipulator.isActive()) {
+
+ QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();
+ if (mouseMovementVector.toPoint().manhattanLength() < Constants::DragStartDistance) {
+ m_singleSelectionManipulator.begin(event->pos());
+
+ if (event->modifiers().testFlag(Qt::ControlModifier))
+ m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::RemoveFromSelection,
+ m_selectOnlyContentItems);
+ else if (event->modifiers().testFlag(Qt::ShiftModifier))
+ m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::AddToSelection,
+ m_selectOnlyContentItems);
+ else
+ m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::InvertSelection,
+ m_selectOnlyContentItems);
+
+ m_singleSelectionManipulator.end(event->pos());
+ } else {
+ m_rubberbandSelectionManipulator.update(event->pos());
+
+ if (event->modifiers().testFlag(Qt::ControlModifier))
+ m_rubberbandSelectionManipulator.select(
+ LiveRubberBandSelectionManipulator::RemoveFromSelection);
+ else if (event->modifiers().testFlag(Qt::ShiftModifier))
+ m_rubberbandSelectionManipulator.select(
+ LiveRubberBandSelectionManipulator::AddToSelection);
+ else
+ m_rubberbandSelectionManipulator.select(
+ LiveRubberBandSelectionManipulator::ReplaceSelection);
+
+ m_rubberbandSelectionManipulator.end();
+ }
+ }
+}
+
+void LiveSelectionTool::mouseDoubleClickEvent(QMouseEvent * /*event*/)
+{
+}
+
+void LiveSelectionTool::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ // disabled for now, cannot move stuff yet.
+ //view()->changeTool(Constants::MoveToolMode);
+ //view()->currentTool()->keyPressEvent(event);
+ break;
+ }
+}
+
+void LiveSelectionTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
+{
+
+}
+
+void LiveSelectionTool::wheelEvent(QWheelEvent *event)
+{
+ if (event->orientation() == Qt::Horizontal || m_rubberbandSelectionMode)
+ return;
+
+ QDeclarativeViewObserverPrivate *observerPrivate
+ = QDeclarativeViewObserverPrivate::get(observer());
+ QList<QGraphicsItem*> itemList = observerPrivate->selectableItems(event->pos());
+
+ if (itemList.isEmpty())
+ return;
+
+ int selectedIdx = 0;
+ if (!observer()->selectedItems().isEmpty()) {
+ selectedIdx = itemList.indexOf(observer()->selectedItems().first());
+ if (selectedIdx >= 0) {
+ if (event->delta() > 0) {
+ selectedIdx++;
+ if (selectedIdx == itemList.length())
+ selectedIdx = 0;
+ } else if (event->delta() < 0) {
+ selectedIdx--;
+ if (selectedIdx == -1)
+ selectedIdx = itemList.length() - 1;
+ }
+ } else {
+ selectedIdx = 0;
+ }
+ }
+
+ QPointF updatePt(0, 0);
+ m_singleSelectionManipulator.begin(updatePt);
+ m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::ReplaceSelection,
+ QList<QGraphicsItem*>() << itemList.at(selectedIdx),
+ false);
+ m_singleSelectionManipulator.end(updatePt);
+
+}
+
+void LiveSelectionTool::setSelectOnlyContentItems(bool selectOnlyContentItems)
+{
+ m_selectOnlyContentItems = selectOnlyContentItems;
+}
+
+void LiveSelectionTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
+{
+}
+
+void LiveSelectionTool::clear()
+{
+ view()->setCursor(Qt::ArrowCursor);
+ m_rubberbandSelectionManipulator.clear(),
+ m_singleSelectionManipulator.clear();
+ m_selectionIndicator.clear();
+ //m_resizeIndicator.clear();
+}
+
+void LiveSelectionTool::selectedItemsChanged(const QList<QGraphicsItem*> &itemList)
+{
+ foreach (const QWeakPointer<QGraphicsObject> &obj, m_selectedItemList) {
+ if (!obj.isNull()) {
+ disconnect(obj.data(), SIGNAL(xChanged()), this, SLOT(repaintBoundingRects()));
+ disconnect(obj.data(), SIGNAL(yChanged()), this, SLOT(repaintBoundingRects()));
+ disconnect(obj.data(), SIGNAL(widthChanged()), this, SLOT(repaintBoundingRects()));
+ disconnect(obj.data(), SIGNAL(heightChanged()), this, SLOT(repaintBoundingRects()));
+ disconnect(obj.data(), SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
+ }
+ }
+
+ QList<QGraphicsObject*> objects = toGraphicsObjectList(itemList);
+ m_selectedItemList.clear();
+
+ foreach (QGraphicsObject *obj, objects) {
+ m_selectedItemList.append(obj);
+ connect(obj, SIGNAL(xChanged()), this, SLOT(repaintBoundingRects()));
+ connect(obj, SIGNAL(yChanged()), this, SLOT(repaintBoundingRects()));
+ connect(obj, SIGNAL(widthChanged()), this, SLOT(repaintBoundingRects()));
+ connect(obj, SIGNAL(heightChanged()), this, SLOT(repaintBoundingRects()));
+ connect(obj, SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
+ }
+
+ m_selectionIndicator.setItems(m_selectedItemList);
+ //m_resizeIndicator.setItems(toGraphicsObjectList(itemList));
+}
+
+void LiveSelectionTool::repaintBoundingRects()
+{
+ m_selectionIndicator.setItems(m_selectedItemList);
+}
+
+void LiveSelectionTool::selectUnderPoint(QMouseEvent *event)
+{
+ m_singleSelectionManipulator.begin(event->pos());
+
+ if (event->modifiers().testFlag(Qt::ControlModifier))
+ m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::RemoveFromSelection,
+ m_selectOnlyContentItems);
+ else if (event->modifiers().testFlag(Qt::ShiftModifier))
+ m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::AddToSelection,
+ m_selectOnlyContentItems);
+ else
+ m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::InvertSelection,
+ m_selectOnlyContentItems);
+
+ m_singleSelectionManipulator.end(event->pos());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool_p.h b/src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool_p.h
new file mode 100644
index 0000000..3daac3d
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/liveselectiontool_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LIVESELECTIONTOOL_H
+#define LIVESELECTIONTOOL_H
+
+#include "abstractliveedittool_p.h"
+#include "liverubberbandselectionmanipulator_p.h"
+#include "livesingleselectionmanipulator_p.h"
+#include "liveselectionindicator_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QTime>
+
+QT_FORWARD_DECLARE_CLASS(QGraphicsItem)
+QT_FORWARD_DECLARE_CLASS(QMouseEvent)
+QT_FORWARD_DECLARE_CLASS(QKeyEvent)
+QT_FORWARD_DECLARE_CLASS(QAction)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class LiveSelectionTool : public AbstractLiveEditTool
+{
+ Q_OBJECT
+
+public:
+ LiveSelectionTool(QDeclarativeViewObserver* editorView);
+ ~LiveSelectionTool();
+
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+ void hoverMoveEvent(QMouseEvent *event);
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *keyEvent);
+ void wheelEvent(QWheelEvent *event);
+
+ void itemsAboutToRemoved(const QList<QGraphicsItem*> &itemList);
+// QVariant itemChange(const QList<QGraphicsItem*> &itemList,
+// QGraphicsItem::GraphicsItemChange change,
+// const QVariant &value );
+
+// void update();
+
+ void clear();
+
+ void selectedItemsChanged(const QList<QGraphicsItem*> &itemList);
+
+ void selectUnderPoint(QMouseEvent *event);
+
+ void setSelectOnlyContentItems(bool selectOnlyContentItems);
+
+ void setRubberbandSelectionMode(bool value);
+
+private slots:
+ void contextMenuElementSelected();
+ void contextMenuElementHovered(QAction *action);
+ void repaintBoundingRects();
+
+private:
+ void createContextMenu(QList<QGraphicsItem*> itemList, QPoint globalPos);
+ LiveSingleSelectionManipulator::SelectionType getSelectionType(Qt::KeyboardModifiers modifiers);
+ bool alreadySelected(const QList<QGraphicsItem*> &itemList) const;
+
+private:
+ bool m_rubberbandSelectionMode;
+ LiveRubberBandSelectionManipulator m_rubberbandSelectionManipulator;
+ LiveSingleSelectionManipulator m_singleSelectionManipulator;
+ LiveSelectionIndicator m_selectionIndicator;
+ //ResizeIndicator m_resizeIndicator;
+ QTime m_mousePressTimer;
+ bool m_selectOnlyContentItems;
+
+ QList<QWeakPointer<QGraphicsObject> > m_selectedItemList;
+
+ QList<QGraphicsItem*> m_contextMenuItemList;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // LIVESELECTIONTOOL_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator.cpp b/src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator.cpp
new file mode 100644
index 0000000..e753b64
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "livesingleselectionmanipulator_p.h"
+
+#include "../qdeclarativeviewobserver_p_p.h"
+
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+LiveSingleSelectionManipulator::LiveSingleSelectionManipulator(QDeclarativeViewObserver *editorView)
+ : m_editorView(editorView),
+ m_isActive(false)
+{
+}
+
+
+void LiveSingleSelectionManipulator::begin(const QPointF &beginPoint)
+{
+ m_beginPoint = beginPoint;
+ m_isActive = true;
+ m_oldSelectionList = QDeclarativeViewObserverPrivate::get(m_editorView)->selectedItems();
+}
+
+void LiveSingleSelectionManipulator::update(const QPointF &/*updatePoint*/)
+{
+ m_oldSelectionList.clear();
+}
+
+void LiveSingleSelectionManipulator::clear()
+{
+ m_beginPoint = QPointF();
+ m_oldSelectionList.clear();
+}
+
+
+void LiveSingleSelectionManipulator::end(const QPointF &/*updatePoint*/)
+{
+ m_oldSelectionList.clear();
+ m_isActive = false;
+}
+
+void LiveSingleSelectionManipulator::select(SelectionType selectionType,
+ const QList<QGraphicsItem*> &items,
+ bool /*selectOnlyContentItems*/)
+{
+ QGraphicsItem *selectedItem = 0;
+
+ foreach (QGraphicsItem* item, items)
+ {
+ //FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
+ if (item
+ /*&& !formEditorItem->qmlItemNode().isRootNode()
+ && (formEditorItem->qmlItemNode().hasShowContent() || !selectOnlyContentItems)*/)
+ {
+ selectedItem = item;
+ break;
+ }
+ }
+
+ QList<QGraphicsItem*> resultList;
+
+ switch (selectionType) {
+ case AddToSelection: {
+ resultList.append(m_oldSelectionList);
+ if (selectedItem && !m_oldSelectionList.contains(selectedItem))
+ resultList.append(selectedItem);
+ }
+ break;
+ case ReplaceSelection: {
+ if (selectedItem)
+ resultList.append(selectedItem);
+ }
+ break;
+ case RemoveFromSelection: {
+ resultList.append(m_oldSelectionList);
+ if (selectedItem)
+ resultList.removeAll(selectedItem);
+ }
+ break;
+ case InvertSelection: {
+ if (selectedItem
+ && !m_oldSelectionList.contains(selectedItem))
+ {
+ resultList.append(selectedItem);
+ }
+ }
+ }
+
+ m_editorView->setSelectedItems(resultList);
+}
+
+void LiveSingleSelectionManipulator::select(SelectionType selectionType, bool selectOnlyContentItems)
+{
+ QDeclarativeViewObserverPrivate *observerPrivate =
+ QDeclarativeViewObserverPrivate::get(m_editorView);
+ QList<QGraphicsItem*> itemList = observerPrivate->selectableItems(m_beginPoint);
+ select(selectionType, itemList, selectOnlyContentItems);
+}
+
+
+bool LiveSingleSelectionManipulator::isActive() const
+{
+ return m_isActive;
+}
+
+QPointF LiveSingleSelectionManipulator::beginPoint() const
+{
+ return m_beginPoint;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator_p.h b/src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator_p.h
new file mode 100644
index 0000000..68329e5
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/livesingleselectionmanipulator_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LIVESINGLESELECTIONMANIPULATOR_H
+#define LIVESINGLESELECTIONMANIPULATOR_H
+
+#include <QtCore/QPointF>
+#include <QtCore/QList>
+
+QT_FORWARD_DECLARE_CLASS(QGraphicsItem)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+
+class LiveSingleSelectionManipulator
+{
+public:
+ LiveSingleSelectionManipulator(QDeclarativeViewObserver *editorView);
+
+ enum SelectionType {
+ ReplaceSelection,
+ AddToSelection,
+ RemoveFromSelection,
+ InvertSelection
+ };
+
+ void begin(const QPointF& beginPoint);
+ void update(const QPointF& updatePoint);
+ void end(const QPointF& updatePoint);
+
+ void select(SelectionType selectionType, const QList<QGraphicsItem*> &items,
+ bool selectOnlyContentItems);
+ void select(SelectionType selectionType, bool selectOnlyContentItems);
+
+ void clear();
+
+ QPointF beginPoint() const;
+
+ bool isActive() const;
+
+private:
+ QList<QGraphicsItem*> m_oldSelectionList;
+ QPointF m_beginPoint;
+ QDeclarativeViewObserver *m_editorView;
+ bool m_isActive;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // LIVESINGLESELECTIONMANIPULATOR_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar.cpp b/src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar.cpp
new file mode 100644
index 0000000..359e9ef
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar.cpp
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltoolbar_p.h"
+#include "toolbarcolorbox_p.h"
+
+#include <QtGui/QLabel>
+#include <QtGui/QIcon>
+#include <QtGui/QAction>
+#include <QtGui/QMenu>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QmlToolBar::QmlToolBar(QWidget *parent)
+ : QToolBar(parent)
+ , m_emitSignals(true)
+ , m_paused(false)
+ , m_animationSpeed(1.0f)
+ , ui(new Ui)
+{
+ ui->playIcon = QIcon(QLatin1String(":/qml/images/play-24.png"));
+ ui->pauseIcon = QIcon(QLatin1String(":/qml/images/pause-24.png"));
+
+ ui->designmode = new QAction(QIcon(QLatin1String(":/qml/images/observermode-24.png")),
+ tr("Observer Mode"), this);
+ ui->play = new QAction(ui->pauseIcon, tr("Play/Pause Animations"), this);
+ ui->select = new QAction(QIcon(QLatin1String(":/qml/images/select-24.png")), tr("Select"), this);
+ ui->selectMarquee = new QAction(QIcon(QLatin1String(":/qml/images/select-marquee-24.png")),
+ tr("Select (Marquee)"), this);
+ ui->zoom = new QAction(QIcon(QLatin1String(":/qml/images/zoom-24.png")), tr("Zoom"), this);
+ ui->colorPicker = new QAction(QIcon(QLatin1String(":/qml/images/color-picker-24.png")),
+ tr("Color Picker"), this);
+ ui->toQml = new QAction(QIcon(QLatin1String(":/qml/images/to-qml-24.png")),
+ tr("Apply Changes to QML Viewer"), this);
+ ui->fromQml = new QAction(QIcon(QLatin1String(":/qml/images/from-qml-24.png")),
+ tr("Apply Changes to Document"), this);
+ ui->designmode->setCheckable(true);
+ ui->designmode->setChecked(false);
+
+ ui->play->setCheckable(false);
+ ui->select->setCheckable(true);
+ ui->selectMarquee->setCheckable(true);
+ ui->zoom->setCheckable(true);
+ ui->colorPicker->setCheckable(true);
+
+ setWindowTitle(tr("Tools"));
+
+ addAction(ui->designmode);
+ addAction(ui->play);
+ addSeparator();
+
+ addAction(ui->select);
+ // disabled because multi selection does not do anything useful without design mode
+ //addAction(ui->selectMarquee);
+ addSeparator();
+ addAction(ui->zoom);
+ addAction(ui->colorPicker);
+ //addAction(ui->fromQml);
+
+ ui->colorBox = new ToolBarColorBox(this);
+ ui->colorBox->setMinimumSize(24, 24);
+ ui->colorBox->setMaximumSize(28, 28);
+ ui->colorBox->setColor(Qt::black);
+ addWidget(ui->colorBox);
+
+ setWindowFlags(Qt::Tool);
+
+ QMenu *playSpeedMenu = new QMenu(this);
+ ui->playSpeedMenuActions = new QActionGroup(this);
+ ui->playSpeedMenuActions->setExclusive(true);
+
+ QAction *speedAction = playSpeedMenu->addAction(tr("1x"), this, SLOT(changeAnimationSpeed()));
+ speedAction->setCheckable(true);
+ speedAction->setChecked(true);
+ speedAction->setData(1.0f);
+ ui->playSpeedMenuActions->addAction(speedAction);
+
+ speedAction = playSpeedMenu->addAction(tr("0.5x"), this, SLOT(changeAnimationSpeed()));
+ speedAction->setCheckable(true);
+ speedAction->setData(2.0f);
+ ui->playSpeedMenuActions->addAction(speedAction);
+
+ speedAction = playSpeedMenu->addAction(tr("0.25x"), this, SLOT(changeAnimationSpeed()));
+ speedAction->setCheckable(true);
+ speedAction->setData(4.0f);
+ ui->playSpeedMenuActions->addAction(speedAction);
+
+ speedAction = playSpeedMenu->addAction(tr("0.125x"), this, SLOT(changeAnimationSpeed()));
+ speedAction->setCheckable(true);
+ speedAction->setData(8.0f);
+ ui->playSpeedMenuActions->addAction(speedAction);
+
+ speedAction = playSpeedMenu->addAction(tr("0.1x"), this, SLOT(changeAnimationSpeed()));
+ speedAction->setCheckable(true);
+ speedAction->setData(10.0f);
+ ui->playSpeedMenuActions->addAction(speedAction);
+
+ ui->play->setMenu(playSpeedMenu);
+
+ connect(ui->designmode, SIGNAL(toggled(bool)), SLOT(setDesignModeBehaviorOnClick(bool)));
+
+ connect(ui->colorPicker, SIGNAL(triggered()), SLOT(activateColorPickerOnClick()));
+
+ connect(ui->play, SIGNAL(triggered()), SLOT(activatePlayOnClick()));
+
+ connect(ui->zoom, SIGNAL(triggered()), SLOT(activateZoomOnClick()));
+ connect(ui->colorPicker, SIGNAL(triggered()), SLOT(activateColorPickerOnClick()));
+ connect(ui->select, SIGNAL(triggered()), SLOT(activateSelectToolOnClick()));
+ connect(ui->selectMarquee, SIGNAL(triggered()), SLOT(activateMarqueeSelectToolOnClick()));
+
+ connect(ui->toQml, SIGNAL(triggered()), SLOT(activateToQml()));
+ connect(ui->fromQml, SIGNAL(triggered()), SLOT(activateFromQml()));
+}
+
+QmlToolBar::~QmlToolBar()
+{
+ delete ui;
+}
+
+void QmlToolBar::activateColorPicker()
+{
+ m_emitSignals = false;
+ activateColorPickerOnClick();
+ m_emitSignals = true;
+}
+
+void QmlToolBar::activateSelectTool()
+{
+ m_emitSignals = false;
+ activateSelectToolOnClick();
+ m_emitSignals = true;
+}
+
+void QmlToolBar::activateMarqueeSelectTool()
+{
+ m_emitSignals = false;
+ activateMarqueeSelectToolOnClick();
+ m_emitSignals = true;
+}
+
+void QmlToolBar::activateZoom()
+{
+ m_emitSignals = false;
+ activateZoomOnClick();
+ m_emitSignals = true;
+}
+
+void QmlToolBar::setAnimationSpeed(qreal slowDownFactor)
+{
+ if (m_animationSpeed == slowDownFactor)
+ return;
+
+ m_emitSignals = false;
+ m_animationSpeed = slowDownFactor;
+
+ foreach (QAction *action, ui->playSpeedMenuActions->actions()) {
+ if (action->data().toReal() == slowDownFactor) {
+ action->setChecked(true);
+ break;
+ }
+ }
+
+ m_emitSignals = true;
+}
+
+void QmlToolBar::setAnimationPaused(bool paused)
+{
+ if (m_paused == paused)
+ return;
+
+ m_paused = paused;
+ updatePlayAction();
+}
+
+void QmlToolBar::changeAnimationSpeed()
+{
+ QAction *action = qobject_cast<QAction*>(sender());
+ m_animationSpeed = action->data().toReal();
+ emit animationSpeedChanged(m_animationSpeed);
+}
+
+void QmlToolBar::setDesignModeBehavior(bool inDesignMode)
+{
+ m_emitSignals = false;
+ ui->designmode->setChecked(inDesignMode);
+ setDesignModeBehaviorOnClick(inDesignMode);
+ m_emitSignals = true;
+}
+
+void QmlToolBar::setDesignModeBehaviorOnClick(bool checked)
+{
+ ui->select->setEnabled(checked);
+ ui->selectMarquee->setEnabled(checked);
+ ui->zoom->setEnabled(checked);
+ ui->colorPicker->setEnabled(checked);
+ ui->toQml->setEnabled(checked);
+ ui->fromQml->setEnabled(checked);
+
+ if (m_emitSignals)
+ emit designModeBehaviorChanged(checked);
+}
+
+void QmlToolBar::setColorBoxColor(const QColor &color)
+{
+ ui->colorBox->setColor(color);
+}
+
+void QmlToolBar::activatePlayOnClick()
+{
+ m_paused = !m_paused;
+ emit animationPausedChanged(m_paused);
+ updatePlayAction();
+}
+
+void QmlToolBar::updatePlayAction()
+{
+ ui->play->setIcon(m_paused ? ui->playIcon : ui->pauseIcon);
+}
+
+void QmlToolBar::activateColorPickerOnClick()
+{
+ ui->zoom->setChecked(false);
+ ui->select->setChecked(false);
+ ui->selectMarquee->setChecked(false);
+
+ ui->colorPicker->setChecked(true);
+ if (m_activeTool != Constants::ColorPickerMode) {
+ m_activeTool = Constants::ColorPickerMode;
+ if (m_emitSignals)
+ emit colorPickerSelected();
+ }
+}
+
+void QmlToolBar::activateSelectToolOnClick()
+{
+ ui->zoom->setChecked(false);
+ ui->selectMarquee->setChecked(false);
+ ui->colorPicker->setChecked(false);
+
+ ui->select->setChecked(true);
+ if (m_activeTool != Constants::SelectionToolMode) {
+ m_activeTool = Constants::SelectionToolMode;
+ if (m_emitSignals)
+ emit selectToolSelected();
+ }
+}
+
+void QmlToolBar::activateMarqueeSelectToolOnClick()
+{
+ ui->zoom->setChecked(false);
+ ui->select->setChecked(false);
+ ui->colorPicker->setChecked(false);
+
+ ui->selectMarquee->setChecked(true);
+ if (m_activeTool != Constants::MarqueeSelectionToolMode) {
+ m_activeTool = Constants::MarqueeSelectionToolMode;
+ if (m_emitSignals)
+ emit marqueeSelectToolSelected();
+ }
+}
+
+void QmlToolBar::activateZoomOnClick()
+{
+ ui->select->setChecked(false);
+ ui->selectMarquee->setChecked(false);
+ ui->colorPicker->setChecked(false);
+
+ ui->zoom->setChecked(true);
+ if (m_activeTool != Constants::ZoomMode) {
+ m_activeTool = Constants::ZoomMode;
+ if (m_emitSignals)
+ emit zoomToolSelected();
+ }
+}
+
+void QmlToolBar::activateFromQml()
+{
+ if (m_emitSignals)
+ emit applyChangesFromQmlFileSelected();
+}
+
+void QmlToolBar::activateToQml()
+{
+ if (m_emitSignals)
+ emit applyChangesToQmlFileSelected();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar_p.h b/src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar_p.h
new file mode 100644
index 0000000..459eafd
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/qmltoolbar_p.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTOOLBAR_H
+#define QMLTOOLBAR_H
+
+#include <QtGui/QToolBar>
+#include <QtGui/QIcon>
+
+#include "../qmlobserverconstants_p.h"
+
+QT_FORWARD_DECLARE_CLASS(QActionGroup)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class ToolBarColorBox;
+
+class QmlToolBar : public QToolBar
+{
+ Q_OBJECT
+
+public:
+ explicit QmlToolBar(QWidget *parent = 0);
+ ~QmlToolBar();
+
+public slots:
+ void setDesignModeBehavior(bool inDesignMode);
+ void setColorBoxColor(const QColor &color);
+ void activateColorPicker();
+ void activateSelectTool();
+ void activateMarqueeSelectTool();
+ void activateZoom();
+
+ void setAnimationSpeed(qreal slowDownFactor);
+ void setAnimationPaused(bool paused);
+
+signals:
+ void animationSpeedChanged(qreal factor);
+ void animationPausedChanged(bool paused);
+
+ void designModeBehaviorChanged(bool inDesignMode);
+ void colorPickerSelected();
+ void selectToolSelected();
+ void marqueeSelectToolSelected();
+ void zoomToolSelected();
+
+ void applyChangesToQmlFileSelected();
+ void applyChangesFromQmlFileSelected();
+
+private slots:
+ void setDesignModeBehaviorOnClick(bool inDesignMode);
+ void activatePlayOnClick();
+ void activateColorPickerOnClick();
+ void activateSelectToolOnClick();
+ void activateMarqueeSelectToolOnClick();
+ void activateZoomOnClick();
+
+ void activateFromQml();
+ void activateToQml();
+
+ void changeAnimationSpeed();
+
+ void updatePlayAction();
+
+private:
+ class Ui {
+ public:
+ QAction *designmode;
+ QAction *play;
+ QAction *select;
+ QAction *selectMarquee;
+ QAction *zoom;
+ QAction *colorPicker;
+ QAction *toQml;
+ QAction *fromQml;
+ QIcon playIcon;
+ QIcon pauseIcon;
+ ToolBarColorBox *colorBox;
+
+ QActionGroup *playSpeedMenuActions;
+ };
+
+ bool m_emitSignals;
+ bool m_paused;
+ qreal m_animationSpeed;
+
+ Constants::DesignTool m_activeTool;
+
+ Ui *ui;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLTOOLBAR_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool.cpp b/src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool.cpp
new file mode 100644
index 0000000..ab77296
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool.cpp
@@ -0,0 +1,364 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "subcomponenteditortool_p.h"
+#include "subcomponentmasklayeritem_p.h"
+#include "livelayeritem_p.h"
+
+#include "../qdeclarativeviewobserver_p_p.h"
+
+#include <QtGui/QGraphicsItem>
+#include <QtGui/QGraphicsObject>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QKeyEvent>
+
+#include <QtCore/QTimer>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+const qreal MaxOpacity = 0.5f;
+
+SubcomponentEditorTool::SubcomponentEditorTool(QDeclarativeViewObserver *view)
+ : AbstractLiveEditTool(view),
+ m_animIncrement(0.05f),
+ m_animTimer(new QTimer(this))
+{
+ QDeclarativeViewObserverPrivate *observerPrivate =
+ QDeclarativeViewObserverPrivate::get(view);
+ m_mask = new SubcomponentMaskLayerItem(view, observerPrivate->manipulatorLayer);
+ connect(m_animTimer, SIGNAL(timeout()), SLOT(animate()));
+ m_animTimer->setInterval(20);
+}
+
+SubcomponentEditorTool::~SubcomponentEditorTool()
+{
+
+}
+
+void SubcomponentEditorTool::mousePressEvent(QMouseEvent * /*event*/)
+{
+
+}
+
+void SubcomponentEditorTool::mouseMoveEvent(QMouseEvent * /*event*/)
+{
+
+}
+
+bool SubcomponentEditorTool::containsCursor(const QPoint &mousePos) const
+{
+ if (!m_currentContext.size())
+ return false;
+
+ QPointF scenePos = view()->mapToScene(mousePos);
+ QRectF itemRect = m_currentContext.top()->boundingRect()
+ | m_currentContext.top()->childrenBoundingRect();
+ QRectF polyRect = m_currentContext.top()->mapToScene(itemRect).boundingRect();
+
+ return polyRect.contains(scenePos);
+}
+
+void SubcomponentEditorTool::mouseReleaseEvent(QMouseEvent * /*event*/)
+{
+
+}
+
+void SubcomponentEditorTool::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ if (event->buttons() & Qt::LeftButton
+ && !containsCursor(event->pos())
+ && m_currentContext.size() > 1)
+ {
+ aboutToPopContext();
+ }
+}
+
+void SubcomponentEditorTool::hoverMoveEvent(QMouseEvent *event)
+{
+ if (!containsCursor(event->pos()) && m_currentContext.size() > 1) {
+ QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
+ }
+}
+
+void SubcomponentEditorTool::wheelEvent(QWheelEvent * /*event*/)
+{
+
+}
+
+void SubcomponentEditorTool::keyPressEvent(QKeyEvent * /*event*/)
+{
+
+}
+
+void SubcomponentEditorTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
+{
+
+}
+
+void SubcomponentEditorTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
+{
+
+}
+
+void SubcomponentEditorTool::animate()
+{
+ if (m_animIncrement > 0) {
+ if (m_mask->opacity() + m_animIncrement < MaxOpacity) {
+ m_mask->setOpacity(m_mask->opacity() + m_animIncrement);
+ } else {
+ m_animTimer->stop();
+ m_mask->setOpacity(MaxOpacity);
+ }
+ } else {
+ if (m_mask->opacity() + m_animIncrement > 0) {
+ m_mask->setOpacity(m_mask->opacity() + m_animIncrement);
+ } else {
+ m_animTimer->stop();
+ m_mask->setOpacity(0);
+ popContext();
+ emit contextPathChanged(m_path);
+ }
+ }
+
+}
+
+void SubcomponentEditorTool::clear()
+{
+ m_currentContext.clear();
+ m_mask->setCurrentItem(0);
+ m_animTimer->stop();
+ m_mask->hide();
+ m_path.clear();
+
+ emit contextPathChanged(m_path);
+ emit cleared();
+}
+
+void SubcomponentEditorTool::selectedItemsChanged(const QList<QGraphicsItem*> &/*itemList*/)
+{
+
+}
+
+void SubcomponentEditorTool::setCurrentItem(QGraphicsItem* contextItem)
+{
+ if (!contextItem)
+ return;
+
+ QGraphicsObject *gfxObject = contextItem->toGraphicsObject();
+ if (!gfxObject)
+ return;
+
+ //QString parentClassName = gfxObject->metaObject()->className();
+ //if (parentClassName.contains(QRegExp("_QMLTYPE_\\d+")))
+
+ bool containsSelectableItems = false;
+ foreach (QGraphicsItem *item, gfxObject->childItems()) {
+ if (item->type() == Constants::EditorItemType
+ || item->type() == Constants::ResizeHandleItemType)
+ {
+ continue;
+ }
+ containsSelectableItems = true;
+ break;
+ }
+
+ if (containsSelectableItems) {
+ m_mask->setCurrentItem(gfxObject);
+ m_mask->setOpacity(0);
+ m_mask->show();
+ m_animIncrement = 0.05f;
+ m_animTimer->start();
+
+ QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
+ observer()->setSelectedItems(QList<QGraphicsItem*>());
+
+ pushContext(gfxObject);
+ }
+}
+
+QGraphicsItem *SubcomponentEditorTool::firstChildOfContext(QGraphicsItem *item) const
+{
+ if (!item)
+ return 0;
+
+ if (isDirectChildOfContext(item))
+ return item;
+
+ QGraphicsItem *parent = item->parentItem();
+ while (parent) {
+ if (isDirectChildOfContext(parent))
+ return parent;
+ parent = parent->parentItem();
+ }
+
+ return 0;
+}
+
+bool SubcomponentEditorTool::isChildOfContext(QGraphicsItem *item) const
+{
+ return (firstChildOfContext(item) != 0);
+}
+
+bool SubcomponentEditorTool::isDirectChildOfContext(QGraphicsItem *item) const
+{
+ return (item->parentItem() == m_currentContext.top());
+}
+
+bool SubcomponentEditorTool::itemIsChildOfQmlSubComponent(QGraphicsItem *item) const
+{
+ if (item->parentItem() && item->parentItem() != m_currentContext.top()) {
+ QGraphicsObject *parent = item->parentItem()->toGraphicsObject();
+ QString parentClassName = QLatin1String(parent->metaObject()->className());
+
+ if (parentClassName.contains(QRegExp(QLatin1String("_QMLTYPE_\\d+")))) {
+ return true;
+ } else {
+ return itemIsChildOfQmlSubComponent(parent);
+ }
+ }
+
+ return false;
+}
+
+void SubcomponentEditorTool::pushContext(QGraphicsObject *contextItem)
+{
+ connect(contextItem, SIGNAL(destroyed(QObject*)), this, SLOT(contextDestroyed(QObject*)));
+ connect(contextItem, SIGNAL(xChanged()), this, SLOT(resizeMask()));
+ connect(contextItem, SIGNAL(yChanged()), this, SLOT(resizeMask()));
+ connect(contextItem, SIGNAL(widthChanged()), this, SLOT(resizeMask()));
+ connect(contextItem, SIGNAL(heightChanged()), this, SLOT(resizeMask()));
+ connect(contextItem, SIGNAL(rotationChanged()), this, SLOT(resizeMask()));
+
+ m_currentContext.push(contextItem);
+ QString title = titleForItem(contextItem);
+ emit contextPushed(title);
+
+ m_path << title;
+ emit contextPathChanged(m_path);
+}
+
+void SubcomponentEditorTool::aboutToPopContext()
+{
+ if (m_currentContext.size() > 2) {
+ popContext();
+ emit contextPathChanged(m_path);
+ } else {
+ m_animIncrement = -0.05f;
+ m_animTimer->start();
+ }
+}
+
+QGraphicsObject *SubcomponentEditorTool::popContext()
+{
+ QGraphicsObject *popped = m_currentContext.pop();
+ m_path.removeLast();
+
+ emit contextPopped();
+
+ disconnect(popped, SIGNAL(xChanged()), this, SLOT(resizeMask()));
+ disconnect(popped, SIGNAL(yChanged()), this, SLOT(resizeMask()));
+ disconnect(popped, SIGNAL(scaleChanged()), this, SLOT(resizeMask()));
+ disconnect(popped, SIGNAL(widthChanged()), this, SLOT(resizeMask()));
+ disconnect(popped, SIGNAL(heightChanged()), this, SLOT(resizeMask()));
+
+ if (m_currentContext.size() > 1) {
+ QGraphicsObject *item = m_currentContext.top();
+ m_mask->setCurrentItem(item);
+ m_mask->setOpacity(MaxOpacity);
+ m_mask->setVisible(true);
+ } else {
+ m_mask->setVisible(false);
+ }
+
+ return popped;
+}
+
+void SubcomponentEditorTool::resizeMask()
+{
+ QGraphicsObject *item = m_currentContext.top();
+ m_mask->setCurrentItem(item);
+}
+
+QGraphicsObject *SubcomponentEditorTool::currentRootItem() const
+{
+ return m_currentContext.top();
+}
+
+void SubcomponentEditorTool::contextDestroyed(QObject *contextToDestroy)
+{
+ disconnect(contextToDestroy, SIGNAL(destroyed(QObject*)),
+ this, SLOT(contextDestroyed(QObject*)));
+
+ // pop out the whole context - it might not be safe anymore.
+ while (m_currentContext.size() > 1) {
+ m_currentContext.pop();
+ m_path.removeLast();
+ emit contextPopped();
+ }
+ m_mask->setVisible(false);
+
+ emit contextPathChanged(m_path);
+}
+
+QGraphicsObject *SubcomponentEditorTool::setContext(int contextIndex)
+{
+ Q_ASSERT(contextIndex >= 0);
+
+ // sometimes we have to delete the context while user was still clicking around,
+ // so just bail out.
+ if (contextIndex >= m_currentContext.size() -1)
+ return 0;
+
+ while (m_currentContext.size() - 1 > contextIndex) {
+ popContext();
+ }
+ emit contextPathChanged(m_path);
+
+ return m_currentContext.top();
+}
+
+int SubcomponentEditorTool::contextIndex() const
+{
+ return m_currentContext.size() - 1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool_p.h b/src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool_p.h
new file mode 100644
index 0000000..15217eb
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/subcomponenteditortool_p.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SUBCOMPONENTEDITORTOOL_H
+#define SUBCOMPONENTEDITORTOOL_H
+
+#include "abstractliveedittool_p.h"
+
+#include <QtCore/QStack>
+#include <QtCore/QStringList>
+
+QT_FORWARD_DECLARE_CLASS(QGraphicsObject)
+QT_FORWARD_DECLARE_CLASS(QPoint)
+QT_FORWARD_DECLARE_CLASS(QTimer)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class SubcomponentMaskLayerItem;
+
+class SubcomponentEditorTool : public AbstractLiveEditTool
+{
+ Q_OBJECT
+
+public:
+ SubcomponentEditorTool(QDeclarativeViewObserver *view);
+ ~SubcomponentEditorTool();
+
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+
+ void hoverMoveEvent(QMouseEvent *event);
+ void wheelEvent(QWheelEvent *event);
+
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *keyEvent);
+ void itemsAboutToRemoved(const QList<QGraphicsItem*> &itemList);
+
+ void clear();
+
+ bool containsCursor(const QPoint &mousePos) const;
+ bool itemIsChildOfQmlSubComponent(QGraphicsItem *item) const;
+
+ bool isChildOfContext(QGraphicsItem *item) const;
+ bool isDirectChildOfContext(QGraphicsItem *item) const;
+ QGraphicsItem *firstChildOfContext(QGraphicsItem *item) const;
+
+ void setCurrentItem(QGraphicsItem *contextObject);
+
+ void pushContext(QGraphicsObject *contextItem);
+
+ QGraphicsObject *currentRootItem() const;
+ QGraphicsObject *setContext(int contextIndex);
+ int contextIndex() const;
+
+signals:
+ void exitContextRequested();
+ void cleared();
+ void contextPushed(const QString &contextTitle);
+ void contextPopped();
+ void contextPathChanged(const QStringList &path);
+
+protected:
+ void selectedItemsChanged(const QList<QGraphicsItem*> &itemList);
+
+private slots:
+ void animate();
+ void contextDestroyed(QObject *context);
+ void resizeMask();
+
+private:
+ QGraphicsObject *popContext();
+ void aboutToPopContext();
+
+private:
+ QStack<QGraphicsObject *> m_currentContext;
+ QStringList m_path;
+
+ qreal m_animIncrement;
+ SubcomponentMaskLayerItem *m_mask;
+ QTimer *m_animTimer;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // SUBCOMPONENTEDITORTOOL_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem.cpp b/src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem.cpp
new file mode 100644
index 0000000..15d2a2c
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "subcomponentmasklayeritem_p.h"
+
+#include "../qmlobserverconstants_p.h"
+#include "../qdeclarativeviewobserver_p.h"
+
+#include <QtGui/QPolygonF>
+
+QT_BEGIN_NAMESPACE
+
+SubcomponentMaskLayerItem::SubcomponentMaskLayerItem(QDeclarativeViewObserver *observer,
+ QGraphicsItem *parentItem) :
+ QGraphicsPolygonItem(parentItem),
+ m_observer(observer),
+ m_currentItem(0),
+ m_borderRect(new QGraphicsRectItem(this))
+{
+ m_borderRect->setRect(0,0,0,0);
+ m_borderRect->setPen(QPen(QColor(60, 60, 60), 1));
+ m_borderRect->setData(Constants::EditorItemDataKey, QVariant(true));
+
+ setBrush(QBrush(QColor(160,160,160)));
+ setPen(Qt::NoPen);
+}
+
+int SubcomponentMaskLayerItem::type() const
+{
+ return Constants::EditorItemType;
+}
+
+static QRectF resizeRect(const QRectF &newRect, const QRectF &oldRect)
+{
+ QRectF result = newRect;
+ if (oldRect.left() < newRect.left())
+ result.setLeft(oldRect.left());
+
+ if (oldRect.top() < newRect.top())
+ result.setTop(oldRect.top());
+
+ if (oldRect.right() > newRect.right())
+ result.setRight(oldRect.right());
+
+ if (oldRect.bottom() > newRect.bottom())
+ result.setBottom(oldRect.bottom());
+
+ return result;
+}
+
+
+void SubcomponentMaskLayerItem::setCurrentItem(QGraphicsItem *item)
+{
+ QGraphicsItem *prevItem = m_currentItem;
+ m_currentItem = item;
+
+ if (!m_currentItem)
+ return;
+
+ QPolygonF viewPoly(QRectF(m_observer->declarativeView()->rect()));
+ viewPoly = m_observer->declarativeView()->mapToScene(viewPoly.toPolygon());
+
+ QRectF itemRect = item->boundingRect() | item->childrenBoundingRect();
+ QPolygonF itemPoly(itemRect);
+ itemPoly = item->mapToScene(itemPoly);
+
+ // if updating the same item as before, resize the rectangle only bigger, not smaller.
+ if (prevItem == item && prevItem != 0) {
+ m_itemPolyRect = resizeRect(itemPoly.boundingRect(), m_itemPolyRect);
+ } else {
+ m_itemPolyRect = itemPoly.boundingRect();
+ }
+ QRectF borderRect = m_itemPolyRect;
+ borderRect.adjust(-1, -1, 1, 1);
+ m_borderRect->setRect(borderRect);
+
+ itemPoly = viewPoly.subtracted(QPolygonF(m_itemPolyRect));
+ setPolygon(itemPoly);
+}
+
+QGraphicsItem *SubcomponentMaskLayerItem::currentItem() const
+{
+ return m_currentItem;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem_p.h b/src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem_p.h
new file mode 100644
index 0000000..e0b892d
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/subcomponentmasklayeritem_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SUBCOMPONENTMASKLAYERITEM_H
+#define SUBCOMPONENTMASKLAYERITEM_H
+
+#include <QtGui/QGraphicsPolygonItem>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+
+class SubcomponentMaskLayerItem : public QGraphicsPolygonItem
+{
+public:
+ explicit SubcomponentMaskLayerItem(QDeclarativeViewObserver *observer,
+ QGraphicsItem *parentItem = 0);
+ int type() const;
+ void setCurrentItem(QGraphicsItem *item);
+ void setBoundingBox(const QRectF &boundingBox);
+ QGraphicsItem *currentItem() const;
+ QRectF itemRect() const;
+
+private:
+ QDeclarativeViewObserver *m_observer;
+ QGraphicsItem *m_currentItem;
+ QGraphicsRectItem *m_borderRect;
+ QRectF m_itemPolyRect;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // SUBCOMPONENTMASKLAYERITEM_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox.cpp b/src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox.cpp
new file mode 100644
index 0000000..35582fb
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "toolbarcolorbox_p.h"
+
+#include "../qmlobserverconstants_p.h"
+
+#include <QtGui/QPixmap>
+#include <QtGui/QPainter>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QClipboard>
+#include <QtGui/QApplication>
+#include <QtGui/QColorDialog>
+#include <QtGui/QDrag>
+
+#include <QtCore/QMimeData>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+ToolBarColorBox::ToolBarColorBox(QWidget *parent) :
+ QLabel(parent)
+{
+ m_copyHexColor = new QAction(QIcon(QLatin1String(":/qml/images/color-picker-hicontrast.png")),
+ tr("Copy Color"), this);
+ connect(m_copyHexColor, SIGNAL(triggered()), SLOT(copyColorToClipboard()));
+ setScaledContents(false);
+}
+
+void ToolBarColorBox::setColor(const QColor &color)
+{
+ m_color = color;
+
+ QPixmap pix = createDragPixmap(width());
+ setPixmap(pix);
+ update();
+}
+
+void ToolBarColorBox::mousePressEvent(QMouseEvent *event)
+{
+ m_dragBeginPoint = event->pos();
+ m_dragStarted = false;
+}
+
+void ToolBarColorBox::mouseMoveEvent(QMouseEvent *event)
+{
+
+ if (event->buttons() & Qt::LeftButton
+ && (QPoint(event->pos() - m_dragBeginPoint).manhattanLength()
+ > Constants::DragStartDistance)
+ && !m_dragStarted)
+ {
+ m_dragStarted = true;
+ QDrag *drag = new QDrag(this);
+ QMimeData *mimeData = new QMimeData;
+
+ mimeData->setText(m_color.name());
+ drag->setMimeData(mimeData);
+ drag->setPixmap(createDragPixmap());
+
+ drag->exec();
+ }
+}
+
+QPixmap ToolBarColorBox::createDragPixmap(int size) const
+{
+ QPixmap pix(size, size);
+ QPainter p(&pix);
+
+ QColor borderColor1 = QColor(143, 143 ,143);
+ QColor borderColor2 = QColor(43, 43, 43);
+
+ p.setBrush(QBrush(m_color));
+ p.setPen(QPen(QBrush(borderColor2),1));
+
+ p.fillRect(0, 0, size, size, borderColor1);
+ p.drawRect(1,1, size - 3, size - 3);
+ return pix;
+}
+
+void ToolBarColorBox::contextMenuEvent(QContextMenuEvent *ev)
+{
+ QMenu contextMenu;
+ contextMenu.addAction(m_copyHexColor);
+ contextMenu.exec(ev->globalPos());
+}
+
+void ToolBarColorBox::copyColorToClipboard()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->setText(m_color.name());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox_p.h b/src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox_p.h
new file mode 100644
index 0000000..d4914fa
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/toolbarcolorbox_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOOLBARCOLORBOX_H
+#define TOOLBARCOLORBOX_H
+
+#include <QtGui/QLabel>
+#include <QtGui/QColor>
+#include <QtCore/QPoint>
+
+QT_FORWARD_DECLARE_CLASS(QContextMenuEvent)
+QT_FORWARD_DECLARE_CLASS(QAction)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class ToolBarColorBox : public QLabel
+{
+ Q_OBJECT
+
+public:
+ explicit ToolBarColorBox(QWidget *parent = 0);
+ void setColor(const QColor &color);
+
+protected:
+ void contextMenuEvent(QContextMenuEvent *ev);
+ void mousePressEvent(QMouseEvent *ev);
+ void mouseMoveEvent(QMouseEvent *ev);
+private slots:
+ void copyColorToClipboard();
+
+private:
+ QPixmap createDragPixmap(int size = 24) const;
+
+private:
+ bool m_dragStarted;
+ QPoint m_dragBeginPoint;
+ QAction *m_copyHexColor;
+ QColor m_color;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // TOOLBARCOLORBOX_H
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/zoomtool.cpp b/src/plugins/qmltooling/declarativeobserver/editor/zoomtool.cpp
new file mode 100644
index 0000000..b70cda5
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/zoomtool.cpp
@@ -0,0 +1,336 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "zoomtool_p.h"
+
+#include "../qdeclarativeviewobserver_p_p.h"
+
+#include <QtGui/QMouseEvent>
+#include <QtGui/QWheelEvent>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+
+#include <QtCore/QRectF>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+ZoomTool::ZoomTool(QDeclarativeViewObserver *view) :
+ AbstractLiveEditTool(view),
+ m_rubberbandManipulator(),
+ m_smoothZoomMultiplier(0.05f),
+ m_currentScale(1.0f)
+{
+ m_zoomTo100Action = new QAction(tr("Zoom to &100%"), this);
+ m_zoomInAction = new QAction(tr("Zoom In"), this);
+ m_zoomOutAction = new QAction(tr("Zoom Out"), this);
+ m_zoomInAction->setShortcut(QKeySequence(Qt::Key_Plus));
+ m_zoomOutAction->setShortcut(QKeySequence(Qt::Key_Minus));
+
+
+ LiveLayerItem *layerItem = QDeclarativeViewObserverPrivate::get(view)->manipulatorLayer;
+ QGraphicsObject *layerObject = reinterpret_cast<QGraphicsObject *>(layerItem);
+ m_rubberbandManipulator = new LiveRubberBandSelectionManipulator(layerObject, view);
+
+
+ connect(m_zoomTo100Action, SIGNAL(triggered()), SLOT(zoomTo100()));
+ connect(m_zoomInAction, SIGNAL(triggered()), SLOT(zoomIn()));
+ connect(m_zoomOutAction, SIGNAL(triggered()), SLOT(zoomOut()));
+}
+
+ZoomTool::~ZoomTool()
+{
+ delete m_rubberbandManipulator;
+}
+
+void ZoomTool::mousePressEvent(QMouseEvent *event)
+{
+ m_mousePos = event->pos();
+
+ QPointF scenePos = view()->mapToScene(event->pos());
+
+ if (event->buttons() & Qt::RightButton) {
+ QMenu contextMenu;
+ contextMenu.addAction(m_zoomTo100Action);
+ contextMenu.addSeparator();
+ contextMenu.addAction(m_zoomInAction);
+ contextMenu.addAction(m_zoomOutAction);
+ contextMenu.exec(event->globalPos());
+ } else if (event->buttons() & Qt::LeftButton) {
+ m_dragBeginPos = scenePos;
+ m_dragStarted = false;
+ }
+}
+
+void ZoomTool::mouseMoveEvent(QMouseEvent *event)
+{
+ m_mousePos = event->pos();
+
+ QPointF scenePos = view()->mapToScene(event->pos());
+
+ if (event->buttons() & Qt::LeftButton
+ && (QPointF(scenePos - m_dragBeginPos).manhattanLength()
+ > Constants::DragStartDistance / 3)
+ && !m_dragStarted)
+ {
+ m_dragStarted = true;
+ m_rubberbandManipulator->begin(m_dragBeginPos);
+ return;
+ }
+
+ if (m_dragStarted)
+ m_rubberbandManipulator->update(scenePos);
+
+}
+
+void ZoomTool::mouseReleaseEvent(QMouseEvent *event)
+{
+ m_mousePos = event->pos();
+ QPointF scenePos = view()->mapToScene(event->pos());
+
+ if (m_dragStarted) {
+ m_rubberbandManipulator->end();
+
+ int x1 = qMin(scenePos.x(), m_rubberbandManipulator->beginPoint().x());
+ int x2 = qMax(scenePos.x(), m_rubberbandManipulator->beginPoint().x());
+ int y1 = qMin(scenePos.y(), m_rubberbandManipulator->beginPoint().y());
+ int y2 = qMax(scenePos.y(), m_rubberbandManipulator->beginPoint().y());
+
+ QPointF scenePosTopLeft = QPoint(x1, y1);
+ QPointF scenePosBottomRight = QPoint(x2, y2);
+
+ QRectF sceneArea(scenePosTopLeft, scenePosBottomRight);
+
+ m_currentScale = qMin(view()->rect().width() / sceneArea.width(),
+ view()->rect().height() / sceneArea.height());
+
+
+ QTransform transform;
+ transform.scale(m_currentScale, m_currentScale);
+
+ view()->setTransform(transform);
+ view()->setSceneRect(sceneArea);
+ } else {
+ Qt::KeyboardModifier modifierKey = Qt::ControlModifier;
+#ifdef Q_WS_MAC
+ modifierKey = Qt::AltModifier;
+#endif
+ if (event->modifiers() & modifierKey) {
+ zoomOut();
+ } else {
+ zoomIn();
+ }
+ }
+}
+
+void ZoomTool::zoomIn()
+{
+ m_currentScale = nextZoomScale(ZoomIn);
+ scaleView(view()->mapToScene(m_mousePos));
+}
+
+void ZoomTool::zoomOut()
+{
+ m_currentScale = nextZoomScale(ZoomOut);
+ scaleView(view()->mapToScene(m_mousePos));
+}
+
+void ZoomTool::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ m_mousePos = event->pos();
+}
+
+
+void ZoomTool::hoverMoveEvent(QMouseEvent *event)
+{
+ m_mousePos = event->pos();
+}
+
+
+void ZoomTool::keyPressEvent(QKeyEvent * /*event*/)
+{
+}
+
+void ZoomTool::wheelEvent(QWheelEvent *event)
+{
+ if (event->orientation() != Qt::Vertical)
+ return;
+
+ Qt::KeyboardModifier smoothZoomModifier = Qt::ControlModifier;
+ if (event->modifiers() & smoothZoomModifier) {
+ int numDegrees = event->delta() / 8;
+ m_currentScale += m_smoothZoomMultiplier * (numDegrees / 15.0f);
+
+ scaleView(view()->mapToScene(m_mousePos));
+
+ } else if (!event->modifiers()) {
+ if (event->delta() > 0) {
+ m_currentScale = nextZoomScale(ZoomIn);
+ } else if (event->delta() < 0) {
+ m_currentScale = nextZoomScale(ZoomOut);
+ }
+ scaleView(view()->mapToScene(m_mousePos));
+ }
+}
+
+void ZoomTool::keyReleaseEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Plus:
+ zoomIn();
+ break;
+ case Qt::Key_Minus:
+ zoomOut();
+ break;
+ case Qt::Key_1:
+ case Qt::Key_2:
+ case Qt::Key_3:
+ case Qt::Key_4:
+ case Qt::Key_5:
+ case Qt::Key_6:
+ case Qt::Key_7:
+ case Qt::Key_8:
+ case Qt::Key_9:
+ {
+ m_currentScale = ((event->key() - Qt::Key_0) * 1.0f);
+ scaleView(view()->mapToScene(m_mousePos)); // view()->mapToScene(view()->rect().center())
+ break;
+ }
+
+ default:
+ break;
+ }
+
+}
+
+void ZoomTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
+{
+}
+
+void ZoomTool::clear()
+{
+ view()->setCursor(Qt::ArrowCursor);
+}
+
+void ZoomTool::selectedItemsChanged(const QList<QGraphicsItem*> &/*itemList*/)
+{
+}
+
+void ZoomTool::scaleView(const QPointF &centerPos)
+{
+
+ QTransform transform;
+ transform.scale(m_currentScale, m_currentScale);
+ view()->setTransform(transform);
+
+ QPointF adjustedCenterPos = centerPos;
+ QSize rectSize(view()->rect().width() / m_currentScale,
+ view()->rect().height() / m_currentScale);
+
+ QRectF sceneRect;
+ if (qAbs(m_currentScale - 1.0f) < Constants::ZoomSnapDelta) {
+ adjustedCenterPos.rx() = rectSize.width() / 2;
+ adjustedCenterPos.ry() = rectSize.height() / 2;
+ }
+
+ if (m_currentScale < 1.0f) {
+ adjustedCenterPos.rx() = rectSize.width() / 2;
+ adjustedCenterPos.ry() = rectSize.height() / 2;
+ sceneRect.setRect(view()->rect().width() / 2 -rectSize.width() / 2,
+ view()->rect().height() / 2 -rectSize.height() / 2,
+ rectSize.width(),
+ rectSize.height());
+ } else {
+ sceneRect.setRect(adjustedCenterPos.x() - rectSize.width() / 2,
+ adjustedCenterPos.y() - rectSize.height() / 2,
+ rectSize.width(),
+ rectSize.height());
+ }
+
+ view()->setSceneRect(sceneRect);
+}
+
+void ZoomTool::zoomTo100()
+{
+ m_currentScale = 1.0f;
+ scaleView(view()->mapToScene(view()->rect().center()));
+}
+
+qreal ZoomTool::nextZoomScale(ZoomDirection direction) const
+{
+ static QList<qreal> zoomScales =
+ QList<qreal>()
+ << 0.125f
+ << 1.0f / 6.0f
+ << 0.25f
+ << 1.0f / 3.0f
+ << 0.5f
+ << 2.0f / 3.0f
+ << 1.0f
+ << 2.0f
+ << 3.0f
+ << 4.0f
+ << 5.0f
+ << 6.0f
+ << 7.0f
+ << 8.0f
+ << 12.0f
+ << 16.0f
+ << 32.0f
+ << 48.0f;
+
+ if (direction == ZoomIn) {
+ for (int i = 0; i < zoomScales.length(); ++i) {
+ if (zoomScales[i] > m_currentScale || i == zoomScales.length() - 1)
+ return zoomScales[i];
+ }
+ } else {
+ for (int i = zoomScales.length() - 1; i >= 0; --i) {
+ if (zoomScales[i] < m_currentScale || i == 0)
+ return zoomScales[i];
+ }
+ }
+
+ return 1.0f;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/declarativeobserver/editor/zoomtool_p.h b/src/plugins/qmltooling/declarativeobserver/editor/zoomtool_p.h
new file mode 100644
index 0000000..6734cf9
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/editor/zoomtool_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ZOOMTOOL_H
+#define ZOOMTOOL_H
+
+#include "abstractliveedittool_p.h"
+#include "liverubberbandselectionmanipulator_p.h"
+
+QT_FORWARD_DECLARE_CLASS(QAction)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class ZoomTool : public AbstractLiveEditTool
+{
+ Q_OBJECT
+
+public:
+ enum ZoomDirection {
+ ZoomIn,
+ ZoomOut
+ };
+
+ explicit ZoomTool(QDeclarativeViewObserver *view);
+
+ virtual ~ZoomTool();
+
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+
+ void hoverMoveEvent(QMouseEvent *event);
+ void wheelEvent(QWheelEvent *event);
+
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *keyEvent);
+ void itemsAboutToRemoved(const QList<QGraphicsItem*> &itemList);
+
+ void clear();
+
+protected:
+ void selectedItemsChanged(const QList<QGraphicsItem*> &itemList);
+
+private slots:
+ void zoomTo100();
+ void zoomIn();
+ void zoomOut();
+
+private:
+ qreal nextZoomScale(ZoomDirection direction) const;
+ void scaleView(const QPointF &centerPos);
+
+private:
+ bool m_dragStarted;
+ QPoint m_mousePos; // in view coords
+ QPointF m_dragBeginPos;
+ QAction *m_zoomTo100Action;
+ QAction *m_zoomInAction;
+ QAction *m_zoomOutAction;
+ LiveRubberBandSelectionManipulator *m_rubberbandManipulator;
+
+ qreal m_smoothZoomMultiplier;
+ qreal m_currentScale;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ZOOMTOOL_H
diff --git a/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.cpp b/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.cpp
new file mode 100644
index 0000000..458b7ef
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativeobserverplugin.h"
+
+#include "qdeclarativeviewobserver_p.h"
+
+#include <QtCore/qplugin.h>
+#include <QtDeclarative/private/qdeclarativeobserverservice_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QDeclarativeObserverPlugin::QDeclarativeObserverPlugin() :
+ m_observer(0)
+{
+}
+
+QDeclarativeObserverPlugin::~QDeclarativeObserverPlugin()
+{
+ delete m_observer;
+}
+
+void QDeclarativeObserverPlugin::activate()
+{
+ QDeclarativeObserverService *service = QDeclarativeObserverService::instance();
+ QList<QDeclarativeView*> views = service->views();
+ if (views.isEmpty())
+ return;
+
+ // TODO: Support multiple views
+ QDeclarativeView *view = service->views().at(0);
+ m_observer = new QDeclarativeViewObserver(view, view);
+}
+
+void QDeclarativeObserverPlugin::deactivate()
+{
+ delete m_observer;
+}
+
+Q_EXPORT_PLUGIN2(declarativeobserver, QDeclarativeObserverPlugin)
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.h b/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.h
new file mode 100644
index 0000000..82d3dbc
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverplugin.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEOBSERVERPLUGIN_H
+#define QDECLARATIVEOBSERVERPLUGIN_H
+
+#include <QtCore/QPointer>
+#include <QtDeclarative/private/qdeclarativeobserverinterface_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeViewObserver;
+
+class QDeclarativeObserverPlugin : public QObject, public QDeclarativeObserverInterface
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QDeclarativeObserverPlugin)
+ Q_INTERFACES(QDeclarativeObserverInterface)
+
+public:
+ QDeclarativeObserverPlugin();
+ ~QDeclarativeObserverPlugin();
+
+ void activate();
+ void deactivate();
+
+private:
+ QPointer<QDeclarativeViewObserver> m_observer;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEOBSERVERPLUGIN_H
diff --git a/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverprotocol.h b/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverprotocol.h
new file mode 100644
index 0000000..eb46693
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qdeclarativeobserverprotocol.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEOBSERVERPROTOCOL_H
+#define QDECLARATIVEOBSERVERPROTOCOL_H
+
+#include <QtCore/QDebug>
+#include <QtCore/QMetaType>
+#include <QtCore/QMetaEnum>
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class ObserverProtocol : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(Message Tool)
+
+public:
+ enum Message {
+ AnimationSpeedChanged = 0,
+ AnimationPausedChanged = 19, // highest value
+ ChangeTool = 1,
+ ClearComponentCache = 2,
+ ColorChanged = 3,
+ ContextPathUpdated = 4,
+ CreateObject = 5,
+ CurrentObjectsChanged = 6,
+ DestroyObject = 7,
+ MoveObject = 8,
+ ObjectIdList = 9,
+ Reload = 10,
+ Reloaded = 11,
+ SetAnimationSpeed = 12,
+ SetAnimationPaused = 18,
+ SetContextPathIdx = 13,
+ SetCurrentObjects = 14,
+ SetDesignMode = 15,
+ ShowAppOnTop = 16,
+ ToolChanged = 17
+ };
+
+ enum Tool {
+ ColorPickerTool,
+ SelectMarqueeTool,
+ SelectTool,
+ ZoomTool
+ };
+
+ static inline QString toString(Message message)
+ {
+ return QLatin1String(staticMetaObject.enumerator(0).valueToKey(message));
+ }
+
+ static inline QString toString(Tool tool)
+ {
+ return QLatin1String(staticMetaObject.enumerator(1).valueToKey(tool));
+ }
+};
+
+inline QDataStream & operator<< (QDataStream &stream, ObserverProtocol::Message message)
+{
+ return stream << static_cast<quint32>(message);
+}
+
+inline QDataStream & operator>> (QDataStream &stream, ObserverProtocol::Message &message)
+{
+ quint32 i;
+ stream >> i;
+ message = static_cast<ObserverProtocol::Message>(i);
+ return stream;
+}
+
+inline QDebug operator<< (QDebug dbg, ObserverProtocol::Message message)
+{
+ dbg << ObserverProtocol::toString(message);
+ return dbg;
+}
+
+inline QDataStream & operator<< (QDataStream &stream, ObserverProtocol::Tool tool)
+{
+ return stream << static_cast<quint32>(tool);
+}
+
+inline QDataStream & operator>> (QDataStream &stream, ObserverProtocol::Tool &tool)
+{
+ quint32 i;
+ stream >> i;
+ tool = static_cast<ObserverProtocol::Tool>(i);
+ return stream;
+}
+
+inline QDebug operator<< (QDebug dbg, ObserverProtocol::Tool tool)
+{
+ dbg << ObserverProtocol::toString(tool);
+ return dbg;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEOBSERVERPROTOCOL_H
diff --git a/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver.cpp b/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver.cpp
new file mode 100644
index 0000000..2286990
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver.cpp
@@ -0,0 +1,1167 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtDeclarative/private/qdeclarativeobserverservice_p.h"
+#include "QtDeclarative/private/qdeclarativedebughelper_p.h"
+
+#include "qdeclarativeviewobserver_p.h"
+#include "qdeclarativeviewobserver_p_p.h"
+#include "qdeclarativeobserverprotocol.h"
+
+#include "editor/liveselectiontool_p.h"
+#include "editor/zoomtool_p.h"
+#include "editor/colorpickertool_p.h"
+#include "editor/livelayeritem_p.h"
+#include "editor/boundingrecthighlighter_p.h"
+#include "editor/subcomponenteditortool_p.h"
+#include "editor/qmltoolbar_p.h"
+
+#include <QtDeclarative/QDeclarativeItem>
+#include <QtDeclarative/QDeclarativeEngine>
+#include <QtDeclarative/QDeclarativeContext>
+#include <QtDeclarative/QDeclarativeExpression>
+#include <QtGui/QWidget>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QGraphicsObject>
+#include <QtGui/QApplication>
+#include <QtCore/QSettings>
+
+static inline void initEditorResource() { Q_INIT_RESOURCE(editor); }
+
+QT_BEGIN_NAMESPACE
+
+const char * const KEY_TOOLBOX_GEOMETRY = "toolBox/geometry";
+
+const int SceneChangeUpdateInterval = 5000;
+
+
+class ToolBox : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ToolBox(QWidget *parent = 0);
+ ~ToolBox();
+
+ QmlToolBar *toolBar() const { return m_toolBar; }
+
+private:
+ QSettings m_settings;
+ QmlToolBar *m_toolBar;
+};
+
+ToolBox::ToolBox(QWidget *parent)
+ : QWidget(parent, Qt::Tool)
+ , m_settings(QLatin1String("Nokia"), QLatin1String("QmlObserver"), this)
+ , m_toolBar(new QmlToolBar)
+{
+ setWindowFlags((windowFlags() & ~Qt::WindowCloseButtonHint) | Qt::CustomizeWindowHint);
+ setWindowTitle(tr("Qt Quick Toolbox"));
+
+ QVBoxLayout *verticalLayout = new QVBoxLayout;
+ verticalLayout->setMargin(0);
+ verticalLayout->addWidget(m_toolBar);
+ setLayout(verticalLayout);
+
+ restoreGeometry(m_settings.value(QLatin1String(KEY_TOOLBOX_GEOMETRY)).toByteArray());
+}
+
+ToolBox::~ToolBox()
+{
+ m_settings.setValue(QLatin1String(KEY_TOOLBOX_GEOMETRY), saveGeometry());
+}
+
+
+QDeclarativeViewObserverPrivate::QDeclarativeViewObserverPrivate(QDeclarativeViewObserver *q) :
+ q(q),
+ designModeBehavior(false),
+ showAppOnTop(false),
+ animationPaused(false),
+ slowDownFactor(1.0f),
+ toolBox(0)
+{
+}
+
+QDeclarativeViewObserverPrivate::~QDeclarativeViewObserverPrivate()
+{
+}
+
+QDeclarativeViewObserver::QDeclarativeViewObserver(QDeclarativeView *view,
+ QObject *parent) :
+ QObject(parent),
+ data(new QDeclarativeViewObserverPrivate(this))
+{
+ initEditorResource();
+
+ data->view = view;
+ data->manipulatorLayer = new LiveLayerItem(view->scene());
+ data->selectionTool = new LiveSelectionTool(this);
+ data->zoomTool = new ZoomTool(this);
+ data->colorPickerTool = new ColorPickerTool(this);
+ data->boundingRectHighlighter = new BoundingRectHighlighter(this);
+ data->subcomponentEditorTool = new SubcomponentEditorTool(this);
+ data->currentTool = data->selectionTool;
+
+ // to capture ChildRemoved event when viewport changes
+ data->view->installEventFilter(this);
+
+ data->setViewport(data->view->viewport());
+
+ data->debugService = QDeclarativeObserverService::instance();
+ connect(data->debugService, SIGNAL(gotMessage(QByteArray)),
+ this, SLOT(handleMessage(QByteArray)));
+
+ connect(data->view, SIGNAL(statusChanged(QDeclarativeView::Status)),
+ data.data(), SLOT(_q_onStatusChanged(QDeclarativeView::Status)));
+
+ connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)),
+ SIGNAL(selectedColorChanged(QColor)));
+ connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)),
+ this, SLOT(sendColorChanged(QColor)));
+
+ connect(data->subcomponentEditorTool, SIGNAL(cleared()), SIGNAL(inspectorContextCleared()));
+ connect(data->subcomponentEditorTool, SIGNAL(contextPushed(QString)),
+ SIGNAL(inspectorContextPushed(QString)));
+ connect(data->subcomponentEditorTool, SIGNAL(contextPopped()),
+ SIGNAL(inspectorContextPopped()));
+ connect(data->subcomponentEditorTool, SIGNAL(contextPathChanged(QStringList)),
+ this, SLOT(sendContextPathUpdated(QStringList)));
+
+ data->_q_changeToSingleSelectTool();
+}
+
+QDeclarativeViewObserver::~QDeclarativeViewObserver()
+{
+}
+
+void QDeclarativeViewObserver::setObserverContext(int contextIndex)
+{
+ if (data->subcomponentEditorTool->contextIndex() != contextIndex) {
+ QGraphicsObject *object = data->subcomponentEditorTool->setContext(contextIndex);
+ if (object)
+ setSelectedItems(QList<QGraphicsItem*>() << object);
+ }
+}
+
+void QDeclarativeViewObserverPrivate::_q_setToolBoxVisible(bool visible)
+{
+#if !defined(Q_OS_SYMBIAN) && !defined(Q_WS_MAEMO_5) && !defined(Q_WS_SIMULATOR)
+ if (!toolBox && visible)
+ createToolBox();
+ if (toolBox)
+ toolBox->setVisible(visible);
+#else
+ Q_UNUSED(visible)
+#endif
+}
+
+void QDeclarativeViewObserverPrivate::_q_reloadView()
+{
+ subcomponentEditorTool->clear();
+ clearHighlight();
+ emit q->reloadRequested();
+}
+
+void QDeclarativeViewObserverPrivate::setViewport(QWidget *widget)
+{
+ if (viewport.data() == widget)
+ return;
+
+ if (viewport)
+ viewport.data()->removeEventFilter(q);
+
+ viewport = widget;
+ if (viewport) {
+ // make sure we get mouse move events
+ viewport.data()->setMouseTracking(true);
+ viewport.data()->installEventFilter(q);
+ }
+}
+
+void QDeclarativeViewObserverPrivate::clearEditorItems()
+{
+ clearHighlight();
+ setSelectedItems(QList<QGraphicsItem*>());
+}
+
+bool QDeclarativeViewObserver::eventFilter(QObject *obj, QEvent *event)
+{
+ if (obj == data->view) {
+ // Event from view
+ if (event->type() == QEvent::ChildRemoved) {
+ // Might mean that viewport has changed
+ if (data->view->viewport() != data->viewport.data())
+ data->setViewport(data->view->viewport());
+ }
+ return QObject::eventFilter(obj, event);
+ }
+
+ // Event from viewport
+ switch (event->type()) {
+ case QEvent::Leave: {
+ if (leaveEvent(event))
+ return true;
+ break;
+ }
+ case QEvent::MouseButtonPress: {
+ if (mousePressEvent(static_cast<QMouseEvent*>(event)))
+ return true;
+ break;
+ }
+ case QEvent::MouseMove: {
+ if (mouseMoveEvent(static_cast<QMouseEvent*>(event)))
+ return true;
+ break;
+ }
+ case QEvent::MouseButtonRelease: {
+ if (mouseReleaseEvent(static_cast<QMouseEvent*>(event)))
+ return true;
+ break;
+ }
+ case QEvent::KeyPress: {
+ if (keyPressEvent(static_cast<QKeyEvent*>(event)))
+ return true;
+ break;
+ }
+ case QEvent::KeyRelease: {
+ if (keyReleaseEvent(static_cast<QKeyEvent*>(event)))
+ return true;
+ break;
+ }
+ case QEvent::MouseButtonDblClick: {
+ if (mouseDoubleClickEvent(static_cast<QMouseEvent*>(event)))
+ return true;
+ break;
+ }
+ case QEvent::Wheel: {
+ if (wheelEvent(static_cast<QWheelEvent*>(event)))
+ return true;
+ break;
+ }
+ default: {
+ break;
+ }
+ } //switch
+
+ // standard event processing
+ return QObject::eventFilter(obj, event);
+}
+
+bool QDeclarativeViewObserver::leaveEvent(QEvent * /*event*/)
+{
+ if (!data->designModeBehavior)
+ return false;
+ data->clearHighlight();
+ return true;
+}
+
+bool QDeclarativeViewObserver::mousePressEvent(QMouseEvent *event)
+{
+ if (!data->designModeBehavior)
+ return false;
+ data->cursorPos = event->pos();
+ data->currentTool->mousePressEvent(event);
+ return true;
+}
+
+bool QDeclarativeViewObserver::mouseMoveEvent(QMouseEvent *event)
+{
+ if (!data->designModeBehavior) {
+ data->clearEditorItems();
+ return false;
+ }
+ data->cursorPos = event->pos();
+
+ QList<QGraphicsItem*> selItems = data->selectableItems(event->pos());
+ if (!selItems.isEmpty()) {
+ declarativeView()->setToolTip(data->currentTool->titleForItem(selItems.first()));
+ } else {
+ declarativeView()->setToolTip(QString());
+ }
+ if (event->buttons()) {
+ data->subcomponentEditorTool->mouseMoveEvent(event);
+ data->currentTool->mouseMoveEvent(event);
+ } else {
+ data->subcomponentEditorTool->hoverMoveEvent(event);
+ data->currentTool->hoverMoveEvent(event);
+ }
+ return true;
+}
+
+bool QDeclarativeViewObserver::mouseReleaseEvent(QMouseEvent *event)
+{
+ if (!data->designModeBehavior)
+ return false;
+ data->subcomponentEditorTool->mouseReleaseEvent(event);
+
+ data->cursorPos = event->pos();
+ data->currentTool->mouseReleaseEvent(event);
+ return true;
+}
+
+bool QDeclarativeViewObserver::keyPressEvent(QKeyEvent *event)
+{
+ if (!data->designModeBehavior)
+ return false;
+
+ data->currentTool->keyPressEvent(event);
+ return true;
+}
+
+bool QDeclarativeViewObserver::keyReleaseEvent(QKeyEvent *event)
+{
+ if (!data->designModeBehavior)
+ return false;
+
+ switch (event->key()) {
+ case Qt::Key_V:
+ data->_q_changeToSingleSelectTool();
+ break;
+// disabled because multiselection does not do anything useful without design mode
+// case Qt::Key_M:
+// data->_q_changeToMarqueeSelectTool();
+// break;
+ case Qt::Key_I:
+ data->_q_changeToColorPickerTool();
+ break;
+ case Qt::Key_Z:
+ data->_q_changeToZoomTool();
+ break;
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ if (!data->selectedItems().isEmpty())
+ data->subcomponentEditorTool->setCurrentItem(data->selectedItems().first());
+ break;
+ case Qt::Key_Space:
+ setAnimationPaused(!data->animationPaused);
+ break;
+ default:
+ break;
+ }
+
+ data->currentTool->keyReleaseEvent(event);
+ return true;
+}
+
+void QDeclarativeViewObserverPrivate::_q_createQmlObject(const QString &qml, QObject *parent,
+ const QStringList &importList,
+ const QString &filename)
+{
+ if (!parent)
+ return;
+
+ QString imports;
+ foreach (const QString &s, importList) {
+ imports += s;
+ imports += QLatin1Char('\n');
+ }
+
+ QDeclarativeContext *parentContext = view->engine()->contextForObject(parent);
+ QDeclarativeComponent component(view->engine(), q);
+ QByteArray constructedQml = QString(imports + qml).toLatin1();
+
+ component.setData(constructedQml, QUrl::fromLocalFile(filename));
+ QObject *newObject = component.create(parentContext);
+ if (newObject) {
+ newObject->setParent(parent);
+ QDeclarativeItem *parentItem = qobject_cast<QDeclarativeItem*>(parent);
+ QDeclarativeItem *newItem = qobject_cast<QDeclarativeItem*>(newObject);
+ if (parentItem && newItem)
+ newItem->setParentItem(parentItem);
+ }
+}
+
+void QDeclarativeViewObserverPrivate::_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 QDeclarativeViewObserverPrivate::_q_clearComponentCache()
+{
+ view->engine()->clearComponentCache();
+}
+
+void QDeclarativeViewObserverPrivate::_q_removeFromSelection(QObject *obj)
+{
+ QList<QGraphicsItem*> items = selectedItems();
+ if (QGraphicsItem *item = qobject_cast<QGraphicsObject*>(obj))
+ items.removeOne(item);
+ setSelectedItems(items);
+}
+
+QGraphicsItem *QDeclarativeViewObserverPrivate::currentRootItem() const
+{
+ return subcomponentEditorTool->currentRootItem();
+}
+
+bool QDeclarativeViewObserver::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ if (!data->designModeBehavior)
+ return false;
+
+ if (data->currentToolMode != Constants::SelectionToolMode
+ && data->currentToolMode != Constants::MarqueeSelectionToolMode)
+ return true;
+
+ QGraphicsItem *itemToEnter = 0;
+ QList<QGraphicsItem*> itemList = data->view->items(event->pos());
+ data->filterForSelection(itemList);
+
+ if (data->selectedItems().isEmpty() && !itemList.isEmpty()) {
+ itemToEnter = itemList.first();
+ } else if (!data->selectedItems().isEmpty() && !itemList.isEmpty()) {
+ itemToEnter = itemList.first();
+ }
+
+ if (itemToEnter)
+ itemToEnter = data->subcomponentEditorTool->firstChildOfContext(itemToEnter);
+
+ data->subcomponentEditorTool->setCurrentItem(itemToEnter);
+ data->subcomponentEditorTool->mouseDoubleClickEvent(event);
+
+ if ((event->buttons() & Qt::LeftButton) && itemToEnter) {
+ if (QGraphicsObject *objectToEnter = itemToEnter->toGraphicsObject())
+ setSelectedItems(QList<QGraphicsItem*>() << objectToEnter);
+ }
+
+ return true;
+}
+
+bool QDeclarativeViewObserver::wheelEvent(QWheelEvent *event)
+{
+ if (!data->designModeBehavior)
+ return false;
+ data->currentTool->wheelEvent(event);
+ return true;
+}
+
+void QDeclarativeViewObserverPrivate::enterContext(QGraphicsItem *itemToEnter)
+{
+ QGraphicsItem *itemUnderCurrentContext = itemToEnter;
+ if (itemUnderCurrentContext)
+ itemUnderCurrentContext = subcomponentEditorTool->firstChildOfContext(itemToEnter);
+
+ if (itemUnderCurrentContext)
+ subcomponentEditorTool->setCurrentItem(itemToEnter);
+}
+
+void QDeclarativeViewObserver::setDesignModeBehavior(bool value)
+{
+ emit designModeBehaviorChanged(value);
+
+ if (data->toolBox)
+ data->toolBox->toolBar()->setDesignModeBehavior(value);
+ sendDesignModeBehavior(value);
+
+ data->designModeBehavior = value;
+ if (data->subcomponentEditorTool) {
+ data->subcomponentEditorTool->clear();
+ data->clearHighlight();
+ data->setSelectedItems(QList<QGraphicsItem*>());
+
+ if (data->view->rootObject())
+ data->subcomponentEditorTool->pushContext(data->view->rootObject());
+ }
+
+ if (!data->designModeBehavior)
+ data->clearEditorItems();
+}
+
+bool QDeclarativeViewObserver::designModeBehavior()
+{
+ return data->designModeBehavior;
+}
+
+bool QDeclarativeViewObserver::showAppOnTop() const
+{
+ return data->showAppOnTop;
+}
+
+void QDeclarativeViewObserver::setShowAppOnTop(bool appOnTop)
+{
+ if (data->view) {
+ QWidget *window = data->view->window();
+ Qt::WindowFlags flags = window->windowFlags();
+ if (appOnTop)
+ flags |= Qt::WindowStaysOnTopHint;
+ else
+ flags &= ~Qt::WindowStaysOnTopHint;
+
+ window->setWindowFlags(flags);
+ window->show();
+ }
+
+ data->showAppOnTop = appOnTop;
+ sendShowAppOnTop(appOnTop);
+
+ emit showAppOnTopChanged(appOnTop);
+}
+
+void QDeclarativeViewObserverPrivate::changeTool(Constants::DesignTool tool,
+ Constants::ToolFlags /*flags*/)
+{
+ switch (tool) {
+ case Constants::SelectionToolMode:
+ _q_changeToSingleSelectTool();
+ break;
+ case Constants::NoTool:
+ default:
+ currentTool = 0;
+ break;
+ }
+}
+
+void QDeclarativeViewObserverPrivate::setSelectedItemsForTools(QList<QGraphicsItem *> items)
+{
+ foreach (const QWeakPointer<QGraphicsObject> &obj, currentSelection) {
+ if (QGraphicsItem *item = obj.data()) {
+ if (!items.contains(item)) {
+ QObject::disconnect(obj.data(), SIGNAL(destroyed(QObject*)),
+ this, SLOT(_q_removeFromSelection(QObject*)));
+ currentSelection.removeOne(obj);
+ }
+ }
+ }
+
+ foreach (QGraphicsItem *item, items) {
+ if (item) {
+ if (QGraphicsObject *obj = item->toGraphicsObject()) {
+ QObject::connect(obj, SIGNAL(destroyed(QObject*)),
+ this, SLOT(_q_removeFromSelection(QObject*)));
+ currentSelection.append(obj);
+ }
+ }
+ }
+
+ currentTool->updateSelectedItems();
+}
+
+void QDeclarativeViewObserverPrivate::setSelectedItems(QList<QGraphicsItem *> items)
+{
+ QList<QWeakPointer<QGraphicsObject> > oldList = currentSelection;
+ setSelectedItemsForTools(items);
+ if (oldList != currentSelection) {
+ QList<QObject*> objectList;
+ foreach (const QWeakPointer<QGraphicsObject> &graphicsObject, currentSelection) {
+ if (graphicsObject)
+ objectList << graphicsObject.data();
+ }
+
+ q->sendCurrentObjects(objectList);
+ }
+}
+
+QList<QGraphicsItem *> QDeclarativeViewObserverPrivate::selectedItems() const
+{
+ QList<QGraphicsItem *> selection;
+ foreach (const QWeakPointer<QGraphicsObject> &selectedObject, currentSelection) {
+ if (selectedObject.data())
+ selection << selectedObject.data();
+ }
+
+ return selection;
+}
+
+void QDeclarativeViewObserver::setSelectedItems(QList<QGraphicsItem *> items)
+{
+ data->setSelectedItems(items);
+}
+
+QList<QGraphicsItem *> QDeclarativeViewObserver::selectedItems() const
+{
+ return data->selectedItems();
+}
+
+QDeclarativeView *QDeclarativeViewObserver::declarativeView()
+{
+ return data->view;
+}
+
+void QDeclarativeViewObserverPrivate::clearHighlight()
+{
+ boundingRectHighlighter->clear();
+}
+
+void QDeclarativeViewObserverPrivate::highlight(QGraphicsObject * item, ContextFlags flags)
+{
+ highlight(QList<QGraphicsObject*>() << item, flags);
+}
+
+void QDeclarativeViewObserverPrivate::highlight(QList<QGraphicsObject *> items, ContextFlags flags)
+{
+ if (items.isEmpty())
+ return;
+
+ QList<QGraphicsObject*> objectList;
+ foreach (QGraphicsItem *item, items) {
+ QGraphicsItem *child = item;
+ if (flags & ContextSensitive)
+ child = subcomponentEditorTool->firstChildOfContext(item);
+
+ if (child) {
+ QGraphicsObject *childObject = child->toGraphicsObject();
+ if (childObject)
+ objectList << childObject;
+ }
+ }
+
+ boundingRectHighlighter->highlight(objectList);
+}
+
+bool QDeclarativeViewObserverPrivate::mouseInsideContextItem() const
+{
+ return subcomponentEditorTool->containsCursor(cursorPos.toPoint());
+}
+
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::selectableItems(
+ const QPointF &scenePos) const
+{
+ QList<QGraphicsItem*> itemlist = view->scene()->items(scenePos);
+ return filterForCurrentContext(itemlist);
+}
+
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::selectableItems(const QPoint &pos) const
+{
+ QList<QGraphicsItem*> itemlist = view->items(pos);
+ return filterForCurrentContext(itemlist);
+}
+
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::selectableItems(
+ const QRectF &sceneRect, Qt::ItemSelectionMode selectionMode) const
+{
+ QList<QGraphicsItem*> itemlist = view->scene()->items(sceneRect, selectionMode);
+
+ return filterForCurrentContext(itemlist);
+}
+
+void QDeclarativeViewObserverPrivate::_q_changeToSingleSelectTool()
+{
+ currentToolMode = Constants::SelectionToolMode;
+ selectionTool->setRubberbandSelectionMode(false);
+
+ changeToSelectTool();
+
+ emit q->selectToolActivated();
+ q->sendCurrentTool(Constants::SelectionToolMode);
+}
+
+void QDeclarativeViewObserverPrivate::changeToSelectTool()
+{
+ if (currentTool == selectionTool)
+ return;
+
+ currentTool->clear();
+ currentTool = selectionTool;
+ currentTool->clear();
+ currentTool->updateSelectedItems();
+}
+
+void QDeclarativeViewObserverPrivate::_q_changeToMarqueeSelectTool()
+{
+ changeToSelectTool();
+ currentToolMode = Constants::MarqueeSelectionToolMode;
+ selectionTool->setRubberbandSelectionMode(true);
+
+ emit q->marqueeSelectToolActivated();
+ q->sendCurrentTool(Constants::MarqueeSelectionToolMode);
+}
+
+void QDeclarativeViewObserverPrivate::_q_changeToZoomTool()
+{
+ currentToolMode = Constants::ZoomMode;
+ currentTool->clear();
+ currentTool = zoomTool;
+ currentTool->clear();
+
+ emit q->zoomToolActivated();
+ q->sendCurrentTool(Constants::ZoomMode);
+}
+
+void QDeclarativeViewObserverPrivate::_q_changeToColorPickerTool()
+{
+ if (currentTool == colorPickerTool)
+ return;
+
+ currentToolMode = Constants::ColorPickerMode;
+ currentTool->clear();
+ currentTool = colorPickerTool;
+ currentTool->clear();
+
+ emit q->colorPickerActivated();
+ q->sendCurrentTool(Constants::ColorPickerMode);
+}
+
+void QDeclarativeViewObserverPrivate::_q_changeContextPathIndex(int index)
+{
+ subcomponentEditorTool->setContext(index);
+}
+
+void QDeclarativeViewObserver::setAnimationSpeed(qreal slowDownFactor)
+{
+ Q_ASSERT(slowDownFactor > 0);
+ if (data->slowDownFactor == slowDownFactor)
+ return;
+
+ animationSpeedChangeRequested(slowDownFactor);
+ sendAnimationSpeed(slowDownFactor);
+}
+
+void QDeclarativeViewObserver::setAnimationPaused(bool paused)
+{
+ if (data->animationPaused == paused)
+ return;
+
+ animationPausedChangeRequested(paused);
+ sendAnimationPaused(paused);
+}
+
+void QDeclarativeViewObserver::animationSpeedChangeRequested(qreal factor)
+{
+ if (data->slowDownFactor != factor) {
+ data->slowDownFactor = factor;
+ emit animationSpeedChanged(factor);
+ }
+
+ const float effectiveFactor = data->animationPaused ? 0 : factor;
+ QDeclarativeDebugHelper::setAnimationSlowDownFactor(effectiveFactor);
+}
+
+void QDeclarativeViewObserver::animationPausedChangeRequested(bool paused)
+{
+ if (data->animationPaused != paused) {
+ data->animationPaused = paused;
+ emit animationPausedChanged(paused);
+ }
+
+ const float effectiveFactor = paused ? 0 : data->slowDownFactor;
+ QDeclarativeDebugHelper::setAnimationSlowDownFactor(effectiveFactor);
+}
+
+
+void QDeclarativeViewObserverPrivate::_q_applyChangesFromClient()
+{
+}
+
+
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::filterForSelection(
+ QList<QGraphicsItem*> &itemlist) const
+{
+ foreach (QGraphicsItem *item, itemlist) {
+ if (isEditorItem(item) || !subcomponentEditorTool->isChildOfContext(item))
+ itemlist.removeOne(item);
+ }
+
+ return itemlist;
+}
+
+QList<QGraphicsItem*> QDeclarativeViewObserverPrivate::filterForCurrentContext(
+ QList<QGraphicsItem*> &itemlist) const
+{
+ foreach (QGraphicsItem *item, itemlist) {
+
+ if (isEditorItem(item) || !subcomponentEditorTool->isDirectChildOfContext(item)) {
+
+ // if we're a child, but not directly, replace with the parent that is directly in context.
+ if (QGraphicsItem *contextParent = subcomponentEditorTool->firstChildOfContext(item)) {
+ if (contextParent != item) {
+ if (itemlist.contains(contextParent)) {
+ itemlist.removeOne(item);
+ } else {
+ itemlist.replace(itemlist.indexOf(item), contextParent);
+ }
+ }
+ } else {
+ itemlist.removeOne(item);
+ }
+ }
+ }
+
+ return itemlist;
+}
+
+bool QDeclarativeViewObserverPrivate::isEditorItem(QGraphicsItem *item) const
+{
+ return (item->type() == Constants::EditorItemType
+ || item->type() == Constants::ResizeHandleItemType
+ || item->data(Constants::EditorItemDataKey).toBool());
+}
+
+void QDeclarativeViewObserverPrivate::_q_onStatusChanged(QDeclarativeView::Status status)
+{
+ if (status == QDeclarativeView::Ready) {
+ if (view->rootObject()) {
+ if (subcomponentEditorTool->contextIndex() != -1)
+ subcomponentEditorTool->clear();
+ subcomponentEditorTool->pushContext(view->rootObject());
+ }
+ q->sendReloaded();
+ }
+}
+
+void QDeclarativeViewObserverPrivate::_q_onCurrentObjectsChanged(QList<QObject*> objects)
+{
+ QList<QGraphicsItem*> items;
+ QList<QGraphicsObject*> gfxObjects;
+ foreach (QObject *obj, objects) {
+ QDeclarativeItem* declarativeItem = qobject_cast<QDeclarativeItem*>(obj);
+ if (declarativeItem) {
+ items << declarativeItem;
+ if (QGraphicsObject *gfxObj = declarativeItem->toGraphicsObject())
+ gfxObjects << gfxObj;
+ }
+ }
+ if (designModeBehavior) {
+ setSelectedItemsForTools(items);
+ clearHighlight();
+ highlight(gfxObjects, QDeclarativeViewObserverPrivate::IgnoreContext);
+ }
+}
+
+// adjusts bounding boxes on edges of screen to be visible
+QRectF QDeclarativeViewObserver::adjustToScreenBoundaries(const QRectF &boundingRectInSceneSpace)
+{
+ int marginFromEdge = 1;
+ QRectF boundingRect(boundingRectInSceneSpace);
+ if (qAbs(boundingRect.left()) - 1 < 2)
+ boundingRect.setLeft(marginFromEdge);
+
+ QRect rect = data->view->rect();
+
+ if (boundingRect.right() >= rect.right())
+ boundingRect.setRight(rect.right() - marginFromEdge);
+
+ if (qAbs(boundingRect.top()) - 1 < 2)
+ boundingRect.setTop(marginFromEdge);
+
+ if (boundingRect.bottom() >= rect.bottom())
+ boundingRect.setBottom(rect.bottom() - marginFromEdge);
+
+ return boundingRect;
+}
+
+void QDeclarativeViewObserverPrivate::createToolBox()
+{
+ toolBox = new ToolBox(q->declarativeView());
+
+ QmlToolBar *toolBar = toolBox->toolBar();
+
+ QObject::connect(q, SIGNAL(selectedColorChanged(QColor)),
+ toolBar, SLOT(setColorBoxColor(QColor)));
+
+ QObject::connect(q, SIGNAL(designModeBehaviorChanged(bool)),
+ toolBar, SLOT(setDesignModeBehavior(bool)));
+
+ QObject::connect(toolBar, SIGNAL(designModeBehaviorChanged(bool)),
+ q, SLOT(setDesignModeBehavior(bool)));
+ QObject::connect(toolBar, SIGNAL(animationSpeedChanged(qreal)), q, SLOT(setAnimationSpeed(qreal)));
+ QObject::connect(toolBar, SIGNAL(animationPausedChanged(bool)), q, SLOT(setAnimationPaused(bool)));
+ QObject::connect(toolBar, SIGNAL(colorPickerSelected()), this, SLOT(_q_changeToColorPickerTool()));
+ QObject::connect(toolBar, SIGNAL(zoomToolSelected()), this, SLOT(_q_changeToZoomTool()));
+ QObject::connect(toolBar, SIGNAL(selectToolSelected()), this, SLOT(_q_changeToSingleSelectTool()));
+ QObject::connect(toolBar, SIGNAL(marqueeSelectToolSelected()),
+ this, SLOT(_q_changeToMarqueeSelectTool()));
+
+ QObject::connect(toolBar, SIGNAL(applyChangesFromQmlFileSelected()),
+ this, SLOT(_q_applyChangesFromClient()));
+
+ QObject::connect(q, SIGNAL(animationSpeedChanged(qreal)), toolBar, SLOT(setAnimationSpeed(qreal)));
+ QObject::connect(q, SIGNAL(animationPausedChanged(bool)), toolBar, SLOT(setAnimationPaused(bool)));
+
+ QObject::connect(q, SIGNAL(selectToolActivated()), toolBar, SLOT(activateSelectTool()));
+
+ // disabled features
+ //connect(d->m_toolBar, SIGNAL(applyChangesToQmlFileSelected()), SLOT(applyChangesToClient()));
+ //connect(q, SIGNAL(resizeToolActivated()), d->m_toolBar, SLOT(activateSelectTool()));
+ //connect(q, SIGNAL(moveToolActivated()), d->m_toolBar, SLOT(activateSelectTool()));
+
+ QObject::connect(q, SIGNAL(colorPickerActivated()), toolBar, SLOT(activateColorPicker()));
+ QObject::connect(q, SIGNAL(zoomToolActivated()), toolBar, SLOT(activateZoom()));
+ QObject::connect(q, SIGNAL(marqueeSelectToolActivated()),
+ toolBar, SLOT(activateMarqueeSelectTool()));
+}
+
+void QDeclarativeViewObserver::handleMessage(const QByteArray &message)
+{
+ QDataStream ds(message);
+
+ ObserverProtocol::Message type;
+ ds >> type;
+
+ switch (type) {
+ case ObserverProtocol::SetCurrentObjects: {
+ int itemCount = 0;
+ ds >> itemCount;
+
+ QList<QObject*> selectedObjects;
+ for (int i = 0; i < itemCount; ++i) {
+ int debugId = -1;
+ ds >> debugId;
+ QObject *obj = QDeclarativeDebugService::objectForId(debugId);
+
+ if (obj)
+ selectedObjects << obj;
+ }
+
+ data->_q_onCurrentObjectsChanged(selectedObjects);
+ break;
+ }
+ case ObserverProtocol::Reload: {
+ data->_q_reloadView();
+ break;
+ }
+ case ObserverProtocol::SetAnimationSpeed: {
+ qreal speed;
+ ds >> speed;
+ animationSpeedChangeRequested(speed);
+ break;
+ }
+ case ObserverProtocol::SetAnimationPaused: {
+ bool paused;
+ ds >> paused;
+ animationPausedChangeRequested(paused);
+ break;
+ }
+ case ObserverProtocol::ChangeTool: {
+ ObserverProtocol::Tool tool;
+ ds >> tool;
+ switch (tool) {
+ case ObserverProtocol::ColorPickerTool:
+ data->_q_changeToColorPickerTool();
+ break;
+ case ObserverProtocol::SelectTool:
+ data->_q_changeToSingleSelectTool();
+ break;
+ case ObserverProtocol::SelectMarqueeTool:
+ data->_q_changeToMarqueeSelectTool();
+ break;
+ case ObserverProtocol::ZoomTool:
+ data->_q_changeToZoomTool();
+ break;
+ default:
+ qWarning() << "Warning: Unhandled tool:" << tool;
+ }
+ break;
+ }
+ case ObserverProtocol::SetDesignMode: {
+ bool inDesignMode;
+ ds >> inDesignMode;
+ setDesignModeBehavior(inDesignMode);
+ break;
+ }
+ case ObserverProtocol::ShowAppOnTop: {
+ bool showOnTop;
+ ds >> showOnTop;
+ setShowAppOnTop(showOnTop);
+ break;
+ }
+ case ObserverProtocol::CreateObject: {
+ QString qml;
+ int parentId;
+ QString filename;
+ QStringList imports;
+ ds >> qml >> parentId >> imports >> filename;
+ data->_q_createQmlObject(qml, QDeclarativeDebugService::objectForId(parentId),
+ imports, filename);
+ break;
+ }
+ case ObserverProtocol::DestroyObject: {
+ int debugId;
+ ds >> debugId;
+ if (QObject* obj = QDeclarativeDebugService::objectForId(debugId))
+ obj->deleteLater();
+ break;
+ }
+ case ObserverProtocol::MoveObject: {
+ int debugId, newParent;
+ ds >> debugId >> newParent;
+ data->_q_reparentQmlObject(QDeclarativeDebugService::objectForId(debugId),
+ QDeclarativeDebugService::objectForId(newParent));
+ break;
+ }
+ case ObserverProtocol::ObjectIdList: {
+ int itemCount;
+ ds >> itemCount;
+ data->stringIdForObjectId.clear();
+ for (int i = 0; i < itemCount; ++i) {
+ int itemDebugId;
+ QString itemIdString;
+ ds >> itemDebugId
+ >> itemIdString;
+
+ data->stringIdForObjectId.insert(itemDebugId, itemIdString);
+ }
+ break;
+ }
+ case ObserverProtocol::SetContextPathIdx: {
+ int contextPathIndex;
+ ds >> contextPathIndex;
+ data->_q_changeContextPathIndex(contextPathIndex);
+ break;
+ }
+ case ObserverProtocol::ClearComponentCache: {
+ data->_q_clearComponentCache();
+ break;
+ }
+ default:
+ qWarning() << "Warning: Not handling message:" << type;
+ }
+}
+
+void QDeclarativeViewObserver::sendDesignModeBehavior(bool inDesignMode)
+{
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ ds << ObserverProtocol::SetDesignMode
+ << inDesignMode;
+
+ data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendCurrentObjects(QList<QObject*> objects)
+{
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ ds << ObserverProtocol::CurrentObjectsChanged
+ << objects.length();
+
+ foreach (QObject *object, objects) {
+ int id = QDeclarativeDebugService::idForObject(object);
+ ds << id;
+ }
+
+ data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendCurrentTool(Constants::DesignTool toolId)
+{
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ ds << ObserverProtocol::ToolChanged
+ << toolId;
+
+ data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendAnimationSpeed(qreal slowDownFactor)
+{
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ ds << ObserverProtocol::AnimationSpeedChanged
+ << slowDownFactor;
+
+ data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendAnimationPaused(bool paused)
+{
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ ds << ObserverProtocol::AnimationPausedChanged
+ << paused;
+
+ data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendReloaded()
+{
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ ds << ObserverProtocol::Reloaded;
+
+ data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendShowAppOnTop(bool showAppOnTop)
+{
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ ds << ObserverProtocol::ShowAppOnTop << showAppOnTop;
+
+ data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendColorChanged(const QColor &color)
+{
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ ds << ObserverProtocol::ColorChanged
+ << color;
+
+ data->debugService->sendMessage(message);
+}
+
+void QDeclarativeViewObserver::sendContextPathUpdated(const QStringList &contextPath)
+{
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ ds << ObserverProtocol::ContextPathUpdated
+ << contextPath;
+
+ data->debugService->sendMessage(message);
+}
+
+QString QDeclarativeViewObserver::idStringForObject(QObject *obj) const
+{
+ int id = QDeclarativeDebugService::idForObject(obj);
+ QString idString = data->stringIdForObjectId.value(id, QString());
+ return idString;
+}
+
+QT_END_NAMESPACE
+
+#include "qdeclarativeviewobserver.moc"
diff --git a/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p.h b/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p.h
new file mode 100644
index 0000000..6e986c2
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEVIEWOBSERVER_P_H
+#define QDECLARATIVEVIEWOBSERVER_P_H
+
+#include <private/qdeclarativeglobal_p.h>
+#include "qmlobserverconstants_p.h"
+
+#include <QtCore/QScopedPointer>
+#include <QtDeclarative/QDeclarativeView>
+
+QT_FORWARD_DECLARE_CLASS(QDeclarativeItem)
+QT_FORWARD_DECLARE_CLASS(QMouseEvent)
+QT_FORWARD_DECLARE_CLASS(QToolBar)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserverPrivate;
+
+class QDeclarativeViewObserver : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit QDeclarativeViewObserver(QDeclarativeView *view, QObject *parent = 0);
+ ~QDeclarativeViewObserver();
+
+ void setSelectedItems(QList<QGraphicsItem *> items);
+ QList<QGraphicsItem *> selectedItems() const;
+
+ QDeclarativeView *declarativeView();
+
+ QRectF adjustToScreenBoundaries(const QRectF &boundingRectInSceneSpace);
+
+ bool showAppOnTop() const;
+
+ void sendDesignModeBehavior(bool inDesignMode);
+ void sendCurrentObjects(QList<QObject*> items);
+ void sendAnimationSpeed(qreal slowDownFactor);
+ void sendAnimationPaused(bool paused);
+ void sendCurrentTool(Constants::DesignTool toolId);
+ void sendReloaded();
+ void sendShowAppOnTop(bool showAppOnTop);
+
+ QString idStringForObject(QObject *obj) const;
+
+public Q_SLOTS:
+ void sendColorChanged(const QColor &color);
+ void sendContextPathUpdated(const QStringList &contextPath);
+
+ void setDesignModeBehavior(bool value);
+ bool designModeBehavior();
+
+ void setShowAppOnTop(bool appOnTop);
+
+ void setAnimationSpeed(qreal factor);
+ void setAnimationPaused(bool paused);
+
+ void setObserverContext(int contextIndex);
+
+Q_SIGNALS:
+ void designModeBehaviorChanged(bool inDesignMode);
+ void showAppOnTopChanged(bool showAppOnTop);
+ void reloadRequested();
+ void marqueeSelectToolActivated();
+ void selectToolActivated();
+ void zoomToolActivated();
+ void colorPickerActivated();
+ void selectedColorChanged(const QColor &color);
+
+ void animationSpeedChanged(qreal factor);
+ void animationPausedChanged(bool paused);
+
+ void inspectorContextCleared();
+ void inspectorContextPushed(const QString &contextTitle);
+ void inspectorContextPopped();
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event);
+
+ bool leaveEvent(QEvent *);
+ bool mousePressEvent(QMouseEvent *event);
+ bool mouseMoveEvent(QMouseEvent *event);
+ bool mouseReleaseEvent(QMouseEvent *event);
+ bool keyPressEvent(QKeyEvent *event);
+ bool keyReleaseEvent(QKeyEvent *keyEvent);
+ bool mouseDoubleClickEvent(QMouseEvent *event);
+ bool wheelEvent(QWheelEvent *event);
+
+ void setSelectedItemsForTools(QList<QGraphicsItem *> items);
+
+private slots:
+ void handleMessage(const QByteArray &message);
+
+ void animationSpeedChangeRequested(qreal factor);
+ void animationPausedChangeRequested(bool paused);
+
+private:
+ Q_DISABLE_COPY(QDeclarativeViewObserver)
+
+ inline QDeclarativeViewObserverPrivate *d_func() { return data.data(); }
+ QScopedPointer<QDeclarativeViewObserverPrivate> data;
+ friend class QDeclarativeViewObserverPrivate;
+ friend class AbstractLiveEditTool;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEVIEWOBSERVER_P_H
diff --git a/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p_p.h b/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p_p.h
new file mode 100644
index 0000000..6022555
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qdeclarativeviewobserver_p_p.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEVIEWOBSERVER_P_P_H
+#define QDECLARATIVEVIEWOBSERVER_P_P_H
+
+#include "qdeclarativeviewobserver_p.h"
+
+#include <QtCore/QWeakPointer>
+#include <QtCore/QPointF>
+
+#include "QtDeclarative/private/qdeclarativeobserverservice_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewObserver;
+class LiveSelectionTool;
+class ZoomTool;
+class ColorPickerTool;
+class LiveLayerItem;
+class BoundingRectHighlighter;
+class SubcomponentEditorTool;
+class ToolBox;
+class AbstractLiveEditTool;
+
+class QDeclarativeViewObserverPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ enum ContextFlags {
+ IgnoreContext,
+ ContextSensitive
+ };
+
+ QDeclarativeViewObserverPrivate(QDeclarativeViewObserver *);
+ ~QDeclarativeViewObserverPrivate();
+
+ QDeclarativeView *view;
+ QDeclarativeViewObserver *q;
+ QDeclarativeObserverService *debugService;
+ QWeakPointer<QWidget> viewport;
+ QHash<int, QString> stringIdForObjectId;
+
+ QPointF cursorPos;
+ QList<QWeakPointer<QGraphicsObject> > currentSelection;
+
+ Constants::DesignTool currentToolMode;
+ AbstractLiveEditTool *currentTool;
+
+ LiveSelectionTool *selectionTool;
+ ZoomTool *zoomTool;
+ ColorPickerTool *colorPickerTool;
+ SubcomponentEditorTool *subcomponentEditorTool;
+ LiveLayerItem *manipulatorLayer;
+
+ BoundingRectHighlighter *boundingRectHighlighter;
+
+ bool designModeBehavior;
+ bool showAppOnTop;
+
+ bool animationPaused;
+ qreal slowDownFactor;
+
+ ToolBox *toolBox;
+
+ void setViewport(QWidget *widget);
+
+ void clearEditorItems();
+ void createToolBox();
+ void changeToSelectTool();
+ QList<QGraphicsItem*> filterForCurrentContext(QList<QGraphicsItem*> &itemlist) const;
+ QList<QGraphicsItem*> filterForSelection(QList<QGraphicsItem*> &itemlist) const;
+
+ QList<QGraphicsItem*> selectableItems(const QPoint &pos) const;
+ QList<QGraphicsItem*> selectableItems(const QPointF &scenePos) const;
+ QList<QGraphicsItem*> selectableItems(const QRectF &sceneRect, Qt::ItemSelectionMode selectionMode) const;
+
+ void setSelectedItemsForTools(QList<QGraphicsItem *> items);
+ void setSelectedItems(QList<QGraphicsItem *> items);
+ QList<QGraphicsItem *> selectedItems() const;
+
+ void changeTool(Constants::DesignTool tool,
+ Constants::ToolFlags flags = Constants::NoToolFlags);
+
+ void clearHighlight();
+ void highlight(QList<QGraphicsObject *> item, ContextFlags flags = ContextSensitive);
+ void highlight(QGraphicsObject *item, ContextFlags flags = ContextSensitive);
+
+ bool mouseInsideContextItem() const;
+ bool isEditorItem(QGraphicsItem *item) const;
+
+ QGraphicsItem *currentRootItem() const;
+
+ void enterContext(QGraphicsItem *itemToEnter);
+
+public slots:
+ void _q_setToolBoxVisible(bool visible);
+
+ void _q_reloadView();
+ void _q_onStatusChanged(QDeclarativeView::Status status);
+ void _q_onCurrentObjectsChanged(QList<QObject*> objects);
+ 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();
+ void _q_changeToZoomTool();
+ void _q_changeToColorPickerTool();
+ void _q_changeContextPathIndex(int index);
+ void _q_clearComponentCache();
+ void _q_removeFromSelection(QObject *);
+
+public:
+ static QDeclarativeViewObserverPrivate *get(QDeclarativeViewObserver *v) { return v->d_func(); }
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEVIEWOBSERVER_P_P_H
diff --git a/src/plugins/qmltooling/declarativeobserver/qmlobserverconstants_p.h b/src/plugins/qmltooling/declarativeobserver/qmlobserverconstants_p.h
new file mode 100644
index 0000000..353e235
--- /dev/null
+++ b/src/plugins/qmltooling/declarativeobserver/qmlobserverconstants_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLOBSERVERCONSTANTS_H
+#define QMLOBSERVERCONSTANTS_H
+
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+namespace Constants {
+
+enum DesignTool {
+ NoTool = 0,
+ SelectionToolMode = 1,
+ MarqueeSelectionToolMode = 2,
+ MoveToolMode = 3,
+ ResizeToolMode = 4,
+ ColorPickerMode = 5,
+ ZoomMode = 6
+};
+
+enum ToolFlags {
+ NoToolFlags = 0,
+ UseCursorPos = 1
+};
+
+static const int DragStartTime = 50;
+
+static const int DragStartDistance = 20;
+
+static const double ZoomSnapDelta = 0.04;
+
+static const int EditorItemDataKey = 1000;
+
+enum GraphicsItemTypes {
+ EditorItemType = 0xEAAA,
+ ResizeHandleItemType = 0xEAEA
+};
+
+
+} // namespace Constants
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLOBSERVERCONSTANTS_H
diff --git a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp
index 1c91c34..ac32081 100644
--- a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp
+++ b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp
@@ -109,6 +109,12 @@ void QmlOstPlugin::disconnect()
d->protocol = 0;
}
+bool QmlOstPlugin::waitForMessage()
+{
+ Q_D(QmlOstPlugin);
+ return d->protocol->waitForReadyRead(-1);
+}
+
void QmlOstPlugin::setPort(int port, bool block)
{
Q_UNUSED(port);
diff --git a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h
index eee6ee1..b4ff377 100644
--- a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h
+++ b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h
@@ -68,6 +68,7 @@ public:
bool isConnected() const;
void send(const QByteArray &message);
void disconnect();
+ bool waitForMessage();
private Q_SLOTS:
void readyRead();
diff --git a/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp b/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp
index 21b0169..d3b2661 100644
--- a/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp
+++ b/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp
@@ -57,6 +57,8 @@ public:
Cancel();
}
+ TInt& AoFlags() { return ((TInt*)&iStatus)[1]; }
+
private:
void RunL();
void DoCancel();
@@ -65,6 +67,7 @@ private:
RUsbOstComm ost;
TBuf8<4096> readBuf;
QByteArray dataBuf;
+ TBool inReadyRead;
};
QOstDevice::QOstDevice(QObject *parent) :
@@ -116,7 +119,11 @@ void QOstDevicePrivate::RunL()
ost.ReadMessage(iStatus, readBuf);
SetActive();
- emit q->readyRead();
+ if (!inReadyRead) {
+ inReadyRead = true;
+ emit q->readyRead();
+ inReadyRead = false;
+ }
} else {
q->setErrorString(QString("Error %1 from RUsbOstComm::ReadMessage()").arg(iStatus.Int()));
}
@@ -178,3 +185,36 @@ qint64 QOstDevice::bytesAvailable() const
Q_D(const QOstDevice);
return d->dataBuf.length();
}
+
+bool QOstDevice::waitForReadyRead(int msecs)
+{
+ Q_D(QOstDevice);
+ if (msecs >= 0) {
+ RTimer timer;
+ TInt err = timer.CreateLocal();
+ if (err) return false;
+ TRequestStatus timeoutStat;
+ timer.After(timeoutStat, msecs*1000);
+ User::WaitForRequest(timeoutStat, d->iStatus);
+ if (timeoutStat != KRequestPending) {
+ // Timed out
+ timer.Close();
+ return false;
+ } else {
+ // We got data, so cancel timer
+ timer.Cancel();
+ User::WaitForRequest(timeoutStat);
+ timer.Close();
+ // And drop through
+ }
+ } else {
+ // Just wait forever for data
+ User::WaitForRequest(d->iStatus);
+ }
+
+ // If we get here we have data
+ TInt err = d->iStatus.Int();
+ d->AoFlags() &= ~3; // This is necessary to clean up the scheduler as you're not supposed to bypass it like this
+ TRAP_IGNORE(d->RunL());
+ return err == KErrNone;
+}
diff --git a/src/plugins/qmltooling/qmldbg_ost/qostdevice.h b/src/plugins/qmltooling/qmldbg_ost/qostdevice.h
index 2c26ff7..200e607 100644
--- a/src/plugins/qmltooling/qmldbg_ost/qostdevice.h
+++ b/src/plugins/qmltooling/qmldbg_ost/qostdevice.h
@@ -61,10 +61,12 @@ public:
bool open(int ostProtocolId);
void close();
+ bool waitForReadyRead(int msecs);
+ qint64 bytesAvailable() const;
+
protected:
qint64 readData(char *data, qint64 maxSize);
qint64 writeData(const char *data, qint64 maxSize);
- qint64 bytesAvailable() const;
private:
QOstDevicePrivate* d_ptr;
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
index 85c43e3..7cd3d73 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
@@ -41,6 +41,7 @@
#include "qtcpserverconnection.h"
+#include <QtCore/qplugin.h>
#include <QtNetwork/qtcpserver.h>
#include <QtNetwork/qtcpsocket.h>
@@ -54,6 +55,7 @@ public:
QTcpServerConnectionPrivate();
int port;
+ bool block;
QTcpSocket *socket;
QPacketProtocol *protocol;
QTcpServer *tcpServer;
@@ -63,6 +65,7 @@ public:
QTcpServerConnectionPrivate::QTcpServerConnectionPrivate() :
port(0),
+ block(false),
socket(0),
protocol(0),
tcpServer(0),
@@ -119,10 +122,17 @@ void QTcpServerConnection::disconnect()
d->socket = 0;
}
+bool QTcpServerConnection::waitForMessage()
+{
+ Q_D(QTcpServerConnection);
+ return d->protocol->waitForReadyRead(-1);
+}
+
void QTcpServerConnection::setPort(int port, bool block)
{
Q_D(QTcpServerConnection);
d->port = port;
+ d->block = block;
listen();
if (block)
@@ -169,8 +179,11 @@ void QTcpServerConnection::newConnection()
d->socket->setParent(this);
d->protocol = new QPacketProtocol(d->socket, this);
QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
-}
+ if (d->block) {
+ d->protocol->waitForReadyRead(-1);
+ }
+}
Q_EXPORT_PLUGIN2(tcpserver, QTcpServerConnection)
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
index 66a10e1..dd5a5ec 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
@@ -42,7 +42,6 @@
#ifndef QTCPSERVERCONNECTION_H
#define QTCPSERVERCONNECTION_H
-#include <QtGui/QStylePlugin>
#include <QtDeclarative/private/qdeclarativedebugserverconnection_p.h>
QT_BEGIN_NAMESPACE
@@ -67,6 +66,7 @@ public:
bool isConnected() const;
void send(const QByteArray &message);
void disconnect();
+ bool waitForMessage();
void listen();
void waitForConnection();
diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro
index 9b3346f..0d60eb1 100644
--- a/src/plugins/qmltooling/qmltooling.pro
+++ b/src/plugins/qmltooling/qmltooling.pro
@@ -1,4 +1,4 @@
TEMPLATE = subdirs
-SUBDIRS = qmldbg_tcp
+SUBDIRS = qmldbg_tcp declarativeobserver
symbian:SUBDIRS += qmldbg_ost
diff --git a/src/script/api/qscriptengineagent_p.h b/src/script/api/qscriptengineagent_p.h
index abe4e9e..b96d19d 100644
--- a/src/script/api/qscriptengineagent_p.h
+++ b/src/script/api/qscriptengineagent_p.h
@@ -57,22 +57,22 @@ public:
static QScriptEngineAgentPrivate* get(QScriptEngineAgent* p) {return p->d_func();}
QScriptEngineAgentPrivate(){}
- virtual ~QScriptEngineAgentPrivate(){};
+ virtual ~QScriptEngineAgentPrivate(){}
void attach();
void detach();
//scripts
- virtual void sourceParsed(JSC::ExecState*, const JSC::SourceCode&, int /*errorLine*/, const JSC::UString& /*errorMsg*/) {};
+ virtual void sourceParsed(JSC::ExecState*, const JSC::SourceCode&, int /*errorLine*/, const JSC::UString& /*errorMsg*/) {}
virtual void scriptUnload(qint64 id)
{
q_ptr->scriptUnload(id);
- };
+ }
virtual void scriptLoad(qint64 id, const JSC::UString &program,
const JSC::UString &fileName, int baseLineNumber)
{
q_ptr->scriptLoad(id,program, fileName, baseLineNumber);
- };
+ }
//exceptions
virtual void exception(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno, bool hasHandler)
@@ -81,7 +81,7 @@ public:
Q_UNUSED(sourceID);
Q_UNUSED(lineno);
Q_UNUSED(hasHandler);
- };
+ }
virtual void exceptionThrow(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, bool hasHandler);
virtual void exceptionCatch(const JSC::DebuggerCallFrame& frame, intptr_t sourceID);
@@ -92,20 +92,20 @@ public:
Q_UNUSED(lineno);
q_ptr->contextPush();
q_ptr->functionEntry(sourceID);
- };
+ }
virtual void returnEvent(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno);
virtual void willExecuteProgram(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno)
{
Q_UNUSED(frame);
Q_UNUSED(sourceID);
Q_UNUSED(lineno);
- };
+ }
virtual void didExecuteProgram(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno)
{
Q_UNUSED(frame);
- Q_UNUSED(sourceID);
+ Q_UNUSED(sourceID);
Q_UNUSED(lineno);
- };
+ }
virtual void functionExit(const JSC::JSValue& returnValue, intptr_t sourceID);
//others
virtual void didReachBreakpoint(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno/*, int column*/);
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index 24a4940..3b20996 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -52,7 +52,6 @@
#include <QAtomicInt>
#include <QLibraryInfo>
#include "qdeclarativetester.h"
-#include <private/qdeclarativedebughelper_p.h>
QT_USE_NAMESPACE
@@ -539,8 +538,6 @@ int main(int argc, char ** argv)
QApplication::setGraphicsSystem(QLatin1String("raster"));
#endif
- QDeclarativeDebugHelper::enableDebugging();
-
Application app(argc, argv);
app.setApplicationName(QLatin1String("QtQmlViewer"));
app.setOrganizationName(QLatin1String("Nokia"));
diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro
index defc368..3d1b84b 100644
--- a/tools/qml/qml.pro
+++ b/tools/qml/qml.pro
@@ -1,5 +1,5 @@
TEMPLATE = app
-CONFIG += qt uic
+CONFIG += qt uic declarative_debug
DESTDIR = ../../bin
include(qml.pri)