1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "subcomponenteditortool.h"
35 #include "../qdeclarativeviewobserver_p.h"
36 #include "subcomponentmasklayeritem.h"
37 #include "layeritem.h"
39 #include <QGraphicsItem>
40 #include <QGraphicsObject>
42 #include <QMouseEvent>
48 namespace QmlJSDebugger {
50 const qreal MaxOpacity = 0.5f;
52 SubcomponentEditorTool::SubcomponentEditorTool(QDeclarativeViewObserver *view)
53 : AbstractFormEditorTool(view),
54 m_animIncrement(0.05f),
55 m_animTimer(new QTimer(this))
57 QDeclarativeViewObserverPrivate *observerPrivate =
58 QDeclarativeViewObserverPrivate::get(view);
59 m_mask = new SubcomponentMaskLayerItem(view, observerPrivate->manipulatorLayer);
60 connect(m_animTimer, SIGNAL(timeout()), SLOT(animate()));
61 m_animTimer->setInterval(20);
64 SubcomponentEditorTool::~SubcomponentEditorTool()
69 void SubcomponentEditorTool::mousePressEvent(QMouseEvent * /*event*/)
74 void SubcomponentEditorTool::mouseMoveEvent(QMouseEvent * /*event*/)
79 bool SubcomponentEditorTool::containsCursor(const QPoint &mousePos) const
81 if (!m_currentContext.size())
84 QPointF scenePos = view()->mapToScene(mousePos);
85 QRectF itemRect = m_currentContext.top()->boundingRect()
86 | m_currentContext.top()->childrenBoundingRect();
87 QRectF polyRect = m_currentContext.top()->mapToScene(itemRect).boundingRect();
89 return polyRect.contains(scenePos);
92 void SubcomponentEditorTool::mouseReleaseEvent(QMouseEvent * /*event*/)
97 void SubcomponentEditorTool::mouseDoubleClickEvent(QMouseEvent *event)
99 if (event->buttons() & Qt::LeftButton
100 && !containsCursor(event->pos())
101 && m_currentContext.size() > 1)
107 void SubcomponentEditorTool::hoverMoveEvent(QMouseEvent *event)
109 if (!containsCursor(event->pos()) && m_currentContext.size() > 1) {
110 QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
114 void SubcomponentEditorTool::wheelEvent(QWheelEvent * /*event*/)
119 void SubcomponentEditorTool::keyPressEvent(QKeyEvent * /*event*/)
124 void SubcomponentEditorTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
129 void SubcomponentEditorTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
134 void SubcomponentEditorTool::animate()
136 if (m_animIncrement > 0) {
137 if (m_mask->opacity() + m_animIncrement < MaxOpacity) {
138 m_mask->setOpacity(m_mask->opacity() + m_animIncrement);
141 m_mask->setOpacity(MaxOpacity);
144 if (m_mask->opacity() + m_animIncrement > 0) {
145 m_mask->setOpacity(m_mask->opacity() + m_animIncrement);
148 m_mask->setOpacity(0);
150 emit contextPathChanged(m_path);
156 void SubcomponentEditorTool::clear()
158 m_currentContext.clear();
159 m_mask->setCurrentItem(0);
164 emit contextPathChanged(m_path);
168 void SubcomponentEditorTool::selectedItemsChanged(const QList<QGraphicsItem*> &/*itemList*/)
173 void SubcomponentEditorTool::setCurrentItem(QGraphicsItem* contextItem)
178 QGraphicsObject *gfxObject = contextItem->toGraphicsObject();
182 //QString parentClassName = gfxObject->metaObject()->className();
183 //if (parentClassName.contains(QRegExp("_QMLTYPE_\\d+")))
185 bool containsSelectableItems = false;
186 foreach(QGraphicsItem *item, gfxObject->childItems()) {
187 if (item->type() == Constants::EditorItemType
188 || item->type() == Constants::ResizeHandleItemType)
192 containsSelectableItems = true;
196 if (containsSelectableItems) {
197 m_mask->setCurrentItem(gfxObject);
198 m_mask->setOpacity(0);
200 m_animIncrement = 0.05f;
201 m_animTimer->start();
203 QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
204 observer()->setSelectedItems(QList<QGraphicsItem*>());
206 pushContext(gfxObject);
210 QGraphicsItem *SubcomponentEditorTool::firstChildOfContext(QGraphicsItem *item) const
215 if (isDirectChildOfContext(item))
218 QGraphicsItem *parent = item->parentItem();
220 if (isDirectChildOfContext(parent))
222 parent = parent->parentItem();
228 bool SubcomponentEditorTool::isChildOfContext(QGraphicsItem *item) const
230 return (firstChildOfContext(item) != 0);
233 bool SubcomponentEditorTool::isDirectChildOfContext(QGraphicsItem *item) const
235 return (item->parentItem() == m_currentContext.top());
238 bool SubcomponentEditorTool::itemIsChildOfQmlSubComponent(QGraphicsItem *item) const
240 if (item->parentItem() && item->parentItem() != m_currentContext.top()) {
241 QGraphicsObject *parent = item->parentItem()->toGraphicsObject();
242 QString parentClassName = parent->metaObject()->className();
244 if (parentClassName.contains(QRegExp("_QMLTYPE_\\d+"))) {
247 return itemIsChildOfQmlSubComponent(parent);
254 void SubcomponentEditorTool::pushContext(QGraphicsObject *contextItem)
256 connect(contextItem, SIGNAL(destroyed(QObject*)), this, SLOT(contextDestroyed(QObject*)));
257 connect(contextItem, SIGNAL(xChanged()), this, SLOT(resizeMask()));
258 connect(contextItem, SIGNAL(yChanged()), this, SLOT(resizeMask()));
259 connect(contextItem, SIGNAL(widthChanged()), this, SLOT(resizeMask()));
260 connect(contextItem, SIGNAL(heightChanged()), this, SLOT(resizeMask()));
261 connect(contextItem, SIGNAL(rotationChanged()), this, SLOT(resizeMask()));
263 m_currentContext.push(contextItem);
264 QString title = titleForItem(contextItem);
265 emit contextPushed(title);
268 emit contextPathChanged(m_path);
271 void SubcomponentEditorTool::aboutToPopContext()
273 if (m_currentContext.size() > 2) {
275 emit contextPathChanged(m_path);
277 m_animIncrement = -0.05f;
278 m_animTimer->start();
282 QGraphicsObject *SubcomponentEditorTool::popContext()
284 QGraphicsObject *popped = m_currentContext.pop();
287 emit contextPopped();
289 disconnect(popped, SIGNAL(xChanged()), this, SLOT(resizeMask()));
290 disconnect(popped, SIGNAL(yChanged()), this, SLOT(resizeMask()));
291 disconnect(popped, SIGNAL(scaleChanged()), this, SLOT(resizeMask()));
292 disconnect(popped, SIGNAL(widthChanged()), this, SLOT(resizeMask()));
293 disconnect(popped, SIGNAL(heightChanged()), this, SLOT(resizeMask()));
295 if (m_currentContext.size() > 1) {
296 QGraphicsObject *item = m_currentContext.top();
297 m_mask->setCurrentItem(item);
298 m_mask->setOpacity(MaxOpacity);
299 m_mask->setVisible(true);
301 m_mask->setVisible(false);
307 void SubcomponentEditorTool::resizeMask()
309 QGraphicsObject *item = m_currentContext.top();
310 m_mask->setCurrentItem(item);
313 QGraphicsObject *SubcomponentEditorTool::currentRootItem() const
315 return m_currentContext.top();
318 void SubcomponentEditorTool::contextDestroyed(QObject *contextToDestroy)
320 disconnect(contextToDestroy, SIGNAL(destroyed(QObject*)),
321 this, SLOT(contextDestroyed(QObject*)));
323 // pop out the whole context - it might not be safe anymore.
324 while (m_currentContext.size() > 1) {
325 m_currentContext.pop();
327 emit contextPopped();
329 m_mask->setVisible(false);
331 emit contextPathChanged(m_path);
334 QGraphicsObject *SubcomponentEditorTool::setContext(int contextIndex)
336 Q_ASSERT(contextIndex >= 0);
338 // sometimes we have to delete the context while user was still clicking around,
340 if (contextIndex >= m_currentContext.size() -1)
343 while (m_currentContext.size() - 1 > contextIndex) {
346 emit contextPathChanged(m_path);
348 return m_currentContext.top();
351 int SubcomponentEditorTool::contextIndex() const
353 return m_currentContext.size() - 1;
356 } // namespace QmlJSDebugger