diff options
author | Lasse Holmstedt <lasse.holmstedt@nokia.com> | 2010-08-06 17:47:49 +0200 |
---|---|---|
committer | Lasse Holmstedt <lasse.holmstedt@nokia.com> | 2010-08-06 17:48:01 +0200 |
commit | 4558477b01da263fd2eac6756805cfba0f12fa83 (patch) | |
tree | 12ae69120410a1850e7f14843d437ca2f74aa333 /share | |
parent | 253a2f7ccf2faf81e289a00d2a53b107e8f59e41 (diff) |
Moved qmljsdebugger to share & debugger lib support for qml app wizard
Reviewed-by: Alessandro Portale
Diffstat (limited to 'share')
84 files changed, 8684 insertions, 7 deletions
diff --git a/share/qtcreator/qmljsdebugger/editor/abstractformeditortool.cpp b/share/qtcreator/qmljsdebugger/editor/abstractformeditortool.cpp new file mode 100644 index 00000000000..7d621c1e978 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/abstractformeditortool.cpp @@ -0,0 +1,193 @@ +/************************************************************************** +** +** 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 "qdeclarativedesignview.h" + +#include <QDeclarativeEngine> + +#include <QtDebug> +#include <QGraphicsItem> +#include <QDeclarativeItem> + +namespace QmlViewer { + +AbstractFormEditorTool::AbstractFormEditorTool(QDeclarativeDesignView *editorView) + : QObject(editorView), m_view(editorView) +{ +} + + +AbstractFormEditorTool::~AbstractFormEditorTool() +{ + +} + +QDeclarativeDesignView* AbstractFormEditorTool::view() const +{ + return m_view; +} + +QGraphicsScene* AbstractFormEditorTool::scene() const +{ + return view()->scene(); +} + +void AbstractFormEditorTool::updateSelectedItems() +{ + selectedItemsChanged(items()); +} + +QList<QGraphicsItem*> AbstractFormEditorTool::items() const +{ + return view()->selectedItems(); +} + +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 = view()->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 = QDeclarativeDesignView::idStringForObject(declarativeItem); + } + + if (!objectStringId.isEmpty()) { + constructedName = objectStringId + " (" + className + ")"; + } else { + if (!gfxObject->objectName().isEmpty()) { + constructedName = gfxObject->objectName() + " (" + className + ")"; + } else { + constructedName = className; + } + } + } + + return constructedName; +} + + +} diff --git a/share/qtcreator/qmljsdebugger/editor/abstractformeditortool.h b/share/qtcreator/qmljsdebugger/editor/abstractformeditortool.h new file mode 100644 index 00000000000..2f8f3420f8f --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/abstractformeditortool.h @@ -0,0 +1,103 @@ +/************************************************************************** +** +** 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; +QT_END_NAMESPACE + +namespace QmlViewer { + +class QDeclarativeDesignView; + + +class FormEditorView; + +class AbstractFormEditorTool : public QObject +{ + Q_OBJECT +public: + AbstractFormEditorTool(QDeclarativeDesignView* view); + + 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; + + 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; + + QDeclarativeDesignView *view() const; + QGraphicsScene* scene() const; + +private: + QDeclarativeDesignView *m_view; + QList<QGraphicsItem*> m_itemList; +}; + +} + +#endif // ABSTRACTFORMEDITORTOOL_H diff --git a/share/qtcreator/qmljsdebugger/editor/boundingrecthighlighter.cpp b/share/qtcreator/qmljsdebugger/editor/boundingrecthighlighter.cpp new file mode 100644 index 00000000000..43ebea001ba --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/boundingrecthighlighter.cpp @@ -0,0 +1,241 @@ +#include "boundingrecthighlighter.h" +#include "qdeclarativedesignview.h" +#include "qmlviewerconstants.h" + +#include <QGraphicsPolygonItem> +#include <QTimer> +#include <QObject> + +#include <QDebug> + +namespace QmlViewer { + +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(QDeclarativeDesignView *view) : + LayerItem(view->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 QmlViewer diff --git a/share/qtcreator/qmljsdebugger/editor/boundingrecthighlighter.h b/share/qtcreator/qmljsdebugger/editor/boundingrecthighlighter.h new file mode 100644 index 00000000000..139b1ac7877 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/boundingrecthighlighter.h @@ -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 QmlViewer { + +class QDeclarativeDesignView; +class BoundingBox; + +class BoundingRectHighlighter : public LayerItem +{ + Q_OBJECT +public: + explicit BoundingRectHighlighter(QDeclarativeDesignView *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); + + QDeclarativeDesignView *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 QmlViewer + +#endif // BOUNDINGRECTHIGHLIGHTER_H diff --git a/share/qtcreator/qmljsdebugger/editor/colorpickertool.cpp b/share/qtcreator/qmljsdebugger/editor/colorpickertool.cpp new file mode 100644 index 00000000000..5bc349cba90 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/colorpickertool.cpp @@ -0,0 +1,89 @@ +#include "colorpickertool.h" +#include "qdeclarativedesignview.h" + +#include <QMouseEvent> +#include <QKeyEvent> +#include <QRectF> +#include <QRgb> +#include <QImage> +#include <QApplication> +#include <QPalette> + +namespace QmlViewer { + +ColorPickerTool::ColorPickerTool(QDeclarativeDesignView *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 QmlViewer diff --git a/share/qtcreator/qmljsdebugger/editor/colorpickertool.h b/share/qtcreator/qmljsdebugger/editor/colorpickertool.h new file mode 100644 index 00000000000..f762179c410 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/colorpickertool.h @@ -0,0 +1,53 @@ +#ifndef COLORPICKERTOOL_H +#define COLORPICKERTOOL_H + +#include "abstractformeditortool.h" + +#include <QColor> + +QT_FORWARD_DECLARE_CLASS(QPoint); + +namespace QmlViewer { + +class ColorPickerTool : public AbstractFormEditorTool +{ + Q_OBJECT +public: + explicit ColorPickerTool(QDeclarativeDesignView *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 QmlViewer + +#endif // COLORPICKERTOOL_H diff --git a/share/qtcreator/qmljsdebugger/editor/editor.pri b/share/qtcreator/qmljsdebugger/editor/editor.pri new file mode 100644 index 00000000000..150ca7dd08e --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/editor.pri @@ -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 diff --git a/share/qtcreator/qmljsdebugger/editor/editor.qrc b/share/qtcreator/qmljsdebugger/editor/editor.qrc new file mode 100644 index 00000000000..09fc2f6fb01 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/editor.qrc @@ -0,0 +1,24 @@ +<RCC> + <qresource prefix="/qml"> + <file>images/resize_handle.png</file> + <file>images/select.png</file> + <file>images/select-marquee.png</file> + <file>images/color-picker.png</file> + <file>images/play.png</file> + <file>images/pause.png</file> + <file>images/from-qml.png</file> + <file>images/to-qml.png</file> + <file>images/designmode.png</file> + <file>images/color-picker-hicontrast.png</file> + <file>images/zoom.png</file> + <file>images/color-picker-24.png</file> + <file>images/designmode-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> + </qresource> +</RCC> diff --git a/share/qtcreator/qmljsdebugger/editor/images/color-picker-24.png b/share/qtcreator/qmljsdebugger/editor/images/color-picker-24.png Binary files differnew file mode 100644 index 00000000000..cff47212a4f --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/color-picker-24.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/color-picker-hicontrast.png b/share/qtcreator/qmljsdebugger/editor/images/color-picker-hicontrast.png Binary files differnew file mode 100644 index 00000000000..b953d08a689 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/color-picker-hicontrast.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/color-picker.png b/share/qtcreator/qmljsdebugger/editor/images/color-picker.png Binary files differnew file mode 100644 index 00000000000..026c31b3e1d --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/color-picker.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/designmode-24.png b/share/qtcreator/qmljsdebugger/editor/images/designmode-24.png Binary files differnew file mode 100644 index 00000000000..b4e0ff43ff7 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/designmode-24.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/designmode.png b/share/qtcreator/qmljsdebugger/editor/images/designmode.png Binary files differnew file mode 100644 index 00000000000..b6a95e77bc2 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/designmode.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/from-qml-24.png b/share/qtcreator/qmljsdebugger/editor/images/from-qml-24.png Binary files differnew file mode 100644 index 00000000000..0ad21f3dbbf --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/from-qml-24.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/from-qml.png b/share/qtcreator/qmljsdebugger/editor/images/from-qml.png Binary files differnew file mode 100644 index 00000000000..666382c06dd --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/from-qml.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/pause-24.png b/share/qtcreator/qmljsdebugger/editor/images/pause-24.png Binary files differnew file mode 100644 index 00000000000..d9a2f6f814b --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/pause-24.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/pause.png b/share/qtcreator/qmljsdebugger/editor/images/pause.png Binary files differnew file mode 100644 index 00000000000..114d89b12bd --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/pause.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/play-24.png b/share/qtcreator/qmljsdebugger/editor/images/play-24.png Binary files differnew file mode 100644 index 00000000000..e2b9fbcf512 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/play-24.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/play.png b/share/qtcreator/qmljsdebugger/editor/images/play.png Binary files differnew file mode 100644 index 00000000000..011598a746f --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/play.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/reload.png b/share/qtcreator/qmljsdebugger/editor/images/reload.png Binary files differnew file mode 100644 index 00000000000..7042bec9ae9 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/reload.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/resize_handle.png b/share/qtcreator/qmljsdebugger/editor/images/resize_handle.png Binary files differnew file mode 100644 index 00000000000..2934f25b743 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/resize_handle.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/select-24.png b/share/qtcreator/qmljsdebugger/editor/images/select-24.png Binary files differnew file mode 100644 index 00000000000..5388a9d16ab --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/select-24.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/select-marquee-24.png b/share/qtcreator/qmljsdebugger/editor/images/select-marquee-24.png Binary files differnew file mode 100644 index 00000000000..0111ddae458 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/select-marquee-24.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/select-marquee.png b/share/qtcreator/qmljsdebugger/editor/images/select-marquee.png Binary files differnew file mode 100644 index 00000000000..92fe40d1adc --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/select-marquee.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/select.png b/share/qtcreator/qmljsdebugger/editor/images/select.png Binary files differnew file mode 100644 index 00000000000..672285582b5 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/select.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/to-qml-24.png b/share/qtcreator/qmljsdebugger/editor/images/to-qml-24.png Binary files differnew file mode 100644 index 00000000000..b72450ddd47 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/to-qml-24.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/to-qml.png b/share/qtcreator/qmljsdebugger/editor/images/to-qml.png Binary files differnew file mode 100644 index 00000000000..2ab951fd082 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/to-qml.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/zoom-24.png b/share/qtcreator/qmljsdebugger/editor/images/zoom-24.png Binary files differnew file mode 100644 index 00000000000..03462001ecb --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/zoom-24.png diff --git a/share/qtcreator/qmljsdebugger/editor/images/zoom.png b/share/qtcreator/qmljsdebugger/editor/images/zoom.png Binary files differnew file mode 100644 index 00000000000..17f0da6d64f --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/images/zoom.png diff --git a/share/qtcreator/qmljsdebugger/editor/layeritem.cpp b/share/qtcreator/qmljsdebugger/editor/layeritem.cpp new file mode 100644 index 00000000000..65261f45953 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/layeritem.cpp @@ -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 "qmlviewerconstants.h" + +#include <QGraphicsScene> + +namespace QmlViewer { + +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 QmlViewer diff --git a/share/qtcreator/qmljsdebugger/editor/layeritem.h b/share/qtcreator/qmljsdebugger/editor/layeritem.h new file mode 100644 index 00000000000..5ce3c82e56f --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/layeritem.h @@ -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 QmlViewer { + +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 diff --git a/share/qtcreator/qmljsdebugger/editor/movemanipulator.cpp b/share/qtcreator/qmljsdebugger/editor/movemanipulator.cpp new file mode 100644 index 00000000000..a9182fad185 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/movemanipulator.cpp @@ -0,0 +1,360 @@ +/************************************************************************** +** +** 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 "movemanipulator.h" +#include "qdeclarativedesignview.h" +//#include "layeritem.h" + +#include <QPointF> +#include <QtDebug> +#include <QColor> +#include <QPen> +#include <QApplication> + +#include <limits> + +namespace QmlViewer { + +MoveManipulator::MoveManipulator(/*LayerItem *layerItem, */QDeclarativeDesignView *view) + : //m_layerItem(layerItem), + m_view(view), + m_isActive(false) +{ +} + +MoveManipulator::~MoveManipulator() +{ + deleteSnapLines(); +} + +QPointF MoveManipulator::beginPoint() const +{ + return m_beginPoint; +} + +QList<QGraphicsItem*> MoveManipulator::itemList() const +{ + return m_itemList; +} + +void MoveManipulator::setItem(QGraphicsItem* item) +{ + QList<QGraphicsItem*> itemList; + itemList.append(item); + + setItems(itemList); +} + +void MoveManipulator::setItems(const QList<QGraphicsItem*> &itemList) +{ + m_itemList = itemList; + + foreach (QGraphicsItem* item, m_itemList) { + //QPointF positionInParentSpace = m_snapper.containerQGraphicsItem()->mapFromScene(m_beginPositionInSceneSpaceHash.value(item)); + //m_beginItemRectHash[item].translate(positionInParentSpace - m_beginPositionHash.value(item)); + qDebug() << item << item->pos(); + m_beginPositionHash.insert(item, item->pos()); + } + +// if (!m_itemList.isEmpty()) { +// if (m_itemList.first()->parentItem()) +// m_snapper.setContainerQGraphicsItem(m_itemList.first()->parentItem()); +// else +// m_snapper.setContainerQGraphicsItem(m_itemList.first()); +// m_snapper.setTransformtionSpaceQGraphicsItem(m_snapper.containerQGraphicsItem()); +// } +} + +void MoveManipulator::updateHashes() +{ +// foreach (QGraphicsItem* item, m_itemList) +// m_beginItemRectHash[item] = item->mapRectToParent(item->qmlItemNode().instanceBoundingRect()); + +// foreach (QGraphicsItem* item, m_itemList) { +// QPointF positionInParentSpace = m_snapper.containerQGraphicsItem()->mapFromScene(m_beginPositionInSceneSpaceHash.value(item)); +// m_beginItemRectHash[item].translate(positionInParentSpace - m_beginPositionHash.value(item)); +// m_beginPositionHash.insert(item, positionInParentSpace); +// } +} + +bool MoveManipulator::itemsCanReparented() const +{ + return true; +} + +void MoveManipulator::begin(const QPointF &beginPoint) +{ + m_isActive = true; + + //m_snapper.updateSnappingLines(m_itemList); + + +// foreach (QGraphicsItem* item, m_itemList) +// m_beginItemRectHash.insert(item, m_snapper.containerQGraphicsItem()->mapRectFromItem(item, item->qmlItemNode().instanceBoundingRect())); + +// foreach (QGraphicsItem* item, m_itemList) { +// QPointF positionInParentSpace(item->qmlItemNode().instancePosition()); +// QPointF positionInScenesSpace = m_snapper.containerQGraphicsItem()->mapToScene(positionInParentSpace); +// m_beginPositionInSceneSpaceHash.insert(item, positionInScenesSpace); +// } + +// foreach (QGraphicsItem* item, m_itemList) { +// QPointF positionInParentSpace = m_snapper.containerQGraphicsItem()->mapFromScene(m_beginPositionInSceneSpaceHash.value(item)); +// m_beginPositionHash.insert(item, positionInParentSpace); + +// QmlAnchors anchors(item->qmlItemNode().anchors()); +// m_beginTopMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Top)); +// m_beginLeftMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Left)); +// m_beginRightMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Right)); +// m_beginBottomMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Bottom)); +// m_beginHorizontalCenterHash.insert(item, anchors.instanceMargin(AnchorLine::HorizontalCenter)); +// m_beginVerticalCenterHash.insert(item, anchors.instanceMargin(AnchorLine::VerticalCenter)); +// } + + m_beginPoint = beginPoint; + +} + +//QPointF MoveManipulator::findSnappingOffset(const QList<QRectF> &boundingRectList) +//{ +// QPointF offset; + +// QMap<double, double> verticalOffsetMap; +// foreach (const QRectF &boundingRect, boundingRectList) { +// double verticalOffset = m_snapper.snappedVerticalOffset(boundingRect); +// if (verticalOffset < std::numeric_limits<double>::max()) +// verticalOffsetMap.insert(qAbs(verticalOffset), verticalOffset); +// } + + +// if (!verticalOffsetMap.isEmpty()) +// offset.rx() = verticalOffsetMap.begin().value(); + + + +// QMap<double, double> horizontalOffsetMap; +// foreach (const QRectF &boundingRect, boundingRectList) { +// double horizontalOffset = m_snapper.snappedHorizontalOffset(boundingRect); +// if (horizontalOffset < std::numeric_limits<double>::max()) +// horizontalOffsetMap.insert(qAbs(horizontalOffset), horizontalOffset); +// } + + +// if (!horizontalOffsetMap.isEmpty()) +// offset.ry() = horizontalOffsetMap.begin().value(); + +// return offset; +//} + +//void MoveManipulator::generateSnappingLines(const QList<QRectF> &boundingRectList) +//{ +// m_graphicsLineList = m_snapper.generateSnappingLines(boundingRectList, +// m_layerItem.data(), +// m_snapper.transformtionSpaceQGraphicsItem()->sceneTransform()); +//} + +QList<QRectF> MoveManipulator::translatedBoundingRects(const QList<QRectF> &boundingRectList, const QPointF& offsetVector) +{ + QList<QRectF> translatedBoundingRectList; + foreach (const QRectF &boundingRect, boundingRectList) + translatedBoundingRectList.append(boundingRect.translated(offsetVector)); + + return translatedBoundingRectList; +} + + + +/* + /brief updates the position of the items. +*/ +void MoveManipulator::update(const QPointF& updatePoint, Snapping /*useSnapping*/, State /*stateToBeManipulated*/) +{ + //deleteSnapLines(); //Since they position is changed and the item is moved the snapping lines are + //are obsolete. The new updated snapping lines (color and visibility) will be + //calculated in snapPoint() called in moveNode() later + + if (m_itemList.isEmpty()) { + return; + } else { + //QPointF updatePointInContainerSpace(m_snapper.containerQGraphicsItem()->mapFromScene(updatePoint)); + //QPointF beginPointInContainerSpace(m_snapper.containerQGraphicsItem()->mapFromScene(m_beginPoint)); + + QPointF offsetVector(updatePoint - m_beginPoint); + +// if (useSnapping == UseSnapping || useSnapping == UseSnappingAndAnchoring) { +// offsetVector -= findSnappingOffset(translatedBoundingRects(m_beginItemRectHash.values(), offsetVector)); +// //generateSnappingLines(translatedBoundingRects(m_beginItemRectHash.values(), offsetVector)); +// } + + foreach (QGraphicsItem* item, m_itemList) { + //qDebug() << "offset:" << m_beginPositionHash.value(item) << offsetVector; + QPointF positionInContainerSpace(m_beginPositionHash.value(item) + offsetVector); + + // don't support anchors for base state because it is not needed by the droptool +// if (stateToBeManipulated == UseActualState) { +// QmlAnchors anchors(item->qmlItemNode().anchors()); + +// if (anchors.instanceHasAnchor(AnchorLine::Top)) { +// anchors.setMargin(AnchorLine::Top, m_beginTopMarginHash.value(item) + offsetVector.y()); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Left)) { +// anchors.setMargin(AnchorLine::Left, m_beginLeftMarginHash.value(item) + offsetVector.x()); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { +// anchors.setMargin(AnchorLine::Bottom, m_beginBottomMarginHash.value(item) - offsetVector.y()); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Right)) { +// anchors.setMargin(AnchorLine::Right, m_beginRightMarginHash.value(item) - offsetVector.x()); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// anchors.setMargin(AnchorLine::HorizontalCenter, m_beginHorizontalCenterHash.value(item) + offsetVector.x()); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// anchors.setMargin(AnchorLine::VerticalCenter, m_beginVerticalCenterHash.value(item) + offsetVector.y()); +// } + +// item->setPos(positionInContainerSpace); +// } else { +// item->qmlItemNode().modelNode().variantProperty("x").setValue(qRound(positionInContainerSpace.x())); +// item->qmlItemNode().modelNode().variantProperty("y").setValue(qRound(positionInContainerSpace.y())); +// } + item->setPos(positionInContainerSpace); + } + } +} + +void MoveManipulator::clear() +{ + deleteSnapLines(); + m_beginItemRectHash.clear(); + m_beginPositionHash.clear(); + m_beginPositionInSceneSpaceHash.clear(); + m_itemList.clear(); + + m_beginTopMarginHash.clear(); + m_beginLeftMarginHash.clear(); + m_beginRightMarginHash.clear(); + m_beginBottomMarginHash.clear(); + m_beginHorizontalCenterHash.clear(); + m_beginVerticalCenterHash.clear(); +} + +void MoveManipulator::reparentTo(QGraphicsItem *newParent) +{ + deleteSnapLines(); + + if (!newParent) + return; + + if (!itemsCanReparented()) + return; + +// foreach (QGraphicsItem* item, m_itemList) { +// QmlItemNode parent(newParent->qmlItemNode()); +// if (parent.isValid()) { +// item->qmlItemNode().setParentProperty(parent.nodeAbstractProperty("data")); +// } +// } + +// m_snapper.setContainerQGraphicsItem(newParent); +// m_snapper.setTransformtionSpaceQGraphicsItem(m_snapper.containerQGraphicsItem()); +// m_snapper.updateSnappingLines(m_itemList); + + updateHashes(); +} + + +void MoveManipulator::end(const QPointF &/*endPoint*/) +{ + m_isActive = false; + deleteSnapLines(); + + clear(); +} + +void MoveManipulator::moveBy(double deltaX, double deltaY) +{ + foreach (QGraphicsItem* item, m_itemList) { +// QmlAnchors anchors(item->qmlItemNode().anchors()); + +// if (anchors.instanceHasAnchor(AnchorLine::Top)) { +// anchors.setMargin(AnchorLine::Top, anchors.instanceMargin(AnchorLine::Top) + deltaY); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Left)) { +// anchors.setMargin(AnchorLine::Left, anchors.instanceMargin(AnchorLine::Left) + deltaX); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { +// anchors.setMargin(AnchorLine::Bottom, anchors.instanceMargin(AnchorLine::Bottom) - deltaY); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Right)) { +// anchors.setMargin(AnchorLine::Right, anchors.instanceMargin(AnchorLine::Right) - deltaX); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// anchors.setMargin(AnchorLine::HorizontalCenter, anchors.instanceMargin(AnchorLine::HorizontalCenter) + deltaX); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// anchors.setMargin(AnchorLine::VerticalCenter, anchors.instanceMargin(AnchorLine::VerticalCenter) + deltaY); +// } + + item->moveBy(deltaX, deltaY); + } +} + +void MoveManipulator::setOpacityForAllElements(qreal opacity) +{ + foreach (QGraphicsItem* item, m_itemList) + item->setOpacity(opacity); +} + +void MoveManipulator::deleteSnapLines() +{ +// if (m_layerItem) { +// foreach (QGraphicsItem *item, m_graphicsLineList) +// m_layerItem->scene()->removeItem(item); +// } +// m_graphicsLineList.clear(); +// m_view->scene()->update(); +} + +bool MoveManipulator::isActive() const +{ + return m_isActive; +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/movemanipulator.h b/share/qtcreator/qmljsdebugger/editor/movemanipulator.h new file mode 100644 index 00000000000..f09a7436249 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/movemanipulator.h @@ -0,0 +1,116 @@ +/************************************************************************** +** +** 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 MOVEMANIPULATOR_H +#define MOVEMANIPULATOR_H + +#include <QWeakPointer> +#include <QGraphicsItem> +#include <QGraphicsLineItem> +#include <QHash> +#include <QPointF> +#include <QRectF> + +//#include "snapper.h" +//#include "formeditorview.h" + +namespace QmlViewer { + +class QDeclarativeDesignView; + +class MoveManipulator +{ +public: + enum Snapping { + UseSnapping, + UseSnappingAndAnchoring, + NoSnapping + }; + + enum State { + UseActualState, + UseBaseState + }; + + MoveManipulator(/*LayerItem *layerItem, */QDeclarativeDesignView *view); + ~MoveManipulator(); + QList<QGraphicsItem*> itemList() const; + void setItems(const QList<QGraphicsItem*> &itemList); + void setItem(QGraphicsItem* item); + + void begin(const QPointF& beginPoint); + void update(const QPointF& updatePoint, Snapping useSnapping, State stateToBeManipulated = UseActualState); + void reparentTo(QGraphicsItem *newParent); + void end(const QPointF& endPoint); + + void moveBy(double deltaX, double deltaY); + + QPointF beginPoint() const; + + void clear(); + + bool isActive() const; + +protected: + void setOpacityForAllElements(qreal opacity); + + //QPointF findSnappingOffset(const QList<QRectF> &boundingRectList); + void deleteSnapLines(); + + QList<QRectF> translatedBoundingRects(const QList<QRectF> &boundingRectList, const QPointF& offset); + QPointF calculateBoundingRectMovementOffset(const QPointF& updatePoint); + QRectF boundingRect(QGraphicsItem* item, const QPointF& updatePoint); + + //void generateSnappingLines(const QList<QRectF> &boundingRectList); + void updateHashes(); + + bool itemsCanReparented() const; + +private: + //Snapper m_snapper; + //QWeakPointer<LayerItem> m_layerItem; + QWeakPointer<QDeclarativeDesignView> m_view; + QList<QGraphicsItem*> m_itemList; + QHash<QGraphicsItem*, QRectF> m_beginItemRectHash; + QHash<QGraphicsItem*, QPointF> m_beginPositionHash; + QHash<QGraphicsItem*, QPointF> m_beginPositionInSceneSpaceHash; + QPointF m_beginPoint; + QHash<QGraphicsItem*, double> m_beginTopMarginHash; + QHash<QGraphicsItem*, double> m_beginLeftMarginHash; + QHash<QGraphicsItem*, double> m_beginRightMarginHash; + QHash<QGraphicsItem*, double> m_beginBottomMarginHash; + QHash<QGraphicsItem*, double> m_beginHorizontalCenterHash; + QHash<QGraphicsItem*, double> m_beginVerticalCenterHash; + QList<QGraphicsItem*> m_graphicsLineList; + bool m_isActive; +}; + +} + +#endif // MOVEMANIPULATOR_H diff --git a/share/qtcreator/qmljsdebugger/editor/movetool.cpp b/share/qtcreator/qmljsdebugger/editor/movetool.cpp new file mode 100644 index 00000000000..20377c10ddb --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/movetool.cpp @@ -0,0 +1,377 @@ +/************************************************************************** +** +** 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 "movetool.h" + +#include "resizehandleitem.h" +#include "qdeclarativedesignview.h" + +#include <QApplication> +#include <QWheelEvent> +#include <QAction> +#include <QMouseEvent> +#include <QtDebug> + +namespace QmlViewer { + +MoveTool::MoveTool(QDeclarativeDesignView *editorView) + : AbstractFormEditorTool(editorView), + m_moving(false), + m_moveManipulator(editorView), + m_selectionIndicator(editorView->manipulatorLayer()), + m_resizeIndicator(editorView->manipulatorLayer()) +{ + +} + + +MoveTool::~MoveTool() +{ + +} + +void MoveTool::clear() +{ + view()->clearHighlightBoundingRect(); + view()->setCursor(Qt::SizeAllCursor); + m_moveManipulator.clear(); + m_movingItems.clear(); + m_resizeIndicator.clear(); + m_selectionIndicator.clear(); +} + +void MoveTool::mousePressEvent(QMouseEvent *event) +{ + QList<QGraphicsItem*> itemList = view()->selectableItems(event->pos()); + + if (event->buttons() & Qt::LeftButton) { + m_moving = true; + + if (itemList.isEmpty()) { + view()->changeTool(Constants::SelectionToolMode); + return; + } + + m_movingItems = movingItems(items()); + if (m_movingItems.isEmpty()) + return; + + m_moveManipulator.setItems(m_movingItems); + + m_moveManipulator.begin(event->pos()); + } else if (event->buttons() & Qt::RightButton) { + view()->changeTool(Constants::SelectionToolMode); + } + +} + +void MoveTool::mouseMoveEvent(QMouseEvent *event) +{ + if (m_movingItems.isEmpty()) + return; + + if (event->buttons() & Qt::LeftButton) { + + m_selectionIndicator.hide(); + m_resizeIndicator.hide(); + +// QGraphicsItem *containerItem = containerQGraphicsItem(itemList, m_movingItems); +// if (containerItem +// && view()->currentState().isBaseState()) { +// if (containerItem != m_movingItems.first()->parentItem() +// && event->modifiers().testFlag(Qt::ShiftModifier)) { +// m_moveManipulator.reparentTo(containerItem); +// } +// } +// bool shouldSnapping = view()->widget()->snappingAction()->isChecked(); +// bool shouldSnappingAndAnchoring = view()->widget()->snappingAndAnchoringAction()->isChecked(); +// MoveManipulator::Snapping useSnapping = MoveManipulator::NoSnapping; +// if (event->modifiers().testFlag(Qt::ControlModifier) != (shouldSnapping || shouldSnappingAndAnchoring)) { +// if (shouldSnappingAndAnchoring) +// useSnapping = MoveManipulator::UseSnappingAndAnchoring; +// else +// useSnapping = MoveManipulator::UseSnapping; +// } + + m_moveManipulator.update(event->pos(), MoveManipulator::NoSnapping); + } +} + +void MoveTool::mouseReleaseEvent(QMouseEvent *event) +{ + if (m_movingItems.isEmpty()) + return; + + if (m_moving) { + QLineF moveVector(event->pos(), m_moveManipulator.beginPoint()); + if (moveVector.length() < QApplication::startDragDistance()) + { + QPointF beginPoint(m_moveManipulator.beginPoint()); + + m_moveManipulator.end(beginPoint); + + m_selectionIndicator.show(); + m_resizeIndicator.show(); + m_movingItems.clear(); + view()->changeTool(Constants::SelectionToolMode, + Constants::UseCursorPos); + } else { + m_moveManipulator.end(event->pos()); + + m_selectionIndicator.show(); + m_resizeIndicator.show(); + m_movingItems.clear(); + } + qDebug() << "releasing"; + view()->changeTool(Constants::ResizeToolMode); + } + + m_moving = false; + + qDebug() << "released"; +} + + +void MoveTool::hoverMoveEvent(QMouseEvent *event) +{ + QList<QGraphicsItem*> itemList = view()->items(event->pos()); + + if (itemList.isEmpty()) { + view()->changeTool(Constants::SelectionToolMode); + return; + } + + ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(itemList.first()); + if (resizeHandle) { + view()->changeTool(Constants::ResizeToolMode); + return; + } + + QList<QGraphicsItem*> selectableItemList = view()->selectableItems(event->pos()); + if (!topSelectedItemIsMovable(selectableItemList)) { + view()->changeTool(Constants::SelectionToolMode); + return; + } +} + +void MoveTool::keyPressEvent(QKeyEvent *event) +{ + switch(event->key()) { + case Qt::Key_Shift: + case Qt::Key_Alt: + case Qt::Key_Control: + case Qt::Key_AltGr: + event->setAccepted(false); + return; + } + + double moveStep = 1.0; + + if (event->modifiers().testFlag(Qt::ShiftModifier)) + moveStep = 10.0; + + if (!event->isAutoRepeat()) { + QList<QGraphicsItem*> movableItems(movingItems(items())); + if (movableItems.isEmpty()) + return; + + m_moveManipulator.setItems(movableItems); + m_selectionIndicator.hide(); + m_resizeIndicator.hide(); + } + + switch(event->key()) { + case Qt::Key_Left: m_moveManipulator.moveBy(-moveStep, 0.0); break; + case Qt::Key_Right: m_moveManipulator.moveBy(moveStep, 0.0); break; + case Qt::Key_Up: m_moveManipulator.moveBy(0.0, -moveStep); break; + case Qt::Key_Down: m_moveManipulator.moveBy(0.0, moveStep); break; + } + + +} + +void MoveTool::keyReleaseEvent(QKeyEvent *keyEvent) +{ + switch(keyEvent->key()) { + case Qt::Key_Shift: + case Qt::Key_Alt: + case Qt::Key_Control: + case Qt::Key_AltGr: + keyEvent->setAccepted(false); + return; + } + + if (!keyEvent->isAutoRepeat()) { + m_moveManipulator.clear(); + m_selectionIndicator.show(); + m_resizeIndicator.show(); + } +} + +void MoveTool::wheelEvent(QWheelEvent */*event*/) +{ + +} + +void MoveTool::mouseDoubleClickEvent(QMouseEvent * /*event*/) +{ + +} + +void MoveTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &removedItemList) +{ + foreach (QGraphicsItem* removedItem, removedItemList) + m_movingItems.removeOne(removedItem); +} + +void MoveTool::selectedItemsChanged(const QList<QGraphicsItem*> &itemList) +{ + m_selectionIndicator.setItems(toGraphicsObjectList(itemList)); + m_resizeIndicator.setItems(toGraphicsObjectList(itemList)); + updateMoveManipulator(); +} + +bool MoveTool::haveSameParent(const QList<QGraphicsItem*> &itemList) +{ + if (itemList.isEmpty()) + return false; + + QGraphicsItem *firstParent = itemList.first()->parentItem(); + foreach (QGraphicsItem* item, itemList) + { + if (firstParent != item->parentItem()) + return false; + } + + return true; +} + +bool MoveTool::isAncestorOfAllItems(QGraphicsItem* maybeAncestorItem, + const QList<QGraphicsItem*> &itemList) +{ + foreach (QGraphicsItem* item, itemList) + { + if (!maybeAncestorItem->isAncestorOf(item) && item != maybeAncestorItem) + return false; + } + + return true; +} + + +QGraphicsItem* MoveTool::ancestorIfOtherItemsAreChild(const QList<QGraphicsItem*> &itemList) +{ + if (itemList.isEmpty()) + return 0; + + + foreach (QGraphicsItem* item, itemList) + { + if (isAncestorOfAllItems(item, itemList)) + return item; + } + + return 0; +} + +void MoveTool::updateMoveManipulator() +{ + if (m_moveManipulator.isActive()) + return; +} + +void MoveTool::beginWithPoint(const QPointF &beginPoint) +{ + m_movingItems = movingItems(items()); + if (m_movingItems.isEmpty()) + return; + + m_moving = true; + m_moveManipulator.setItems(m_movingItems); + m_moveManipulator.begin(beginPoint); +} + +//static bool isNotAncestorOfItemInList(QGraphicsItem *graphicsItem, const QList<QGraphicsItem*> &itemList) +//{ +// foreach (QGraphicsItem *item, itemList) { +// if (item->qmlItemNode().isAncestorOf(graphicsItem->qmlItemNode())) +// return false; +// } + +// return true; +//} + +//QGraphicsItem* MoveTool::containerQGraphicsItem(const QList<QGraphicsItem*> &itemUnderMouseList, +// const QList<QGraphicsItem*> &selectedItemList) +//{ +// Q_ASSERT(!selectedItemList.isEmpty()); + +// foreach (QGraphicsItem* item, itemUnderMouseList) { +// QGraphicsItem *QGraphicsItem = QGraphicsItem::fromQGraphicsItem(item); +// if (QGraphicsItem +// && !selectedItemList.contains(QGraphicsItem) +// && isNotAncestorOfItemInList(QGraphicsItem, selectedItemList)) +// return QGraphicsItem; + +// } + +// return 0; +//} + + +QList<QGraphicsItem*> MoveTool::movingItems(const QList<QGraphicsItem*> &selectedItemList) +{ + QGraphicsItem* ancestorItem = ancestorIfOtherItemsAreChild(selectedItemList); + +// if (ancestorItem != 0 && ancestorItem->qmlItemNode().isRootNode()) { +// view()->changeTool(QDeclarativeDesignView::SelectionToolMode); +// return QList<QGraphicsItem*>(); +// } + + if (ancestorItem != 0 && ancestorItem->parentItem() != 0) { + QList<QGraphicsItem*> ancestorItemList; + ancestorItemList.append(ancestorItem); + return ancestorItemList; + } + + if (!haveSameParent(selectedItemList)) { + view()->changeTool(Constants::SelectionToolMode); + return QList<QGraphicsItem*>(); + } + + return selectedItemList; +} + +void MoveTool::graphicsObjectsChanged(const QList<QGraphicsObject*> &itemList) +{ + m_selectionIndicator.updateItems(itemList); + m_resizeIndicator.updateItems(itemList); +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/movetool.h b/share/qtcreator/qmljsdebugger/editor/movetool.h new file mode 100644 index 00000000000..7514cf68664 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/movetool.h @@ -0,0 +1,91 @@ +/************************************************************************** +** +** 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 MOVETOOL_H +#define MOVETOOL_H + +#include "abstractformeditortool.h" +#include "movemanipulator.h" +#include "resizeindicator.h" +#include "selectionindicator.h" +#include <QHash> + +namespace QmlViewer { + +class MoveTool : public AbstractFormEditorTool +{ +public: + MoveTool(QDeclarativeDesignView* editorView); + ~MoveTool(); + + 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 selectedItemsChanged(const QList<QGraphicsItem*> &itemList); + + void updateMoveManipulator(); + + void beginWithPoint(const QPointF &beginPoint); + + void clear(); + + void graphicsObjectsChanged(const QList<QGraphicsObject*> &itemList); + +protected: + static bool haveSameParent(const QList<QGraphicsItem*> &itemList); + + QList<QGraphicsItem*> movingItems(const QList<QGraphicsItem*> &selectedItemList); + + static QGraphicsItem* containerFormEditorItem(const QList<QGraphicsItem*> &itemUnderMouseList, + const QList<QGraphicsItem*> &selectedItemList); + + static bool isAncestorOfAllItems(QGraphicsItem* maybeAncestorItem, + const QList<QGraphicsItem*> &itemList); + static QGraphicsItem* ancestorIfOtherItemsAreChild(const QList<QGraphicsItem*> &itemList); + +private: + bool m_moving; + MoveManipulator m_moveManipulator; + SelectionIndicator m_selectionIndicator; + ResizeIndicator m_resizeIndicator; + QList<QGraphicsItem*> m_movingItems; +}; + +} + +#endif // MOVETOOL_H diff --git a/share/qtcreator/qmljsdebugger/editor/qmltoolbar.cpp b/share/qtcreator/qmljsdebugger/editor/qmltoolbar.cpp new file mode 100644 index 00000000000..585996a80cb --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/qmltoolbar.cpp @@ -0,0 +1,241 @@ +#include <QLabel> +#include <QIcon> +#include <QAction> + +#include "qmltoolbar.h" +#include "toolbarcolorbox.h" + +#include <QDebug> + +namespace QmlViewer { + +QmlToolbar::QmlToolbar(QWidget *parent) : + QToolBar(parent), + m_emitSignals(true), + m_isRunning(false), + ui(new Ui) +{ + ui->designmode = new QAction(QIcon(QLatin1String(":/qml/images/designmode-24.png")), tr("Design Mode"), this); + ui->play = new QAction(QIcon(QLatin1String(":/qml/images/play-24.png")), tr("Play"), this); + ui->pause = new QAction(QIcon(QLatin1String(":/qml/images/pause-24.png")), tr("Pause"), 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(true); + ui->play->setChecked(true); + ui->pause->setCheckable(true); + 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); + addAction(ui->pause); + addSeparator(); + + addAction(ui->select); + 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); + + 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->pause, SIGNAL(triggered()), SLOT(activatePauseOnClick())); + + 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::startExecution() +{ + m_emitSignals = false; + activatePlayOnClick(); + m_emitSignals = true; +} + +void QmlToolbar::pauseExecution() +{ + m_emitSignals = false; + activatePauseOnClick(); + m_emitSignals = true; +} + +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::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->pause->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() +{ + ui->pause->setChecked(false); + ui->play->setChecked(true); + if (!m_isRunning) { + m_isRunning = true; + if (m_emitSignals) + emit executionStarted(); + } +} + +void QmlToolbar::activatePauseOnClick() +{ + ui->play->setChecked(false); + ui->pause->setChecked(true); + if (m_isRunning) { + m_isRunning = false; + if (m_emitSignals) + emit executionPaused(); + } +} + +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(); +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/qmltoolbar.h b/share/qtcreator/qmljsdebugger/editor/qmltoolbar.h new file mode 100644 index 00000000000..640d72320fc --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/qmltoolbar.h @@ -0,0 +1,77 @@ +#ifndef QMLTOOLBAR_H +#define QMLTOOLBAR_H + +#include <QToolBar> +#include "qmlviewerconstants.h" + +namespace QmlViewer { + +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 startExecution(); + void pauseExecution(); + void activateColorPicker(); + void activateSelectTool(); + void activateMarqueeSelectTool(); + void activateZoom(); + +signals: + void executionStarted(); + void executionPaused(); + + 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 activatePauseOnClick(); + void activateColorPickerOnClick(); + void activateSelectToolOnClick(); + void activateMarqueeSelectToolOnClick(); + void activateZoomOnClick(); + + void activateFromQml(); + void activateToQml(); + +private: + class Ui { + public: + QAction *designmode; + QAction *play; + QAction *pause; + QAction *select; + QAction *selectMarquee; + QAction *zoom; + QAction *colorPicker; + QAction *toQml; + QAction *fromQml; + ToolBarColorBox *colorBox; + }; + + bool m_emitSignals; + bool m_isRunning; + Constants::DesignTool m_activeTool; + Ui *ui; +}; + +} + +#endif // QMLTOOLBAR_H diff --git a/share/qtcreator/qmljsdebugger/editor/resize_handle.png b/share/qtcreator/qmljsdebugger/editor/resize_handle.png Binary files differnew file mode 100644 index 00000000000..2934f25b743 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/resize_handle.png diff --git a/share/qtcreator/qmljsdebugger/editor/resizecontroller.cpp b/share/qtcreator/qmljsdebugger/editor/resizecontroller.cpp new file mode 100644 index 00000000000..27e5daf9176 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/resizecontroller.cpp @@ -0,0 +1,293 @@ +/************************************************************************** +** +** 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 "resizecontroller.h" +#include "layeritem.h" + +#include <resizehandleitem.h> +#include <QCursor> +#include <QGraphicsScene> +#include <QGraphicsItem> + +#include <QDebug> + +namespace QmlViewer { + +ResizeControllerData::ResizeControllerData(LayerItem *layerItem, QGraphicsObject *formEditorItem) + : + layerItem(layerItem), + formEditorItem(formEditorItem), + topLeftItem(0), + topRightItem(0), + bottomLeftItem(0), + bottomRightItem(0), + topItem(0), + leftItem(0), + rightItem(0), + bottomItem(0) +{ + +} + +ResizeControllerData::~ResizeControllerData() +{ + clear(); +} + +void ResizeControllerData::clear() +{ + if (!formEditorItem.isNull() && topLeftItem) { + formEditorItem.data()->scene()->removeItem(topLeftItem); + formEditorItem.data()->scene()->removeItem(topRightItem); + formEditorItem.data()->scene()->removeItem(bottomLeftItem); + formEditorItem.data()->scene()->removeItem(bottomRightItem); + formEditorItem.data()->scene()->removeItem(topItem); + formEditorItem.data()->scene()->removeItem(leftItem); + formEditorItem.data()->scene()->removeItem(rightItem); + formEditorItem.data()->scene()->removeItem(bottomItem); + formEditorItem.clear(); + layerItem.clear(); + topLeftItem = 0; + topRightItem = 0; + bottomLeftItem = 0; + bottomRightItem = 0; + topItem = 0; + leftItem = 0; + rightItem = 0; + bottomItem = 0; + } +} + +ResizeController::ResizeController() + : m_data(new ResizeControllerData(0, 0)) +{ + +} + +ResizeController::~ResizeController() +{ + delete m_data; + m_data = 0; +} + +void ResizeController::setItem(LayerItem *layerItem, QGraphicsObject *item) +{ + createFor(layerItem, item); +} + +ResizeController::ResizeController(LayerItem *layerItem, QGraphicsObject *formEditorItem) : + m_data(new ResizeControllerData(layerItem, formEditorItem)) +{ + createFor(layerItem, formEditorItem); +} + +void ResizeController::createFor(LayerItem *layerItem, QGraphicsObject *formEditorItem) +{ + if (m_data) + m_data->clear(); + else + m_data = new ResizeControllerData(layerItem, formEditorItem); + + m_data->formEditorItem = formEditorItem; + m_data->layerItem = layerItem; + + m_data->topLeftItem = new ResizeHandleItem(layerItem, this); + m_data->topLeftItem->setZValue(3020); + m_data->topLeftItem->setCustomCursor(Qt::SizeFDiagCursor); + + m_data->topRightItem = new ResizeHandleItem(layerItem, this); + m_data->topRightItem->setZValue(3010); + m_data->topRightItem->setCustomCursor(Qt::SizeBDiagCursor); + + m_data->bottomLeftItem = new ResizeHandleItem(layerItem, this); + m_data->bottomLeftItem->setZValue(3010); + m_data->bottomLeftItem->setCustomCursor(Qt::SizeBDiagCursor); + + m_data->bottomRightItem = new ResizeHandleItem(layerItem, this); + m_data->bottomRightItem->setZValue(3050); + m_data->bottomRightItem->setCustomCursor(Qt::SizeFDiagCursor); + + m_data->topItem = new ResizeHandleItem(layerItem, this); + m_data->topItem->setZValue(3000); + m_data->topItem->setCustomCursor(Qt::SizeVerCursor); + + m_data->leftItem = new ResizeHandleItem(layerItem, this); + m_data->leftItem->setZValue(3000); + m_data->leftItem->setCustomCursor(Qt::SizeHorCursor); + + m_data->rightItem = new ResizeHandleItem(layerItem, this); + m_data->rightItem->setZValue(3000); + m_data->rightItem->setCustomCursor(Qt::SizeHorCursor); + + m_data->bottomItem = new ResizeHandleItem(layerItem, this); + m_data->bottomItem->setZValue(3000); + m_data->bottomItem->setCustomCursor(Qt::SizeVerCursor); + + updatePosition(); +} + +bool ResizeController::isValid() const +{ + return !m_data->formEditorItem.isNull(); +} + +void ResizeController::show() +{ + updatePosition(); + + m_data->topLeftItem->show(); + m_data->topRightItem->show(); + m_data->bottomLeftItem->show(); + m_data->bottomRightItem->show(); + m_data->topItem->show(); + m_data->leftItem->show(); + m_data->rightItem->show(); + m_data->bottomItem->show(); +} +void ResizeController::hide() +{ + m_data->topLeftItem->hide(); + m_data->topRightItem->hide(); + m_data->bottomLeftItem->hide(); + m_data->bottomRightItem->hide(); + m_data->topItem->hide(); + m_data->leftItem->hide(); + m_data->rightItem->hide(); + m_data->bottomItem->hide(); +} + + +static QPointF topCenter(const QRectF &rect) +{ + return QPointF(rect.center().x(), rect.top()); +} + +static QPointF leftCenter(const QRectF &rect) +{ + return QPointF(rect.left(), rect.center().y()); +} + +static QPointF rightCenter(const QRectF &rect) +{ + return QPointF(rect.right(), rect.center().y()); +} + +static QPointF bottomCenter(const QRectF &rect) +{ + return QPointF(rect.center().x(), rect.bottom()); +} + + +void ResizeController::updatePosition() +{ + QGraphicsItem *formEditorItem = m_data->formEditorItem.data(); + QRectF boundingRect =formEditorItem->boundingRect(); + QPointF topLeftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + boundingRect.topLeft())); + QPointF topRightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + boundingRect.topRight())); + QPointF bottomLeftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + boundingRect.bottomLeft())); + QPointF bottomRightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + boundingRect.bottomRight())); + + QPointF topPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + topCenter(boundingRect))); + QPointF leftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + leftCenter(boundingRect))); + + QPointF rightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + rightCenter(boundingRect))); + QPointF bottomPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + bottomCenter(boundingRect))); + + + m_data->topRightItem->setHandlePosition(topRightPointInLayerSpace, boundingRect.topRight()); + m_data->topLeftItem->setHandlePosition(topLeftPointInLayerSpace, boundingRect.topLeft()); + m_data->bottomLeftItem->setHandlePosition(bottomLeftPointInLayerSpace, boundingRect.bottomLeft()); + m_data->bottomRightItem->setHandlePosition(bottomRightPointInLayerSpace, boundingRect.bottomRight()); + m_data->topItem->setHandlePosition(topPointInLayerSpace, topCenter(boundingRect)); + m_data->leftItem->setHandlePosition(leftPointInLayerSpace, leftCenter(boundingRect)); + m_data->rightItem->setHandlePosition(rightPointInLayerSpace, rightCenter(boundingRect)); + m_data->bottomItem->setHandlePosition(bottomPointInLayerSpace, bottomCenter(boundingRect)); + +} + + +QGraphicsObject* ResizeController::formEditorItem() const +{ + return m_data->formEditorItem.data(); +} + +ResizeControllerData *ResizeController::data() const +{ + return m_data; +} + +bool ResizeController::isTopLeftHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->topLeftItem; +} + +bool ResizeController::isTopRightHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->topRightItem; +} + +bool ResizeController::isBottomLeftHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->bottomLeftItem; +} + +bool ResizeController::isBottomRightHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->bottomRightItem; +} + +bool ResizeController::isTopHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->topItem; +} + +bool ResizeController::isLeftHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->leftItem; +} + +bool ResizeController::isRightHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->rightItem; +} + +bool ResizeController::isBottomHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->bottomItem; +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/resizecontroller.h b/share/qtcreator/qmljsdebugger/editor/resizecontroller.h new file mode 100644 index 00000000000..6b214195709 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/resizecontroller.h @@ -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 RESIZECONTROLLER_H +#define RESIZECONTROLLER_H + +#include <QWeakPointer> +#include <QSharedPointer> +#include <QGraphicsItem> +#include <QGraphicsObject> + +namespace QmlViewer { + +class LayerItem; +class ResizeHandleItem; + +class ResizeControllerData +{ +public: + ResizeControllerData(LayerItem *layerItem, + QGraphicsObject *formEditorItem); + //ResizeControllerData(const ResizeControllerData &other); + ~ResizeControllerData(); + void clear(); + + QWeakPointer<LayerItem> layerItem; + QWeakPointer<QGraphicsObject> formEditorItem; + ResizeHandleItem *topLeftItem; + ResizeHandleItem *topRightItem; + ResizeHandleItem *bottomLeftItem; + ResizeHandleItem *bottomRightItem; + ResizeHandleItem *topItem; + ResizeHandleItem *leftItem; + ResizeHandleItem *rightItem; + ResizeHandleItem *bottomItem; +}; + + + + +class ResizeController +{ +public: + friend class ResizeHandleItem; + + ResizeController(); + ~ResizeController(); + ResizeController(LayerItem *layerItem, QGraphicsObject *formEditorItem); + + void show(); + void hide(); + void setItem(LayerItem *layerItem, QGraphicsObject *item); + + void updatePosition(); + + bool isValid() const; + + QGraphicsObject *formEditorItem() const; + + bool isTopLeftHandle(const ResizeHandleItem *handle) const; + bool isTopRightHandle(const ResizeHandleItem *handle) const; + bool isBottomLeftHandle(const ResizeHandleItem *handle) const; + bool isBottomRightHandle(const ResizeHandleItem *handle) const; + + bool isTopHandle(const ResizeHandleItem *handle) const; + bool isLeftHandle(const ResizeHandleItem *handle) const; + bool isRightHandle(const ResizeHandleItem *handle) const; + bool isBottomHandle(const ResizeHandleItem *handle) const; + +private: // functions + void createFor(LayerItem *layerItem, QGraphicsObject *formEditorItem); + ResizeControllerData *data() const; + +private: // variables + ResizeControllerData *m_data; +}; + +} + +#endif // RESIZECONTROLLER_H diff --git a/share/qtcreator/qmljsdebugger/editor/resizehandleitem.cpp b/share/qtcreator/qmljsdebugger/editor/resizehandleitem.cpp new file mode 100644 index 00000000000..88d50b4650c --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/resizehandleitem.cpp @@ -0,0 +1,126 @@ +/************************************************************************** +** +** 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 "resizehandleitem.h" + +#include <QCursor> + +namespace QmlViewer { + +ResizeHandleItem::ResizeHandleItem(QGraphicsItem *parent, ResizeController *resizeController) + : QGraphicsPixmapItem(QPixmap(":/editor/handle/resize_handle.png"), parent), + m_resizeController(resizeController) +{ + setShapeMode(QGraphicsPixmapItem::BoundingRectShape); + setOffset(-pixmap().rect().center()); + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIgnoresTransformations, true); +} + +void ResizeHandleItem::setHandlePosition(const QPointF & globalPosition, const QPointF & itemSpacePosition) +{ + m_itemSpacePosition = itemSpacePosition; + setPos(globalPosition); +} + +QRectF ResizeHandleItem::boundingRect() const +{ + return QGraphicsPixmapItem::boundingRect().adjusted(-1, -1, 1, 1); +} + +QPainterPath ResizeHandleItem::shape() const +{ + return QGraphicsItem::shape(); +} + +ResizeController * ResizeHandleItem::resizeController() const +{ + return m_resizeController; +} + +ResizeHandleItem* ResizeHandleItem::fromGraphicsItem(QGraphicsItem *item) +{ + return qgraphicsitem_cast<ResizeHandleItem*>(item); +} + +bool ResizeHandleItem::isTopLeftHandle() const +{ + return resizeController()->isTopLeftHandle(this); +} + +bool ResizeHandleItem::isTopRightHandle() const +{ + return resizeController()->isTopRightHandle(this); +} + +bool ResizeHandleItem::isBottomLeftHandle() const +{ + return resizeController()->isBottomLeftHandle(this); +} + +bool ResizeHandleItem::isBottomRightHandle() const +{ + return resizeController()->isBottomRightHandle(this); +} + +bool ResizeHandleItem::isTopHandle() const +{ + return resizeController()->isTopHandle(this); +} + +bool ResizeHandleItem::isLeftHandle() const +{ + return resizeController()->isLeftHandle(this); +} + +bool ResizeHandleItem::isRightHandle() const +{ + return resizeController()->isRightHandle(this); +} + +bool ResizeHandleItem::isBottomHandle() const +{ + return resizeController()->isBottomHandle(this); +} + +QPointF ResizeHandleItem::itemSpacePosition() const +{ + return m_itemSpacePosition; +} + +QCursor ResizeHandleItem::customCursor() const +{ + return m_customCursor; +} +void ResizeHandleItem::setCustomCursor(const QCursor &cursor) +{ + m_customCursor = cursor; +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/resizehandleitem.h b/share/qtcreator/qmljsdebugger/editor/resizehandleitem.h new file mode 100644 index 00000000000..d036590d210 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/resizehandleitem.h @@ -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. +** +**************************************************************************/ + +#ifndef RESIZEHANDLEITEM_H +#define RESIZEHANDLEITEM_H + +#include <QGraphicsPixmapItem> +#include <QCursor> + +#include "resizecontroller.h" + +namespace QmlViewer { + +class ResizeHandleItem : public QGraphicsPixmapItem +{ +public: + enum + { + Type = 0xEAEA + }; + + + ResizeHandleItem(QGraphicsItem *parent, ResizeController *resizeController); + + void setHandlePosition(const QPointF & globalPosition, const QPointF & itemSpacePosition); + + int type() const; + QRectF boundingRect() const; + QPainterPath shape() const; + +<<<<<<< HEAD:src/tools/qml/qmlobserver/editor/resizehandleitem.h + ResizeController * resizeController() const; +======= + virtual bool initialize(const QStringList &arguments, QString *errorString); + virtual void extensionsInitialized(); + virtual ShutdownFlag aboutToShutdown(); +>>>>>>> 9eba87bd92aa2de00e2c191119bc9a9e015e1de5:src/plugins/qmlinspector/qmlinspectorplugin.h + + static ResizeHandleItem* fromGraphicsItem(QGraphicsItem *item); + + bool isTopLeftHandle() const; + bool isTopRightHandle() const; + bool isBottomLeftHandle() const; + bool isBottomRightHandle() const; + + bool isTopHandle() const; + bool isLeftHandle() const; + bool isRightHandle() const; + bool isBottomHandle() const; + + QPointF itemSpacePosition() const; + QCursor customCursor() const; + void setCustomCursor(const QCursor &cursor); + +private: + ResizeController *m_resizeController; + QPointF m_itemSpacePosition; + QCursor m_customCursor; + +}; + +inline int ResizeHandleItem::type() const +{ + return Type; +} + +} + +#endif // RESIZEHANDLEITEM_H diff --git a/share/qtcreator/qmljsdebugger/editor/resizeindicator.cpp b/share/qtcreator/qmljsdebugger/editor/resizeindicator.cpp new file mode 100644 index 00000000000..62a7eb29cff --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/resizeindicator.cpp @@ -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 "resizeindicator.h" +#include "layeritem.h" + +#include <QGraphicsObject> + +namespace QmlViewer { + +ResizeIndicator::ResizeIndicator(LayerItem *layerItem) + : m_layerItem(layerItem) +{ + +} + +ResizeIndicator::~ResizeIndicator() +{ + m_itemControllerHash.clear(); +} + +void ResizeIndicator::show() +{ + QHashIterator<QGraphicsObject*, ResizeController*> itemControllerIterator(m_itemControllerHash); + while (itemControllerIterator.hasNext()) { + ResizeController *controller = itemControllerIterator.next().value(); + controller->show(); + } +} +void ResizeIndicator::hide() +{ + QHashIterator<QGraphicsObject*, ResizeController*> itemControllerIterator(m_itemControllerHash); + while (itemControllerIterator.hasNext()) { + ResizeController *controller = itemControllerIterator.next().value(); + controller->hide(); + } +} + +void ResizeIndicator::clear() +{ + QHashIterator<QGraphicsObject*, ResizeController*> itemControllerIterator(m_itemControllerHash); + while(itemControllerIterator.hasNext()) { + itemControllerIterator.next(); + delete itemControllerIterator.value(); + } + m_itemControllerHash.clear(); +} + +void ResizeIndicator::setItems(const QList<QGraphicsObject*> &itemList) +{ + clear(); + + foreach (QGraphicsObject* item, itemList) { + ResizeController *controller = new ResizeController(m_layerItem.data(), item); + m_itemControllerHash.insert(item, controller); + } +} + +void ResizeIndicator::updateItems(const QList<QGraphicsObject*> &/*itemList*/) +{ +// foreach (QDeclarativeItem* item, itemList) { +// if (m_itemControllerHash.contains(item)) { +// ResizeController *controller = new ResizeController(m_itemControllerHash.value(item)); +// controller.updatePosition(); +// } +// } +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/resizeindicator.h b/share/qtcreator/qmljsdebugger/editor/resizeindicator.h new file mode 100644 index 00000000000..360dba72b7b --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/resizeindicator.h @@ -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 RESIZEINDICATOR_H +#define RESIZEINDICATOR_H + +#include <QHash> +#include <QPair> +#include <QGraphicsObject> +#include <QDeclarativeItem> +#include <QWeakPointer> + +#include "resizecontroller.h" + +QT_FORWARD_DECLARE_CLASS(QGraphicsRectItem); + +namespace QmlViewer { + +class LayerItem; + +class ResizeIndicator +{ +public: + enum Orientation { + Top = 1, + Right = 2, + Bottom = 4, + Left = 8 + }; + + ResizeIndicator(LayerItem *layerItem); + ~ResizeIndicator(); + + void show(); + void hide(); + + void clear(); + + void setItems(const QList<QGraphicsObject*> &itemList); + void updateItems(const QList<QGraphicsObject*> &itemList); + +// +// QPair<FormEditorItem*,Orientation> pick(QGraphicsRectItem* pickedItem) const; +// +// void show(); +// void hide(); + +private: + QWeakPointer<LayerItem> m_layerItem; + QHash<QGraphicsObject*, ResizeController*> m_itemControllerHash; + +}; + +} + +#endif // SCALEINDICATOR_H diff --git a/share/qtcreator/qmljsdebugger/editor/resizemanipulator.cpp b/share/qtcreator/qmljsdebugger/editor/resizemanipulator.cpp new file mode 100644 index 00000000000..329404244d6 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/resizemanipulator.cpp @@ -0,0 +1,529 @@ +/************************************************************************** +** +** 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 "resizemanipulator.h" +#include "resizehandleitem.h" + +#include "mathutils.h" + +#include <QtDebug> +#include <QDeclarativeItem> +#include <QApplication> +#include <limits> + +namespace QmlViewer { + +ResizeManipulator::ResizeManipulator(LayerItem *layer, QDeclarativeView *view) + : m_view(view), + m_resizeController(0), + m_beginTopMargin(0.0), + m_beginLeftMargin(0.0), + m_beginRightMargin(0.0), + m_beginBottomMargin(0.0), + m_resizeHandle(0), + m_layerItem(layer) +{ +} + +ResizeManipulator::~ResizeManipulator() +{ + deleteSnapLines(); +} + +void ResizeManipulator::setHandle(ResizeHandleItem *resizeHandle) +{ + Q_ASSERT(resizeHandle); + m_view->setCursor(resizeHandle->customCursor()); + m_resizeHandle = resizeHandle; + m_resizeController = resizeHandle->resizeController(); + //m_snapper.setContainerFormEditorItem(m_resizeController.formEditorItem()->parentItem()); + //m_snapper.setTransformtionSpaceFormEditorItem(m_resizeController.formEditorItem()); + Q_ASSERT(m_resizeController->isValid()); +} + +void ResizeManipulator::removeHandle() +{ + m_resizeController = 0; + m_resizeHandle = 0; +} + +void ResizeManipulator::begin(const QPointF &/*beginPoint*/) +{ + + if (m_resizeController->isValid()) { + m_beginBoundingRect = m_resizeController->formEditorItem()->boundingRect(); + m_beginToSceneTransform = m_resizeController->formEditorItem()->sceneTransform(); + m_beginFromSceneTransform = m_beginToSceneTransform.inverted(); + + if (m_resizeController->formEditorItem()->parentItem()) { + m_beginToParentTransform = m_resizeController->formEditorItem()->itemTransform(m_resizeController->formEditorItem()->parentItem()); + } else { + m_beginToParentTransform = QTransform(); + } + + //m_snapper.updateSnappingLines(m_resizeController.formEditorItem()); + m_beginBottomRightPoint = m_beginToParentTransform.map(m_resizeController->formEditorItem()->boundingRect().bottomRight()); + + //QmlAnchors anchors(m_resizeController.formEditorItem()->qmlItemNode().anchors()); + m_beginTopMargin = 0;//anchors.instanceMargin(AnchorLine::Top); + m_beginLeftMargin = 0;//anchors.instanceMargin(AnchorLine::Left); + m_beginRightMargin = 0;//anchors.instanceMargin(AnchorLine::Right); + m_beginBottomMargin = 0;//anchors.instanceMargin(AnchorLine::Bottom); + } +} + +//static QSizeF mapSizeToParent(const QSizeF &size, QGraphicsItem *item) +//{ +// QPointF sizeAsPoint(size.width(), size.height()); +// sizeAsPoint = item->mapToParent(sizeAsPoint); +// return QSizeF(sizeAsPoint.x(), sizeAsPoint.y()); +//} + +void ResizeManipulator::update(const QPointF& updatePoint, Snapping useSnapping) +{ + if (!m_resizeHandle || !m_resizeController) + return; + + const double minimumWidth = 15.0; + const double minimumHeight = 15.0; + + deleteSnapLines(); + + bool snap = useSnapping == UseSnapping || useSnapping == UseSnappingAndAnchoring; + + if (m_resizeController->isValid()) { + + QDeclarativeItem *formEditorItem = qobject_cast<QDeclarativeItem*>(m_resizeController->formEditorItem()); + + if (!formEditorItem) + return; + + //FormEditorItem *containerItem = m_snapper.containerFormEditorItem(); + +// if (!containerItem) +// return; +// QPointF updatePointInLocalSpace = QPointF(0,0); +// if (formEditorItem->parentItem()) { +// updatePointInLocalSpace = formEditorItem->parentItem()->mapFromScene(updatePoint); +// } else { +// updatePointInLocalSpace = updatePoint; //= m_beginFromSceneTransform.map(updatePoint); +// } + + QPointF updatePointInLocalSpace = m_beginFromSceneTransform.map(updatePoint); + //QmlAnchors anchors(formEditorItem->qmlItemNode().anchors()); + + QRectF boundingRect(m_beginBoundingRect); + if (m_resizeHandle->isBottomRightHandle()) { + boundingRect.setBottomRight(updatePointInLocalSpace); + + if (snap) { +// double rightOffset = m_snapper.snapRightOffset(boundingRect); +// if (rightOffset < std::numeric_limits<double>::max()) +// updatePointInLocalSpace.rx() -= rightOffset; + +// double bottomOffset = m_snapper.snapBottomOffset(boundingRect); +// if (bottomOffset < std::numeric_limits<double>::max()) +// updatePointInLocalSpace.ry() -= bottomOffset; + } + boundingRect.setBottomRight(updatePointInLocalSpace); + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// boundingRect.setLeft(boundingRect.left() - (updatePointInLocalSpace.x() - m_beginBoundingRect.right())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// boundingRect.setTop(boundingRect.top() - (updatePointInLocalSpace.y() - m_beginBoundingRect.bottom())); +// } + + + if (boundingRect.width() < minimumWidth) + boundingRect.setWidth(minimumWidth); + if (boundingRect.height() < minimumHeight) + boundingRect.setHeight(minimumHeight); + + formEditorItem->setSize(boundingRect.size()); + +// if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { +// anchors.setMargin(AnchorLine::Bottom, +// m_beginBottomMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).y()); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Right)) { +// anchors.setMargin(AnchorLine::Right, +// m_beginRightMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).x()); +// } + } else if (m_resizeHandle->isTopLeftHandle()) { + boundingRect.setTopLeft(updatePointInLocalSpace); + + if (snap) { +// double leftOffset = m_snapper.snapLeftOffset(boundingRect); +// if (leftOffset < std::numeric_limits<double>::max()) +// updatePointInLocalSpace.rx() -= leftOffset; + +// double topOffset = m_snapper.snapTopOffset(boundingRect); +// if (topOffset < std::numeric_limits<double>::max()) +// updatePointInLocalSpace.ry() -= topOffset; + } + //boundingRect.setTopLeft(updatePointInLocalSpace); + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// boundingRect.setRight(boundingRect.right() - (updatePointInLocalSpace.x() - m_beginBoundingRect.left())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// boundingRect.setBottom(boundingRect.bottom() - (updatePointInLocalSpace.y() - m_beginBoundingRect.top())); +// } + + + if (boundingRect.width() < minimumWidth) + boundingRect.setLeft(boundingRect.left() - minimumWidth + boundingRect.width()); + if (boundingRect.height() < minimumHeight) + boundingRect.setTop(boundingRect.top() - minimumHeight + boundingRect.height()); + + formEditorItem->setSize(boundingRect.size()); + formEditorItem->setPos(m_beginToParentTransform.map(boundingRect.topLeft())); + + +// if (anchors.instanceHasAnchor(AnchorLine::Top)) { +// anchors.setMargin(AnchorLine::Top, +// m_beginTopMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).y() + m_beginToParentTransform.map(boundingRect.topLeft()).y())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Left)) { +// anchors.setMargin(AnchorLine::Left, +// m_beginLeftMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).x() + m_beginToParentTransform.map(boundingRect.topLeft()).x())); +// } + + } else if (m_resizeHandle->isTopRightHandle()) { + boundingRect.setTopRight(updatePointInLocalSpace); + + if (snap) { +// double rightOffset = m_snapper.snapRightOffset(boundingRect); +// if (rightOffset < std::numeric_limits<double>::max()) +// updatePointInLocalSpace.rx() -= rightOffset; + +// double topOffset = m_snapper.snapTopOffset(boundingRect); +// if (topOffset < std::numeric_limits<double>::max()) +// updatePointInLocalSpace.ry() -= topOffset; + } + boundingRect.setTopRight(updatePointInLocalSpace); + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// boundingRect.setLeft(boundingRect.left() - (updatePointInLocalSpace.x() - m_beginBoundingRect.right())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// boundingRect.setBottom(boundingRect.bottom() - (updatePointInLocalSpace.y() - m_beginBoundingRect.top())); +// } + + if (boundingRect.height() < minimumHeight) + boundingRect.setTop(boundingRect.top() - minimumHeight + boundingRect.height()); + if (boundingRect.width() < minimumWidth) + boundingRect.setWidth(minimumWidth); + + formEditorItem->setSize(boundingRect.size()); + + // was: setPositionWithBorder + formEditorItem->setPos(m_beginToParentTransform.map(boundingRect.topLeft())); + +// if (anchors.instanceHasAnchor(AnchorLine::Top)) { +// anchors.setMargin(AnchorLine::Top, +// m_beginTopMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).y() + m_beginToParentTransform.map(boundingRect.topLeft()).y())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Right)) { +// anchors.setMargin(AnchorLine::Right, +// m_beginRightMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).x()); +// } + } else if (m_resizeHandle->isBottomLeftHandle()) { + boundingRect.setBottomLeft(updatePointInLocalSpace); + + if (snap) { +// double leftOffset = m_snapper.snapLeftOffset(boundingRect); +// if (leftOffset < std::numeric_limits<double>::max()) +// updatePointInLocalSpace.rx() -= leftOffset; + +// double bottomOffset = m_snapper.snapBottomOffset(boundingRect); +// if (bottomOffset < std::numeric_limits<double>::max()) +// updatePointInLocalSpace.ry() -= bottomOffset; + } + + boundingRect.setBottomLeft(updatePointInLocalSpace); + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// boundingRect.setRight(boundingRect.right() - (updatePointInLocalSpace.x() - m_beginBoundingRect.left())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// boundingRect.setTop(boundingRect.top() - (updatePointInLocalSpace.y() - m_beginBoundingRect.bottom())); +// } + + if (boundingRect.height() < minimumHeight) + boundingRect.setHeight(minimumHeight); + if (boundingRect.width() < minimumWidth) + boundingRect.setLeft(boundingRect.left() - minimumWidth + boundingRect.width()); + + formEditorItem->setSize(boundingRect.size()); + formEditorItem->setPos(m_beginToParentTransform.map(boundingRect.topLeft())); + +// if (anchors.instanceHasAnchor(AnchorLine::Left)) { +// anchors.setMargin(AnchorLine::Left, +// m_beginLeftMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).x() + m_beginToParentTransform.map(boundingRect.topLeft()).x())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { +// anchors.setMargin(AnchorLine::Bottom, +// m_beginBottomMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).y()); +// } + } else if (m_resizeHandle->isBottomHandle()) { + boundingRect.setBottom(updatePointInLocalSpace.y()); + + if (snap) { +// double bottomOffset = m_snapper.snapBottomOffset(boundingRect); +// if (bottomOffset < std::numeric_limits<double>::max()) +// updatePointInLocalSpace.ry() -= bottomOffset; + } + + boundingRect.setBottom(updatePointInLocalSpace.y()); + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// boundingRect.setTop(boundingRect.top() - (updatePointInLocalSpace.y() - m_beginBoundingRect.bottom())); +// } + + if (boundingRect.height() < minimumHeight) + boundingRect.setHeight(minimumHeight); + + formEditorItem->setSize(boundingRect.size()); + +// if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { +// anchors.setMargin(AnchorLine::Bottom, +// m_beginBottomMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).y()); +// } + } else if (m_resizeHandle->isTopHandle()) { + boundingRect.setTop(updatePointInLocalSpace.y()); + + if (snap) { +// double topOffset = m_snapper.snapTopOffset(boundingRect); +// if (topOffset < std::numeric_limits<double>::max()) +// updatePointInLocalSpace.ry() -= topOffset; + } + + boundingRect.setTop(updatePointInLocalSpace.y()); + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// boundingRect.setBottom(boundingRect.bottom() - (updatePointInLocalSpace.y() - m_beginBoundingRect.top())); +// } + + if (boundingRect.height() < minimumHeight) + boundingRect.setTop(boundingRect.top() - minimumHeight + boundingRect.height()); + + formEditorItem->setSize(boundingRect.size()); + formEditorItem->setPos(m_beginToParentTransform.map(boundingRect.topLeft())); + +// if (anchors.instanceHasAnchor(AnchorLine::Top)) { +// anchors.setMargin(AnchorLine::Top, +// m_beginTopMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).y() + m_beginToParentTransform.map(boundingRect.topLeft()).y())); +// } + } else if (m_resizeHandle->isRightHandle()) { + boundingRect.setRight(updatePointInLocalSpace.x()); + + if (snap) { +// double rightOffset = m_snapper.snapRightOffset(boundingRect); +// if (rightOffset < std::numeric_limits<double>::max()) +// updatePointInLocalSpace.rx() -= rightOffset; + } + + boundingRect.setRight(updatePointInLocalSpace.x()); + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// boundingRect.setLeft(boundingRect.left() - (updatePointInLocalSpace.x() - m_beginBoundingRect.right())); +// } + + if (boundingRect.width() < minimumWidth) + boundingRect.setWidth(minimumWidth); + + formEditorItem->setSize(boundingRect.size()); + + +// if (anchors.instanceHasAnchor(AnchorLine::Right)) { +// anchors.setMargin(AnchorLine::Right, +// m_beginRightMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).x()); +// } + } else if (m_resizeHandle->isLeftHandle()) { + boundingRect.setLeft(updatePointInLocalSpace.x()); + + if (snap) { +// double leftOffset = m_snapper.snapLeftOffset(boundingRect); +// if (leftOffset < std::numeric_limits<double>::max()) +// updatePointInLocalSpace.rx() -= leftOffset; + } + + boundingRect.setLeft(updatePointInLocalSpace.x()); + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// boundingRect.setRight(boundingRect.right() - (updatePointInLocalSpace.x() - m_beginBoundingRect.left())); +// } + + if (boundingRect.width() < minimumWidth) + boundingRect.setLeft(boundingRect.left() - minimumWidth + boundingRect.width()); + + formEditorItem->setSize(boundingRect.size()); + formEditorItem->setPos(m_beginToParentTransform.map(boundingRect.topLeft())); + +// if (anchors.instanceHasAnchor(AnchorLine::Left)) { +// anchors.setMargin(AnchorLine::Left, +// m_beginLeftMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).x() + m_beginToParentTransform.map(boundingRect.topLeft()).x())); +// } + } + +// if (snap) +// m_graphicsLineList = m_snapper.generateSnappingLines(boundingRect, +// m_layerItem.data(), +// m_beginToSceneTransform); + } + m_resizeController->updatePosition(); +} + +void ResizeManipulator::end() +{ + //m_rewriterTransaction.commit(); + clear(); + removeHandle(); +} + +//void ResizeManipulator::moveBy(double deltaX, double deltaY) +//{ +// if (resizeHandle()) { +// //QmlItemNode qmlItemNode(m_resizeController.formEditorItem()->qmlItemNode()); +// //QmlAnchors anchors(qmlItemNode.anchors()); + +// if (m_resizeController.isLeftHandle(resizeHandle()) +// || m_resizeController.isTopLeftHandle(resizeHandle()) +// || m_resizeController.isBottomLeftHandle(resizeHandle())) { +// qmlItemNode.setVariantProperty("x", round((qmlItemNode.instanceValue("x").toDouble() + deltaX), 4)); +// qmlItemNode.setVariantProperty("width", round(qmlItemNode.instanceValue("width").toDouble() - deltaX, 4)); + + +//// if (anchors.instanceHasAnchor(AnchorLine::Left)) { +//// anchors.setMargin(AnchorLine::Left, anchors.instanceMargin(AnchorLine::Left) + deltaX); +//// } + +//// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +//// qmlItemNode.setVariantProperty("width", round(qmlItemNode.instanceValue("width").toDouble() - (deltaX * 2), 4)); +//// } +// } + +// if (m_resizeController.isRightHandle(resizeHandle()) +// || m_resizeController.isTopRightHandle(resizeHandle()) +// || m_resizeController.isBottomRightHandle(resizeHandle())) { +// qmlItemNode.setVariantProperty("width", round(qmlItemNode.instanceValue("width").toDouble() + deltaX, 4)); + +//// if (anchors.instanceHasAnchor(AnchorLine::Right)) { +//// anchors.setMargin(AnchorLine::Right, round(anchors.instanceMargin(AnchorLine::Right) - deltaX, 4)); +//// } + +//// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +//// qmlItemNode.setVariantProperty("width", round(qmlItemNode.instanceValue("width").toDouble() + (deltaX * 2), 4)); +//// } +// } + + +// if (m_resizeController.isTopHandle(resizeHandle()) +// || m_resizeController.isTopLeftHandle(resizeHandle()) +// || m_resizeController.isTopRightHandle(resizeHandle())) { +// qmlItemNode.setVariantProperty("y", round(qmlItemNode.instanceValue("y").toDouble() + deltaY, 4)); +// qmlItemNode.setVariantProperty("height", round(qmlItemNode.instanceValue("height").toDouble() - deltaY, 4)); + +//// if (anchors.instanceHasAnchor(AnchorLine::Top)) { +//// anchors.setMargin(AnchorLine::Top, anchors.instanceMargin(AnchorLine::Top) + deltaY); +//// } + +//// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +//// qmlItemNode.setVariantProperty("height", round(qmlItemNode.instanceValue("height").toDouble() - (deltaY * 2), 4)); +//// } +// } + +// if (m_resizeController.isBottomHandle(resizeHandle()) +// || m_resizeController.isBottomLeftHandle(resizeHandle()) +// || m_resizeController.isBottomRightHandle(resizeHandle())) { +// qmlItemNode.setVariantProperty("height", round(qmlItemNode.instanceValue("height").toDouble() + deltaY, 4)); + +//// if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { +//// anchors.setMargin(AnchorLine::Bottom, anchors.instanceMargin(AnchorLine::Bottom) - deltaY); +//// } + +//// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +//// qmlItemNode.setVariantProperty("height", round(qmlItemNode.instanceValue("height").toDouble() + (deltaY * 2), 4)); +//// } +// } + +// } +//} + +bool ResizeManipulator::isInvalidSize(const QSizeF & size) +{ + if (size.width() < 15 || size.height() < 15) + return true; + + return false; +} + +void ResizeManipulator::deleteSnapLines() +{ +// if (m_layerItem) { +// foreach (QGraphicsItem *item, m_graphicsLineList) +// m_layerItem->scene()->removeItem(item); +// } + + m_graphicsLineList.clear(); + m_view->scene()->update(); +} + +ResizeHandleItem *ResizeManipulator::resizeHandle() +{ + return m_resizeHandle; +} + +void ResizeManipulator::clear() +{ + //m_rewriterTransaction.commit(); + + deleteSnapLines(); + m_beginBoundingRect = QRectF(); + m_beginFromSceneTransform = QTransform(); + m_beginToSceneTransform = QTransform(); + m_beginToParentTransform = QTransform(); + m_beginTopMargin = 0.0; + m_beginLeftMargin = 0.0; + m_beginRightMargin = 0.0; + m_beginBottomMargin = 0.0; + removeHandle(); +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/resizemanipulator.h b/share/qtcreator/qmljsdebugger/editor/resizemanipulator.h new file mode 100644 index 00000000000..87bd943be31 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/resizemanipulator.h @@ -0,0 +1,93 @@ +/************************************************************************** +** +** 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 RESIZEMANIPULATOR_H +#define RESIZEMANIPULATOR_H + +#include <QWeakPointer> +#include "layeritem.h" +#include "resizehandleitem.h" + +#include <QDeclarativeItem> +#include <QDeclarativeView> + +namespace QmlViewer { + +class ResizeHandleItem; +class Model; + +class ResizeManipulator +{ +public: + enum Snapping { + UseSnapping, + UseSnappingAndAnchoring, + NoSnapping + }; + + ResizeManipulator(LayerItem *layer, QDeclarativeView *view); + ~ResizeManipulator(); + + void setHandle(ResizeHandleItem *resizeHandle); + void removeHandle(); + + void begin(const QPointF& beginPoint); + void update(const QPointF& updatePoint, Snapping useSnapping); + void end(); + + void moveBy(double deltaX, double deltaY); + + void clear(); + +protected: + bool isInvalidSize(const QSizeF & size); + void deleteSnapLines(); + ResizeHandleItem *resizeHandle(); + +private: +// Snapper m_snapper; + QWeakPointer<QDeclarativeView> m_view; + QList<QGraphicsItem*> m_graphicsLineList; + ResizeController *m_resizeController; + QTransform m_beginFromSceneTransform; + QTransform m_beginToSceneTransform; + QTransform m_beginToParentTransform; + QRectF m_beginBoundingRect; + QPointF m_beginBottomRightPoint; + double m_beginTopMargin; + double m_beginLeftMargin; + double m_beginRightMargin; + double m_beginBottomMargin; + ResizeHandleItem *m_resizeHandle; + QWeakPointer<LayerItem> m_layerItem; +}; + +} + +#endif // RESIZEMANIPULATOR_H diff --git a/share/qtcreator/qmljsdebugger/editor/resizetool.cpp b/share/qtcreator/qmljsdebugger/editor/resizetool.cpp new file mode 100644 index 00000000000..d5845be6672 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/resizetool.cpp @@ -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 "resizetool.h" +#include "resizehandleitem.h" +#include "qdeclarativedesignview.h" + +#include <QApplication> +#include <QGraphicsSceneMouseEvent> +#include <QAction> +#include <QKeyEvent> +#include <QGraphicsObject> +#include <QWheelEvent> + +#include <QtDebug> + +namespace QmlViewer { + +ResizeTool::ResizeTool(QDeclarativeDesignView *view) + : AbstractFormEditorTool(view), + m_selectionIndicator(view->manipulatorLayer()), + m_resizeManipulator(new ResizeManipulator(view->manipulatorLayer(), view)), + m_resizeIndicator(view->manipulatorLayer()) +{ +} + + +ResizeTool::~ResizeTool() +{ + delete m_resizeManipulator; +} + +void ResizeTool::mousePressEvent(QMouseEvent *event) +{ + QList<QGraphicsItem*> itemList = view()->items(event->pos()); + + if (itemList.isEmpty()) + return; + + ResizeHandleItem *resizeHandle = ResizeHandleItem::fromGraphicsItem(itemList.first()); + + if (resizeHandle) + qDebug() << resizeHandle->resizeController(); + + if (resizeHandle + && resizeHandle->resizeController() + && resizeHandle->resizeController()->isValid()) + { + m_resizeManipulator->setHandle(resizeHandle); + m_resizeManipulator->begin(view()->mapToScene(event->pos())); + m_resizeIndicator.hide(); + } else { + view()->setCursor(Qt::ArrowCursor); + } +} + +void ResizeTool::mouseMoveEvent(QMouseEvent *event) +{ + + bool shouldSnapping = false; //view()->widget()->snappingAction()->isChecked(); + bool shouldSnappingAndAnchoring = false; //view()->widget()->snappingAndAnchoringAction()->isChecked(); + + ResizeManipulator::Snapping useSnapping = ResizeManipulator::NoSnapping; + if (event->modifiers().testFlag(Qt::ControlModifier) != (shouldSnapping || shouldSnappingAndAnchoring)) { + if (shouldSnappingAndAnchoring) + useSnapping = ResizeManipulator::UseSnappingAndAnchoring; + else + useSnapping = ResizeManipulator::UseSnapping; + } + m_resizeManipulator->update(view()->mapToScene(event->pos()), useSnapping); +} + +void ResizeTool::hoverMoveEvent(QMouseEvent *event) +{ + QList<QGraphicsItem*> itemList = view()->items(event->pos()); + + if (itemList.isEmpty()) + return; + + ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(itemList.first()); + if (resizeHandle && resizeHandle->resizeController()->isValid()) { + m_resizeManipulator->setHandle(resizeHandle); + } else { + qDebug() << "resize -> selection tool"; + view()->changeTool(Constants::SelectionToolMode); + return; + } +} + +void ResizeTool::mouseReleaseEvent(QMouseEvent *event) +{ + QList<QGraphicsItem*> itemList = view()->selectableItems(event->pos()); + if (itemList.isEmpty()) + return; + + view()->setCursor(Qt::ArrowCursor); + m_selectionIndicator.show(); + m_resizeIndicator.show(); + m_resizeManipulator->end(); +} + +void ResizeTool::mouseDoubleClickEvent(QMouseEvent * /*event*/) +{ +} + +void ResizeTool::keyPressEvent(QKeyEvent * event) +{ + switch(event->key()) { + case Qt::Key_Shift: + case Qt::Key_Alt: + case Qt::Key_Control: + case Qt::Key_AltGr: + event->setAccepted(false); + return; + } + + double moveStep = 1.0; + + if (event->modifiers().testFlag(Qt::ShiftModifier)) + moveStep = 10.0; + +// switch(event->key()) { +// case Qt::Key_Left: m_resizeManipulator->moveBy(-moveStep, 0.0); break; +// case Qt::Key_Right: m_resizeManipulator->moveBy(moveStep, 0.0); break; +// case Qt::Key_Up: m_resizeManipulator->moveBy(0.0, -moveStep); break; +// case Qt::Key_Down: m_resizeManipulator->moveBy(0.0, moveStep); break; +// } + +} + +void ResizeTool::keyReleaseEvent(QKeyEvent * keyEvent) +{ + switch(keyEvent->key()) { + case Qt::Key_Shift: + case Qt::Key_Alt: + case Qt::Key_Control: + case Qt::Key_AltGr: + keyEvent->setAccepted(false); + return; + } + + if (!keyEvent->isAutoRepeat()) + m_resizeManipulator->clear(); +} + +void ResizeTool::wheelEvent(QWheelEvent */*event*/) +{ + +} + +void ResizeTool::itemsAboutToRemoved(const QList<QGraphicsItem*> & /*itemList*/) +{ + +} + +void ResizeTool::selectedItemsChanged(const QList<QGraphicsItem*> & itemList) +{ + m_selectionIndicator.setItems(toGraphicsObjectList(itemList)); + + m_resizeIndicator.setItems(toGraphicsObjectList(itemList)); +} + +void ResizeTool::clear() +{ + view()->clearHighlightBoundingRect(); + view()->setCursor(Qt::ArrowCursor); + m_selectionIndicator.clear(); + m_resizeIndicator.clear(); + m_resizeManipulator->clear(); +} + +void ResizeTool::graphicsObjectsChanged(const QList<QGraphicsObject*> &itemList) +{ + m_selectionIndicator.updateItems(itemList); + m_resizeIndicator.updateItems(itemList); +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/resizetool.h b/share/qtcreator/qmljsdebugger/editor/resizetool.h new file mode 100644 index 00000000000..250441a4e5c --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/resizetool.h @@ -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 RESIZETOOL_H +#define RESIZETOOL_H + +#include <QMouseEvent> +#include <QKeyEvent> +#include <QDeclarativeItem> + +#include "resizeindicator.h" + +#include "resizemanipulator.h" +#include "abstractformeditortool.h" +#include "selectionindicator.h" + +#include "resizeindicator.h" + +namespace QmlViewer { + +class QDeclarativeDesignView; + +class ResizeTool : public AbstractFormEditorTool +{ +public: + ResizeTool(QDeclarativeDesignView *view); + ~ResizeTool(); + + bool isActive() const; + + 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 selectedItemsChanged(const QList<QGraphicsItem*> &itemList); + + void clear(); + void graphicsObjectsChanged(const QList<QGraphicsObject*> &itemList); + +private: + SelectionIndicator m_selectionIndicator; + ResizeManipulator *m_resizeManipulator; + ResizeIndicator m_resizeIndicator; +}; + +} + +#endif // RESIZETOOL_H diff --git a/share/qtcreator/qmljsdebugger/editor/rubberbandselectionmanipulator.cpp b/share/qtcreator/qmljsdebugger/editor/rubberbandselectionmanipulator.cpp new file mode 100644 index 00000000000..8f24552890d --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/rubberbandselectionmanipulator.cpp @@ -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 "qdeclarativedesignview_p.h" + +#include <QDebug> + +namespace QmlViewer { + +RubberBandSelectionManipulator::RubberBandSelectionManipulator(QGraphicsObject *layerItem, QDeclarativeDesignView *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(QDeclarativeDesignViewPrivate::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 = QDeclarativeDesignViewPrivate::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; + +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/rubberbandselectionmanipulator.h b/share/qtcreator/qmljsdebugger/editor/rubberbandselectionmanipulator.h new file mode 100644 index 00000000000..272d054b650 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/rubberbandselectionmanipulator.h @@ -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 QmlViewer { + +class QDeclarativeDesignView; + +class RubberBandSelectionManipulator +{ +public: + enum SelectionType { + ReplaceSelection, + AddToSelection, + RemoveFromSelection + }; + + + RubberBandSelectionManipulator(QGraphicsObject *layerItem, QDeclarativeDesignView *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; + QDeclarativeDesignView *m_editorView; + QGraphicsItem *m_beginFormEditorItem; + bool m_isActive; +}; + +} + +#endif // RUBBERBANDSELECTIONMANIPULATOR_H diff --git a/share/qtcreator/qmljsdebugger/editor/selectionindicator.cpp b/share/qtcreator/qmljsdebugger/editor/selectionindicator.cpp new file mode 100644 index 00000000000..8b303276b81 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/selectionindicator.cpp @@ -0,0 +1,124 @@ +/************************************************************************** +** +** 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 "qdeclarativedesignview_p.h" +#include "qmlviewerconstants.h" + +#include <QPen> +#include <cmath> +#include <QGraphicsScene> +#include <QDebug> + +namespace QmlViewer { + +SelectionIndicator::SelectionIndicator(QDeclarativeDesignView *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)) + polygon = polygon.united(item->mapToScene(item->boundingRect())); + + foreach(QGraphicsItem *child, item->childItems()) { + if (!QDeclarativeDesignViewPrivate::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 QmlViewer + diff --git a/share/qtcreator/qmljsdebugger/editor/selectionindicator.h b/share/qtcreator/qmljsdebugger/editor/selectionindicator.h new file mode 100644 index 00000000000..9880111c6bd --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/selectionindicator.h @@ -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 QmlViewer { + +class QDeclarativeDesignView; + +class SelectionIndicator +{ +public: + SelectionIndicator(QDeclarativeDesignView* 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; + QDeclarativeDesignView *m_view; + +}; + +} + +#endif // SELECTIONINDICATOR_H diff --git a/share/qtcreator/qmljsdebugger/editor/selectionrectangle.cpp b/share/qtcreator/qmljsdebugger/editor/selectionrectangle.cpp new file mode 100644 index 00000000000..832a2d4ba21 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/selectionrectangle.cpp @@ -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 "qmlviewerconstants.h" + +#include <QPen> +#include <QGraphicsScene> +#include <QtDebug> +#include <cmath> +#include <QGraphicsScene> + +namespace QmlViewer { + +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); +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/selectionrectangle.h b/share/qtcreator/qmljsdebugger/editor/selectionrectangle.h new file mode 100644 index 00000000000..3301a95793b --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/selectionrectangle.h @@ -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 QmlViewer { + +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 diff --git a/share/qtcreator/qmljsdebugger/editor/selectiontool.cpp b/share/qtcreator/qmljsdebugger/editor/selectiontool.cpp new file mode 100644 index 00000000000..e64301414ac --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/selectiontool.cpp @@ -0,0 +1,445 @@ +/************************************************************************** +** +** 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 "qdeclarativedesignview_p.h" + +#include <QDeclarativeEngine> + +#include <QApplication> +#include <QWheelEvent> +#include <QMouseEvent> +#include <QClipboard> +#include <QMenu> +#include <QAction> +#include <QDeclarativeItem> +#include <QGraphicsObject> + +#include <QDebug> + +namespace QmlViewer { + +SelectionTool::SelectionTool(QDeclarativeDesignView *editorView) + : AbstractFormEditorTool(editorView), + m_rubberbandSelectionMode(false), + m_rubberbandSelectionManipulator(QDeclarativeDesignViewPrivate::get(editorView)->manipulatorLayer, editorView), + m_singleSelectionManipulator(editorView), + m_selectionIndicator(editorView, QDeclarativeDesignViewPrivate::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 = QDeclarativeDesignViewPrivate::get(view())->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 = QDeclarativeDesignViewPrivate::get(view())->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()) { + QDeclarativeDesignViewPrivate::get(view())->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()) { + view()->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 (!QDeclarativeDesignViewPrivate::get(view())->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 (view()->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); + m_singleSelectionManipulator.begin(updatePt); + m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection, + QList<QGraphicsItem*>() << m_contextMenuItemList.at(itemListIndex), + false); + m_singleSelectionManipulator.end(updatePt); + } +} + +void SelectionTool::contextMenuElementHovered(QAction *action) +{ + int itemListIndex = action->data().toInt(); + if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) { + QGraphicsObject *item = m_contextMenuItemList.at(itemListIndex)->toGraphicsObject(); + QDeclarativeDesignViewPrivate::get(view())->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 = QDeclarativeDesignViewPrivate::get(view())->selectableItems(event->pos()); + if (!selectableItemList.isEmpty()) { + QGraphicsObject *item = selectableItemList.first()->toGraphicsObject(); + if (item) + QDeclarativeDesignViewPrivate::get(view())->highlight(item); + + return; + } + + QDeclarativeDesignViewPrivate::get(view())->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 = QDeclarativeDesignViewPrivate::get(view())->selectableItems(event->pos()); + + int selectedIdx = 0; + if (!view()->selectedItems().isEmpty()) { + selectedIdx = itemList.indexOf(view()->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()); +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/selectiontool.h b/share/qtcreator/qmljsdebugger/editor/selectiontool.h new file mode 100644 index 00000000000..9fa6e8825e2 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/selectiontool.h @@ -0,0 +1,111 @@ +/************************************************************************** +** +** 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 "movemanipulator.h" +#include "rubberbandselectionmanipulator.h" +#include "singleselectionmanipulator.h" +#include "selectionindicator.h" +#include "resizeindicator.h" + +#include <QHash> +#include <QList> +#include <QTime> + +QT_FORWARD_DECLARE_CLASS(QGraphicsItem); +QT_FORWARD_DECLARE_CLASS(QMouseEvent); +QT_FORWARD_DECLARE_CLASS(QKeyEvent); + +namespace QmlViewer { + +class SelectionTool : public AbstractFormEditorTool +{ + Q_OBJECT + +public: + SelectionTool(QDeclarativeDesignView* 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 diff --git a/share/qtcreator/qmljsdebugger/editor/singleselectionmanipulator.cpp b/share/qtcreator/qmljsdebugger/editor/singleselectionmanipulator.cpp new file mode 100644 index 00000000000..3c5fed7cca3 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/singleselectionmanipulator.cpp @@ -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 "qdeclarativedesignview.h" +#include "qdeclarativedesignview_p.h" +#include <QtDebug> + +namespace QmlViewer { + +SingleSelectionManipulator::SingleSelectionManipulator(QDeclarativeDesignView *editorView) + : m_editorView(editorView), + m_isActive(false) +{ +} + + +void SingleSelectionManipulator::begin(const QPointF &beginPoint) +{ + m_beginPoint = beginPoint; + m_isActive = true; + m_oldSelectionList = QDeclarativeDesignViewPrivate::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 = QDeclarativeDesignViewPrivate::get(m_editorView)->selectableItems(m_beginPoint); + select(selectionType, itemList, selectOnlyContentItems); +} + + +bool SingleSelectionManipulator::isActive() const +{ + return m_isActive; +} + +QPointF SingleSelectionManipulator::beginPoint() const +{ + return m_beginPoint; +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/singleselectionmanipulator.h b/share/qtcreator/qmljsdebugger/editor/singleselectionmanipulator.h new file mode 100644 index 00000000000..04f339640fc --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/singleselectionmanipulator.h @@ -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 QmlViewer { + +class QDeclarativeDesignView; + +class SingleSelectionManipulator +{ +public: + SingleSelectionManipulator(QDeclarativeDesignView *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; + QDeclarativeDesignView *m_editorView; + bool m_isActive; +}; + +} + +#endif // SINGLESELECTIONMANIPULATOR_H diff --git a/share/qtcreator/qmljsdebugger/editor/snappinglinecreator.cpp b/share/qtcreator/qmljsdebugger/editor/snappinglinecreator.cpp new file mode 100644 index 00000000000..4a0e3498376 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/snappinglinecreator.cpp @@ -0,0 +1,188 @@ +/************************************************************************** +** +** 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 "snappinglinecreator.h" + +#include <QGraphicsItem> +#include "formeditoritem.h" + +namespace QmlDesigner { + +SnappingLineCreator::SnappingLineCreator(FormEditorItem *formEditorItem) + : m_formEditorItem(formEditorItem), + m_topOffset(formEditorItem->formEditorView()->spacing()), + m_bottomOffset(formEditorItem->formEditorView()->spacing()), + m_leftOffset(formEditorItem->formEditorView()->spacing()), + m_rightOffset(formEditorItem->formEditorView()->spacing()), + m_topMargin(formEditorItem->formEditorView()->margins()), + m_bottomMargin(formEditorItem->formEditorView()->margins()), + m_leftMargin(formEditorItem->formEditorView()->margins()), + m_rightMargin(formEditorItem->formEditorView()->margins()) +{ + Q_ASSERT(m_formEditorItem); +} + +void SnappingLineCreator::clearLines() +{ + m_topLineMap.clear(); + m_bottomLineMap.clear(); + m_leftLineMap.clear(); + m_rightLineMap.clear(); + m_horizontalCenterLineMap.clear(); + m_verticalCenterLineMap.clear(); + + m_topOffsetMap.clear(); + m_bottomOffsetMap.clear(); + m_leftOffsetMap.clear(); + m_rightOffsetMap.clear(); + +} + +void SnappingLineCreator::addLines(const QRectF &rectInSceneSpace, FormEditorItem *item) +{ + m_topLineMap.insert(rectInSceneSpace.top(), qMakePair(rectInSceneSpace, item)); + m_bottomLineMap.insert(rectInSceneSpace.bottom(), qMakePair(rectInSceneSpace, item)); + m_leftLineMap.insert(rectInSceneSpace.left(), qMakePair(rectInSceneSpace, item)); + m_rightLineMap.insert(rectInSceneSpace.right(), qMakePair(rectInSceneSpace, item)); + QPointF centerPoint(rectInSceneSpace.center()); + m_horizontalCenterLineMap.insert(centerPoint.y(), qMakePair(rectInSceneSpace, item)); + m_verticalCenterLineMap.insert(centerPoint.x(), qMakePair(rectInSceneSpace, item)); +} + +void SnappingLineCreator::addOffsets(const QRectF &rectInSceneSpace, FormEditorItem *item) +{ + m_topOffsetMap.insert(rectInSceneSpace.top() - m_topOffset, qMakePair(rectInSceneSpace, item)); + m_bottomOffsetMap.insert(rectInSceneSpace.bottom() + m_bottomOffset, qMakePair(rectInSceneSpace, item)); + m_leftOffsetMap.insert(rectInSceneSpace.left() - m_leftOffset, qMakePair(rectInSceneSpace, item)); + m_rightOffsetMap.insert(rectInSceneSpace.right() + m_rightOffset, qMakePair(rectInSceneSpace, item)); +} + +void SnappingLineCreator::generateLines(const QList<FormEditorItem*> &exceptionList, + FormEditorItem *transformationSpaceItem) +{ + Q_ASSERT(transformationSpaceItem); + { + QRectF containerBoundingRectInTransformationSpace = m_formEditorItem->mapRectToItem(transformationSpaceItem, + m_formEditorItem->qmlItemNode().instanceBoundingRect()); + + addLines(containerBoundingRectInTransformationSpace, m_formEditorItem); + containerBoundingRectInTransformationSpace.adjust(m_leftMargin, m_topMargin, -m_rightMargin, -m_rightMargin); + addLines(containerBoundingRectInTransformationSpace, m_formEditorItem); + } + + foreach (FormEditorItem *item, m_formEditorItem->childFormEditorItems()) { + if (exceptionList.contains(item)) + continue; + QRectF boundingRectInContainerSpace; + + boundingRectInContainerSpace = item->mapRectToItem(transformationSpaceItem, item->qmlItemNode().instanceBoundingRect()); + + boundingRectInContainerSpace = boundingRectInContainerSpace.toRect(); // round to integer + + addLines(boundingRectInContainerSpace, item); + addOffsets(boundingRectInContainerSpace, item); + } +} + +void SnappingLineCreator::setMargins(double margin) +{ + m_topMargin = margin; + m_bottomMargin = margin; + m_leftMargin = margin; + m_rightMargin = margin; +} + +void SnappingLineCreator::setSpacing(double spacing) +{ + m_topOffset = spacing; + m_bottomOffset = spacing; + m_leftOffset = spacing; + m_rightOffset = spacing; +} + +void SnappingLineCreator::update(const QList<FormEditorItem*> &exceptionList, + FormEditorItem *transformationSpaceItem) +{ + clearLines(); + setMargins(m_formEditorItem->formEditorView()->margins()); + setSpacing(m_formEditorItem->formEditorView()->spacing()); + generateLines(exceptionList, transformationSpaceItem); +} + +SnapLineMap SnappingLineCreator::topLines() const +{ + return m_topLineMap; +} + +SnapLineMap SnappingLineCreator::bottomLines() const +{ + return m_bottomLineMap; +} + +SnapLineMap SnappingLineCreator::leftLines() const +{ + return m_leftLineMap; +} + +SnapLineMap SnappingLineCreator::rightLines() const +{ + return m_rightLineMap; +} + +SnapLineMap SnappingLineCreator::horizontalCenterLines() const +{ + return m_horizontalCenterLineMap; +} + +SnapLineMap SnappingLineCreator::verticalCenterLines() const +{ + return m_verticalCenterLineMap; +} + +SnapLineMap SnappingLineCreator::topOffsets() const +{ + return m_topOffsetMap; +} + +SnapLineMap SnappingLineCreator::bottomOffsets() const +{ + return m_bottomOffsetMap; +} + +SnapLineMap SnappingLineCreator::leftOffsets() const +{ + return m_leftOffsetMap; +} + +SnapLineMap SnappingLineCreator::rightOffsets() const +{ + return m_rightOffsetMap; +} + +} diff --git a/share/qtcreator/qmljsdebugger/editor/snappinglinecreator.h b/share/qtcreator/qmljsdebugger/editor/snappinglinecreator.h new file mode 100644 index 00000000000..dd4f38eeeed --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/snappinglinecreator.h @@ -0,0 +1,102 @@ +/************************************************************************** +** +** 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 SNAPPINGLINECREATOR_H +#define SNAPPINGLINECREATOR_H + +#include "layeritem.h" +#include <QPair> + +namespace QmlDesigner { + +class FormEditorItem; + +typedef QMultiMap<double, QPair<QRectF, FormEditorItem*> > SnapLineMap; +typedef QMapIterator<double, QPair<QRectF, FormEditorItem*> > SnapLineMapIterator; + +class FormEditorItem; + +class SnappingLineCreator +{ +public: + SnappingLineCreator(FormEditorItem *formEditorItem); + + void update(const QList<FormEditorItem*> &exceptionList, + FormEditorItem *transformationSpaceItem); + + + SnapLineMap topLines() const; + SnapLineMap bottomLines() const; + SnapLineMap leftLines() const; + SnapLineMap rightLines() const; + SnapLineMap horizontalCenterLines() const; + SnapLineMap verticalCenterLines() const; + + SnapLineMap topOffsets() const; + SnapLineMap bottomOffsets() const; + SnapLineMap leftOffsets() const; + SnapLineMap rightOffsets() const; + + void setMargins(double margin); + void setSpacing(double spacing); + +protected: + void addLines(const QRectF &rectInSceneSpace, FormEditorItem *item); + void addOffsets(const QRectF &rectInSceneSpace, FormEditorItem *item); + + void clearLines(); + void generateLines(const QList<FormEditorItem*> &exceptionList, + FormEditorItem *transformationSpaceItem); + +private: + SnapLineMap m_topLineMap; + SnapLineMap m_bottomLineMap; + SnapLineMap m_leftLineMap; + SnapLineMap m_rightLineMap; + SnapLineMap m_horizontalCenterLineMap; + SnapLineMap m_verticalCenterLineMap; + + SnapLineMap m_topOffsetMap; + SnapLineMap m_bottomOffsetMap; + SnapLineMap m_leftOffsetMap; + SnapLineMap m_rightOffsetMap; + + FormEditorItem *m_formEditorItem; + double m_topOffset; + double m_bottomOffset; + double m_leftOffset; + double m_rightOffset; + double m_topMargin; + double m_bottomMargin; + double m_leftMargin; + double m_rightMargin; +}; + +} +#endif // SNAPPINGLINECREATOR_H diff --git a/share/qtcreator/qmljsdebugger/editor/subcomponenteditortool.cpp b/share/qtcreator/qmljsdebugger/editor/subcomponenteditortool.cpp new file mode 100644 index 00000000000..2bd96c80efd --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/subcomponenteditortool.cpp @@ -0,0 +1,320 @@ +#include "subcomponenteditortool.h" +#include "qdeclarativedesignview_p.h" +#include "subcomponentmasklayeritem.h" +#include "layeritem.h" + +#include <QGraphicsItem> +#include <QGraphicsObject> +#include <QTimer> +#include <QMouseEvent> +#include <QKeyEvent> + +#include <QDebug> + + +namespace QmlViewer { + +const qreal MaxOpacity = 0.5f; + +SubcomponentEditorTool::SubcomponentEditorTool(QDeclarativeDesignView *view) + : AbstractFormEditorTool(view), + m_animIncrement(0.05f), + m_animTimer(new QTimer(this)) +{ + m_mask = new SubcomponentMaskLayerItem(view, QDeclarativeDesignViewPrivate::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) { + QDeclarativeDesignViewPrivate::get(view())->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(); + + QDeclarativeDesignViewPrivate::get(view())->clearHighlight(); + view()->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 QmlViewer diff --git a/share/qtcreator/qmljsdebugger/editor/subcomponenteditortool.h b/share/qtcreator/qmljsdebugger/editor/subcomponenteditortool.h new file mode 100644 index 00000000000..d54b6a71dc0 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/subcomponenteditortool.h @@ -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 QmlViewer { + +class SubcomponentMaskLayerItem; + +class SubcomponentEditorTool : public AbstractFormEditorTool +{ + Q_OBJECT + +public: + SubcomponentEditorTool(QDeclarativeDesignView *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 QmlViewer + +#endif // SUBCOMPONENTEDITORTOOL_H diff --git a/share/qtcreator/qmljsdebugger/editor/subcomponentmasklayeritem.cpp b/share/qtcreator/qmljsdebugger/editor/subcomponentmasklayeritem.cpp new file mode 100644 index 00000000000..ce1b4371319 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/subcomponentmasklayeritem.cpp @@ -0,0 +1,80 @@ +#include "subcomponentmasklayeritem.h" +#include "qmlviewerconstants.h" +#include "qdeclarativedesignview.h" +#include <QPolygonF> + +namespace QmlViewer { + +SubcomponentMaskLayerItem::SubcomponentMaskLayerItem(QDeclarativeDesignView *view, QGraphicsItem *parentItem) : + QGraphicsPolygonItem(parentItem), + m_view(view), + 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_view->rect())); + viewPoly = m_view->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 QmlViewer diff --git a/share/qtcreator/qmljsdebugger/editor/subcomponentmasklayeritem.h b/share/qtcreator/qmljsdebugger/editor/subcomponentmasklayeritem.h new file mode 100644 index 00000000000..9a646364612 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/subcomponentmasklayeritem.h @@ -0,0 +1,29 @@ +#ifndef SUBCOMPONENTMASKLAYERITEM_H +#define SUBCOMPONENTMASKLAYERITEM_H + +#include <QGraphicsPolygonItem> + +namespace QmlViewer { + +class QDeclarativeDesignView; + +class SubcomponentMaskLayerItem : public QGraphicsPolygonItem +{ +public: + explicit SubcomponentMaskLayerItem(QDeclarativeDesignView *view, QGraphicsItem *parentItem = 0); + int type() const; + void setCurrentItem(QGraphicsItem *item); + void setBoundingBox(const QRectF &boundingBox); + QGraphicsItem *currentItem() const; + QRectF itemRect() const; + +private: + QDeclarativeDesignView *m_view; + QGraphicsItem *m_currentItem; + QGraphicsRectItem *m_borderRect; + QRectF m_itemPolyRect; +}; + +} // namespace QmlViewer + +#endif // SUBCOMPONENTMASKLAYERITEM_H diff --git a/share/qtcreator/qmljsdebugger/editor/toolbarcolorbox.cpp b/share/qtcreator/qmljsdebugger/editor/toolbarcolorbox.cpp new file mode 100644 index 00000000000..e72f7084268 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/toolbarcolorbox.cpp @@ -0,0 +1,96 @@ +#include "toolbarcolorbox.h" +#include "qmlviewerconstants.h" + +#include <QPixmap> +#include <QPainter> +#include <QMenu> +#include <QAction> +#include <QContextMenuEvent> +#include <QClipboard> +#include <QApplication> +#include <QColorDialog> +#include <QDrag> +#include <QMimeData> + +#include <QDebug> + +namespace QmlViewer { + +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 QmlViewer diff --git a/share/qtcreator/qmljsdebugger/editor/toolbarcolorbox.h b/share/qtcreator/qmljsdebugger/editor/toolbarcolorbox.h new file mode 100644 index 00000000000..f3d3afea697 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/toolbarcolorbox.h @@ -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 QmlViewer { + +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 QmlViewer + +#endif // ToolBarColorBox_H diff --git a/share/qtcreator/qmljsdebugger/editor/zoomtool.cpp b/share/qtcreator/qmljsdebugger/editor/zoomtool.cpp new file mode 100644 index 00000000000..05937eafc2c --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/zoomtool.cpp @@ -0,0 +1,287 @@ +#include "zoomtool.h" +#include "qdeclarativedesignview_p.h" + +#include <QMouseEvent> +#include <QWheelEvent> +#include <QKeyEvent> +#include <QRectF> +#include <QMenu> +#include <QAction> + +#include <QDebug> + +namespace QmlViewer { + +ZoomTool::ZoomTool(QDeclarativeDesignView *view) : + AbstractFormEditorTool(view), + m_rubberbandManipulator(reinterpret_cast<QGraphicsObject *>(QDeclarativeDesignViewPrivate::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 ¢erPos) +{ + + 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 QmlViewer diff --git a/share/qtcreator/qmljsdebugger/editor/zoomtool.h b/share/qtcreator/qmljsdebugger/editor/zoomtool.h new file mode 100644 index 00000000000..f3774efa11c --- /dev/null +++ b/share/qtcreator/qmljsdebugger/editor/zoomtool.h @@ -0,0 +1,65 @@ +#ifndef ZOOMTOOL_H +#define ZOOMTOOL_H + +#include "abstractformeditortool.h" +#include "rubberbandselectionmanipulator.h" + +QT_FORWARD_DECLARE_CLASS(QAction); + +namespace QmlViewer { + +class ZoomTool : public AbstractFormEditorTool +{ + Q_OBJECT +public: + enum ZoomDirection { + ZoomIn, + ZoomOut + }; + + explicit ZoomTool(QDeclarativeDesignView *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 ¢erPos); + +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 QmlViewer + +#endif // ZOOMTOOL_H diff --git a/share/qtcreator/qmljsdebugger/include/jsdebuggeragent.h b/share/qtcreator/qmljsdebugger/include/jsdebuggeragent.h new file mode 100644 index 00000000000..d27fea95235 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/include/jsdebuggeragent.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** 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_BEGIN_NAMESPACE + +class JSAgentWatchData; +class QScriptContext; + +class QMLJSDEBUGGER_EXPORT JSDebuggerAgent : public QDeclarativeDebugService , public QScriptEngineAgent +{ Q_OBJECT +public: + JSDebuggerAgent(QScriptEngine *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) +}; + +QT_END_NAMESPACE + +#endif diff --git a/share/qtcreator/qmljsdebugger/include/qdeclarativedesigndebugserver.h b/share/qtcreator/qmljsdebugger/include/qdeclarativedesigndebugserver.h new file mode 100644 index 00000000000..53a554949a6 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/include/qdeclarativedesigndebugserver.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** 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 "qmlviewerconstants.h" +#include "qmljsdebugger_global.h" + +#include <QHash> + +QT_BEGIN_NAMESPACE + +class QColor; +class QDeclarativeEngine; +class QDeclarativeContext; +class QDeclarativeWatcher; +class QDataStream; + +class QMLJSDEBUGGER_EXPORT QDeclarativeDesignDebugServer : public QDeclarativeDebugService +{ + Q_OBJECT +public: + QDeclarativeDesignDebugServer(QObject *parent = 0); + + void setDesignModeBehavior(bool inDesignMode); + void setCurrentObjects(QList<QObject*> items); + void setAnimationSpeed(qreal slowdownFactor); + void setCurrentTool(QmlViewer::Constants::DesignTool toolId); + void reloaded(); + QString idStringForObject(QObject *obj) const; + +public Q_SLOTS: + void selectedColorChanged(const QColor &color); + void contextPathUpdated(const QStringList &contextPath); + void sceneItemCountChanged(); + +Q_SIGNALS: + 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()); + + // 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 messageReceived(const QByteArray &); + +private: + QHash<int, QString> m_stringIdForObjectId; + +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVEDESIGNDEBUGSERVER_H diff --git a/share/qtcreator/qmljsdebugger/include/qdeclarativedesignview.h b/share/qtcreator/qmljsdebugger/include/qdeclarativedesignview.h new file mode 100644 index 00000000000..7b8241e242b --- /dev/null +++ b/share/qtcreator/qmljsdebugger/include/qdeclarativedesignview.h @@ -0,0 +1,124 @@ +/************************************************************************** +** +** 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_H +#define QDECLARATIVEDESIGNVIEW_H + +#include "qmljsdebugger_global.h" +#include "qmlviewerconstants.h" +#include <qdeclarativeview.h> +#include <QWeakPointer> + +QT_FORWARD_DECLARE_CLASS(QDeclarativeItem); +QT_FORWARD_DECLARE_CLASS(QMouseEvent); +QT_FORWARD_DECLARE_CLASS(QToolBar); + +namespace QmlViewer { + +class CrumblePath; +class QDeclarativeDesignViewPrivate; + +class QMLJSDEBUGGER_EXPORT QDeclarativeDesignView : public QDeclarativeView +{ + Q_OBJECT +public: + + explicit QDeclarativeDesignView(QWidget *parent = 0); + ~QDeclarativeDesignView(); + + void setSelectedItems(QList<QGraphicsItem *> items); + QList<QGraphicsItem *> selectedItems(); + + QToolBar *toolbar() const; + static QString idStringForObject(QObject *obj); + QRectF adjustToScreenBoundaries(const QRectF &boundingRectInSceneSpace); + +public Q_SLOTS: + void setDesignModeBehavior(bool value); + bool designModeBehavior(); + + void changeAnimationSpeed(qreal slowdownFactor); + void continueExecution(qreal slowdownFactor = 1.0f); + void pauseExecution(); + + void setInspectorContext(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: + void leaveEvent(QEvent *); + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *keyEvent); + void mouseDoubleClickEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + + void setSelectedItemsForTools(QList<QGraphicsItem *> items); + +private: + Q_DISABLE_COPY(QDeclarativeDesignView) + 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_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()); + Q_PRIVATE_SLOT(d_func(), void _q_sceneChanged(const QList<QRectF> &areas)); + Q_PRIVATE_SLOT(d_func(), void _q_checkSceneItemCount()); + + inline QDeclarativeDesignViewPrivate *d_func() { return data.data(); } + QScopedPointer<QDeclarativeDesignViewPrivate> data; + friend class QDeclarativeDesignViewPrivate; + +}; + +} //namespace QmlViewer + +#endif // QDECLARATIVEDESIGNVIEW_H diff --git a/share/qtcreator/qmljsdebugger/include/qmljsdebugger_global.h b/share/qtcreator/qmljsdebugger/include/qmljsdebugger_global.h new file mode 100644 index 00000000000..6aba5be4262 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/include/qmljsdebugger_global.h @@ -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 diff --git a/share/qtcreator/qmljsdebugger/include/qmlviewerconstants.h b/share/qtcreator/qmljsdebugger/include/qmlviewerconstants.h new file mode 100644 index 00000000000..4cf90e19eee --- /dev/null +++ b/share/qtcreator/qmljsdebugger/include/qmlviewerconstants.h @@ -0,0 +1,39 @@ +#ifndef QMLVIEWERCONSTANTS_H +#define QMLVIEWERCONSTANTS_H + +namespace QmlViewer { +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 QmlViewer + +#endif // QMLVIEWERCONSTANTS_H diff --git a/share/qtcreator/qmljsdebugger/jsdebuggeragent.cpp b/share/qtcreator/qmljsdebugger/jsdebuggeragent.cpp new file mode 100644 index 00000000000..b94b0a81292 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/jsdebuggeragent.cpp @@ -0,0 +1,509 @@ +/**************************************************************************** +** +** 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> + +QT_BEGIN_NAMESPACE + +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) +{} + +/*! + 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); +// qDebug() << Q_FUNC_INFO << exception.toString() << hasHandler; + if (!hasHandler && state != Stopped) + stopped(true, exception); +} + +/*! + \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); + QDeclarativeDebugService::enabledChanged(on); +} + +QT_END_NAMESPACE diff --git a/share/qtcreator/qmljsdebugger/qdeclarativedesigndebugserver.cpp b/share/qtcreator/qmljsdebugger/qdeclarativedesigndebugserver.cpp new file mode 100644 index 00000000000..9bb3546ee87 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/qdeclarativedesigndebugserver.cpp @@ -0,0 +1,188 @@ +#include "qdeclarativedesigndebugserver.h" + +#include <QStringList> +#include <QColor> + +#include <QDebug> + +QDeclarativeDesignDebugServer::QDeclarativeDesignDebugServer(QObject *parent) + : QDeclarativeDebugService(QLatin1String("QDeclarativeDesignMode"), parent) +{ +} + +void QDeclarativeDesignDebugServer::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 == "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 QDeclarativeDesignDebugServer::setDesignModeBehavior(bool inDesignMode) +{ + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("SET_DESIGN_MODE") + << inDesignMode; + + sendMessage(message); +} + +void QDeclarativeDesignDebugServer::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 QDeclarativeDesignDebugServer::setCurrentTool(QmlViewer::Constants::DesignTool toolId) +{ + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("TOOL_CHANGED") + << toolId; + + sendMessage(message); +} + +void QDeclarativeDesignDebugServer::setAnimationSpeed(qreal slowdownFactor) +{ + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("ANIMATION_SPEED_CHANGED") + << slowdownFactor; + + sendMessage(message); +} + +void QDeclarativeDesignDebugServer::reloaded() +{ + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("RELOADED"); + + sendMessage(message); +} + +void QDeclarativeDesignDebugServer::selectedColorChanged(const QColor &color) +{ + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("COLOR_CHANGED") + << color; + + sendMessage(message); +} + +void QDeclarativeDesignDebugServer::contextPathUpdated(const QStringList &contextPath) +{ + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("CONTEXT_PATH_UPDATED") + << contextPath; + + sendMessage(message); +} + +void QDeclarativeDesignDebugServer::sceneItemCountChanged() +{ + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("SCENE_ITEM_COUNT_CHANGED"); + + sendMessage(message); +} + +QString QDeclarativeDesignDebugServer::idStringForObject(QObject *obj) const +{ + int id = idForObject(obj); + QString idString = m_stringIdForObjectId.value(id, QString()); + return idString; +} diff --git a/share/qtcreator/qmljsdebugger/qdeclarativedesignview.cpp b/share/qtcreator/qmljsdebugger/qdeclarativedesignview.cpp new file mode 100644 index 00000000000..5335ca38ed1 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/qdeclarativedesignview.cpp @@ -0,0 +1,776 @@ +/************************************************************************** +** +** 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 "qdeclarativedesignview.h" +#include "qdeclarativedesignview_p.h" +#include "qdeclarativedesigndebugserver.h" +#include "selectiontool.h" +#include "zoomtool.h" +#include "colorpickertool.h" +#include "layeritem.h" +#include "boundingrecthighlighter.h" +#include "subcomponenteditortool.h" +#include "qmltoolbar.h" + +#include <QDeclarativeItem> +#include <QDeclarativeEngine> +#include <QDeclarativeContext> +#include <QDeclarativeExpression> +#include <QWidget> +#include <QMouseEvent> +#include <QGraphicsObject> +#include <QApplication> + +#include <QAbstractAnimation> +#include <private/qabstractanimation_p.h> + +namespace QmlViewer { + +const int SceneChangeUpdateInterval = 5000; +const int MaxSceneChangedTimerRestartCount = 15; + +Q_GLOBAL_STATIC(QDeclarativeDesignDebugServer, qmlDesignDebugServer) + +QDeclarativeDesignViewPrivate::QDeclarativeDesignViewPrivate(QDeclarativeDesignView *q) : + q(q), + designModeBehavior(false), + executionPaused(false), + slowdownFactor(1.0f), + toolbar(0), + sceneChangedTimerRestartCount(0) +{ + sceneChangedTimer.setInterval(SceneChangeUpdateInterval); + sceneChangedTimer.setSingleShot(true); +} + +QDeclarativeDesignViewPrivate::~QDeclarativeDesignViewPrivate() +{ +} + +QDeclarativeDesignView::QDeclarativeDesignView(QWidget *parent) : + QDeclarativeView(parent), data(new QDeclarativeDesignViewPrivate(this)) +{ + data->manipulatorLayer = new LayerItem(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; + + connect(scene(), SIGNAL(changed(QList<QRectF>)), SLOT(_q_sceneChanged(QList<QRectF>))); + setMouseTracking(true); + + connect(qmlDesignDebugServer(), SIGNAL(designModeBehaviorChanged(bool)), SLOT(setDesignModeBehavior(bool))); + connect(qmlDesignDebugServer(), SIGNAL(reloadRequested()), SLOT(_q_reloadView())); + connect(qmlDesignDebugServer(), + SIGNAL(currentObjectsChanged(QList<QObject*>)), + SLOT(_q_onCurrentObjectsChanged(QList<QObject*>))); + connect(qmlDesignDebugServer(), SIGNAL(animationSpeedChangeRequested(qreal)), SLOT(changeAnimationSpeed(qreal))); + connect(qmlDesignDebugServer(), SIGNAL(colorPickerToolRequested()), SLOT(_q_changeToColorPickerTool())); + connect(qmlDesignDebugServer(), SIGNAL(selectMarqueeToolRequested()), SLOT(_q_changeToMarqueeSelectTool())); + connect(qmlDesignDebugServer(), SIGNAL(selectToolRequested()), SLOT(_q_changeToSingleSelectTool())); + connect(qmlDesignDebugServer(), SIGNAL(zoomToolRequested()), SLOT(_q_changeToZoomTool())); + connect(qmlDesignDebugServer(), + SIGNAL(objectCreationRequested(QString,QObject*,QStringList,QString)), + SLOT(_q_createQmlObject(QString,QObject*,QStringList,QString))); + connect(qmlDesignDebugServer(), SIGNAL(contextPathIndexChanged(int)), SLOT(_q_changeContextPathIndex(int))); + connect(qmlDesignDebugServer(), SIGNAL(clearComponentCacheRequested()), SLOT(_q_clearComponentCache())); + connect(this, SIGNAL(statusChanged(QDeclarativeView::Status)), SLOT(_q_onStatusChanged(QDeclarativeView::Status))); + + connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)), SIGNAL(selectedColorChanged(QColor))); + connect(data->colorPickerTool, SIGNAL(selectedColorChanged(QColor)), + qmlDesignDebugServer(), 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)), qmlDesignDebugServer(), SLOT(contextPathUpdated(QStringList))); + + connect(&(data->sceneChangedTimer), SIGNAL(timeout()), SLOT(_q_checkSceneItemCount())); + + data->createToolbar(); + + data->_q_changeToSingleSelectTool(); +} + +QDeclarativeDesignView::~QDeclarativeDesignView() +{ +} + +void QDeclarativeDesignView::setInspectorContext(int contextIndex) +{ + if (data->subcomponentEditorTool->contextIndex() != contextIndex) { + QGraphicsObject *object = data->subcomponentEditorTool->setContext(contextIndex); + if (object) + qmlDesignDebugServer()->setCurrentObjects(QList<QObject*>() << object); + } +} + +void QDeclarativeDesignViewPrivate::_q_reloadView() +{ + subcomponentEditorTool->clear(); + clearHighlight(); + emit q->reloadRequested(); +} + +void QDeclarativeDesignViewPrivate::clearEditorItems() +{ + clearHighlight(); + setSelectedItems(QList<QGraphicsItem*>()); +} + +void QDeclarativeDesignView::leaveEvent(QEvent *event) +{ + if (!data->designModeBehavior) { + QDeclarativeView::leaveEvent(event); + return; + } + data->clearHighlight(); +} + +void QDeclarativeDesignView::mousePressEvent(QMouseEvent *event) +{ + if (!data->designModeBehavior) { + QDeclarativeView::mousePressEvent(event); + return; + } + data->cursorPos = event->pos(); + data->currentTool->mousePressEvent(event); +} + +void QDeclarativeDesignView::mouseMoveEvent(QMouseEvent *event) +{ + if (!data->designModeBehavior) { + data->clearEditorItems(); + QDeclarativeView::mouseMoveEvent(event); + return; + } + data->cursorPos = event->pos(); + + QList<QGraphicsItem*> selItems = data->selectableItems(event->pos()); + if (!selItems.isEmpty()) { + setToolTip(AbstractFormEditorTool::titleForItem(selItems.first())); + } else { + setToolTip(QString()); + } + if (event->buttons()) { + data->subcomponentEditorTool->mouseMoveEvent(event); + data->currentTool->mouseMoveEvent(event); + } else { + data->subcomponentEditorTool->hoverMoveEvent(event); + data->currentTool->hoverMoveEvent(event); + } +} + +void QDeclarativeDesignView::mouseReleaseEvent(QMouseEvent *event) +{ + if (!data->designModeBehavior) { + QDeclarativeView::mouseReleaseEvent(event); + return; + } + data->subcomponentEditorTool->mouseReleaseEvent(event); + + data->cursorPos = event->pos(); + data->currentTool->mouseReleaseEvent(event); + + qmlDesignDebugServer()->setCurrentObjects(AbstractFormEditorTool::toObjectList(selectedItems())); +} + +void QDeclarativeDesignView::keyPressEvent(QKeyEvent *event) +{ + if (!data->designModeBehavior) { + QDeclarativeView::keyPressEvent(event); + return; + } + data->currentTool->keyPressEvent(event); +} + +void QDeclarativeDesignView::keyReleaseEvent(QKeyEvent *event) +{ + if (!data->designModeBehavior) { + QDeclarativeView::keyReleaseEvent(event); + return; + } + + switch(event->key()) { + case Qt::Key_V: + data->_q_changeToSingleSelectTool(); + break; + 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); +} + +void QDeclarativeDesignViewPrivate::_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 = q->engine()->contextForObject(parent); + QDeclarativeComponent component(q->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 QDeclarativeDesignViewPrivate::_q_clearComponentCache() +{ + q->engine()->clearComponentCache(); +} + +QGraphicsItem *QDeclarativeDesignViewPrivate::currentRootItem() const +{ + return subcomponentEditorTool->currentRootItem(); +} + +void QDeclarativeDesignView::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (!data->designModeBehavior) { + QDeclarativeView::mouseDoubleClickEvent(event); + return; + } + + if (data->currentToolMode != Constants::SelectionToolMode + && data->currentToolMode != Constants::MarqueeSelectionToolMode) + { + return; + } + + QGraphicsItem *itemToEnter = 0; + QList<QGraphicsItem*> itemList = 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) + qmlDesignDebugServer()->setCurrentObjects(QList<QObject*>() << objectToEnter); + } + +} +void QDeclarativeDesignView::wheelEvent(QWheelEvent *event) +{ + if (!data->designModeBehavior) { + QDeclarativeView::wheelEvent(event); + return; + } + data->currentTool->wheelEvent(event); +} + +void QDeclarativeDesignView::setDesignModeBehavior(bool value) +{ + emit designModeBehaviorChanged(value); + + data->toolbar->setDesignModeBehavior(value); + qmlDesignDebugServer()->setDesignModeBehavior(value); + + data->designModeBehavior = value; + if (data->subcomponentEditorTool) { + data->subcomponentEditorTool->clear(); + data->clearHighlight(); + data->setSelectedItems(QList<QGraphicsItem*>()); + + if (rootObject()) + data->subcomponentEditorTool->pushContext(rootObject()); + } + + if (!data->designModeBehavior) + data->clearEditorItems(); +} + +bool QDeclarativeDesignView::designModeBehavior() +{ + return data->designModeBehavior; +} + +void QDeclarativeDesignViewPrivate::changeTool(Constants::DesignTool tool, Constants::ToolFlags /*flags*/) +{ + switch(tool) { + case Constants::SelectionToolMode: + _q_changeToSingleSelectTool(); + break; + case Constants::NoTool: + default: + currentTool = 0; + break; + } +} + +void QDeclarativeDesignViewPrivate::setSelectedItemsForTools(QList<QGraphicsItem *> items) +{ + currentSelection.clear(); + foreach(QGraphicsItem *item, items) { + if (item) { + QGraphicsObject *obj = item->toGraphicsObject(); + if (obj) + currentSelection << obj; + } + } + currentTool->updateSelectedItems(); +} + +void QDeclarativeDesignViewPrivate::setSelectedItems(QList<QGraphicsItem *> items) +{ + setSelectedItemsForTools(items); + qmlDesignDebugServer()->setCurrentObjects(AbstractFormEditorTool::toObjectList(items)); +} + +QList<QGraphicsItem *> QDeclarativeDesignViewPrivate::selectedItems() +{ + QList<QGraphicsItem *> selection; + foreach(const QWeakPointer<QGraphicsObject> &selectedObject, currentSelection) { + if (selectedObject.isNull()) { + currentSelection.removeOne(selectedObject); + } else { + selection << selectedObject.data(); + } + } + + return selection; +} + +void QDeclarativeDesignView::setSelectedItems(QList<QGraphicsItem *> items) +{ + data->setSelectedItems(items); +} + +QList<QGraphicsItem *> QDeclarativeDesignView::selectedItems() +{ + return data->selectedItems(); +} + +void QDeclarativeDesignViewPrivate::clearHighlight() +{ + boundingRectHighlighter->clear(); +} + +void QDeclarativeDesignViewPrivate::highlight(QGraphicsObject * item, ContextFlags flags) +{ + highlight(QList<QGraphicsObject*>() << item, flags); +} + +void QDeclarativeDesignViewPrivate::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 QDeclarativeDesignViewPrivate::mouseInsideContextItem() const +{ + return subcomponentEditorTool->containsCursor(cursorPos.toPoint()); +} + +QList<QGraphicsItem*> QDeclarativeDesignViewPrivate::selectableItems(const QPointF &scenePos) const +{ + QList<QGraphicsItem*> itemlist = q->scene()->items(scenePos); + return filterForCurrentContext(itemlist); +} + +QList<QGraphicsItem*> QDeclarativeDesignViewPrivate::selectableItems(const QPoint &pos) const +{ + QList<QGraphicsItem*> itemlist = q->items(pos); + return filterForCurrentContext(itemlist); +} + +QList<QGraphicsItem*> QDeclarativeDesignViewPrivate::selectableItems(const QRectF &sceneRect, Qt::ItemSelectionMode selectionMode) const +{ + QList<QGraphicsItem*> itemlist = q->scene()->items(sceneRect, selectionMode); + + return filterForCurrentContext(itemlist); +} + +void QDeclarativeDesignViewPrivate::_q_changeToSingleSelectTool() +{ + currentToolMode = Constants::SelectionToolMode; + selectionTool->setRubberbandSelectionMode(false); + + changeToSelectTool(); + + emit q->selectToolActivated(); + qmlDesignDebugServer()->setCurrentTool(Constants::SelectionToolMode); +} + +void QDeclarativeDesignViewPrivate::changeToSelectTool() +{ + if (currentTool == selectionTool) + return; + + currentTool->clear(); + currentTool = selectionTool; + currentTool->clear(); + currentTool->updateSelectedItems(); +} + +void QDeclarativeDesignViewPrivate::_q_changeToMarqueeSelectTool() +{ + changeToSelectTool(); + currentToolMode = Constants::MarqueeSelectionToolMode; + selectionTool->setRubberbandSelectionMode(true); + + emit q->marqueeSelectToolActivated(); + qmlDesignDebugServer()->setCurrentTool(Constants::MarqueeSelectionToolMode); +} + +void QDeclarativeDesignViewPrivate::_q_changeToZoomTool() +{ + currentToolMode = Constants::ZoomMode; + currentTool->clear(); + currentTool = zoomTool; + currentTool->clear(); + + emit q->zoomToolActivated(); + qmlDesignDebugServer()->setCurrentTool(Constants::ZoomMode); +} + +void QDeclarativeDesignViewPrivate::_q_changeToColorPickerTool() +{ + if (currentTool == colorPickerTool) + return; + + currentToolMode = Constants::ColorPickerMode; + currentTool->clear(); + currentTool = colorPickerTool; + currentTool->clear(); + + emit q->colorPickerActivated(); + qmlDesignDebugServer()->setCurrentTool(Constants::ColorPickerMode); +} + +void QDeclarativeDesignViewPrivate::_q_changeContextPathIndex(int index) +{ + subcomponentEditorTool->setContext(index); +} + +void QDeclarativeDesignViewPrivate::_q_sceneChanged(const QList<QRectF> & /*areas*/) +{ + if (designModeBehavior) + return; + + sceneChangedTimerRestartCount++; + if (sceneChangedTimerRestartCount == MaxSceneChangedTimerRestartCount) { + _q_checkSceneItemCount(); + } + + sceneChangedTimer.start(); +} + +void QDeclarativeDesignViewPrivate::_q_checkSceneItemCount() +{ + bool hasNewItems = hasNewGraphicsObjects(q->rootObject()); + sceneChangedTimerRestartCount = 0; + + if (hasNewItems) { + qmlDesignDebugServer()->sceneItemCountChanged(); + } +} + +static bool hasNewGraphicsObjectsRecur(QGraphicsObject *object, + QSet<QGraphicsObject *> &newItems, + const QSet<QGraphicsObject *> &previousItems) +{ + bool hasNew = false; + + newItems << object; + + foreach(QGraphicsItem *item, object->childItems()) { + QGraphicsObject *gfxObject = item->toGraphicsObject(); + if (gfxObject) { + newItems << gfxObject; + + hasNew = hasNewGraphicsObjectsRecur(gfxObject, newItems, previousItems) || hasNew; + if (!previousItems.contains(gfxObject)) + hasNew = true; + } + } + + return hasNew; +} + +bool QDeclarativeDesignViewPrivate::hasNewGraphicsObjects(QGraphicsObject *object) +{ + QSet<QGraphicsObject *> newItems; + bool ret = hasNewGraphicsObjectsRecur(object, newItems, sceneGraphicsObjects); + sceneGraphicsObjects = newItems; + + return ret; +} + +void QDeclarativeDesignView::changeAnimationSpeed(qreal slowdownFactor) +{ + data->slowdownFactor = slowdownFactor; + + if (data->slowdownFactor != 0) { + continueExecution(data->slowdownFactor); + } else { + pauseExecution(); + } +} + +void QDeclarativeDesignView::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); + qmlDesignDebugServer()->setAnimationSpeed(data->slowdownFactor); +} + +void QDeclarativeDesignView::pauseExecution() +{ + QUnifiedTimer *timer = QUnifiedTimer::instance(); + timer->setSlowdownFactor(0); + timer->setSlowModeEnabled(true); + data->executionPaused = true; + + emit executionPaused(); + qmlDesignDebugServer()->setAnimationSpeed(0); +} + +void QDeclarativeDesignViewPrivate::_q_applyChangesFromClient() +{ + +} + + +QList<QGraphicsItem*> QDeclarativeDesignViewPrivate::filterForSelection(QList<QGraphicsItem*> &itemlist) const +{ + foreach(QGraphicsItem *item, itemlist) { + if (isEditorItem(item) || !subcomponentEditorTool->isChildOfContext(item)) + itemlist.removeOne(item); + } + + return itemlist; +} + +QList<QGraphicsItem*> QDeclarativeDesignViewPrivate::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 QDeclarativeDesignViewPrivate::isEditorItem(QGraphicsItem *item) const +{ + return (item->type() == Constants::EditorItemType + || item->type() == Constants::ResizeHandleItemType + || item->data(Constants::EditorItemDataKey).toBool()); +} + +void QDeclarativeDesignViewPrivate::_q_onStatusChanged(QDeclarativeView::Status status) +{ + if (status == QDeclarativeView::Ready) { + if (q->rootObject()) { + sceneChangedTimerRestartCount = 0; + hasNewGraphicsObjects(q->rootObject()); + if (subcomponentEditorTool->contextIndex() != -1) + subcomponentEditorTool->clear(); + subcomponentEditorTool->pushContext(q->rootObject()); + emit q->executionStarted(1.0f); + + } + qmlDesignDebugServer()->reloaded(); + } +} + +void QDeclarativeDesignViewPrivate::_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, QDeclarativeDesignViewPrivate::IgnoreContext); +} + +QString QDeclarativeDesignView::idStringForObject(QObject *obj) +{ + return qmlDesignDebugServer()->idStringForObject(obj); +} + +// adjusts bounding boxes on edges of screen to be visible +QRectF QDeclarativeDesignView::adjustToScreenBoundaries(const QRectF &boundingRectInSceneSpace) +{ + int marginFromEdge = 1; + QRectF boundingRect(boundingRectInSceneSpace); + if (qAbs(boundingRect.left()) - 1 < 2) { + boundingRect.setLeft(marginFromEdge); + } + + 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 *QDeclarativeDesignView::toolbar() const +{ + return data->toolbar; +} + +void QDeclarativeDesignViewPrivate::createToolbar() +{ + toolbar = new QmlToolbar(q); + 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(executionStarted()), q, SLOT(continueExecution())); + QObject::connect(toolbar, SIGNAL(executionPaused()), q, SLOT(pauseExecution())); + 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(startExecution())); + QObject::connect(q, SIGNAL(executionPaused()), toolbar, SLOT(pauseExecution())); + + 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())); +} + +} //namespace QmlViewer + +#include <moc_qdeclarativedesignview.cpp> diff --git a/share/qtcreator/qmljsdebugger/qdeclarativedesignview_p.h b/share/qtcreator/qmljsdebugger/qdeclarativedesignview_p.h new file mode 100644 index 00000000000..6791f236fdf --- /dev/null +++ b/share/qtcreator/qmljsdebugger/qdeclarativedesignview_p.h @@ -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 "qdeclarativedesignview.h" + +namespace QmlViewer { + +class QDeclarativeDesignView; +class SelectionTool; +class ZoomTool; +class ColorPickerTool; +class LayerItem; +class BoundingRectHighlighter; +class SubcomponentEditorTool; +class QmlToolbar; +class CrumblePath; +class AbstractFormEditorTool; + +class QDeclarativeDesignViewPrivate +{ + +public: + + enum ContextFlags { + IgnoreContext, + ContextSensitive + }; + + QDeclarativeDesignViewPrivate(QDeclarativeDesignView *); + ~QDeclarativeDesignViewPrivate(); + + QDeclarativeDesignView *q; + 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; + + QmlToolbar *toolbar; + int sceneChangedTimerRestartCount; + QTimer sceneChangedTimer; + QSet<QGraphicsObject *> sceneGraphicsObjects; + + 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; + + bool hasNewGraphicsObjects(QGraphicsObject *object); + + 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 _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_changeToSingleSelectTool(); + void _q_changeToMarqueeSelectTool(); + void _q_changeToZoomTool(); + void _q_changeToColorPickerTool(); + void _q_changeContextPathIndex(int index); + void _q_clearComponentCache(); + void _q_sceneChanged(const QList<QRectF> &areas); + void _q_changeDebugObjectCount(int objectCount); + void _q_checkSceneItemCount(); + + static QDeclarativeDesignViewPrivate *get(QDeclarativeDesignView *v) { return v->d_func(); } +}; + +} // namespace QmlViewer + +#endif // QDECLARATIVEDESIGNVIEW_P_H diff --git a/share/qtcreator/qmljsdebugger/qmljsdebugger-lib.pri b/share/qtcreator/qmljsdebugger/qmljsdebugger-lib.pri new file mode 100644 index 00000000000..7421f0e9ec5 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/qmljsdebugger-lib.pri @@ -0,0 +1,31 @@ +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 +} + +## Once is not enough +include($$PWD/../../../src/private_headers.pri) +include($$PWD/../../../src/private_headers.pri) + +include($$PWD/editor/editor.pri) + +## Input +HEADERS += \ + include/jsdebuggeragent.h \ + include/qdeclarativedesignview.h \ + include/qdeclarativedesigndebugserver.h \ + include/qmlviewerconstants.h \ + include/qmljsdebugger_global.h \ + qdeclarativedesignview_p.h + +SOURCES += \ + jsdebuggeragent.cpp \ + qdeclarativedesignview.cpp \ + qdeclarativedesigndebugserver.cpp + +OTHER_FILES += qmljsdebugger.pri diff --git a/share/qtcreator/qmljsdebugger/qmljsdebugger.pri b/share/qtcreator/qmljsdebugger/qmljsdebugger.pri new file mode 100644 index 00000000000..34483da17d9 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/qmljsdebugger.pri @@ -0,0 +1,5 @@ +INCLUDEPATH += $$PWD/include +DEPENDPATH += $$PWD $$PWD/include $$PWD/editor +QT += declarative script + +LIBS *= -l$$qtLibraryName(QmlJSDebugger) diff --git a/share/qtcreator/qmljsdebugger/qmljsdebugger.pro b/share/qtcreator/qmljsdebugger/qmljsdebugger.pro new file mode 100644 index 00000000000..457644a2a53 --- /dev/null +++ b/share/qtcreator/qmljsdebugger/qmljsdebugger.pro @@ -0,0 +1,8 @@ +TEMPLATE = lib +CONFIG+=dll +TARGET = QmlJSDebugger + +unix:QMAKE_CXXFLAGS_DEBUG += -O3 + +include(../../../src/qtcreatorlibrary.pri) +include(qmljsdebugger-lib.pri) diff --git a/share/qtcreator/templates/qmlapp/app.pro b/share/qtcreator/templates/qmlapp/app.pro index 5a7b728ff43..ac891471866 100644 --- a/share/qtcreator/templates/qmlapp/app.pro +++ b/share/qtcreator/templates/qmlapp/app.pro @@ -19,15 +19,20 @@ OTHER_FILES = qml/app/app.qml # TARGETUID3 # symbian:TARGET.UID3 = 0xE1111234 - - +# QMLJSINSPECTOR # +#DEFINES += Q_QML_JS_INSPECTOR +contains(DEFINES, Q_QML_JS_INSPECTOR) { +# QMLJSINSPECTOR_LIB_PATH # +INSPECTOR_LIBRARY_PATH = $$PWD/../../../../share/qtcreator/qmljsdebugger +include($$INSPECTOR_LIBRARY_PATH/qmljsdebugger-lib.pri) +} # Edit the code below on your own risk. QT += declarative -SOURCES = cpp/main.cpp cpp/qmlapplicationview.cpp -HEADERS = cpp/qmlapplicationview.h +SOURCES += cpp/main.cpp cpp/qmlapplicationview.cpp +HEADERS += cpp/qmlapplicationview.h INCLUDEPATH += cpp symbian { diff --git a/share/qtcreator/templates/qmlapp/cpp/qmlapplicationview.cpp b/share/qtcreator/templates/qmlapp/cpp/qmlapplicationview.cpp index 2d0f505acc3..30a7fcb455e 100644 --- a/share/qtcreator/templates/qmlapp/cpp/qmlapplicationview.cpp +++ b/share/qtcreator/templates/qmlapp/cpp/qmlapplicationview.cpp @@ -20,8 +20,12 @@ class QmlApplicationViewPrivate friend class QmlApplicationView; }; -QmlApplicationView::QmlApplicationView(const QString &mainQmlFile, QWidget *parent) - : QDeclarativeView(parent) +QmlApplicationView::QmlApplicationView(const QString &mainQmlFile, QWidget *parent) : +#ifdef Q_QML_JS_INSPECTOR + QmlViewer::QDeclarativeDesignView(parent) +#else + QDeclarativeView(parent) +#endif , m_d(new QmlApplicationViewPrivate) { #ifdef Q_OS_MAC diff --git a/share/qtcreator/templates/qmlapp/cpp/qmlapplicationview.h b/share/qtcreator/templates/qmlapp/cpp/qmlapplicationview.h index 0b8b998f975..ef608830f4b 100644 --- a/share/qtcreator/templates/qmlapp/cpp/qmlapplicationview.h +++ b/share/qtcreator/templates/qmlapp/cpp/qmlapplicationview.h @@ -3,7 +3,12 @@ #include <QtDeclarative/QDeclarativeView> +#ifdef Q_QML_JS_INSPECTOR +#include <qdeclarativedesignview.h> +class QmlApplicationView : public QmlViewer::QDeclarativeDesignView +#else class QmlApplicationView : public QDeclarativeView +#endif { public: enum Orientation { diff --git a/share/share.pro b/share/share.pro index bbf224f2042..ef05076c144 100644 --- a/share/share.pro +++ b/share/share.pro @@ -1,2 +1,4 @@ TEMPLATE = subdirs -SUBDIRS = qtcreator/static.pro qtcreator/translations +SUBDIRS = qtcreator/static.pro \ + qtcreator/translations \ + qtcreator/qmljsdebugger |