1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
33 #include "subcomponenteditortool.h"
34 #include "../qdeclarativeviewobserver_p.h"
35 #include "subcomponentmasklayeritem.h"
36 #include "livelayeritem.h"
38 #include <QtGui/QGraphicsItem>
39 #include <QtGui/QGraphicsObject>
40 #include <QtGui/QMouseEvent>
41 #include <QtGui/QKeyEvent>
43 #include <QtCore/QTimer>
44 #include <QtCore/QDebug>
46 namespace QmlJSDebugger {
48 const qreal MaxOpacity = 0.5f;
50 SubcomponentEditorTool::SubcomponentEditorTool(QDeclarativeViewObserver *view)
51 : AbstractLiveEditTool(view),
52 m_animIncrement(0.05f),
53 m_animTimer(new QTimer(this))
55 QDeclarativeViewObserverPrivate *observerPrivate =
56 QDeclarativeViewObserverPrivate::get(view);
57 m_mask = new SubcomponentMaskLayerItem(view, observerPrivate->manipulatorLayer);
58 connect(m_animTimer, SIGNAL(timeout()), SLOT(animate()));
59 m_animTimer->setInterval(20);
62 SubcomponentEditorTool::~SubcomponentEditorTool()
67 void SubcomponentEditorTool::mousePressEvent(QMouseEvent * /*event*/)
72 void SubcomponentEditorTool::mouseMoveEvent(QMouseEvent * /*event*/)
77 bool SubcomponentEditorTool::containsCursor(const QPoint &mousePos) const
79 if (!m_currentContext.size())
82 QPointF scenePos = view()->mapToScene(mousePos);
83 QRectF itemRect = m_currentContext.top()->boundingRect()
84 | m_currentContext.top()->childrenBoundingRect();
85 QRectF polyRect = m_currentContext.top()->mapToScene(itemRect).boundingRect();
87 return polyRect.contains(scenePos);
90 void SubcomponentEditorTool::mouseReleaseEvent(QMouseEvent * /*event*/)
95 void SubcomponentEditorTool::mouseDoubleClickEvent(QMouseEvent *event)
97 if (event->buttons() & Qt::LeftButton
98 && !containsCursor(event->pos())
99 && m_currentContext.size() > 1)
105 void SubcomponentEditorTool::hoverMoveEvent(QMouseEvent *event)
107 if (!containsCursor(event->pos()) && m_currentContext.size() > 1) {
108 QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
112 void SubcomponentEditorTool::wheelEvent(QWheelEvent * /*event*/)
117 void SubcomponentEditorTool::keyPressEvent(QKeyEvent * /*event*/)
122 void SubcomponentEditorTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
127 void SubcomponentEditorTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
132 void SubcomponentEditorTool::animate()
134 if (m_animIncrement > 0) {
135 if (m_mask->opacity() + m_animIncrement < MaxOpacity) {
136 m_mask->setOpacity(m_mask->opacity() + m_animIncrement);
139 m_mask->setOpacity(MaxOpacity);
142 if (m_mask->opacity() + m_animIncrement > 0) {
143 m_mask->setOpacity(m_mask->opacity() + m_animIncrement);
146 m_mask->setOpacity(0);
148 emit contextPathChanged(m_path);
154 void SubcomponentEditorTool::clear()
156 m_currentContext.clear();
157 m_mask->setCurrentItem(0);
162 emit contextPathChanged(m_path);
166 void SubcomponentEditorTool::selectedItemsChanged(const QList<QGraphicsItem*> &/*itemList*/)
171 void SubcomponentEditorTool::setCurrentItem(QGraphicsItem* contextItem)
176 QGraphicsObject *gfxObject = contextItem->toGraphicsObject();
180 //QString parentClassName = gfxObject->metaObject()->className();
181 //if (parentClassName.contains(QRegExp("_QMLTYPE_\\d+")))
183 bool containsSelectableItems = false;
184 foreach (QGraphicsItem *item, gfxObject->childItems()) {
185 if (item->type() == Constants::EditorItemType
186 || item->type() == Constants::ResizeHandleItemType)
190 containsSelectableItems = true;
194 if (containsSelectableItems) {
195 m_mask->setCurrentItem(gfxObject);
196 m_mask->setOpacity(0);
198 m_animIncrement = 0.05f;
199 m_animTimer->start();
201 QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
202 observer()->setSelectedItems(QList<QGraphicsItem*>());
204 pushContext(gfxObject);
208 QGraphicsItem *SubcomponentEditorTool::firstChildOfContext(QGraphicsItem *item) const
213 if (isDirectChildOfContext(item))
216 QGraphicsItem *parent = item->parentItem();
218 if (isDirectChildOfContext(parent))
220 parent = parent->parentItem();
226 bool SubcomponentEditorTool::isChildOfContext(QGraphicsItem *item) const
228 return (firstChildOfContext(item) != 0);
231 bool SubcomponentEditorTool::isDirectChildOfContext(QGraphicsItem *item) const
233 return (item->parentItem() == m_currentContext.top());
236 bool SubcomponentEditorTool::itemIsChildOfQmlSubComponent(QGraphicsItem *item) const
238 if (item->parentItem() && item->parentItem() != m_currentContext.top()) {
239 QGraphicsObject *parent = item->parentItem()->toGraphicsObject();
240 QString parentClassName = parent->metaObject()->className();
242 if (parentClassName.contains(QRegExp("_QMLTYPE_\\d+"))) {
245 return itemIsChildOfQmlSubComponent(parent);
252 void SubcomponentEditorTool::pushContext(QGraphicsObject *contextItem)
254 connect(contextItem, SIGNAL(destroyed(QObject*)), this, SLOT(contextDestroyed(QObject*)));
255 connect(contextItem, SIGNAL(xChanged()), this, SLOT(resizeMask()));
256 connect(contextItem, SIGNAL(yChanged()), this, SLOT(resizeMask()));
257 connect(contextItem, SIGNAL(widthChanged()), this, SLOT(resizeMask()));
258 connect(contextItem, SIGNAL(heightChanged()), this, SLOT(resizeMask()));
259 connect(contextItem, SIGNAL(rotationChanged()), this, SLOT(resizeMask()));
261 m_currentContext.push(contextItem);
262 QString title = titleForItem(contextItem);
263 emit contextPushed(title);
266 emit contextPathChanged(m_path);
269 void SubcomponentEditorTool::aboutToPopContext()
271 if (m_currentContext.size() > 2) {
273 emit contextPathChanged(m_path);
275 m_animIncrement = -0.05f;
276 m_animTimer->start();
280 QGraphicsObject *SubcomponentEditorTool::popContext()
282 QGraphicsObject *popped = m_currentContext.pop();
285 emit contextPopped();
287 disconnect(popped, SIGNAL(xChanged()), this, SLOT(resizeMask()));
288 disconnect(popped, SIGNAL(yChanged()), this, SLOT(resizeMask()));
289 disconnect(popped, SIGNAL(scaleChanged()), this, SLOT(resizeMask()));
290 disconnect(popped, SIGNAL(widthChanged()), this, SLOT(resizeMask()));
291 disconnect(popped, SIGNAL(heightChanged()), this, SLOT(resizeMask()));
293 if (m_currentContext.size() > 1) {
294 QGraphicsObject *item = m_currentContext.top();
295 m_mask->setCurrentItem(item);
296 m_mask->setOpacity(MaxOpacity);
297 m_mask->setVisible(true);
299 m_mask->setVisible(false);
305 void SubcomponentEditorTool::resizeMask()
307 QGraphicsObject *item = m_currentContext.top();
308 m_mask->setCurrentItem(item);
311 QGraphicsObject *SubcomponentEditorTool::currentRootItem() const
313 return m_currentContext.top();
316 void SubcomponentEditorTool::contextDestroyed(QObject *contextToDestroy)
318 disconnect(contextToDestroy, SIGNAL(destroyed(QObject*)),
319 this, SLOT(contextDestroyed(QObject*)));
321 // pop out the whole context - it might not be safe anymore.
322 while (m_currentContext.size() > 1) {
323 m_currentContext.pop();
325 emit contextPopped();
327 m_mask->setVisible(false);
329 emit contextPathChanged(m_path);
332 QGraphicsObject *SubcomponentEditorTool::setContext(int contextIndex)
334 Q_ASSERT(contextIndex >= 0);
336 // sometimes we have to delete the context while user was still clicking around,
338 if (contextIndex >= m_currentContext.size() -1)
341 while (m_currentContext.size() - 1 > contextIndex) {
344 emit contextPathChanged(m_path);
346 return m_currentContext.top();
349 int SubcomponentEditorTool::contextIndex() const
351 return m_currentContext.size() - 1;
354 } // namespace QmlJSDebugger