aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp')
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp427
1 files changed, 427 insertions, 0 deletions
diff --git a/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp
new file mode 100644
index 0000000000..cc6b4ffb8c
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp
@@ -0,0 +1,427 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "inspecttool.h"
+
+#include "highlight.h"
+#include "qquickviewinspector.h"
+
+#include <QtCore/QLineF>
+
+#include <QtGui/QMouseEvent>
+#include <QtGui/QWheelEvent>
+#include <QtGui/QTouchEvent>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QStyleHints>
+
+#include <QtQuick/QQuickView>
+#include <QtQuick/QQuickItem>
+
+QT_BEGIN_NAMESPACE
+
+namespace QmlJSDebugger {
+
+static const double ZoomSnapDelta = 0.04;
+static const int PressAndHoldTimeout = 800;
+
+InspectTool::InspectTool(QQuickViewInspector *inspector, QQuickView *view) :
+ AbstractTool(inspector),
+ m_originalSmooth(view->contentItem()->smooth()),
+ m_dragStarted(false),
+ m_pinchStarted(false),
+ m_didPressAndHold(false),
+ m_tapEvent(false),
+ m_contentItem(view->contentItem()),
+ m_originalPosition(view->contentItem()->position()),
+ m_smoothScaleFactor(ZoomSnapDelta),
+ m_minScale(0.125f),
+ m_maxScale(48.0f),
+ m_originalScale(view->contentItem()->scale()),
+ m_touchTimestamp(0),
+ m_hoverHighlight(new HoverHighlight(inspector->overlay())),
+ m_lastItem(0),
+ m_lastClickedItem(0)
+{
+ //Press and Hold Timer
+ m_pressAndHoldTimer.setSingleShot(true);
+ m_pressAndHoldTimer.setInterval(PressAndHoldTimeout);
+ connect(&m_pressAndHoldTimer, SIGNAL(timeout()), SLOT(zoomTo100()));
+ //Timer to display selected item's name
+ m_nameDisplayTimer.setSingleShot(true);
+ m_nameDisplayTimer.setInterval(QGuiApplication::styleHints()->mouseDoubleClickInterval());
+ connect(&m_nameDisplayTimer, SIGNAL(timeout()), SLOT(showSelectedItemName()));
+ enable(true);
+}
+
+InspectTool::~InspectTool()
+{
+ enable(false);
+}
+
+void InspectTool::enable(bool enable)
+{
+ if (!enable) {
+ inspector()->setSelectedItems(QList<QQuickItem*>());
+ // restoring the original states.
+ if (m_contentItem) {
+ m_contentItem->setScale(m_originalScale);
+ m_contentItem->setPosition(m_originalPosition);
+ m_contentItem->setSmooth(m_originalSmooth);
+ }
+ } else {
+ if (m_contentItem) {
+ m_originalSmooth = m_contentItem->smooth();
+ m_originalScale = m_contentItem->scale();
+ m_originalPosition = m_contentItem->position();
+ m_contentItem->setSmooth(true);
+ }
+ }
+}
+
+void InspectTool::leaveEvent(QEvent *)
+{
+ m_hoverHighlight->setVisible(false);
+}
+
+void InspectTool::mousePressEvent(QMouseEvent *event)
+{
+ m_mousePosition = event->localPos();
+ if (event->button() == Qt::LeftButton) {
+ m_pressAndHoldTimer.start();
+ initializeDrag(event->localPos());
+ }
+}
+
+void InspectTool::mouseReleaseEvent(QMouseEvent *event)
+{
+ m_mousePosition = event->localPos();
+ m_pressAndHoldTimer.stop();
+ if (event->button() == Qt::LeftButton && !m_dragStarted) {
+ selectItem();
+ m_hoverHighlight->setVisible(false);
+ }
+}
+
+void InspectTool::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ m_mousePosition = event->localPos();
+ m_pressAndHoldTimer.stop();
+ if (event->button() == Qt::LeftButton) {
+ selectNextItem();
+ m_hoverHighlight->setVisible(false);
+ }
+}
+
+void InspectTool::mouseMoveEvent(QMouseEvent *event)
+{
+ m_mousePosition = event->localPos();
+ moveItem(event->buttons() & Qt::LeftButton);
+}
+
+void InspectTool::hoverMoveEvent(QMouseEvent *event)
+{
+ m_mousePosition = event->localPos();
+ m_pressAndHoldTimer.stop();
+ QQuickItem *item = inspector()->topVisibleItemAt(event->pos());
+ if (!item || item == m_lastClickedItem) {
+ m_hoverHighlight->setVisible(false);
+ } else {
+ m_hoverHighlight->setItem(item);
+ m_hoverHighlight->setVisible(true);
+ }
+}
+
+#ifndef QT_NO_WHEELEVENT
+void InspectTool::wheelEvent(QWheelEvent *event)
+{
+ if (event->orientation() != Qt::Vertical)
+ return;
+
+ Qt::KeyboardModifier smoothZoomModifier = Qt::ControlModifier;
+ if (event->modifiers() & smoothZoomModifier) {
+ int numDegrees = event->delta() / 8;
+ qreal newScale = m_contentItem->scale() + m_smoothScaleFactor * (numDegrees / 15.0f);
+ scaleView(newScale / m_contentItem->scale(), m_mousePosition, m_mousePosition);
+ } else if (!event->modifiers()) {
+ if (event->delta() > 0) {
+ zoomIn();
+ } else if (event->delta() < 0) {
+ zoomOut();
+ }
+ }
+}
+#endif
+
+void InspectTool::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: {
+ qreal newScale = ((event->key() - Qt::Key_0) * 1.0f);
+ scaleView(newScale / m_contentItem->scale(), m_mousePosition, m_mousePosition);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void InspectTool::touchEvent(QTouchEvent *event)
+{
+ QList<QTouchEvent::TouchPoint> touchPoints = event->touchPoints();
+
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ if (touchPoints.count() == 1 && (event->touchPointStates() & Qt::TouchPointPressed)) {
+ if (!m_pressAndHoldTimer.isActive())
+ m_pressAndHoldTimer.start();
+ m_mousePosition = touchPoints.first().pos();
+ initializeDrag(touchPoints.first().pos());
+ m_tapEvent = true;
+ } else {
+ m_tapEvent = false;
+ }
+ break;
+ case QEvent::TouchUpdate: {
+ if (touchPoints.count() > 1)
+ m_tapEvent = false;
+ if ((touchPoints.count() == 1)
+ && (event->touchPointStates() & Qt::TouchPointMoved)) {
+ m_mousePosition = touchPoints.first().pos();
+ moveItem(true);
+ } else if ((touchPoints.count() == 2)
+ && (!(event->touchPointStates() & Qt::TouchPointReleased))) {
+ // determine scale factor
+ const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.first();
+ const QTouchEvent::TouchPoint &touchPoint1 = touchPoints.last();
+
+ qreal touchScaleFactor =
+ QLineF(touchPoint0.pos(), touchPoint1.pos()).length()
+ / QLineF(touchPoint0.lastPos(), touchPoint1.lastPos()).length();
+
+ QPointF oldcenter = (touchPoint0.lastPos() + touchPoint1.lastPos()) / 2;
+ QPointF newcenter = (touchPoint0.pos() + touchPoint1.pos()) / 2;
+
+ m_pinchStarted = true;
+ scaleView(touchScaleFactor, newcenter, oldcenter);
+ }
+ break;
+ }
+ case QEvent::TouchEnd: {
+ m_pressAndHoldTimer.stop();
+ if (m_pinchStarted) {
+ m_pinchStarted = false;
+ }
+ if (touchPoints.count() == 1 && !m_dragStarted &&
+ !m_didPressAndHold && m_tapEvent) {
+ m_tapEvent = false;
+ bool doubleTap = event->timestamp() - m_touchTimestamp
+ < static_cast<ulong>(QGuiApplication::styleHints()->mouseDoubleClickInterval());
+ if (doubleTap) {
+ m_nameDisplayTimer.stop();
+ selectNextItem();
+ }
+ else {
+ selectItem();
+ }
+ m_touchTimestamp = event->timestamp();
+ }
+ m_didPressAndHold = false;
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void InspectTool::scaleView(const qreal &factor, const QPointF &newcenter, const QPointF &oldcenter)
+{
+ m_pressAndHoldTimer.stop();
+ if (((m_contentItem->scale() * factor) > m_maxScale)
+ || ((m_contentItem->scale() * factor) < m_minScale)) {
+ return;
+ }
+ //New position = new center + scalefactor * (oldposition - oldcenter)
+ QPointF newPosition = newcenter + (factor * (m_contentItem->position() - oldcenter));
+ m_contentItem->setScale(m_contentItem->scale() * factor);
+ m_contentItem->setPosition(newPosition);
+}
+
+void InspectTool::zoomIn()
+{
+ qreal newScale = nextZoomScale(ZoomIn);
+ scaleView(newScale / m_contentItem->scale(), m_mousePosition, m_mousePosition);
+}
+
+void InspectTool::zoomOut()
+{
+ qreal newScale = nextZoomScale(ZoomOut);
+ scaleView(newScale / m_contentItem->scale(), m_mousePosition, m_mousePosition);
+}
+
+void InspectTool::zoomTo100()
+{
+ m_didPressAndHold = true;
+
+ m_contentItem->setPosition(QPointF(0, 0));
+ m_contentItem->setScale(1.0);
+}
+
+qreal InspectTool::nextZoomScale(ZoomDirection direction)
+{
+ 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_contentItem->scale())
+ return zoomScales[i];
+ }
+ return zoomScales.last();
+ } else {
+ for (int i = zoomScales.length() - 1; i >= 0; --i) {
+ if (zoomScales[i] < m_contentItem->scale())
+ return zoomScales[i];
+ }
+ return zoomScales.first();
+ }
+
+ return 1.0f;
+}
+
+void InspectTool::initializeDrag(const QPointF &pos)
+{
+ m_dragStartPosition = pos;
+ m_dragStarted = false;
+}
+
+void InspectTool::dragItemToPosition()
+{
+ QPointF newPosition = m_contentItem->position() + m_mousePosition - m_dragStartPosition;
+ m_dragStartPosition = m_mousePosition;
+ m_contentItem->setPosition(newPosition);
+}
+
+void InspectTool::moveItem(bool valid)
+{
+ if (m_pinchStarted)
+ return;
+
+ if (!m_dragStarted
+ && valid
+ && ((m_dragStartPosition - m_mousePosition).manhattanLength()
+ > QGuiApplication::styleHints()->startDragDistance())) {
+ m_pressAndHoldTimer.stop();
+ m_dragStarted = true;
+ }
+ if (m_dragStarted)
+ dragItemToPosition();
+}
+
+void InspectTool::selectNextItem()
+{
+ if (m_lastClickedItem != inspector()->topVisibleItemAt(m_mousePosition))
+ return;
+ QList<QQuickItem*> items = inspector()->itemsAt(m_mousePosition);
+ for (int i = 0; i < items.count(); i++) {
+ if (m_lastItem == items[i]) {
+ if (i + 1 < items.count())
+ m_lastItem = items[i+1];
+ else
+ m_lastItem = items[0];
+ inspector()->setSelectedItems(QList<QQuickItem*>() << m_lastItem);
+ showSelectedItemName();
+ break;
+ }
+ }
+}
+
+void InspectTool::selectItem()
+{
+ if (!inspector()->topVisibleItemAt(m_mousePosition))
+ return;
+ if (m_lastClickedItem == inspector()->topVisibleItemAt(m_mousePosition)) {
+ m_nameDisplayTimer.start();
+ return;
+ }
+ m_lastClickedItem = inspector()->topVisibleItemAt(m_mousePosition);
+ m_lastItem = m_lastClickedItem;
+ inspector()->setSelectedItems(QList<QQuickItem*>() << m_lastClickedItem);
+ showSelectedItemName();
+}
+
+QQuickViewInspector *InspectTool::inspector() const
+{
+ return static_cast<QQuickViewInspector*>(AbstractTool::inspector());
+}
+
+void InspectTool::showSelectedItemName()
+{
+ inspector()->showSelectedItemName(m_lastItem, m_mousePosition);
+}
+
+} // namespace QmlJSDebugger
+
+QT_END_NAMESPACE