forked from qt-creator/qt-creator
		
	The library not only contains the observer part, but also the javascript debugger. Reflect this in the namespace.
		
			
				
	
	
		
			321 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			321 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "subcomponenteditortool.h"
 | |
| #include "qdeclarativeviewobserver_p.h"
 | |
| #include "subcomponentmasklayeritem.h"
 | |
| #include "layeritem.h"
 | |
| 
 | |
| #include <QGraphicsItem>
 | |
| #include <QGraphicsObject>
 | |
| #include <QTimer>
 | |
| #include <QMouseEvent>
 | |
| #include <QKeyEvent>
 | |
| 
 | |
| #include <QDebug>
 | |
| 
 | |
| 
 | |
| namespace QmlJSDebugger {
 | |
| 
 | |
| const qreal MaxOpacity = 0.5f;
 | |
| 
 | |
| SubcomponentEditorTool::SubcomponentEditorTool(QDeclarativeViewObserver *view)
 | |
|     : AbstractFormEditorTool(view),
 | |
|     m_animIncrement(0.05f),
 | |
|     m_animTimer(new QTimer(this))
 | |
| {
 | |
|     m_mask = new SubcomponentMaskLayerItem(view, QDeclarativeViewObserverPrivate::get(view)->manipulatorLayer);
 | |
|     connect(m_animTimer, SIGNAL(timeout()), SLOT(animate()));
 | |
|     m_animTimer->setInterval(20);
 | |
| }
 | |
| 
 | |
| SubcomponentEditorTool::~SubcomponentEditorTool()
 | |
| {
 | |
| 
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::mousePressEvent(QMouseEvent * /*event*/)
 | |
| {
 | |
| 
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::mouseMoveEvent(QMouseEvent * /*event*/)
 | |
| {
 | |
| 
 | |
| }
 | |
| 
 | |
| bool SubcomponentEditorTool::containsCursor(const QPoint &mousePos) const
 | |
| {
 | |
|     if (!m_currentContext.size())
 | |
|         return false;
 | |
| 
 | |
|     QPointF scenePos = view()->mapToScene(mousePos);
 | |
|     QRectF itemRect = m_currentContext.top()->boundingRect() | m_currentContext.top()->childrenBoundingRect();
 | |
|     QRectF polyRect = m_currentContext.top()->mapToScene(itemRect).boundingRect();
 | |
| 
 | |
|     return polyRect.contains(scenePos);
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::mouseReleaseEvent(QMouseEvent * /*event*/)
 | |
| {
 | |
| 
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::mouseDoubleClickEvent(QMouseEvent *event)
 | |
| {
 | |
|     if (event->buttons() & Qt::LeftButton
 | |
|         && !containsCursor(event->pos())
 | |
|         && m_currentContext.size() > 1)
 | |
|     {
 | |
|         aboutToPopContext();
 | |
|     }
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::hoverMoveEvent(QMouseEvent *event)
 | |
| {
 | |
|     if (!containsCursor(event->pos()) && m_currentContext.size() > 1) {
 | |
|         QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
 | |
|     }
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::wheelEvent(QWheelEvent * /*event*/)
 | |
| {
 | |
| 
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::keyPressEvent(QKeyEvent * /*event*/)
 | |
| {
 | |
| 
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
 | |
| {
 | |
| 
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
 | |
| {
 | |
| 
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::animate()
 | |
| {
 | |
|     if (m_animIncrement > 0) {
 | |
|         if (m_mask->opacity() + m_animIncrement < MaxOpacity) {
 | |
|             m_mask->setOpacity(m_mask->opacity() + m_animIncrement);
 | |
|         } else {
 | |
|             m_animTimer->stop();
 | |
|             m_mask->setOpacity(MaxOpacity);
 | |
|         }
 | |
|     } else {
 | |
|         if (m_mask->opacity() + m_animIncrement > 0) {
 | |
|             m_mask->setOpacity(m_mask->opacity() + m_animIncrement);
 | |
|         } else {
 | |
|             m_animTimer->stop();
 | |
|             m_mask->setOpacity(0);
 | |
|             popContext();
 | |
|             emit contextPathChanged(m_path);
 | |
|         }
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::clear()
 | |
| {
 | |
|     m_currentContext.clear();
 | |
|     m_mask->setCurrentItem(0);
 | |
|     m_animTimer->stop();
 | |
|     m_mask->hide();
 | |
|     m_path.clear();
 | |
| 
 | |
|     emit contextPathChanged(m_path);
 | |
|     emit cleared();
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::selectedItemsChanged(const QList<QGraphicsItem*> &/*itemList*/)
 | |
| {
 | |
| 
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::setCurrentItem(QGraphicsItem* contextItem)
 | |
| {
 | |
|     if (!contextItem)
 | |
|         return;
 | |
| 
 | |
|     QGraphicsObject *gfxObject = contextItem->toGraphicsObject();
 | |
|     if (!gfxObject)
 | |
|         return;
 | |
| 
 | |
|     //QString parentClassName = gfxObject->metaObject()->className();
 | |
|     //if (parentClassName.contains(QRegExp("_QMLTYPE_\\d+")))
 | |
| 
 | |
|     bool containsSelectableItems = false;
 | |
|     foreach(QGraphicsItem *item, gfxObject->childItems()) {
 | |
|         if (item->type() == Constants::EditorItemType
 | |
|          || item->type() == Constants::ResizeHandleItemType)
 | |
|         {
 | |
|             continue;
 | |
|         }
 | |
|         containsSelectableItems = true;
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     if (containsSelectableItems) {
 | |
|         m_mask->setCurrentItem(gfxObject);
 | |
|         m_mask->setOpacity(0);
 | |
|         m_mask->show();
 | |
|         m_animIncrement = 0.05f;
 | |
|         m_animTimer->start();
 | |
| 
 | |
|         QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
 | |
|         observer()->setSelectedItems(QList<QGraphicsItem*>());
 | |
| 
 | |
|         pushContext(gfxObject);
 | |
|     }
 | |
| }
 | |
| 
 | |
| QGraphicsItem *SubcomponentEditorTool::firstChildOfContext(QGraphicsItem *item) const
 | |
| {
 | |
|     if (!item)
 | |
|         return 0;
 | |
| 
 | |
|     if (isDirectChildOfContext(item))
 | |
|         return item;
 | |
| 
 | |
|     QGraphicsItem *parent = item->parentItem();
 | |
|     while (parent) {
 | |
|         if (isDirectChildOfContext(parent))
 | |
|             return parent;
 | |
|         parent = parent->parentItem();
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| bool SubcomponentEditorTool::isChildOfContext(QGraphicsItem *item) const
 | |
| {
 | |
|     return (firstChildOfContext(item) != 0);
 | |
| }
 | |
| 
 | |
| bool SubcomponentEditorTool::isDirectChildOfContext(QGraphicsItem *item) const
 | |
| {
 | |
|     return (item->parentItem() == m_currentContext.top());
 | |
| }
 | |
| 
 | |
| bool SubcomponentEditorTool::itemIsChildOfQmlSubComponent(QGraphicsItem *item) const
 | |
| {
 | |
|     if (item->parentItem() && item->parentItem() != m_currentContext.top()) {
 | |
|         QGraphicsObject *parent = item->parentItem()->toGraphicsObject();
 | |
|         QString parentClassName = parent->metaObject()->className();
 | |
| 
 | |
|         if (parentClassName.contains(QRegExp("_QMLTYPE_\\d+"))) {
 | |
|             return true;
 | |
|         } else {
 | |
|             return itemIsChildOfQmlSubComponent(parent);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::pushContext(QGraphicsObject *contextItem)
 | |
| {
 | |
|     connect(contextItem, SIGNAL(destroyed(QObject*)), this, SLOT(contextDestroyed(QObject*)));
 | |
|     connect(contextItem, SIGNAL(xChanged()), this, SLOT(resizeMask()));
 | |
|     connect(contextItem, SIGNAL(yChanged()), this, SLOT(resizeMask()));
 | |
|     connect(contextItem, SIGNAL(widthChanged()), this, SLOT(resizeMask()));
 | |
|     connect(contextItem, SIGNAL(heightChanged()), this, SLOT(resizeMask()));
 | |
|     connect(contextItem, SIGNAL(rotationChanged()), this, SLOT(resizeMask()));
 | |
| 
 | |
|     m_currentContext.push(contextItem);
 | |
|     QString title = titleForItem(contextItem);
 | |
|     emit contextPushed(title);
 | |
| 
 | |
|     m_path << title;
 | |
|     emit contextPathChanged(m_path);
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::aboutToPopContext()
 | |
| {
 | |
|     if (m_currentContext.size() > 2) {
 | |
|         popContext();
 | |
|         emit contextPathChanged(m_path);
 | |
|     } else {
 | |
|         m_animIncrement = -0.05f;
 | |
|         m_animTimer->start();
 | |
|     }
 | |
| }
 | |
| 
 | |
| QGraphicsObject *SubcomponentEditorTool::popContext()
 | |
| {
 | |
|     QGraphicsObject *popped = m_currentContext.pop();
 | |
|     m_path.removeLast();
 | |
| 
 | |
|     emit contextPopped();
 | |
| 
 | |
|     disconnect(popped, SIGNAL(xChanged()), this, SLOT(resizeMask()));
 | |
|     disconnect(popped, SIGNAL(yChanged()), this, SLOT(resizeMask()));
 | |
|     disconnect(popped, SIGNAL(scaleChanged()), this, SLOT(resizeMask()));
 | |
|     disconnect(popped, SIGNAL(widthChanged()), this, SLOT(resizeMask()));
 | |
|     disconnect(popped, SIGNAL(heightChanged()), this, SLOT(resizeMask()));
 | |
| 
 | |
|     if (m_currentContext.size() > 1) {
 | |
|         QGraphicsObject *item = m_currentContext.top();
 | |
|         m_mask->setCurrentItem(item);
 | |
|         m_mask->setOpacity(MaxOpacity);
 | |
|         m_mask->setVisible(true);
 | |
|     } else {
 | |
|         m_mask->setVisible(false);
 | |
|     }
 | |
| 
 | |
|     return popped;
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::resizeMask()
 | |
| {
 | |
|     QGraphicsObject *item = m_currentContext.top();
 | |
|     m_mask->setCurrentItem(item);
 | |
| }
 | |
| 
 | |
| QGraphicsObject *SubcomponentEditorTool::currentRootItem() const
 | |
| {
 | |
|     return m_currentContext.top();
 | |
| }
 | |
| 
 | |
| void SubcomponentEditorTool::contextDestroyed(QObject *contextToDestroy)
 | |
| {
 | |
|     disconnect(contextToDestroy, SIGNAL(destroyed(QObject*)), this, SLOT(contextDestroyed(QObject*)));
 | |
| 
 | |
|     // pop out the whole context - it might not be safe anymore.
 | |
|     while (m_currentContext.size() > 1) {
 | |
|         m_currentContext.pop();
 | |
|         m_path.removeLast();
 | |
|         emit contextPopped();
 | |
|     }
 | |
|     m_mask->setVisible(false);
 | |
| 
 | |
|     emit contextPathChanged(m_path);
 | |
| }
 | |
| 
 | |
| QGraphicsObject *SubcomponentEditorTool::setContext(int contextIndex)
 | |
| {
 | |
|     Q_ASSERT(contextIndex >= 0);
 | |
| 
 | |
|     // sometimes we have to delete the context while user was still clicking around,
 | |
|     // so just bail out.
 | |
|     if (contextIndex >= m_currentContext.size() -1)
 | |
|         return 0;
 | |
| 
 | |
|     while (m_currentContext.size() - 1 > contextIndex) {
 | |
|         popContext();
 | |
|     }
 | |
|     emit contextPathChanged(m_path);
 | |
| 
 | |
|     return m_currentContext.top();
 | |
| }
 | |
| 
 | |
| int SubcomponentEditorTool::contextIndex() const
 | |
| {
 | |
|     return m_currentContext.size() - 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| } // namespace QmlJSDebugger
 |