QML Observer: Build together on runtime with debugging tools

Moved qmljsdebugger to a dir under qml/, made qmlobserver compile
without creator dependencies and made it compile with debugging
helpers.

Reviewed-by: hjk
This commit is contained in:
Lasse Holmstedt
2010-09-27 17:22:57 +02:00
parent 5d9858129a
commit 96d991bbdc
110 changed files with 1061 additions and 179 deletions

View File

@@ -0,0 +1,204 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "abstractformeditortool.h"
#include "qdeclarativeviewobserver.h"
#include "qdeclarativeviewobserver_p.h"
#include <QDeclarativeEngine>
#include <QtDebug>
#include <QGraphicsItem>
#include <QDeclarativeItem>
namespace QmlJSDebugger {
AbstractFormEditorTool::AbstractFormEditorTool(QDeclarativeViewObserver *editorView)
: QObject(editorView), m_observer(editorView)
{
}
AbstractFormEditorTool::~AbstractFormEditorTool()
{
}
QDeclarativeViewObserver *AbstractFormEditorTool::observer() const
{
return m_observer;
}
QDeclarativeView *AbstractFormEditorTool::view() const
{
return m_observer->declarativeView();
}
QGraphicsScene* AbstractFormEditorTool::scene() const
{
return view()->scene();
}
void AbstractFormEditorTool::updateSelectedItems()
{
selectedItemsChanged(items());
}
QList<QGraphicsItem*> AbstractFormEditorTool::items() const
{
return observer()->selectedItems();
}
void AbstractFormEditorTool::enterContext(QGraphicsItem *itemToEnter)
{
observer()->data->enterContext(itemToEnter);
}
bool AbstractFormEditorTool::topItemIsMovable(const QList<QGraphicsItem*> & itemList)
{
QGraphicsItem *firstSelectableItem = topMovableGraphicsItem(itemList);
if (firstSelectableItem == 0)
return false;
QDeclarativeItem *declarativeItem = dynamic_cast<QDeclarativeItem*>(firstSelectableItem->toGraphicsObject());
if (declarativeItem != 0)
return true;
return false;
}
bool AbstractFormEditorTool::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 AbstractFormEditorTool::topItemIsResizeHandle(const QList<QGraphicsItem*> &/*itemList*/)
{
return false;
}
QDeclarativeItem *AbstractFormEditorTool::toQDeclarativeItem(QGraphicsItem *item)
{
return dynamic_cast<QDeclarativeItem*>(item->toGraphicsObject());
}
QGraphicsItem *AbstractFormEditorTool::topMovableGraphicsItem(const QList<QGraphicsItem*> &itemList)
{
foreach (QGraphicsItem *item, itemList) {
if (item->flags().testFlag(QGraphicsItem::ItemIsMovable))
return item;
}
return 0;
}
QDeclarativeItem *AbstractFormEditorTool::topMovableDeclarativeItem(const QList<QGraphicsItem*> &itemList)
{
foreach (QGraphicsItem *item, itemList) {
QDeclarativeItem *declarativeItem = toQDeclarativeItem(item);
if (declarativeItem /*&& (declarativeItem->qmlItemNode().hasShowContent())*/)
return declarativeItem;
}
return 0;
}
QList<QGraphicsObject*> AbstractFormEditorTool::toGraphicsObjectList(const QList<QGraphicsItem*> &itemList)
{
QList<QGraphicsObject*> gfxObjects;
foreach(QGraphicsItem *item, itemList) {
QGraphicsObject *obj = item->toGraphicsObject();
if (obj)
gfxObjects << obj;
}
return gfxObjects;
}
QList<QObject*> AbstractFormEditorTool::toObjectList(const QList<QGraphicsItem*> &itemList)
{
QList<QObject*> objects;
foreach(QGraphicsItem *item, itemList) {
QObject *obj = item->toGraphicsObject();
if (obj)
objects << obj;
}
return objects;
}
QString AbstractFormEditorTool::titleForItem(QGraphicsItem *item)
{
QString className("QGraphicsItem");
QString objectStringId;
QString constructedName;
QGraphicsObject *gfxObject = item->toGraphicsObject();
if (gfxObject) {
className = gfxObject->metaObject()->className();
className.replace(QRegExp("_QMLTYPE_\\d+"), "");
className.replace(QRegExp("_QML_\\d+"), "");
if (className.startsWith(QLatin1String("QDeclarative")))
className = className.replace(QLatin1String("QDeclarative"), "");
QDeclarativeItem *declarativeItem = qobject_cast<QDeclarativeItem*>(gfxObject);
if (declarativeItem) {
objectStringId = QDeclarativeViewObserver::idStringForObject(declarativeItem);
}
if (!objectStringId.isEmpty()) {
constructedName = objectStringId + " (" + className + ")";
} else {
if (!gfxObject->objectName().isEmpty()) {
constructedName = gfxObject->objectName() + " (" + className + ")";
} else {
constructedName = className;
}
}
}
return constructedName;
}
}

View File

@@ -0,0 +1,106 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef ABSTRACTFORMEDITORTOOL_H
#define ABSTRACTFORMEDITORTOOL_H
#include <qglobal.h>
#include <QList>
#include <QObject>
QT_BEGIN_NAMESPACE
class QMouseEvent;
class QGraphicsItem;
class QDeclarativeItem;
class QKeyEvent;
class QGraphicsScene;
class QGraphicsObject;
class QWheelEvent;
class QDeclarativeView;
QT_END_NAMESPACE
namespace QmlJSDebugger {
class QDeclarativeViewObserver;
class FormEditorView;
class AbstractFormEditorTool : public QObject
{
Q_OBJECT
public:
AbstractFormEditorTool(QDeclarativeViewObserver* observer);
virtual ~AbstractFormEditorTool();
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);
static QString titleForItem(QGraphicsItem *item);
static QList<QObject*> toObjectList(const QList<QGraphicsItem*> &itemList);
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;
};
}
#endif // ABSTRACTFORMEDITORTOOL_H

View File

@@ -0,0 +1,241 @@
#include "boundingrecthighlighter.h"
#include "qdeclarativeviewobserver.h"
#include "qmlobserverconstants.h"
#include <QGraphicsPolygonItem>
#include <QTimer>
#include <QObject>
#include <QDebug>
namespace QmlJSDebugger {
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) :
LayerItem(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);
}
} // namespace QmlJSDebugger

View File

@@ -0,0 +1,78 @@
#ifndef BOUNDINGRECTHIGHLIGHTER_H
#define BOUNDINGRECTHIGHLIGHTER_H
#include <QObject>
#include <QWeakPointer>
#include "layeritem.h"
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);
namespace QmlJSDebugger {
class QDeclarativeViewObserver;
class BoundingBox;
class BoundingRectHighlighter : public LayerItem
{
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;
};
} // namespace QmlJSDebugger
#endif // BOUNDINGRECTHIGHLIGHTER_H

View File

@@ -0,0 +1,89 @@
#include "colorpickertool.h"
#include "qdeclarativeviewobserver.h"
#include <QMouseEvent>
#include <QKeyEvent>
#include <QRectF>
#include <QRgb>
#include <QImage>
#include <QApplication>
#include <QPalette>
namespace QmlJSDebugger {
ColorPickerTool::ColorPickerTool(QDeclarativeViewObserver *view) :
AbstractFormEditorTool(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);
}
} // namespace QmlJSDebugger

View File

@@ -0,0 +1,53 @@
#ifndef COLORPICKERTOOL_H
#define COLORPICKERTOOL_H
#include "abstractformeditortool.h"
#include <QColor>
QT_FORWARD_DECLARE_CLASS(QPoint);
namespace QmlJSDebugger {
class ColorPickerTool : public AbstractFormEditorTool
{
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;
};
} // namespace QmlJSDebugger
#endif // COLORPICKERTOOL_H

View File

@@ -0,0 +1,37 @@
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/abstractformeditortool.h \
$$PWD/selectiontool.h \
$$PWD/layeritem.h \
$$PWD/singleselectionmanipulator.h \
$$PWD/rubberbandselectionmanipulator.h \
$$PWD/selectionrectangle.h \
$$PWD/selectionindicator.h \
$$PWD/boundingrecthighlighter.h \
$$PWD/subcomponenteditortool.h \
$$PWD/subcomponentmasklayeritem.h \
$$PWD/zoomtool.h \
$$PWD/colorpickertool.h \
$$PWD/qmltoolbar.h \
$$PWD/toolbarcolorbox.h
SOURCES += \
$$PWD/abstractformeditortool.cpp \
$$PWD/selectiontool.cpp \
$$PWD/layeritem.cpp \
$$PWD/singleselectionmanipulator.cpp \
$$PWD/rubberbandselectionmanipulator.cpp \
$$PWD/selectionrectangle.cpp \
$$PWD/selectionindicator.cpp \
$$PWD/boundingrecthighlighter.cpp \
$$PWD/subcomponenteditortool.cpp \
$$PWD/subcomponentmasklayeritem.cpp \
$$PWD/zoomtool.cpp \
$$PWD/colorpickertool.cpp \
$$PWD/qmltoolbar.cpp \
$$PWD/toolbarcolorbox.cpp
RESOURCES += $$PWD/editor.qrc
DEFINES += QWEAKPOINTER_ENABLE_ARROW

View File

@@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,78 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "layeritem.h"
#include "qmlobserverconstants.h"
#include <QGraphicsScene>
namespace QmlJSDebugger {
LayerItem::LayerItem(QGraphicsScene* scene)
: QGraphicsObject()
{
scene->addItem(this);
setZValue(1);
setFlag(QGraphicsItem::ItemIsMovable, false);
}
LayerItem::~LayerItem()
{
}
void LayerItem::paint(QPainter * /*painter*/, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{
}
int LayerItem::type() const
{
return Constants::EditorItemType;
}
QRectF LayerItem::boundingRect() const
{
return childrenBoundingRect();
}
QList<QGraphicsItem*> LayerItem::findAllChildItems() const
{
return findAllChildItems(this);
}
QList<QGraphicsItem*> LayerItem::findAllChildItems(const QGraphicsItem *item) const
{
QList<QGraphicsItem*> itemList(item->childItems());
foreach (QGraphicsItem *childItem, item->childItems())
itemList += findAllChildItems(childItem);
return itemList;
}
} // namespace QmlJSDebugger

View File

@@ -0,0 +1,57 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef LAYERITEM_H
#define LAYERITEM_H
#include <QGraphicsObject>
#include <QWeakPointer>
namespace QmlJSDebugger {
class FormEditorScene;
class LayerItem : public QGraphicsObject
{
public:
LayerItem(QGraphicsScene* scene);
~LayerItem();
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;
};
}
#endif // LAYERITEM_H

View File

@@ -0,0 +1,323 @@
#include <QLabel>
#include <QIcon>
#include <QAction>
#include <QMenu>
#include "qmltoolbar.h"
#include "toolbarcolorbox.h"
#include <QDebug>
namespace QmlJSDebugger {
QmlToolbar::QmlToolbar(QWidget *parent)
: QToolBar(parent)
, m_emitSignals(true)
, m_isRunning(false)
, m_animationSpeed(1.0f)
, m_previousAnimationSpeed(0.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);
QActionGroup *playSpeedMenuActions = new QActionGroup(this);
playSpeedMenuActions->setExclusive(true);
playSpeedMenu->addAction(tr("Animation Speed"));
playSpeedMenu->addSeparator();
ui->defaultAnimSpeedAction = playSpeedMenu->addAction(tr("1x"), this, SLOT(changeToDefaultAnimSpeed()));
ui->defaultAnimSpeedAction->setCheckable(true);
ui->defaultAnimSpeedAction->setChecked(true);
playSpeedMenuActions->addAction(ui->defaultAnimSpeedAction);
ui->halfAnimSpeedAction = playSpeedMenu->addAction(tr("0.5x"), this, SLOT(changeToHalfAnimSpeed()));
ui->halfAnimSpeedAction->setCheckable(true);
playSpeedMenuActions->addAction(ui->halfAnimSpeedAction);
ui->fourthAnimSpeedAction = playSpeedMenu->addAction(tr("0.25x"), this, SLOT(changeToFourthAnimSpeed()));
ui->fourthAnimSpeedAction->setCheckable(true);
playSpeedMenuActions->addAction(ui->fourthAnimSpeedAction);
ui->eighthAnimSpeedAction = playSpeedMenu->addAction(tr("0.125x"), this, SLOT(changeToEighthAnimSpeed()));
ui->eighthAnimSpeedAction->setCheckable(true);
playSpeedMenuActions->addAction(ui->eighthAnimSpeedAction);
ui->tenthAnimSpeedAction = playSpeedMenu->addAction(tr("0.1x"), this, SLOT(changeToTenthAnimSpeed()));
ui->tenthAnimSpeedAction->setCheckable(true);
playSpeedMenuActions->addAction(ui->tenthAnimSpeedAction);
ui->menuPauseAction = playSpeedMenu->addAction(tr("Pause"), this, SLOT(updatePauseAction()));
ui->menuPauseAction->setCheckable(true);
ui->menuPauseAction->setIcon(ui->pauseIcon);
playSpeedMenuActions->addAction(ui->menuPauseAction);
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)
{
m_emitSignals = false;
if (slowdownFactor != 0) {
m_animationSpeed = slowdownFactor;
if (slowdownFactor == 1.0f) {
ui->defaultAnimSpeedAction->setChecked(true);
} else if (slowdownFactor == 2.0f) {
ui->halfAnimSpeedAction->setChecked(true);
} else if (slowdownFactor == 4.0f) {
ui->fourthAnimSpeedAction->setChecked(true);
} else if (slowdownFactor == 8.0f) {
ui->eighthAnimSpeedAction->setChecked(true);
} else if (slowdownFactor == 10.0f) {
ui->tenthAnimSpeedAction->setChecked(true);
}
updatePlayAction();
} else {
ui->menuPauseAction->setChecked(true);
updatePauseAction();
}
m_emitSignals = true;
}
void QmlToolbar::changeToDefaultAnimSpeed()
{
m_animationSpeed = 1.0f;
updatePlayAction();
}
void QmlToolbar::changeToHalfAnimSpeed()
{
m_animationSpeed = 2.0f;
updatePlayAction();
}
void QmlToolbar::changeToFourthAnimSpeed()
{
m_animationSpeed = 4.0f;
updatePlayAction();
}
void QmlToolbar::changeToEighthAnimSpeed()
{
m_animationSpeed = 8.0f;
updatePlayAction();
}
void QmlToolbar::changeToTenthAnimSpeed()
{
m_animationSpeed = 10.0f;
updatePlayAction();
}
void QmlToolbar::setDesignModeBehavior(bool inDesignMode)
{
m_emitSignals = false;
ui->designmode->setChecked(inDesignMode);
setDesignModeBehaviorOnClick(inDesignMode);
m_emitSignals = true;
}
void QmlToolbar::setDesignModeBehaviorOnClick(bool checked)
{
ui->play->setEnabled(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()
{
if (m_isRunning) {
updatePauseAction();
} else {
updatePlayAction();
}
}
void QmlToolbar::updatePlayAction()
{
m_isRunning = true;
ui->play->setIcon(ui->pauseIcon);
if (m_animationSpeed != m_previousAnimationSpeed)
m_previousAnimationSpeed = m_animationSpeed;
if (m_emitSignals)
emit animationSpeedChanged(m_animationSpeed);
}
void QmlToolbar::updatePauseAction()
{
m_isRunning = false;
ui->play->setIcon(ui->playIcon);
if (m_emitSignals)
emit animationSpeedChanged(0.0f);
}
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();
}
}

View File

@@ -0,0 +1,96 @@
#ifndef QMLTOOLBAR_H
#define QMLTOOLBAR_H
#include <QToolBar>
#include <QIcon>
#include "qmlobserverconstants.h"
namespace QmlJSDebugger {
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 = 0.0f);
signals:
void animationSpeedChanged(qreal slowdownFactor = 1.0f);
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 changeToDefaultAnimSpeed();
void changeToHalfAnimSpeed();
void changeToFourthAnimSpeed();
void changeToEighthAnimSpeed();
void changeToTenthAnimSpeed();
void updatePlayAction();
void updatePauseAction();
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;
QAction *defaultAnimSpeedAction;
QAction *halfAnimSpeedAction;
QAction *fourthAnimSpeedAction;
QAction *eighthAnimSpeedAction;
QAction *tenthAnimSpeedAction;
QAction *menuPauseAction;
};
bool m_emitSignals;
bool m_isRunning;
qreal m_animationSpeed;
qreal m_previousAnimationSpeed;
Constants::DesignTool m_activeTool;
Ui *ui;
};
}
#endif // QMLTOOLBAR_H

View File

@@ -0,0 +1,144 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "rubberbandselectionmanipulator.h"
#include "qdeclarativeviewobserver_p.h"
#include <QDebug>
namespace QmlJSDebugger {
RubberBandSelectionManipulator::RubberBandSelectionManipulator(QGraphicsObject *layerItem, QDeclarativeViewObserver *editorView)
: m_selectionRectangleElement(layerItem),
m_editorView(editorView),
m_beginFormEditorItem(0),
m_isActive(false)
{
m_selectionRectangleElement.hide();
}
void RubberBandSelectionManipulator::clear()
{
m_selectionRectangleElement.clear();
m_isActive = false;
m_beginPoint = QPointF();
m_itemList.clear();
m_oldSelectionList.clear();
}
QGraphicsItem *RubberBandSelectionManipulator::topFormEditorItem(const QList<QGraphicsItem*> &itemList)
{
if (itemList.isEmpty())
return 0;
return itemList.first();
}
void RubberBandSelectionManipulator::begin(const QPointF& beginPoint)
{
m_beginPoint = beginPoint;
m_selectionRectangleElement.setRect(m_beginPoint, m_beginPoint);
m_selectionRectangleElement.show();
m_isActive = true;
m_beginFormEditorItem = topFormEditorItem(QDeclarativeViewObserverPrivate::get(m_editorView)->selectableItems(beginPoint));
m_oldSelectionList = m_editorView->selectedItems();
}
void RubberBandSelectionManipulator::update(const QPointF& updatePoint)
{
m_selectionRectangleElement.setRect(m_beginPoint, updatePoint);
}
void RubberBandSelectionManipulator::end()
{
m_oldSelectionList.clear();
m_selectionRectangleElement.hide();
m_isActive = false;
}
void RubberBandSelectionManipulator::select(SelectionType selectionType)
{
QList<QGraphicsItem*> itemList = QDeclarativeViewObserverPrivate::get(m_editorView)->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 RubberBandSelectionManipulator::setItems(const QList<QGraphicsItem*> &itemList)
{
m_itemList = itemList;
}
QPointF RubberBandSelectionManipulator::beginPoint() const
{
return m_beginPoint;
}
bool RubberBandSelectionManipulator::isActive() const
{
return m_isActive;
}
}

View File

@@ -0,0 +1,82 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef RUBBERBANDSELECTIONMANIPULATOR_H
#define RUBBERBANDSELECTIONMANIPULATOR_H
#include "selectionrectangle.h"
namespace QmlJSDebugger {
class QDeclarativeViewObserver;
class RubberBandSelectionManipulator
{
public:
enum SelectionType {
ReplaceSelection,
AddToSelection,
RemoveFromSelection
};
RubberBandSelectionManipulator(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;
SelectionRectangle m_selectionRectangleElement;
QPointF m_beginPoint;
QDeclarativeViewObserver *m_editorView;
QGraphicsItem *m_beginFormEditorItem;
bool m_isActive;
};
}
#endif // RUBBERBANDSELECTIONMANIPULATOR_H

View File

@@ -0,0 +1,127 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "selectionindicator.h"
#include "qdeclarativeviewobserver_p.h"
#include "qmlobserverconstants.h"
#include <QPen>
#include <cmath>
#include <QGraphicsScene>
#include <QDebug>
namespace QmlJSDebugger {
SelectionIndicator::SelectionIndicator(QDeclarativeViewObserver *editorView, QGraphicsObject *layerItem)
: m_layerItem(layerItem), m_view(editorView)
{
}
SelectionIndicator::~SelectionIndicator()
{
clear();
}
void SelectionIndicator::show()
{
foreach (QGraphicsPolygonItem *item, m_indicatorShapeHash.values())
item->show();
}
void SelectionIndicator::hide()
{
foreach (QGraphicsPolygonItem *item, m_indicatorShapeHash.values())
item->hide();
}
void SelectionIndicator::clear()
{
if (!m_layerItem.isNull()) {
QHashIterator<QGraphicsItem*, QGraphicsPolygonItem *> iter(m_indicatorShapeHash);
while(iter.hasNext()) {
iter.next();
m_layerItem->scene()->removeItem(iter.value());
delete iter.value();
}
}
m_indicatorShapeHash.clear();
}
QPolygonF SelectionIndicator::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 SelectionIndicator::setItems(const QList<QWeakPointer<QGraphicsObject> > &itemList)
{
clear();
// set selections to also all children if they are not editor items
foreach (QWeakPointer<QGraphicsObject> obj, itemList) {
if (obj.isNull())
continue;
QGraphicsItem *item = obj.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->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);
}
}
}
} //namespace QmlJSDebugger

View File

@@ -0,0 +1,66 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef SELECTIONINDICATOR_H
#define SELECTIONINDICATOR_H
#include <QWeakPointer>
#include <QGraphicsPolygonItem>
#include <QGraphicsObject>
namespace QmlJSDebugger {
class QDeclarativeViewObserver;
class SelectionIndicator
{
public:
SelectionIndicator(QDeclarativeViewObserver* editorView, QGraphicsObject *layerItem);
~SelectionIndicator();
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;
};
}
#endif // SELECTIONINDICATOR_H

View File

@@ -0,0 +1,95 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "selectionrectangle.h"
#include "qmlobserverconstants.h"
#include <QPen>
#include <QGraphicsScene>
#include <QtDebug>
#include <cmath>
#include <QGraphicsScene>
namespace QmlJSDebugger {
class SelectionRectShape : public QGraphicsRectItem
{
public:
SelectionRectShape(QGraphicsItem *parent = 0) : QGraphicsRectItem(parent) {}
int type() const { return Constants::EditorItemType; }
};
SelectionRectangle::SelectionRectangle(QGraphicsObject *layerItem)
: m_controlShape(new SelectionRectShape(layerItem)),
m_layerItem(layerItem)
{
m_controlShape->setPen(QPen(Qt::black));
m_controlShape->setBrush(QColor(128, 128, 128, 50));
}
SelectionRectangle::~SelectionRectangle()
{
if (m_layerItem)
m_layerItem->scene()->removeItem(m_controlShape);
}
void SelectionRectangle::clear()
{
hide();
}
void SelectionRectangle::show()
{
m_controlShape->show();
}
void SelectionRectangle::hide()
{
m_controlShape->hide();
}
QRectF SelectionRectangle::rect() const
{
return m_controlShape->mapFromScene(m_controlShape->rect()).boundingRect();
}
void SelectionRectangle::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);
}
}

View File

@@ -0,0 +1,62 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef SELECTIONRECTANGLE_H
#define SELECTIONRECTANGLE_H
#include <QWeakPointer>
#include <QGraphicsRectItem>
#include <QGraphicsObject>
namespace QmlJSDebugger {
class SelectionRectangle
{
public:
SelectionRectangle(QGraphicsObject *layerItem);
~SelectionRectangle();
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;
};
}
#endif // SELECTIONRECTANGLE_H

View File

@@ -0,0 +1,447 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "selectiontool.h"
#include "layeritem.h"
//#include "resizehandleitem.h"
#include "qdeclarativeviewobserver_p.h"
#include <QDeclarativeEngine>
#include <QApplication>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QClipboard>
#include <QMenu>
#include <QAction>
#include <QDeclarativeItem>
#include <QGraphicsObject>
#include <QDebug>
namespace QmlJSDebugger {
SelectionTool::SelectionTool(QDeclarativeViewObserver *editorView)
: AbstractFormEditorTool(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)
{
}
SelectionTool::~SelectionTool()
{
}
void SelectionTool::setRubberbandSelectionMode(bool value)
{
m_rubberbandSelectionMode = value;
}
SingleSelectionManipulator::SelectionType SelectionTool::getSelectionType(Qt::KeyboardModifiers modifiers)
{
SingleSelectionManipulator::SelectionType selectionType = SingleSelectionManipulator::ReplaceSelection;
if (modifiers.testFlag(Qt::ControlModifier)) {
selectionType = SingleSelectionManipulator::RemoveFromSelection;
} else if (modifiers.testFlag(Qt::ShiftModifier)) {
selectionType = SingleSelectionManipulator::AddToSelection;
}
return selectionType;
}
bool SelectionTool::alreadySelected(const QList<QGraphicsItem*> &itemList) const
{
const QList<QGraphicsItem*> selectedItems = QDeclarativeViewObserverPrivate::get(observer())->selectedItems();
if (selectedItems.isEmpty())
return false;
foreach(QGraphicsItem *item, itemList) {
if (selectedItems.contains(item)) {
return true;
}
}
return false;
}
void SelectionTool::mousePressEvent(QMouseEvent *event)
{
QList<QGraphicsItem*> itemList = QDeclarativeViewObserverPrivate::get(observer())->selectableItems(event->pos());
SingleSelectionManipulator::SelectionType selectionType = getSelectionType(event->modifiers());
if (event->buttons() & Qt::LeftButton) {
m_mousePressTimer.start();
if (m_rubberbandSelectionMode) {
m_rubberbandSelectionManipulator.begin(event->pos());
} else {
if (itemList.isEmpty()) {
QDeclarativeViewObserverPrivate::get(observer())->setSelectedItems(itemList);
return;
}
if ((selectionType == SingleSelectionManipulator::InvertSelection
|| selectionType == SingleSelectionManipulator::ReplaceSelection)
&& alreadySelected(itemList))
{
//view()->changeToMoveTool(event->pos());
return;
}
QGraphicsItem* item = itemList.first();
if (item->children().isEmpty()) {
m_singleSelectionManipulator.begin(event->pos());
m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
} else {
m_mousePressTimer.start();
if (itemList.isEmpty()) {
observer()->setSelectedItems(itemList);
return;
}
if (item->children().isEmpty()) {
m_singleSelectionManipulator.begin(event->pos());
m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
} else {
m_singleSelectionManipulator.begin(event->pos());
m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
m_singleSelectionManipulator.end(event->pos());
//view()->changeToMoveTool(event->pos());
}
m_singleSelectionManipulator.begin(event->pos());
m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
m_singleSelectionManipulator.end(event->pos());
//view()->changeToMoveTool(event->pos());
}
}
} else if (event->buttons() & Qt::RightButton) {
createContextMenu(itemList, event->globalPos());
}
}
void SelectionTool::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("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 SelectionTool::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(SingleSelectionManipulator::InvertSelection,
QList<QGraphicsItem*>() << item,
false);
m_singleSelectionManipulator.end(updatePt);
enterContext(item);
}
}
void SelectionTool::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 SelectionTool::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(RubberBandSelectionManipulator::RemoveFromSelection);
else if (event->modifiers().testFlag(Qt::ShiftModifier))
m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::AddToSelection);
else
m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::ReplaceSelection);
}
}
}
void SelectionTool::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);
// }
QList<QGraphicsItem*> selectableItemList = QDeclarativeViewObserverPrivate::get(observer())->selectableItems(event->pos());
if (!selectableItemList.isEmpty()) {
QGraphicsObject *item = selectableItemList.first()->toGraphicsObject();
if (item)
QDeclarativeViewObserverPrivate::get(observer())->highlight(item);
return;
}
QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
}
void SelectionTool::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(SingleSelectionManipulator::RemoveFromSelection, m_selectOnlyContentItems);
else if (event->modifiers().testFlag(Qt::ShiftModifier))
m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection, m_selectOnlyContentItems);
else
m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection, m_selectOnlyContentItems);
m_singleSelectionManipulator.end(event->pos());
} else {
m_rubberbandSelectionManipulator.update(event->pos());
if (event->modifiers().testFlag(Qt::ControlModifier))
m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::RemoveFromSelection);
else if (event->modifiers().testFlag(Qt::ShiftModifier))
m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::AddToSelection);
else
m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::ReplaceSelection);
m_rubberbandSelectionManipulator.end();
}
}
}
void SelectionTool::mouseDoubleClickEvent(QMouseEvent * /*event*/)
{
}
void SelectionTool::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 SelectionTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
{
}
void SelectionTool::wheelEvent(QWheelEvent *event)
{
if (event->orientation() == Qt::Horizontal || m_rubberbandSelectionMode)
return;
QList<QGraphicsItem*> itemList = QDeclarativeViewObserverPrivate::get(observer())->selectableItems(event->pos());
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(SingleSelectionManipulator::ReplaceSelection,
QList<QGraphicsItem*>() << itemList.at(selectedIdx),
false);
m_singleSelectionManipulator.end(updatePt);
}
void SelectionTool::setSelectOnlyContentItems(bool selectOnlyContentItems)
{
m_selectOnlyContentItems = selectOnlyContentItems;
}
void SelectionTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
{
}
void SelectionTool::clear()
{
view()->setCursor(Qt::ArrowCursor);
m_rubberbandSelectionManipulator.clear(),
m_singleSelectionManipulator.clear();
m_selectionIndicator.clear();
//m_resizeIndicator.clear();
}
void SelectionTool::selectedItemsChanged(const QList<QGraphicsItem*> &itemList)
{
foreach(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 SelectionTool::repaintBoundingRects()
{
m_selectionIndicator.setItems(m_selectedItemList);
}
void SelectionTool::selectUnderPoint(QMouseEvent *event)
{
m_singleSelectionManipulator.begin(event->pos());
if (event->modifiers().testFlag(Qt::ControlModifier))
m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection, m_selectOnlyContentItems);
else if (event->modifiers().testFlag(Qt::ShiftModifier))
m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection, m_selectOnlyContentItems);
else
m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection, m_selectOnlyContentItems);
m_singleSelectionManipulator.end(event->pos());
}
}

View File

@@ -0,0 +1,110 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef SELECTIONTOOL_H
#define SELECTIONTOOL_H
#include "abstractformeditortool.h"
#include "rubberbandselectionmanipulator.h"
#include "singleselectionmanipulator.h"
#include "selectionindicator.h"
#include <QHash>
#include <QList>
#include <QTime>
#include <QAction>
QT_FORWARD_DECLARE_CLASS(QGraphicsItem);
QT_FORWARD_DECLARE_CLASS(QMouseEvent);
QT_FORWARD_DECLARE_CLASS(QKeyEvent);
namespace QmlJSDebugger {
class SelectionTool : public AbstractFormEditorTool
{
Q_OBJECT
public:
SelectionTool(QDeclarativeViewObserver* editorView);
~SelectionTool();
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);
SingleSelectionManipulator::SelectionType getSelectionType(Qt::KeyboardModifiers modifiers);
bool alreadySelected(const QList<QGraphicsItem*> &itemList) const;
private:
bool m_rubberbandSelectionMode;
RubberBandSelectionManipulator m_rubberbandSelectionManipulator;
SingleSelectionManipulator m_singleSelectionManipulator;
SelectionIndicator m_selectionIndicator;
//ResizeIndicator m_resizeIndicator;
QTime m_mousePressTimer;
bool m_selectOnlyContentItems;
QList<QWeakPointer<QGraphicsObject> > m_selectedItemList;
QList<QGraphicsItem*> m_contextMenuItemList;
};
}
#endif // SELECTIONTOOL_H

View File

@@ -0,0 +1,134 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "singleselectionmanipulator.h"
#include "qdeclarativeviewobserver.h"
#include "qdeclarativeviewobserver_p.h"
#include <QtDebug>
namespace QmlJSDebugger {
SingleSelectionManipulator::SingleSelectionManipulator(QDeclarativeViewObserver *editorView)
: m_editorView(editorView),
m_isActive(false)
{
}
void SingleSelectionManipulator::begin(const QPointF &beginPoint)
{
m_beginPoint = beginPoint;
m_isActive = true;
m_oldSelectionList = QDeclarativeViewObserverPrivate::get(m_editorView)->selectedItems();
}
void SingleSelectionManipulator::update(const QPointF &/*updatePoint*/)
{
m_oldSelectionList.clear();
}
void SingleSelectionManipulator::clear()
{
m_beginPoint = QPointF();
m_oldSelectionList.clear();
}
void SingleSelectionManipulator::end(const QPointF &/*updatePoint*/)
{
m_oldSelectionList.clear();
m_isActive = false;
}
void SingleSelectionManipulator::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 SingleSelectionManipulator::select(SelectionType selectionType, bool selectOnlyContentItems)
{
QList<QGraphicsItem*> itemList = QDeclarativeViewObserverPrivate::get(m_editorView)->selectableItems(m_beginPoint);
select(selectionType, itemList, selectOnlyContentItems);
}
bool SingleSelectionManipulator::isActive() const
{
return m_isActive;
}
QPointF SingleSelectionManipulator::beginPoint() const
{
return m_beginPoint;
}
}

View File

@@ -0,0 +1,76 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef SINGLESELECTIONMANIPULATOR_H
#define SINGLESELECTIONMANIPULATOR_H
#include <QPointF>
#include <QList>
QT_FORWARD_DECLARE_CLASS(QGraphicsItem);
namespace QmlJSDebugger {
class QDeclarativeViewObserver;
class SingleSelectionManipulator
{
public:
SingleSelectionManipulator(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;
};
}
#endif // SINGLESELECTIONMANIPULATOR_H

View File

@@ -0,0 +1,320 @@
#include "subcomponenteditortool.h"
#include "qdeclarativeviewobserver_p.h"
#include "subcomponentmasklayeritem.h"
#include "layeritem.h"
#include <QGraphicsItem>
#include <QGraphicsObject>
#include <QTimer>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QDebug>
namespace QmlJSDebugger {
const qreal MaxOpacity = 0.5f;
SubcomponentEditorTool::SubcomponentEditorTool(QDeclarativeViewObserver *view)
: AbstractFormEditorTool(view),
m_animIncrement(0.05f),
m_animTimer(new QTimer(this))
{
m_mask = new SubcomponentMaskLayerItem(view, QDeclarativeViewObserverPrivate::get(view)->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 = parent->metaObject()->className();
if (parentClassName.contains(QRegExp("_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;
}
} // namespace QmlJSDebugger

View File

@@ -0,0 +1,83 @@
#ifndef SUBCOMPONENTEDITORTOOL_H
#define SUBCOMPONENTEDITORTOOL_H
#include "abstractformeditortool.h"
#include <QStack>
#include <QStringList>
QT_FORWARD_DECLARE_CLASS(QGraphicsObject)
QT_FORWARD_DECLARE_CLASS(QPoint)
QT_FORWARD_DECLARE_CLASS(QTimer)
namespace QmlJSDebugger {
class SubcomponentMaskLayerItem;
class SubcomponentEditorTool : public AbstractFormEditorTool
{
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;
};
} // namespace QmlJSDebugger
#endif // SUBCOMPONENTEDITORTOOL_H

View File

@@ -0,0 +1,80 @@
#include "subcomponentmasklayeritem.h"
#include "qmlobserverconstants.h"
#include "qdeclarativeviewobserver.h"
#include <QPolygonF>
namespace QmlJSDebugger {
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;
}
} // namespace QmlJSDebugger

View File

@@ -0,0 +1,29 @@
#ifndef SUBCOMPONENTMASKLAYERITEM_H
#define SUBCOMPONENTMASKLAYERITEM_H
#include <QGraphicsPolygonItem>
namespace QmlJSDebugger {
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;
};
} // namespace QmlJSDebugger
#endif // SUBCOMPONENTMASKLAYERITEM_H

View File

@@ -0,0 +1,96 @@
#include "toolbarcolorbox.h"
#include "qmlobserverconstants.h"
#include <QPixmap>
#include <QPainter>
#include <QMenu>
#include <QAction>
#include <QContextMenuEvent>
#include <QClipboard>
#include <QApplication>
#include <QColorDialog>
#include <QDrag>
#include <QMimeData>
#include <QDebug>
namespace QmlJSDebugger {
ToolBarColorBox::ToolBarColorBox(QWidget *parent) :
QLabel(parent)
{
m_copyHexColor = new QAction(QIcon(QLatin1String(":/qml/images/color-picker-hicontrast.png")), tr("Copy"), 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::mouseDoubleClickEvent(QMouseEvent *)
{
QColorDialog dialog(m_color);
dialog.show();
}
void ToolBarColorBox::copyColorToClipboard()
{
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(m_color.name());
}
} // namespace QmlJSDebugger

View File

@@ -0,0 +1,41 @@
#ifndef ToolBarColorBox_H
#define ToolBarColorBox_H
#include <QLabel>
#include <QColor>
#include <QPoint>
QT_FORWARD_DECLARE_CLASS(QContextMenuEvent);
QT_FORWARD_DECLARE_CLASS(QAction);
namespace QmlJSDebugger {
class ToolBarColorBox : public QLabel
{
Q_OBJECT
public:
explicit ToolBarColorBox(QWidget *parent = 0);
void setColor(const QColor &color);
protected:
void contextMenuEvent(QContextMenuEvent *ev);
void mouseDoubleClickEvent(QMouseEvent *);
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;
};
} // namespace QmlJSDebugger
#endif // ToolBarColorBox_H

View File

@@ -0,0 +1,287 @@
#include "zoomtool.h"
#include "qdeclarativeviewobserver_p.h"
#include <QMouseEvent>
#include <QWheelEvent>
#include <QKeyEvent>
#include <QRectF>
#include <QMenu>
#include <QAction>
#include <QDebug>
namespace QmlJSDebugger {
ZoomTool::ZoomTool(QDeclarativeViewObserver *view) :
AbstractFormEditorTool(view),
m_rubberbandManipulator(reinterpret_cast<QGraphicsObject *>(QDeclarativeViewObserverPrivate::get(view)->manipulatorLayer), view),
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));
connect(m_zoomTo100Action, SIGNAL(triggered()), SLOT(zoomTo100()));
connect(m_zoomInAction, SIGNAL(triggered()), SLOT(zoomIn()));
connect(m_zoomOutAction, SIGNAL(triggered()), SLOT(zoomOut()));
}
ZoomTool::~ZoomTool()
{
}
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;
}
} // namespace QmlJSDebugger

View File

@@ -0,0 +1,65 @@
#ifndef ZOOMTOOL_H
#define ZOOMTOOL_H
#include "abstractformeditortool.h"
#include "rubberbandselectionmanipulator.h"
QT_FORWARD_DECLARE_CLASS(QAction);
namespace QmlJSDebugger {
class ZoomTool : public AbstractFormEditorTool
{
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;
RubberBandSelectionManipulator m_rubberbandManipulator;
qreal m_smoothZoomMultiplier;
qreal m_currentScale;
};
} // namespace QmlJSDebugger
#endif // ZOOMTOOL_H

View File

@@ -0,0 +1,144 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSCriptTools 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 QSCRIPTDEBUGGERAGENT_P_H
#define QSCRIPTDEBUGGERAGENT_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 <QtScript/QScriptValue>
#include <QtCore/QEventLoop>
#include <QtCore/QSet>
#include <private/qdeclarativedebugservice_p.h>
#include <QtCore/QStringList>
#include "qmljsdebugger_global.h"
QT_FORWARD_DECLARE_CLASS(QScriptContext);
QT_FORWARD_DECLARE_CLASS(QDeclarativeEngine);
namespace QmlJSDebugger {
class JSAgentWatchData;
class QMLJSDEBUGGER_EXPORT JSDebuggerAgent : public QDeclarativeDebugService , public QScriptEngineAgent
{
Q_OBJECT
public:
JSDebuggerAgent(QScriptEngine *engine);
JSDebuggerAgent(QDeclarativeEngine *engine);
~JSDebuggerAgent();
// 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());
void messageReceived(const QByteArray &);
void enabledChanged(bool);
public slots:
// void pauses();
private:
class SetupExecEnv;
friend class SetupExecEnv;
enum State {
NoState,
SteppingIntoState,
SteppingOverState,
SteppingOutState,
Stopped
};
State state;
int stepDepth;
int stepCount;
void continueExec();
void stopped(bool becauseOfException = false, const QScriptValue &exception = QScriptValue());
void recordKnownObjects(const QList<JSAgentWatchData> &);
QList<JSAgentWatchData> getLocals(QScriptContext *);
QEventLoop loop;
QHash <qint64, QString> filenames;
QSet< QPair<QString, qint32> > breakpointList;
QStringList watchExpressions;
QSet<qint64> knownObjectIds;
Q_DISABLE_COPY(JSDebuggerAgent)
};
} // namespace QmlJSDebugger
#endif

View File

@@ -0,0 +1,110 @@
/****************************************************************************
**
** Copyright (C) 2010 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 QDECLARATIVEDESIGNDEBUGSERVER_H
#define QDECLARATIVEDESIGNDEBUGSERVER_H
#include <private/qdeclarativedebugservice_p.h>
#include "qmlobserverconstants.h"
#include "qmljsdebugger_global.h"
#include <QHash>
QT_FORWARD_DECLARE_CLASS(QColor)
QT_FORWARD_DECLARE_CLASS(QDeclarativeEngine)
QT_FORWARD_DECLARE_CLASS(QDeclarativeContext)
QT_FORWARD_DECLARE_CLASS(QDeclarativeWatcher)
QT_FORWARD_DECLARE_CLASS(QDataStream)
namespace QmlJSDebugger {
class QMLJSDEBUGGER_EXPORT QDeclarativeObserverService : public QDeclarativeDebugService
{
Q_OBJECT
public:
QDeclarativeObserverService();
static QDeclarativeObserverService *instance();
void setDesignModeBehavior(bool inDesignMode);
void setCurrentObjects(QList<QObject*> items);
void setAnimationSpeed(qreal slowdownFactor);
void setCurrentTool(QmlJSDebugger::Constants::DesignTool toolId);
void reloaded();
QString idStringForObject(QObject *obj) const;
public Q_SLOTS:
void selectedColorChanged(const QColor &color);
void contextPathUpdated(const QStringList &contextPath);
Q_SIGNALS:
void debuggingClientChanged(bool hasDebuggingClient);
void currentObjectsChanged(const QList<QObject*> &objects);
void designModeBehaviorChanged(bool inDesignMode);
void reloadRequested();
void selectToolRequested();
void selectMarqueeToolRequested();
void zoomToolRequested();
void colorPickerToolRequested();
void objectCreationRequested(const QString &qml, QObject *parent,
const QStringList &imports, const QString &filename = QString());
void objectReparentRequested(QObject *object, QObject *newParent);
// 1 = normal speed,
// 0 = paused,
// 1 < x < 16 = slowdown by some factor
void animationSpeedChangeRequested(qreal speedFactor);
void contextPathIndexChanged(int contextPathIndex);
void clearComponentCacheRequested();
protected:
virtual void enabledChanged(bool enabled);
virtual void messageReceived(const QByteArray &);
private:
QHash<int, QString> m_stringIdForObjectId;
};
} // namespace QmlJSDebugger
#endif // QDECLARATIVEDESIGNDEBUGSERVER_H

View File

@@ -0,0 +1,129 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef QDECLARATIVEVIEWOBSERVER_H
#define QDECLARATIVEVIEWOBSERVER_H
#include "qmljsdebugger_global.h"
#include "qmlobserverconstants.h"
#include <qdeclarativeview.h>
#include <QWeakPointer>
QT_FORWARD_DECLARE_CLASS(QDeclarativeItem);
QT_FORWARD_DECLARE_CLASS(QMouseEvent);
QT_FORWARD_DECLARE_CLASS(QToolBar);
namespace QmlJSDebugger {
class CrumblePath;
class QDeclarativeViewObserverPrivate;
class QMLJSDEBUGGER_EXPORT QDeclarativeViewObserver : public QObject
{
Q_OBJECT
public:
explicit QDeclarativeViewObserver(QDeclarativeView *view, QObject *parent = 0);
~QDeclarativeViewObserver();
void setSelectedItems(QList<QGraphicsItem *> items);
QList<QGraphicsItem *> selectedItems();
QDeclarativeView *declarativeView();
QToolBar *toolbar() const;
static QString idStringForObject(QObject *obj);
QRectF adjustToScreenBoundaries(const QRectF &boundingRectInSceneSpace);
void setDebugMode(bool isDebugMode);
public Q_SLOTS:
void setDesignModeBehavior(bool value);
bool designModeBehavior();
void changeAnimationSpeed(qreal slowdownFactor);
void continueExecution(qreal slowdownFactor = 1.0f);
void pauseExecution();
void setObserverContext(int contextIndex);
Q_SIGNALS:
void designModeBehaviorChanged(bool inDesignMode);
void reloadRequested();
void marqueeSelectToolActivated();
void selectToolActivated();
void zoomToolActivated();
void colorPickerActivated();
void selectedColorChanged(const QColor &color);
void executionStarted(qreal slowdownFactor);
void executionPaused();
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:
Q_DISABLE_COPY(QDeclarativeViewObserver)
Q_PRIVATE_SLOT(d_func(), void _q_reloadView())
Q_PRIVATE_SLOT(d_func(), void _q_onStatusChanged(QDeclarativeView::Status))
Q_PRIVATE_SLOT(d_func(), void _q_onCurrentObjectsChanged(QList<QObject*>))
Q_PRIVATE_SLOT(d_func(), void _q_applyChangesFromClient())
Q_PRIVATE_SLOT(d_func(), void _q_createQmlObject(const QString &, QObject *, const QStringList &, const QString &))
Q_PRIVATE_SLOT(d_func(), void _q_reparentQmlObject(QObject *, QObject *))
Q_PRIVATE_SLOT(d_func(), void _q_changeToSingleSelectTool())
Q_PRIVATE_SLOT(d_func(), void _q_changeToMarqueeSelectTool())
Q_PRIVATE_SLOT(d_func(), void _q_changeToZoomTool())
Q_PRIVATE_SLOT(d_func(), void _q_changeToColorPickerTool())
Q_PRIVATE_SLOT(d_func(), void _q_changeContextPathIndex(int index))
Q_PRIVATE_SLOT(d_func(), void _q_clearComponentCache());
inline QDeclarativeViewObserverPrivate *d_func() { return data.data(); }
QScopedPointer<QDeclarativeViewObserverPrivate> data;
friend class QDeclarativeViewObserverPrivate;
friend class AbstractFormEditorTool;
};
} //namespace QmlJSDebugger
#endif // QDECLARATIVEVIEWOBSERVER_H

View File

@@ -0,0 +1,43 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef QMLJSDEBUGGER_GLOBAL_H
#define QMLJSDEBUGGER_GLOBAL_H
#include <QtCore/qglobal.h>
# if defined(BUILD_QMLJSDEBUGGER_LIB)
# define QMLJSDEBUGGER_EXPORT Q_DECL_EXPORT
# elif defined(BUILD_QMLJSDEBUGGER_STATIC_LIB)
# define QMLJSDEBUGGER_EXPORT
# else
# define QMLJSDEBUGGER_EXPORT Q_DECL_IMPORT
#endif
#endif // QMLJSDEBUGGER_GLOBAL_H

View File

@@ -0,0 +1,68 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef QMLOBSERVERCONSTANTS_H
#define QMLOBSERVERCONSTANTS_H
namespace QmlJSDebugger {
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
} // namespace QmlJSDebugger
#endif // QMLOBSERVERCONSTANTS_H

View File

@@ -0,0 +1,519 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSCriptTools 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 "jsdebuggeragent.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qset.h>
#include <QtScript/qscriptengine.h>
#include <QtScript/QScriptContextInfo>
#include <QtCore/QDebug>
#include <QtCore/QUrl>
#include <QtCore/QDateTime>
#include <QtScript/qscriptvalueiterator.h>
#include <private/qdeclarativeengine_p.h>
namespace QmlJSDebugger {
class JSDebuggerAgent::SetupExecEnv {
JSDebuggerAgent* agent;
JSDebuggerAgent::State previousState;
bool hadException;
public:
SetupExecEnv(JSDebuggerAgent *a)
: agent(a),
previousState(a->state),
hadException(a->engine()->hasUncaughtException())
{
agent->state = JSDebuggerAgent::Stopped;
}
~SetupExecEnv() {
if (!hadException && agent->engine()->hasUncaughtException())
agent->engine()->clearExceptions();
agent->state = previousState;
}
};
class JSAgentWatchData {
public:
QByteArray exp;
QString name;
QString value;
QString type;
bool hasChildren;
quint64 objectId;
static JSAgentWatchData fromScriptValue(const QString &expression, const QScriptValue &value)
{
JSAgentWatchData data;
data.exp = expression.toUtf8();
data.name = expression;
data.hasChildren = false;
data.value = value.toString();
data.objectId = value.objectId();
if (value.isArray()) {
data.type = QLatin1String("Array");
data.value = QString::fromLatin1("[Array of length %1]").arg(value.property("length").toString());
data.hasChildren = true;
} else if (value.isBool()) {
data.type = QLatin1String("Bool");
// data.value = value.toBool() ? QLatin1String("true") : QLatin1String("false");
} else if (value.isDate()) {
data.type = QLatin1String("Date");
data.value = value.toDateTime().toString();
} else if (value.isError()) {
data.type = QLatin1String("Error");
} else if (value.isFunction()) {
data.type = QLatin1String("Function");
} else if (value.isUndefined()) {
data.type = QLatin1String("<undefined>");
} else if (value.isNumber()) {
data.type = QLatin1String("Number");
} else if (value.isRegExp()) {
data.type = QLatin1String("RegExp");
} else if (value.isString()) {
data.type = QLatin1String("String");
} else if (value.isVariant()) {
data.type = QLatin1String("Variant");
} else if (value.isQObject()) {
const QObject *obj = value.toQObject();
data.value = QString::fromLatin1("[%1]").arg(obj->metaObject()->className());
data.type = QLatin1String("Object");
data.hasChildren = true;
} else if (value.isObject()) {
data.type = QLatin1String("Object");
data.hasChildren = true;
data.type = QLatin1String("Object");
data.value = QLatin1String("[Object]");
} else if (value.isNull()) {
data.type = QLatin1String("<null>");
} else {
data.type = QLatin1String("<unknown>");
}
return data;
}
};
QDataStream& operator<<(QDataStream& s, const JSAgentWatchData& data)
{
return s << data.exp << data.name << data.value << data.type << data.hasChildren << data.objectId;
}
static QList<JSAgentWatchData> expandObject(const QScriptValue &object)
{
QList<JSAgentWatchData> result;
QScriptValueIterator it(object);
QByteArray expPrefix = '@' + QByteArray::number(object.objectId(), 16) + "->";
while (it.hasNext()) {
it.next();
if (it.flags() & QScriptValue::SkipInEnumeration)
continue;
if (object.isQObject() && it.value().isFunction()) {
// cosmetics: skip all signals and slot, there is too many of them,
// and it is not usefull in the debugger.
continue;
}
JSAgentWatchData data = JSAgentWatchData::fromScriptValue(it.name(), it.value());
data.exp.prepend(expPrefix);
result << data;
}
return result;
}
void JSDebuggerAgent::recordKnownObjects(const QList<JSAgentWatchData>& list)
{
foreach (const JSAgentWatchData &data, list)
knownObjectIds << data.objectId;
}
QList<JSAgentWatchData> JSDebuggerAgent::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())
locals.prepend(JSAgentWatchData::fromScriptValue("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.
*/
JSDebuggerAgent::JSDebuggerAgent(QScriptEngine *engine)
: QDeclarativeDebugService("JSDebugger"), QScriptEngineAgent(engine)
, state(NoState)
{}
JSDebuggerAgent::JSDebuggerAgent(QDeclarativeEngine *engine)
: QDeclarativeDebugService("JSDebugger")
, QScriptEngineAgent(QDeclarativeEnginePrivate::getScriptEngine(engine))
, state(NoState)
{}
/*!
Destroys this QScriptDebuggerAgent.
*/
JSDebuggerAgent::~JSDebuggerAgent()
{}
/*!
\reimp
*/
void JSDebuggerAgent::scriptLoad(qint64 id, const QString & program,
const QString &fileName, int )
{
Q_UNUSED(program);
filenames.insert(id, QUrl(fileName).toLocalFile());
}
/*!
\reimp
*/
void JSDebuggerAgent::scriptUnload(qint64 id)
{
filenames.remove(id);
}
/*!
\reimp
*/
void JSDebuggerAgent::contextPush()
{
}
/*!
\reimp
*/
void JSDebuggerAgent::contextPop()
{
}
/*!
\reimp
*/
void JSDebuggerAgent::functionEntry(qint64 scriptId)
{
Q_UNUSED(scriptId);
stepDepth++;
}
/*!
\reimp
*/
void JSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue)
{
Q_UNUSED(scriptId);
Q_UNUSED(returnValue);
stepDepth--;
}
/*!
\reimp
*/
void JSDebuggerAgent::positionChange(qint64 scriptId,
int lineNumber, int columnNumber)
{
Q_UNUSED(columnNumber);
if(state == Stopped)
return; //no re-entrency
// check breakpoints
if (!breakpointList.isEmpty()) {
QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
if (it == filenames.constEnd()) {
// It is possible that the scripts are loaded before the agent is attached
QString filename = QUrl(QScriptContextInfo(engine()->currentContext()).fileName()).toLocalFile();
QPair<QString, qint32> key = qMakePair(filename, lineNumber);
it = filenames.insert(scriptId, filename);
}
QPair<QString, qint32> key = qMakePair(*it, lineNumber);
if (breakpointList.contains(key)) {
stopped();
return;
}
}
switch (state) {
case NoState:
case Stopped:
// Do nothing
break;
case SteppingOutState:
if (stepDepth >= 0)
break;
//fallthough
case SteppingOverState:
if (stepDepth > 0)
break;
//fallthough
case SteppingIntoState:
stopped();
break;
}
}
/*!
\reimp
*/
void JSDebuggerAgent::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 != Stopped)
stopped(true, exception);
#endif
}
/*!
\reimp
*/
void JSDebuggerAgent::exceptionCatch(qint64 scriptId,
const QScriptValue &exception)
{
Q_UNUSED(scriptId);
Q_UNUSED(exception);
}
bool JSDebuggerAgent::supportsExtension(QScriptEngineAgent::Extension extension) const
{
return extension == QScriptEngineAgent::DebuggerInvocationRequest;
}
QVariant JSDebuggerAgent::extension(QScriptEngineAgent::Extension extension, const QVariant& argument)
{
if (extension == QScriptEngineAgent::DebuggerInvocationRequest) {
stopped();
return QVariant();
}
return QScriptEngineAgent::extension(extension, argument);
}
void JSDebuggerAgent::messageReceived(const QByteArray& message)
{
QDataStream ds(message);
QByteArray command;
ds >> command;
if (command == "BREAKPOINTS") {
ds >> breakpointList;
} else if (command == "WATCH_EXPRESSIONS") {
ds >> watchExpressions;
} else if (command == "STEPOVER") {
stepDepth = 0;
state = SteppingOverState;
continueExec();
} else if (command == "STEPINTO" || command == "INTERRUPT") {
stepDepth = 0;
state = SteppingIntoState;
continueExec();
} else if (command == "STEPOUT") {
stepDepth = 0;
state = SteppingOutState;
continueExec();
} else if (command == "CONTINUE") {
state = NoState;
continueExec();
} else if (command == "EXEC") {
SetupExecEnv execEnv(this);
QByteArray id;
QString expr;
ds >> id >> expr;
JSAgentWatchData data = JSAgentWatchData::fromScriptValue(expr, engine()->evaluate(expr));
knownObjectIds << data.objectId;
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("RESULT") << id << data;
sendMessage(reply);
} else if (command == "EXPAND") {
SetupExecEnv execEnv(this);
QByteArray requestId;
quint64 objectId;
ds >> requestId >> objectId;
QScriptValue v;
if (knownObjectIds.contains(objectId))
v = engine()->objectById(objectId);
QList<JSAgentWatchData> result = expandObject(v);
recordKnownObjects(result);
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("EXPANDED") << requestId << result;
sendMessage(reply);
} else if (command == "ACTIVATE_FRAME") {
SetupExecEnv execEnv(this);
int frameId;
ds >> frameId;
int deep = 0;
QScriptContext *ctx = engine()->currentContext();
while (ctx && deep < frameId) {
ctx = ctx->parentContext();
deep++;
}
QList<JSAgentWatchData> locals = getLocals(ctx);
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("LOCALS") << frameId << locals;
sendMessage(reply);
} else if (command == "SET_PROPERTY") {
SetupExecEnv execEnv(this);
QByteArray id;
qint64 objectId;
QString property;
QString value;
ds >> id >> objectId >> property >> value;
if (knownObjectIds.contains(objectId)) {
QScriptValue object;
object = engine()->objectById(objectId);
if(object.isObject()) {
QScriptValue result = engine()->evaluate(value);
object.setProperty(property, result);
}
}
//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 JSDebuggerAgent::stopped(bool becauseOfException, const QScriptValue& exception)
{
knownObjectIds.clear();
state = Stopped;
QList<QPair<QString, QPair<QString, qint32> > > backtrace;
for (QScriptContext* ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
QScriptContextInfo info(ctx);
QString functionName = info.functionName();
if (functionName.isEmpty()) {
if (ctx->parentContext()) {
switch (info.functionType()) {
case QScriptContextInfo::ScriptFunction:
functionName = QLatin1String("<anonymous>");
break;
case QScriptContextInfo::NativeFunction:
functionName = QLatin1String("<native>");
break;
case QScriptContextInfo::QtFunction:
case QScriptContextInfo::QtPropertyFunction:
functionName = QLatin1String("<native slot>");
break;
}
} else {
functionName = QLatin1String("<global>");
}
}
int lineNumber = info.lineNumber();
if (lineNumber == -1) // if the line number is unknown, fallback to the function line number
lineNumber = info.functionStartLineNumber();
backtrace.append(qMakePair(functionName, qMakePair( QUrl(info.fileName()).toLocalFile(), lineNumber ) ) );
}
QList<JSAgentWatchData> watches;
foreach (const QString &expr, watchExpressions)
watches << JSAgentWatchData::fromScriptValue(expr, engine()->evaluate(expr));
recordKnownObjects(watches);
QList<JSAgentWatchData> locals = getLocals(engine()->currentContext());
if (!becauseOfException) {
// Clear any exceptions occurred during locals evaluation.
engine()->clearExceptions();
}
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("STOPPED") << backtrace << watches << locals << becauseOfException << exception.toString();
sendMessage(reply);
loop.exec(QEventLoop::ExcludeUserInputEvents);
}
void JSDebuggerAgent::continueExec()
{
loop.quit();
}
void JSDebuggerAgent::enabledChanged(bool on)
{
engine()->setAgent(on ? this : 0);
}
} // namespace QmlJSDebugger

View File

@@ -0,0 +1,17 @@
# Try to find location of Qt private headers (see README)
isEmpty(QT_PRIVATE_HEADERS) {
QT_PRIVATE_HEADERS = $$[QT_INSTALL_HEADERS]
}
INCLUDEPATH += \
$${QT_PRIVATE_HEADERS} \
$${QT_PRIVATE_HEADERS}/QtCore \
$${QT_PRIVATE_HEADERS}/QtGui \
$${QT_PRIVATE_HEADERS}/QtScript \
$${QT_PRIVATE_HEADERS}/QtDeclarative
DEPENDPATH += \
$${QT_PRIVATE_HEADERS} \
$${QT_PRIVATE_HEADERS}/QtCore \
$${QT_PRIVATE_HEADERS}/QtGui \
$${QT_PRIVATE_HEADERS}/QtScript \
$${QT_PRIVATE_HEADERS}/QtDeclarative

View File

@@ -0,0 +1,239 @@
/****************************************************************************
**
** Copyright (C) 2010 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 "qdeclarativeobserverservice.h"
#include <QStringList>
#include <QColor>
#include <QDebug>
namespace QmlJSDebugger {
Q_GLOBAL_STATIC(QDeclarativeObserverService, serviceInstance)
QDeclarativeObserverService::QDeclarativeObserverService()
: QDeclarativeDebugService(QLatin1String("QDeclarativeObserverMode"))
{
}
QDeclarativeObserverService *QDeclarativeObserverService::instance()
{
return serviceInstance();
}
void QDeclarativeObserverService::enabledChanged(bool enabled)
{
emit debuggingClientChanged(enabled);
}
void QDeclarativeObserverService::messageReceived(const QByteArray &message)
{
QDataStream ds(message);
QByteArray type;
ds >> type;
if (type == "SET_CURRENT_OBJECTS") {
int itemCount = 0;
ds >> itemCount;
QList<QObject*> selectedObjects;
for(int i = 0; i < itemCount; ++i) {
int debugId = -1;
ds >> debugId;
QObject *obj = objectForId(debugId);
if (obj)
selectedObjects << obj;
}
emit currentObjectsChanged(selectedObjects);
} else if (type == "RELOAD") {
emit reloadRequested();
} else if (type == "SET_ANIMATION_SPEED") {
qreal speed;
ds >> speed;
emit animationSpeedChangeRequested(speed);
} else if (type == "CHANGE_TOOL") {
QByteArray toolName;
ds >> toolName;
if (toolName == "COLOR_PICKER") {
emit colorPickerToolRequested();
} else if (toolName == "SELECT") {
emit selectToolRequested();
} else if (toolName == "SELECT_MARQUEE") {
emit selectMarqueeToolRequested();
} else if (toolName == "ZOOM") {
emit zoomToolRequested();
}
} else if (type == "SET_DESIGN_MODE") {
bool inDesignMode;
ds >> inDesignMode;
emit designModeBehaviorChanged(inDesignMode);
} else if (type == "CREATE_OBJECT") {
QString qml;
int parentId;
QString filename;
QStringList imports;
ds >> qml >> parentId >> imports >> filename;
emit objectCreationRequested(qml, objectForId(parentId), imports, filename);
} else if (type == "DESTROY_OBJECT") {
int debugId;
ds >> debugId;
if (QObject* obj = objectForId(debugId))
obj->deleteLater();
} else if (type == "MOVE_OBJECT") {
int debugId, newParent;
ds >> debugId >> newParent;
emit objectReparentRequested(objectForId(debugId), objectForId(newParent));
} else if (type == "OBJECT_ID_LIST") {
int itemCount;
ds >> itemCount;
m_stringIdForObjectId.clear();
for(int i = 0; i < itemCount; ++i) {
int itemDebugId;
QString itemIdString;
ds >> itemDebugId
>> itemIdString;
m_stringIdForObjectId.insert(itemDebugId, itemIdString);
}
} else if (type == "SET_CONTEXT_PATH_IDX") {
int contextPathIndex;
ds >> contextPathIndex;
emit contextPathIndexChanged(contextPathIndex);
} else if (type == "CLEAR_COMPONENT_CACHE") {
emit clearComponentCacheRequested();
}
}
void QDeclarativeObserverService::setDesignModeBehavior(bool inDesignMode)
{
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
ds << QByteArray("SET_DESIGN_MODE")
<< inDesignMode;
sendMessage(message);
}
void QDeclarativeObserverService::setCurrentObjects(QList<QObject*> objects)
{
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
ds << QByteArray("CURRENT_OBJECTS_CHANGED")
<< objects.length();
foreach(QObject *object, objects) {
int id = idForObject(object);
ds << id;
}
sendMessage(message);
}
void QDeclarativeObserverService::setCurrentTool(QmlJSDebugger::Constants::DesignTool toolId)
{
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
ds << QByteArray("TOOL_CHANGED")
<< toolId;
sendMessage(message);
}
void QDeclarativeObserverService::setAnimationSpeed(qreal slowdownFactor)
{
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
ds << QByteArray("ANIMATION_SPEED_CHANGED")
<< slowdownFactor;
sendMessage(message);
}
void QDeclarativeObserverService::reloaded()
{
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
ds << QByteArray("RELOADED");
sendMessage(message);
}
void QDeclarativeObserverService::selectedColorChanged(const QColor &color)
{
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
ds << QByteArray("COLOR_CHANGED")
<< color;
sendMessage(message);
}
void QDeclarativeObserverService::contextPathUpdated(const QStringList &contextPath)
{
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
ds << QByteArray("CONTEXT_PATH_UPDATED")
<< contextPath;
sendMessage(message);
}
QString QDeclarativeObserverService::idStringForObject(QObject *obj) const
{
int id = idForObject(obj);
QString idString = m_stringIdForObjectId.value(id, QString());
return idString;
}
} // namespace QmlJSDebugger

View File

@@ -0,0 +1,804 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "qdeclarativeviewobserver.h"
#include "qdeclarativeviewobserver_p.h"
#include "qdeclarativeobserverservice.h"
#include "selectiontool.h"
#include "zoomtool.h"
#include "colorpickertool.h"
#include "layeritem.h"
#include "boundingrecthighlighter.h"
#include "subcomponenteditortool.h"
#include "qmltoolbar.h"
#include "jsdebuggeragent.h"
#include <QDeclarativeItem>
#include <QDeclarativeEngine>
#include <QDeclarativeContext>
#include <QDeclarativeExpression>
#include <QWidget>
#include <QMouseEvent>
#include <QGraphicsObject>
#include <QApplication>
#include <QAbstractAnimation>
#include <private/qdeclarativeengine_p.h>
#include <private/qabstractanimation_p.h>
namespace QmlJSDebugger {
const int SceneChangeUpdateInterval = 5000;
QDeclarativeViewObserverPrivate::QDeclarativeViewObserverPrivate(QDeclarativeViewObserver *q) :
q(q),
designModeBehavior(false),
executionPaused(false),
slowdownFactor(1.0f),
jsDebuggerAgent(0),
toolbar(0)
{
}
QDeclarativeViewObserverPrivate::~QDeclarativeViewObserverPrivate()
{
}
QDeclarativeViewObserver::QDeclarativeViewObserver(QDeclarativeView *view, QObject *parent) :
QObject(parent), data(new QDeclarativeViewObserverPrivate(this))
{
data->view = view;
data->manipulatorLayer = new LayerItem(view->scene());
data->selectionTool = new SelectionTool(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;
data->view->setMouseTracking(true);
data->view->viewport()->installEventFilter(this);
data->debugService = QDeclarativeObserverService::instance();
connect(data->debugService, SIGNAL(designModeBehaviorChanged(bool)), SLOT(setDesignModeBehavior(bool)));
connect(data->debugService, SIGNAL(reloadRequested()), SLOT(_q_reloadView()));
connect(data->debugService,
SIGNAL(currentObjectsChanged(QList<QObject*>)),
SLOT(_q_onCurrentObjectsChanged(QList<QObject*>)));
connect(data->debugService, SIGNAL(animationSpeedChangeRequested(qreal)), SLOT(changeAnimationSpeed(qreal)));
connect(data->debugService, SIGNAL(colorPickerToolRequested()), SLOT(_q_changeToColorPickerTool()));
connect(data->debugService, SIGNAL(selectMarqueeToolRequested()), SLOT(_q_changeToMarqueeSelectTool()));
connect(data->debugService, SIGNAL(selectToolRequested()), SLOT(_q_changeToSingleSelectTool()));
connect(data->debugService, SIGNAL(zoomToolRequested()), SLOT(_q_changeToZoomTool()));
connect(data->debugService,
SIGNAL(objectCreationRequested(QString,QObject*,QStringList,QString)),
SLOT(_q_createQmlObject(QString,QObject*,QStringList,QString)));
connect(data->debugService,
SIGNAL(objectReparentRequested(QObject *, QObject *)),
SLOT(_q_reparentQmlObject(QObject *, QObject *)));
connect(data->debugService, SIGNAL(contextPathIndexChanged(int)), SLOT(_q_changeContextPathIndex(int)));
connect(data->debugService, SIGNAL(clearComponentCacheRequested()), SLOT(_q_clearComponentCache()));
connect(data->view, SIGNAL(statusChanged(QDeclarativeView::Status)), SLOT(_q_onStatusChanged(QDeclarativeView::Status)));
connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)), SIGNAL(selectedColorChanged(QColor)));
connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)),
data->debugService, SLOT(selectedColorChanged(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)), data->debugService, SLOT(contextPathUpdated(QStringList)));
data->createToolbar();
data->_q_changeToSingleSelectTool();
// always start debug mode - that's what this design view is for.
setDebugMode(true);
}
QDeclarativeViewObserver::~QDeclarativeViewObserver()
{
}
void QDeclarativeViewObserver::setObserverContext(int contextIndex)
{
if (data->subcomponentEditorTool->contextIndex() != contextIndex) {
QGraphicsObject *object = data->subcomponentEditorTool->setContext(contextIndex);
if (object)
data->debugService->setCurrentObjects(QList<QObject*>() << object);
}
}
void QDeclarativeViewObserverPrivate::_q_reloadView()
{
subcomponentEditorTool->clear();
clearHighlight();
emit q->reloadRequested();
}
void QDeclarativeViewObserverPrivate::clearEditorItems()
{
clearHighlight();
setSelectedItems(QList<QGraphicsItem*>());
}
bool QDeclarativeViewObserver::eventFilter(QObject *obj, QEvent *event)
{
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(AbstractFormEditorTool::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);
data->debugService->setCurrentObjects(AbstractFormEditorTool::toObjectList(selectedItems()));
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:
if (data->executionPaused) {
continueExecution(data->slowdownFactor);
} else {
pauseExecution();
}
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 + "\n";
}
QDeclarativeContext *parentContext = view->engine()->contextForObject(parent);
QDeclarativeComponent component(view->engine(), q);
QByteArray constructedQml = QString(imports + qml).toLatin1();
component.setData(constructedQml, 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();
}
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) {
QGraphicsObject *objectToEnter = itemToEnter->toGraphicsObject();
if (objectToEnter)
data->debugService->setCurrentObjects(QList<QObject*>() << 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);
data->toolbar->setDesignModeBehavior(value);
data->debugService->setDesignModeBehavior(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;
}
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)
{
currentSelection.clear();
foreach(QGraphicsItem *item, items) {
if (item) {
QGraphicsObject *obj = item->toGraphicsObject();
if (obj)
currentSelection << obj;
}
}
currentTool->updateSelectedItems();
}
void QDeclarativeViewObserverPrivate::setSelectedItems(QList<QGraphicsItem *> items)
{
setSelectedItemsForTools(items);
debugService->setCurrentObjects(AbstractFormEditorTool::toObjectList(items));
}
QList<QGraphicsItem *> QDeclarativeViewObserverPrivate::selectedItems()
{
QList<QGraphicsItem *> selection;
foreach(const QWeakPointer<QGraphicsObject> &selectedObject, currentSelection) {
if (selectedObject.isNull()) {
currentSelection.removeOne(selectedObject);
} else {
selection << selectedObject.data();
}
}
return selection;
}
void QDeclarativeViewObserver::setSelectedItems(QList<QGraphicsItem *> items)
{
data->setSelectedItems(items);
}
QList<QGraphicsItem *> QDeclarativeViewObserver::selectedItems()
{
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();
debugService->setCurrentTool(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();
debugService->setCurrentTool(Constants::MarqueeSelectionToolMode);
}
void QDeclarativeViewObserverPrivate::_q_changeToZoomTool()
{
currentToolMode = Constants::ZoomMode;
currentTool->clear();
currentTool = zoomTool;
currentTool->clear();
emit q->zoomToolActivated();
debugService->setCurrentTool(Constants::ZoomMode);
}
void QDeclarativeViewObserverPrivate::_q_changeToColorPickerTool()
{
if (currentTool == colorPickerTool)
return;
currentToolMode = Constants::ColorPickerMode;
currentTool->clear();
currentTool = colorPickerTool;
currentTool->clear();
emit q->colorPickerActivated();
debugService->setCurrentTool(Constants::ColorPickerMode);
}
void QDeclarativeViewObserverPrivate::_q_changeContextPathIndex(int index)
{
subcomponentEditorTool->setContext(index);
}
void QDeclarativeViewObserver::changeAnimationSpeed(qreal slowdownFactor)
{
data->slowdownFactor = slowdownFactor;
if (data->slowdownFactor != 0) {
continueExecution(data->slowdownFactor);
} else {
pauseExecution();
}
}
void QDeclarativeViewObserver::continueExecution(qreal slowdownFactor)
{
Q_ASSERT(slowdownFactor > 0);
data->slowdownFactor = slowdownFactor;
static const qreal animSpeedSnapDelta = 0.01f;
bool useStandardSpeed = (qAbs(1.0f - data->slowdownFactor) < animSpeedSnapDelta);
QUnifiedTimer *timer = QUnifiedTimer::instance();
timer->setSlowdownFactor(data->slowdownFactor);
timer->setSlowModeEnabled(!useStandardSpeed);
data->executionPaused = false;
emit executionStarted(data->slowdownFactor);
data->debugService->setAnimationSpeed(data->slowdownFactor);
}
void QDeclarativeViewObserver::pauseExecution()
{
QUnifiedTimer *timer = QUnifiedTimer::instance();
timer->setSlowdownFactor(0);
timer->setSlowModeEnabled(true);
data->executionPaused = true;
emit executionPaused();
data->debugService->setAnimationSpeed(0);
}
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());
emit q->executionStarted(1.0f);
}
debugService->reloaded();
}
}
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;
QGraphicsObject *gfxObj = declarativeItem->toGraphicsObject();
if (gfxObj)
gfxObjects << gfxObj;
}
}
setSelectedItemsForTools(items);
clearHighlight();
highlight(gfxObjects, QDeclarativeViewObserverPrivate::IgnoreContext);
}
QString QDeclarativeViewObserver::idStringForObject(QObject *obj)
{
return QDeclarativeObserverService::instance()->idStringForObject(obj);
}
// 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;
}
QToolBar *QDeclarativeViewObserver::toolbar() const
{
return data->toolbar;
}
void QDeclarativeViewObserverPrivate::createToolbar()
{
toolbar = new QmlToolbar(q->declarativeView());
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(changeAnimationSpeed(qreal)));
QObject::connect(toolbar, SIGNAL(colorPickerSelected()), q, SLOT(_q_changeToColorPickerTool()));
QObject::connect(toolbar, SIGNAL(zoomToolSelected()), q, SLOT(_q_changeToZoomTool()));
QObject::connect(toolbar, SIGNAL(selectToolSelected()), q, SLOT(_q_changeToSingleSelectTool()));
QObject::connect(toolbar, SIGNAL(marqueeSelectToolSelected()), q, SLOT(_q_changeToMarqueeSelectTool()));
QObject::connect(toolbar, SIGNAL(applyChangesFromQmlFileSelected()), q, SLOT(_q_applyChangesFromClient()));
QObject::connect(q, SIGNAL(executionStarted(qreal)), toolbar, SLOT(setAnimationSpeed(qreal)));
QObject::connect(q, SIGNAL(executionPaused()), toolbar, SLOT(setAnimationSpeed()));
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::setDebugMode(bool isDebugMode)
{
if (isDebugMode && !data->jsDebuggerAgent)
data->jsDebuggerAgent = new JSDebuggerAgent(QDeclarativeEnginePrivate::getScriptEngine(data->view->engine()));
}
} //namespace QmlJSDebugger
#include <moc_qdeclarativeviewobserver.cpp>

View File

@@ -0,0 +1,141 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef QDECLARATIVEDESIGNVIEW_P_H
#define QDECLARATIVEDESIGNVIEW_P_H
#include <QWeakPointer>
#include <QPointF>
#include <QTimer>
#include "qdeclarativeviewobserver.h"
#include "qdeclarativeobserverservice.h"
namespace QmlJSDebugger {
class JSDebuggerAgent;
class QDeclarativeViewObserver;
class SelectionTool;
class ZoomTool;
class ColorPickerTool;
class LayerItem;
class BoundingRectHighlighter;
class SubcomponentEditorTool;
class QmlToolbar;
class CrumblePath;
class AbstractFormEditorTool;
class QDeclarativeViewObserverPrivate
{
public:
enum ContextFlags {
IgnoreContext,
ContextSensitive
};
QDeclarativeViewObserverPrivate(QDeclarativeViewObserver *);
~QDeclarativeViewObserverPrivate();
QDeclarativeView *view;
QDeclarativeViewObserver *q;
QDeclarativeObserverService *debugService;
QPointF cursorPos;
QList<QWeakPointer<QGraphicsObject> > currentSelection;
Constants::DesignTool currentToolMode;
AbstractFormEditorTool *currentTool;
SelectionTool *selectionTool;
ZoomTool *zoomTool;
ColorPickerTool *colorPickerTool;
SubcomponentEditorTool *subcomponentEditorTool;
LayerItem *manipulatorLayer;
BoundingRectHighlighter *boundingRectHighlighter;
bool designModeBehavior;
bool executionPaused;
qreal slowdownFactor;
JSDebuggerAgent *jsDebuggerAgent;
QmlToolbar *toolbar;
void clearEditorItems();
void createToolbar();
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();
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);
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();
static QDeclarativeViewObserverPrivate *get(QDeclarativeViewObserver *v) { return v->d_func(); }
};
} // namespace QmlJSDebugger
#endif // QDECLARATIVEDESIGNVIEW_P_H

View File

@@ -0,0 +1,35 @@
QT += declarative script
INCLUDEPATH += $$PWD $$PWD/include editor
DEPENDPATH += $$PWD $$PWD/include editor
contains(CONFIG, dll) {
DEFINES += BUILD_QMLJSDEBUGGER_LIB
} else {
DEFINES += BUILD_QMLJSDEBUGGER_STATIC_LIB
}
include($$PWD/private_headers.pri)
## Input
HEADERS += \
$$PWD/include/jsdebuggeragent.h \
$$PWD/include/qmljsdebugger_global.h
SOURCES += \
$$PWD/jsdebuggeragent.cpp
contains(DEFINES, QMLOBSERVER) {
include($$PWD/editor/editor.pri)
HEADERS += \
$$PWD/include/qdeclarativeviewobserver.h \
$$PWD/include/qdeclarativeobserverservice.h \
$$PWD/include/qmlobserverconstants.h \
$$PWD/qdeclarativeviewobserver_p.h
SOURCES += \
$$PWD/qdeclarativeviewobserver.cpp \
$$PWD/qdeclarativeobserverservice.cpp
}
OTHER_FILES += $$PWD/qmljsdebugger.pri

View File

@@ -0,0 +1,5 @@
INCLUDEPATH += $$PWD/include
DEPENDPATH += $PPWD/include
QT += declarative script
LIBS *= -l$$qtLibraryName(QmlJSDebugger)

View File

@@ -0,0 +1,10 @@
TEMPLATE = lib
CONFIG+=dll
TARGET = QmlJSDebugger
DEFINES += QMLOBSERVER
unix:QMAKE_CXXFLAGS_DEBUG += -O3
include(../../../src/qtcreatorlibrary.pri)
include(qmljsdebugger-lib.pri)