From 83187ba54fd63b9d9985d5f7fcddc7d8d3463c28 Mon Sep 17 00:00:00 2001 From: Knud Dollereder Date: Thu, 12 Nov 2020 12:08:22 +0100 Subject: [PATCH] Enable pan and zoom gestures for the formeditor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use continuous zoom for mouse-wheel zoom Directly apply zoom and not by detouring through custom notification Moved logic related to zooming from the zoom-action into the view Change-Id: Ib56779f3ea686736cc419aec94d7b5566091fb96 Reviewed-by: Henning Gründl Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/CMakeLists.txt | 1 + .../componentcore/componentcore.pri | 2 + .../components/componentcore/gestures.cpp | 156 +++++++++++++ .../components/componentcore/gestures.h | 72 ++++++ .../components/componentcore/navigation2d.cpp | 42 +++- .../components/componentcore/navigation2d.h | 4 + .../components/componentcore/zoomaction.cpp | 205 +++++++++--------- .../components/componentcore/zoomaction.h | 33 ++- .../formeditor/formeditorgraphicsview.cpp | 70 +++++- .../formeditor/formeditorgraphicsview.h | 17 +- .../components/formeditor/formeditorview.cpp | 45 +--- .../formeditor/formeditorwidget.cpp | 197 +++++++++-------- .../components/formeditor/formeditorwidget.h | 5 +- src/plugins/qmldesigner/qmldesignerplugin.cpp | 3 + src/plugins/qmldesigner/qmldesignerplugin.qbs | 2 + 15 files changed, 578 insertions(+), 276 deletions(-) create mode 100644 src/plugins/qmldesigner/components/componentcore/gestures.cpp create mode 100644 src/plugins/qmldesigner/components/componentcore/gestures.h diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index eaf5df1d5a5..14f060a191a 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -208,6 +208,7 @@ extend_qtc_plugin(QmlDesigner modelnodecontextmenu_helper.cpp modelnodecontextmenu_helper.h modelnodeoperations.cpp modelnodeoperations.h navigation2d.cpp navigation2d.h + gestures.cpp gestures.h qmldesignericonprovider.cpp qmldesignericonprovider.h selectioncontext.cpp selectioncontext.h theme.cpp theme.h diff --git a/src/plugins/qmldesigner/components/componentcore/componentcore.pri b/src/plugins/qmldesigner/components/componentcore/componentcore.pri index decf24a5a83..ef97a93343c 100644 --- a/src/plugins/qmldesigner/components/componentcore/componentcore.pri +++ b/src/plugins/qmldesigner/components/componentcore/componentcore.pri @@ -5,6 +5,7 @@ SOURCES += addimagesdialog.cpp SOURCES += changestyleaction.cpp SOURCES += theme.cpp SOURCES += findimplementation.cpp +SOURCES += gestures.cpp SOURCES += addsignalhandlerdialog.cpp SOURCES += layoutingridlayout.cpp SOURCES += abstractactiongroup.cpp @@ -24,6 +25,7 @@ HEADERS += addimagesdialog.h HEADERS += changestyleaction.h HEADERS += theme.h HEADERS += findimplementation.h +HEADERS += gestures.h HEADERS += addsignalhandlerdialog.h HEADERS += layoutingridlayout.h HEADERS += abstractactiongroup.h diff --git a/src/plugins/qmldesigner/components/componentcore/gestures.cpp b/src/plugins/qmldesigner/components/componentcore/gestures.cpp new file mode 100644 index 00000000000..29ff23c2435 --- /dev/null +++ b/src/plugins/qmldesigner/components/componentcore/gestures.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "gestures.h" + +#include + +namespace QmlDesigner { + +Qt::GestureType TwoFingerSwipe::m_type = static_cast(0); + +TwoFingerSwipe::TwoFingerSwipe() {} + +Qt::GestureType TwoFingerSwipe::type() +{ + return m_type; +} + +void TwoFingerSwipe::registerRecognizer() +{ + m_type = QGestureRecognizer::registerRecognizer(new TwoFingerSwipeRecognizer()); +} + +QPointF TwoFingerSwipe::direction() const +{ + return m_current.center() - m_last.center(); +} + +void TwoFingerSwipe::reset() +{ + m_start = QLineF(); + m_current = QLineF(); + m_last = QLineF(); +} + +QGestureRecognizer::Result TwoFingerSwipe::begin(QTouchEvent *event) +{ + Q_UNUSED(event); + return QGestureRecognizer::MayBeGesture; +} + +QGestureRecognizer::Result TwoFingerSwipe::update(QTouchEvent *event) +{ + if (event->touchPoints().size() != 2) { + if (state() == Qt::NoGesture) + return QGestureRecognizer::Ignore; + else + return QGestureRecognizer::FinishGesture; + } + + QTouchEvent::TouchPoint p0 = event->touchPoints().at(0); + QTouchEvent::TouchPoint p1 = event->touchPoints().at(1); + + QLineF line(p0.scenePos(), p1.screenPos()); + + if (m_start.isNull()) { + m_start = line; + m_current = line; + m_last = line; + } else { + auto deltaLength = line.length() - m_current.length(); + auto deltaCenter = QLineF(line.center(), m_current.center()).length(); + if (deltaLength > deltaCenter) + return QGestureRecognizer::CancelGesture; + + m_last = m_current; + m_current = line; + } + + setHotSpot(m_current.center()); + + return QGestureRecognizer::TriggerGesture; +} + +QGestureRecognizer::Result TwoFingerSwipe::end(QTouchEvent *event) +{ + Q_UNUSED(event); + bool finish = state() != Qt::NoGesture; + + reset(); + + if (finish) + return QGestureRecognizer::FinishGesture; + else + return QGestureRecognizer::CancelGesture; +} + +TwoFingerSwipeRecognizer::TwoFingerSwipeRecognizer() + : QGestureRecognizer() +{} + +QGesture *TwoFingerSwipeRecognizer::create(QObject *target) +{ + if (target && target->isWidgetType()) + qobject_cast(target)->setAttribute(Qt::WA_AcceptTouchEvents); + + return new TwoFingerSwipe; +} + +QGestureRecognizer::Result TwoFingerSwipeRecognizer::recognize(QGesture *gesture, + QObject *, + QEvent *event) +{ + if (gesture->gestureType() != TwoFingerSwipe::type()) + return QGestureRecognizer::Ignore; + + TwoFingerSwipe *swipe = static_cast(gesture); + QTouchEvent *touch = static_cast(event); + + switch (event->type()) { + case QEvent::TouchBegin: + return swipe->begin(touch); + + case QEvent::TouchUpdate: + return swipe->update(touch); + + case QEvent::TouchEnd: + return swipe->end(touch); + + default: + return QGestureRecognizer::Ignore; + } +} + +void TwoFingerSwipeRecognizer::reset(QGesture *gesture) +{ + if (gesture->gestureType() == TwoFingerSwipe::type()) { + TwoFingerSwipe *swipe = static_cast(gesture); + swipe->reset(); + } + QGestureRecognizer::reset(gesture); +} + +} // End namespace QmlDesigner. diff --git a/src/plugins/qmldesigner/components/componentcore/gestures.h b/src/plugins/qmldesigner/components/componentcore/gestures.h new file mode 100644 index 00000000000..3100560904b --- /dev/null +++ b/src/plugins/qmldesigner/components/componentcore/gestures.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include +#include +#include + +QT_FORWARD_DECLARE_CLASS(QTouchEvent) + +namespace QmlDesigner { + +class TwoFingerSwipe : public QGesture +{ + Q_OBJECT + +public: + TwoFingerSwipe(); + + static Qt::GestureType type(); + static void registerRecognizer(); + + QPointF direction() const; + + void reset(); + QGestureRecognizer::Result begin(QTouchEvent *event); + QGestureRecognizer::Result update(QTouchEvent *event); + QGestureRecognizer::Result end(QTouchEvent *event); + +private: + static Qt::GestureType m_type; + + QLineF m_start; + QLineF m_current; + QLineF m_last; +}; + +class TwoFingerSwipeRecognizer : public QGestureRecognizer +{ +public: + TwoFingerSwipeRecognizer(); + + QGesture *create(QObject *target) override; + + QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event) override; + + void reset(QGesture *gesture) override; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/componentcore/navigation2d.cpp b/src/plugins/qmldesigner/components/componentcore/navigation2d.cpp index 94d6b5ad38f..eccd8a517ed 100644 --- a/src/plugins/qmldesigner/components/componentcore/navigation2d.cpp +++ b/src/plugins/qmldesigner/components/componentcore/navigation2d.cpp @@ -23,10 +23,13 @@ ** ****************************************************************************/ #include "navigation2d.h" +#include "gestures.h" #include #include +#include + namespace QmlDesigner { Navigation2dScrollBar::Navigation2dScrollBar(QWidget *parent) @@ -53,39 +56,60 @@ Navigation2dFilter::Navigation2dFilter(QWidget *parent, Navigation2dScrollBar *s : QObject(parent) , m_scrollbar(scrollbar) { - if (parent) + if (parent) { parent->grabGesture(Qt::PinchGesture); + if (!scrollbar) + parent->grabGesture(TwoFingerSwipe::type()); + } } -bool Navigation2dFilter::eventFilter(QObject *, QEvent *event) +bool Navigation2dFilter::eventFilter(QObject *object, QEvent *event) { if (event->type() == QEvent::Gesture) return gestureEvent(static_cast(event)); - else if (event->type() == QEvent::Wheel && m_scrollbar) + else if (event->type() == QEvent::Wheel) return wheelEvent(static_cast(event)); - return QObject::event(event); + return QObject::eventFilter(object, event); } bool Navigation2dFilter::gestureEvent(QGestureEvent *event) { if (QPinchGesture *pinch = static_cast(event->gesture(Qt::PinchGesture))) { QPinchGesture::ChangeFlags changeFlags = pinch->changeFlags(); - if (changeFlags & QPinchGesture::ScaleFactorChanged) { + if (changeFlags.testFlag(QPinchGesture::ScaleFactorChanged)) { emit zoomChanged(-(1.0 - pinch->scaleFactor()), pinch->startCenterPoint()); event->accept(); return true; } + } else if (TwoFingerSwipe *swipe = static_cast( + event->gesture(TwoFingerSwipe::type()))) { + emit panChanged(swipe->direction()); + event->accept(); + return true; } return false; } bool Navigation2dFilter::wheelEvent(QWheelEvent *event) { - if (m_scrollbar->postEvent(event)) - event->ignore(); - - return false; + if (m_scrollbar) { + if (m_scrollbar->postEvent(event)) + event->ignore(); + } else if (event->source() == Qt::MouseEventNotSynthesized) { + if (event->modifiers().testFlag(Qt::ControlModifier)) { + if (QPointF angle = event->angleDelta(); !angle.isNull()) { + double delta = std::abs(angle.x()) > std::abs(angle.y()) ? angle.x() : angle.y(); + if (delta > 0) + emit zoomIn(); + else + emit zoomOut(); + event->accept(); + return true; + } + } + } + return true; } } // End namespace QmlDesigner. diff --git a/src/plugins/qmldesigner/components/componentcore/navigation2d.h b/src/plugins/qmldesigner/components/componentcore/navigation2d.h index 434b59055ca..fe432b4a6b4 100644 --- a/src/plugins/qmldesigner/components/componentcore/navigation2d.h +++ b/src/plugins/qmldesigner/components/componentcore/navigation2d.h @@ -51,6 +51,10 @@ class Navigation2dFilter : public QObject signals: void zoomChanged(double scale, const QPointF &pos); + void panChanged(const QPointF &direction); + + void zoomIn(); + void zoomOut(); public: Navigation2dFilter(QWidget *parent = nullptr, Navigation2dScrollBar *scrollbar = nullptr); diff --git a/src/plugins/qmldesigner/components/componentcore/zoomaction.cpp b/src/plugins/qmldesigner/components/componentcore/zoomaction.cpp index c59c1ffe836..024dd605028 100644 --- a/src/plugins/qmldesigner/components/componentcore/zoomaction.cpp +++ b/src/plugins/qmldesigner/components/componentcore/zoomaction.cpp @@ -24,130 +24,135 @@ ****************************************************************************/ #include "zoomaction.h" +#include "formeditorwidget.h" +#include +#include +#include -#include #include +#include +#include + +#include namespace QmlDesigner { -const int defaultZoomIndex = 13; +// Order matters! +std::array ZoomAction::m_zooms = { + 0.01, 0.02, 0.05, 0.0625, 0.1, 0.125, 0.2, 0.25, 0.33, 0.5, 0.66, 0.75, 0.9, + 1.0, 1.1, 1.25, 1.33, 1.5, 1.66, 1.75, 2.0, 3.0, 4.0, 6.0, 8.0, 10.0, 16.0 +}; + +bool isValidIndex(int index) +{ + if (index >= 0 && index < static_cast(ZoomAction::zoomLevels().size())) + return true; + + return false; +} ZoomAction::ZoomAction(QObject *parent) - : QWidgetAction(parent), - m_zoomLevel(1.0), - m_currentComboBoxIndex(defaultZoomIndex) -{ + : QWidgetAction(parent) + , m_combo(nullptr) +{} +std::array ZoomAction::zoomLevels() +{ + return m_zooms; } -float ZoomAction::zoomLevel() const +int ZoomAction::indexOf(double zoom) { - return m_zoomLevel; -} + auto finder = [zoom](double val) { return qFuzzyCompare(val, zoom); }; + if (auto iter = std::find_if(m_zooms.begin(), m_zooms.end(), finder); iter != m_zooms.end()) + return static_cast(std::distance(m_zooms.begin(), iter)); -void ZoomAction::zoomIn() -{ - if (m_currentComboBoxIndex < (m_comboBoxModel->rowCount() - 1)) - emit indexChanged(m_currentComboBoxIndex + 1); -} - -void ZoomAction::zoomOut() -{ - if (m_currentComboBoxIndex > 0) - emit indexChanged(m_currentComboBoxIndex - 1); -} - -void ZoomAction::resetZoomLevel() -{ - m_zoomLevel = 1.0; - m_currentComboBoxIndex = defaultZoomIndex; - emit reseted(); -} - -void ZoomAction::setZoomLevel(float zoomLevel) -{ - if (qFuzzyCompare(m_zoomLevel, zoomLevel)) - return; - - forceZoomLevel(zoomLevel); -} - -void ZoomAction::forceZoomLevel(float zoomLevel) -{ - m_zoomLevel = qBound(0.01f, zoomLevel, 16.0f); - emit zoomLevelChanged(m_zoomLevel); -} - -//initial m_zoomLevel and m_currentComboBoxIndex -const QVector s_zoomFactors = {0.01f, 0.02f, 0.05f, 0.0625f, 0.1f, 0.125f, 0.2f, 0.25f, - 0.33f, 0.5f, 0.66f, 0.75f, 0.9f, 1.0f, 1.1f, 1.25f, 1.33f, - 1.5f, 1.66f, 1.75f, 2.0f, 3.0f, 4.0f, 6.0f, 8.0f, 10.0f, 16.0f }; - -int getZoomIndex(float zoom) -{ - for (int i = 0; i < s_zoomFactors.length(); i++) { - if (qFuzzyCompare(s_zoomFactors.at(i), zoom)) - return i; - } return -1; } -float ZoomAction::getClosestZoomLevel(float zoomLevel) +void ZoomAction::setZoomFactor(double zoom) { - int i = 0; - while (i < s_zoomFactors.size() && s_zoomFactors[i] < zoomLevel) - ++i; + if (int index = indexOf(zoom); index >= 0) { + m_combo->setCurrentIndex(index); + m_combo->setToolTip(m_combo->currentText()); + return; + } + int rounded = static_cast(std::round(zoom * 100)); + m_combo->setEditable(true); + m_combo->setEditText(QString::number(rounded) + " %"); + m_combo->setToolTip(m_combo->currentText()); +} - return s_zoomFactors[qBound(0, i - 1, s_zoomFactors.size() - 1)]; +double ZoomAction::setNextZoomFactor(double zoom) +{ + if (zoom >= m_zooms.back()) + return zoom; + + auto greater = [zoom](double val) { return val > zoom; }; + if (auto iter = std::find_if(m_zooms.begin(), m_zooms.end(), greater); iter != m_zooms.end()) { + auto index = std::distance(m_zooms.begin(), iter); + m_combo->setCurrentIndex(static_cast(index)); + m_combo->setToolTip(m_combo->currentText()); + return *iter; + } + return zoom; +} + +double ZoomAction::setPreviousZoomFactor(double zoom) +{ + if (zoom <= m_zooms.front()) + return zoom; + + auto smaller = [zoom](double val) { return val < zoom; }; + if (auto iter = std::find_if(m_zooms.rbegin(), m_zooms.rend(), smaller); iter != m_zooms.rend()) { + auto index = std::distance(iter, m_zooms.rend() - 1); + m_combo->setCurrentIndex(static_cast(index)); + m_combo->setToolTip(m_combo->currentText()); + return *iter; + } + return zoom; +} + +bool parentIsFormEditor(QWidget *parent) +{ + while (parent) { + if (qobject_cast(parent)) + return true; + parent = qobject_cast(parent->parent()); + } + return false; +} + +QComboBox *createZoomComboBox(QWidget *parent) +{ + auto *combo = new QComboBox(parent); + for (double z : ZoomAction::zoomLevels()) { + const QString name = QString::number(z * 100., 'g', 4) + " %"; + combo->addItem(name, z); + } + return combo; } QWidget *ZoomAction::createWidget(QWidget *parent) { - auto comboBox = new QComboBox(parent); + if (!m_combo && parentIsFormEditor(parent)) { + m_combo = createZoomComboBox(parent); + m_combo->setProperty("hideborder", true); + m_combo->setCurrentIndex(indexOf(1.0)); + m_combo->setToolTip(m_combo->currentText()); - /* - * When add zoom levels do not forget to update defaultZoomIndex - */ - if (m_comboBoxModel.isNull()) { - m_comboBoxModel = comboBox->model(); - for (float z : s_zoomFactors) { - const QString name = QString::number(z * 100, 'g', 4) + " %"; - comboBox->addItem(name, z); - } - } else { - comboBox->setModel(m_comboBoxModel.data()); + auto currentChanged = QOverload::of(&QComboBox::currentIndexChanged); + connect(m_combo, currentChanged, this, &ZoomAction::emitZoomLevelChanged); + + return m_combo.data(); } + return nullptr; +} - comboBox->setCurrentIndex(m_currentComboBoxIndex); - comboBox->setToolTip(comboBox->currentText()); - connect(this, &ZoomAction::reseted, comboBox, [this, comboBox]() { - blockSignals(true); - comboBox->setCurrentIndex(m_currentComboBoxIndex); - blockSignals(false); - }); - connect(comboBox, QOverload::of(&QComboBox::currentIndexChanged), - [this, comboBox](int index) { - m_currentComboBoxIndex = index; - - if (index == -1) - return; - - const QModelIndex modelIndex(m_comboBoxModel.data()->index(index, 0)); - setZoomLevel(m_comboBoxModel.data()->data(modelIndex, Qt::UserRole).toFloat()); - comboBox->setToolTip(modelIndex.data().toString()); - }); - - connect(this, &ZoomAction::indexChanged, comboBox, &QComboBox::setCurrentIndex); - - connect(this, &ZoomAction::zoomLevelChanged, comboBox, [comboBox](double zoom){ - const int index = getZoomIndex(zoom); - if (comboBox->currentIndex() != index) - comboBox->setCurrentIndex(index); - }); - - comboBox->setProperty("hideborder", true); - comboBox->setMaximumWidth(qMax(comboBox->view()->sizeHintForColumn(0) / 2, 16)); - return comboBox; +void ZoomAction::emitZoomLevelChanged(int index) +{ + if (index >= 0 && index < static_cast(m_zooms.size())) + emit zoomLevelChanged(m_zooms[static_cast(index)]); } } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/componentcore/zoomaction.h b/src/plugins/qmldesigner/components/componentcore/zoomaction.h index bd46f915d91..85d855c1d1e 100644 --- a/src/plugins/qmldesigner/components/componentcore/zoomaction.h +++ b/src/plugins/qmldesigner/components/componentcore/zoomaction.h @@ -26,11 +26,13 @@ #include -#include #include +#include + +#include QT_BEGIN_NAMESPACE -class QAbstractItemModel; +class QComboBox; QT_END_NAMESPACE namespace QmlDesigner { @@ -39,30 +41,27 @@ class QMLDESIGNERCORE_EXPORT ZoomAction : public QWidgetAction { Q_OBJECT +signals: + void zoomLevelChanged(double zoom); + public: ZoomAction(QObject *parent); - float zoomLevel() const; + static std::array zoomLevels(); + static int indexOf(double zoom); - void zoomIn(); - void zoomOut(); - void resetZoomLevel(); - void setZoomLevel(float zoomLevel); - void forceZoomLevel(float zoomLevel); - - static float getClosestZoomLevel(float zoomLevel); + void setZoomFactor(double zoom); + double setNextZoomFactor(double zoom); + double setPreviousZoomFactor(double zoom); protected: QWidget *createWidget(QWidget *parent) override; -signals: - void zoomLevelChanged(float zoom); - void indexChanged(int); - void reseted(); private: - QPointer m_comboBoxModel; - float m_zoomLevel; - int m_currentComboBoxIndex; + void emitZoomLevelChanged(int index); + + static std::array m_zooms; + QPointer m_combo; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp index dfb5cdd9568..4cfa6402d56 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp @@ -24,20 +24,24 @@ ****************************************************************************/ #include "formeditorgraphicsview.h" +#include "formeditoritem.h" +#include "formeditorwidget.h" +#include "navigation2d.h" -#include -#include -#include -#include -#include +#include #include +#include +#include +#include +#include +#include #include namespace QmlDesigner { -FormEditorGraphicsView::FormEditorGraphicsView(QWidget *parent) : - QGraphicsView(parent) +FormEditorGraphicsView::FormEditorGraphicsView(QWidget *parent) + : QGraphicsView(parent) { setTransformationAnchor(QGraphicsView::AnchorUnderMouse); setResizeAnchor(QGraphicsView::AnchorViewCenter); @@ -57,6 +61,39 @@ FormEditorGraphicsView::FormEditorGraphicsView(QWidget *parent) : // as mousetracking only works for mouse key it is better to handle it in the // eventFilter method so it works also for the space scrolling case as expected QCoreApplication::instance()->installEventFilter(this); + + QmlDesigner::Navigation2dFilter *filter = new QmlDesigner::Navigation2dFilter(this); + connect(filter, &Navigation2dFilter::zoomIn, this, &FormEditorGraphicsView::zoomIn); + connect(filter, &Navigation2dFilter::zoomOut, this, &FormEditorGraphicsView::zoomOut); + + auto panChanged = &Navigation2dFilter::panChanged; + connect(filter, panChanged, [this](const QPointF &direction) { + QScrollBar *sbx = horizontalScrollBar(); + QScrollBar *sby = verticalScrollBar(); + + // max - min + pageStep = sceneRect.size * scale + QPointF min(sbx->minimum(), sby->minimum()); + QPointF max(sbx->maximum(), sby->maximum()); + QPointF step(sbx->pageStep(), sby->pageStep()); + + QPointF d1 = max - min; + QPointF d2 = d1 + step; + + QPoint val = QPointF((direction.x() / d2.x()) * d1.x(), (direction.y() / d2.y()) * d1.y()) + .toPoint(); + + sbx->setValue(sbx->value() - val.x()); + sby->setValue(sby->value() - val.y()); + }); + + auto zoomChanged = &Navigation2dFilter::zoomChanged; + connect(filter, zoomChanged, [this](double s, const QPointF &/*pos*/) { + if (auto trans = transform() * QTransform::fromScale(1.0 + s, 1.0 + s); trans.m11() > 0) { + setTransform(trans); + emit this->zoomChanged(transform().m11()); + } + }); + installEventFilter(filter); } bool FormEditorGraphicsView::eventFilter(QObject *watched, QEvent *event) @@ -67,7 +104,7 @@ bool FormEditorGraphicsView::eventFilter(QObject *watched, QEvent *event) stopPanning(event); } if (event->type() == QEvent::MouseMove) { - auto mouseEvent = static_cast(event); + auto mouseEvent = static_cast(event); if (!m_panningStartPosition.isNull()) { horizontalScrollBar()->setValue(horizontalScrollBar()->value() - (mouseEvent->x() - m_panningStartPosition.x())); @@ -86,7 +123,7 @@ void FormEditorGraphicsView::wheelEvent(QWheelEvent *event) { if (event->modifiers().testFlag(Qt::ControlModifier)) event->ignore(); - else + else if (event->source() == Qt::MouseEventNotSynthesized) QGraphicsView::wheelEvent(event); } @@ -109,7 +146,7 @@ void FormEditorGraphicsView::mouseReleaseEvent(QMouseEvent *event) QGraphicsView::mouseReleaseEvent(event); } -bool isTextInputItem(QGraphicsItem* item) +bool isTextInputItem(QGraphicsItem *item) { if (item && item->isWidget()) { auto graphicsWidget = static_cast(item); @@ -128,7 +165,7 @@ void FormEditorGraphicsView::keyPressEvent(QKeyEvent *event) { // check for autorepeat to avoid a stoped space panning by leave event to be restarted if (!event->isAutoRepeat() && m_isPanning == Panning::NotStarted && event->key() == Qt::Key_Space && - !isTextInputItem(scene()->focusItem())) { + !isTextInputItem(scene()->focusItem())) { startPanning(event); return; } @@ -203,4 +240,15 @@ void FormEditorGraphicsView::drawBackground(QPainter *painter, const QRectF &rec painter->restore(); } +void FormEditorGraphicsView::frame(const QRectF &boundingRect) +{ + fitInView(boundingRect, Qt::KeepAspectRatio); +} + +void FormEditorGraphicsView::setZoomFactor(double zoom) +{ + resetTransform(); + scale(zoom, zoom); +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h index 2c6a57b425c..701639f75c1 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h @@ -30,7 +30,13 @@ namespace QmlDesigner { class FormEditorGraphicsView : public QGraphicsView { -Q_OBJECT + Q_OBJECT + +signals: + void zoomChanged(double zoom); + void zoomIn(); + void zoomOut(); + public: explicit FormEditorGraphicsView(QWidget *parent = nullptr); @@ -41,6 +47,9 @@ public: void activateColoredBackground(const QColor &color); void drawBackground(QPainter *painter, const QRectF &rect) override; + void setZoomFactor(double zoom); + void frame(const QRectF &bbox); + protected: bool eventFilter(QObject *watched, QEvent *event) override; void wheelEvent(QWheelEvent *event) override; @@ -48,13 +57,13 @@ protected: void mouseReleaseEvent(QMouseEvent *event) override; void keyPressEvent(QKeyEvent *event) override; void keyReleaseEvent(QKeyEvent *event) override; + private: - enum Panning{ - NotStarted, MouseWheelStarted, SpaceKeyStarted - }; + enum Panning { NotStarted, MouseWheelStarted, SpaceKeyStarted }; void startPanning(QEvent *event); void stopPanning(QEvent *event); + Panning m_isPanning = Panning::NotStarted; QPoint m_panningStartPosition; QRectF m_rootItemRect; diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp index ac67e58394f..19a3b1c647b 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp @@ -443,53 +443,12 @@ void FormEditorView::documentMessagesChanged(const QList &error m_formEditorWidget->hideErrorMessageBox(); } -void FormEditorView::customNotification(const AbstractView * /*view*/, const QString &identifier, const QList &nodeList, const QList &/*data*/) +void FormEditorView::customNotification(const AbstractView * /*view*/, const QString &identifier, const QList &/*nodeList*/, const QList &/*data*/) { if (identifier == QLatin1String("puppet crashed")) m_dragTool->clearMoveDelay(); if (identifier == QLatin1String("reset QmlPuppet")) temporaryBlockView(); - if (identifier == QLatin1String("zoom all")) { - if (QmlItemNode(rootModelNode()).isFlowView()) { - QRectF boundingRect; - for (QGraphicsItem *item : scene()->items()) { - if (auto formEditorItem = FormEditorItem::fromQGraphicsItem(item)) { - if (!formEditorItem->qmlItemNode().modelNode().isRootNode() - && !formEditorItem->sceneBoundingRect().isNull()) - boundingRect = boundingRect.united(formEditorItem->sceneBoundingRect()); - } - } - m_formEditorWidget->graphicsView()->fitInView(boundingRect, - Qt::KeepAspectRatio); - } else { - m_formEditorWidget->graphicsView()->fitInView(m_formEditorWidget->rootItemRect(), - Qt::KeepAspectRatio); - } - - const qreal scaleFactor = m_formEditorWidget->graphicsView()->viewportTransform().m11(); - float zoomLevel = ZoomAction::getClosestZoomLevel(scaleFactor); - m_formEditorWidget->zoomAction()->forceZoomLevel(zoomLevel); - } - if (identifier == QLatin1String("zoom selection")) { - if (nodeList.isEmpty()) - return; - - QRectF boundingRect; - for (const ModelNode &node : nodeList) { - if (FormEditorItem *item = scene()->itemForQmlItemNode(node)) - boundingRect = boundingRect.united(item->sceneBoundingRect()); - } - - m_formEditorWidget->graphicsView()->fitInView(boundingRect, - Qt::KeepAspectRatio); - const qreal scaleFactor = m_formEditorWidget->graphicsView()->viewportTransform().m11(); - float zoomLevel = ZoomAction::getClosestZoomLevel(scaleFactor); - m_formEditorWidget->zoomAction()->forceZoomLevel(zoomLevel); - } - if (identifier == QLatin1String("zoom in")) - m_formEditorWidget->zoomAction()->zoomIn(); - if (identifier == QLatin1String("zoom out")) - m_formEditorWidget->zoomAction()->zoomOut(); } void FormEditorView::currentStateChanged(const ModelNode & /*node*/) @@ -791,7 +750,7 @@ void FormEditorView::setupFormEditorWidget() if (QmlItemNode::isValidQmlItemNode(rootModelNode())) setupFormEditorItemTree(rootModelNode()); - m_formEditorWidget->updateActions(); + m_formEditorWidget->initialize(); if (!rewriterView()->errors().isEmpty()) m_formEditorWidget->showErrorMessageBox(rewriterView()->errors()); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp index aeaa3c1e9d1..e858ae56376 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp @@ -23,13 +23,13 @@ ** ****************************************************************************/ -#include "designeractionmanager.h" #include "formeditorwidget.h" -#include "formeditorscene.h" -#include "qmldesignerplugin.h" +#include "designeractionmanager.h" #include "designersettings.h" +#include "formeditorscene.h" #include "qmldesignerconstants.h" #include "qmldesignericons.h" +#include "qmldesignerplugin.h" #include "viewmanager.h" #include #include @@ -39,16 +39,16 @@ #include #include #include -#include #include +#include #include #include #include #include -#include #include +#include #include #include @@ -59,8 +59,8 @@ namespace QmlDesigner { -FormEditorWidget::FormEditorWidget(FormEditorView *view) : - m_formEditorView(view) +FormEditorWidget::FormEditorWidget(FormEditorView *view) + : m_formEditorView(view) { Core::Context context(Constants::C_QMLFORMEDITOR); m_context = new Core::IContext(this); @@ -72,7 +72,7 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view) : fillLayout->setSpacing(0); setLayout(fillLayout); - QList upperActions; + QList upperActions; m_toolActionGroup = new QActionGroup(this); @@ -128,7 +128,7 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view) : addAction(m_rootWidthAction.data()); upperActions.append(m_rootWidthAction.data()); - m_rootHeightAction = new LineEditAction(tr("Override Height"), this); + m_rootHeightAction = new LineEditAction(tr("Override Height"), this); m_rootHeightAction->setToolTip(tr("Override height of root item.")); connect(m_rootHeightAction.data(), &LineEditAction::textChanged, this, &FormEditorWidget::changeRootItemHeight); @@ -150,9 +150,8 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view) : const QString fontName = "qtds_propertyIconFont.ttf"; const QColor textColorNormal(Theme::getColor(Theme::MenuItemTextColorNormal)); const QColor textColorDisabled(Theme::getColor(Theme::MenuBarItemTextColorDisabled)); - const QIcon zoomAllIcon = Utils::StyleHelper::getIconFromIconFont(fontName, - Theme::getIconUnicode(Theme::Icon::zoomAll), - 28, 28, textColorNormal); + const QIcon zoomAllIcon = Utils::StyleHelper::getIconFromIconFont( + fontName, Theme::getIconUnicode(Theme::Icon::zoomAll), 28, 28, textColorNormal); const QString zoomSelectionUnicode = Theme::getIconUnicode(Theme::Icon::zoomSelection); const auto zoomSelectionNormal = Utils::StyleHelper::IconFontHelper(zoomSelectionUnicode, @@ -167,68 +166,101 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view) : const QIcon zoomSelectionIcon = Utils::StyleHelper::getIconFromIconFont(fontName, {zoomSelectionNormal, zoomSelectionDisabeld}); - const QIcon zoomInIcon = Utils::StyleHelper::getIconFromIconFont(fontName, - Theme::getIconUnicode(Theme::Icon::zoomIn), - 28, 28, textColorNormal); - const QIcon zoomOutIcon = Utils::StyleHelper::getIconFromIconFont(fontName, - Theme::getIconUnicode(Theme::Icon::zoomOut), - 28, 28, textColorNormal); + const QIcon zoomInIcon = Utils::StyleHelper::getIconFromIconFont( + fontName, Theme::getIconUnicode(Theme::Icon::zoomIn), 28, 28, textColorNormal); + const QIcon zoomOutIcon = Utils::StyleHelper::getIconFromIconFont( + fontName, Theme::getIconUnicode(Theme::Icon::zoomOut), 28, 28, textColorNormal); + + auto writeZoomLevel = [this]() { + double level = m_graphicsView->transform().m11(); + if (level == 1.0) { + if (m_formEditorView->rootModelNode().hasAuxiliaryData("formeditorZoom")) + m_formEditorView->rootModelNode().setAuxiliaryData("formeditorZoom", {}); + } else { + m_formEditorView->rootModelNode().setAuxiliaryData("formeditorZoom", level); + } + }; + + auto setZoomLevel = [this, writeZoomLevel](double level) { + if (m_graphicsView) { + m_graphicsView->setZoomFactor(level); + writeZoomLevel(); + } + }; + + auto zoomIn = [this, writeZoomLevel]() { + if (m_graphicsView) { + double zoom = m_graphicsView->transform().m11(); + zoom = m_zoomAction->setNextZoomFactor(zoom); + m_graphicsView->setZoomFactor(zoom); + writeZoomLevel(); + } + }; + + auto zoomOut = [this, writeZoomLevel]() { + if (m_graphicsView) { + double zoom = m_graphicsView->transform().m11(); + zoom = m_zoomAction->setPreviousZoomFactor(zoom); + m_graphicsView->setZoomFactor(zoom); + writeZoomLevel(); + } + }; + + auto frameAll = [this, zoomOut]() { + if (m_graphicsView) { + m_graphicsView->frame(m_graphicsView->rootItemRect()); + zoomOut(); + } + }; + + auto frameSelection = [this, zoomOut]() { + if (m_graphicsView) { + QRectF boundingRect; + const QList nodeList = m_formEditorView->selectedModelNodes(); + for (const ModelNode &node : nodeList) { + if (FormEditorItem *item = m_formEditorView->scene()->itemForQmlItemNode(node)) + boundingRect |= item->sceneBoundingRect(); + } + m_graphicsView->frame(boundingRect); + zoomOut(); + } + }; m_zoomInAction = new QAction(zoomInIcon, tr("Zoom in"), this); m_zoomInAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Plus)); - connect(m_zoomInAction.data(), &QAction::triggered, this, [this] { - if (!m_formEditorView) - return; - - m_formEditorView->emitCustomNotification(QStringLiteral("zoom in")); - }); addAction(m_zoomInAction.data()); upperActions.append(m_zoomInAction.data()); m_toolBox->addRightSideAction(m_zoomInAction.data()); + connect(m_zoomInAction.data(), &QAction::triggered, zoomIn); m_zoomOutAction = new QAction(zoomOutIcon, tr("Zoom out"), this); m_zoomOutAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Minus)); - connect(m_zoomOutAction.data(), &QAction::triggered, this, [this] { - if (!m_formEditorView) - return; - - m_formEditorView->emitCustomNotification(QStringLiteral("zoom out")); - }); addAction(m_zoomOutAction.data()); upperActions.append(m_zoomOutAction.data()); m_toolBox->addRightSideAction(m_zoomOutAction.data()); + connect(m_zoomOutAction.data(), &QAction::triggered, zoomOut); m_zoomAction = new ZoomAction(m_toolActionGroup.data()); - connect(m_zoomAction.data(), &ZoomAction::zoomLevelChanged, - this, &FormEditorWidget::setZoomLevel); addAction(m_zoomAction.data()); upperActions.append(m_zoomAction.data()); m_toolBox->addRightSideAction(m_zoomAction.data()); + connect(m_zoomAction.data(), &ZoomAction::zoomLevelChanged, setZoomLevel); m_zoomAllAction = new QAction(zoomAllIcon, tr("Zoom screen to fit all content"), this); m_zoomAllAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_0)); - connect(m_zoomAllAction.data(), &QAction::triggered, this, [this] { - if (!m_formEditorView) - return; - - m_formEditorView->emitCustomNotification(QStringLiteral("zoom all")); - }); addAction(m_zoomAllAction.data()); upperActions.append(m_zoomAllAction.data()); m_toolBox->addRightSideAction(m_zoomAllAction.data()); + connect(m_zoomAllAction.data(), &QAction::triggered, frameAll); - m_zoomSelectionAction = new QAction(zoomSelectionIcon, tr("Zoom screen to fit current selection"), this); + m_zoomSelectionAction = new QAction(zoomSelectionIcon, + tr("Zoom screen to fit current selection"), + this); m_zoomSelectionAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_I)); - connect(m_zoomSelectionAction.data(), &QAction::triggered, this, [this] { - if (!m_formEditorView) - return; - - m_formEditorView->emitCustomNotification(QStringLiteral("zoom selection"), - m_formEditorView->selectedModelNodes()); - }); addAction(m_zoomSelectionAction.data()); upperActions.append(m_zoomSelectionAction.data()); m_toolBox->addRightSideAction(m_zoomSelectionAction.data()); + connect(m_zoomSelectionAction.data(), &QAction::triggered, frameSelection); m_resetAction = new QAction(Utils::Icons::RESET_TOOLBAR.icon(), tr("Reset View"), this); registerActionAsCommand(m_resetAction, Constants::FORMEDITOR_REFRESH, QKeySequence(Qt::Key_R)); @@ -238,6 +270,10 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view) : m_toolBox->addRightSideAction(m_resetAction.data()); m_graphicsView = new FormEditorGraphicsView(this); + auto applyZoom = [this](double zoom) { zoomAction()->setZoomFactor(zoom); }; + connect(m_graphicsView, &FormEditorGraphicsView::zoomChanged, applyZoom); + connect(m_graphicsView, &FormEditorGraphicsView::zoomIn, zoomIn); + connect(m_graphicsView, &FormEditorGraphicsView::zoomOut, zoomOut); fillLayout->addWidget(m_graphicsView.data()); @@ -293,50 +329,46 @@ void FormEditorWidget::registerActionAsCommand(QAction *action, Utils::Id id, co command->augmentActionWithShortcutToolTip(action); } -void FormEditorWidget::wheelEvent(QWheelEvent *event) +void FormEditorWidget::initialize() { - if (event->modifiers().testFlag(Qt::ControlModifier)) { - if (event->angleDelta().y() > 0) - zoomAction()->zoomIn(); - else - zoomAction()->zoomOut(); - - event->accept(); - } else { - QWidget::wheelEvent(event); + double defaultZoom = 1.0; + if (m_formEditorView->model() && m_formEditorView->rootModelNode().isValid()) { + if (m_formEditorView->rootModelNode().hasAuxiliaryData("formeditorZoom")) + defaultZoom = m_formEditorView->rootModelNode().auxiliaryData("formeditorZoom").toDouble(); } - + m_graphicsView->setZoomFactor(defaultZoom); + m_zoomAction->setZoomFactor(defaultZoom); + updateActions(); } void FormEditorWidget::updateActions() { if (m_formEditorView->model() && m_formEditorView->rootModelNode().isValid()) { - if (m_formEditorView->rootModelNode().hasAuxiliaryData("width") && m_formEditorView->rootModelNode().auxiliaryData("width").isValid()) - m_rootWidthAction->setLineEditText(m_formEditorView->rootModelNode().auxiliaryData("width").toString()); + if (m_formEditorView->rootModelNode().hasAuxiliaryData("width") + && m_formEditorView->rootModelNode().auxiliaryData("width").isValid()) + m_rootWidthAction->setLineEditText( + m_formEditorView->rootModelNode().auxiliaryData("width").toString()); else m_rootWidthAction->clearLineEditText(); - if (m_formEditorView->rootModelNode().hasAuxiliaryData("height") && m_formEditorView->rootModelNode().auxiliaryData("height").isValid()) - m_rootHeightAction->setLineEditText(m_formEditorView->rootModelNode().auxiliaryData("height").toString()); + if (m_formEditorView->rootModelNode().hasAuxiliaryData("height") + && m_formEditorView->rootModelNode().auxiliaryData("height").isValid()) + m_rootHeightAction->setLineEditText( + m_formEditorView->rootModelNode().auxiliaryData("height").toString()); else m_rootHeightAction->clearLineEditText(); if (m_formEditorView->rootModelNode().hasAuxiliaryData("formeditorColor")) - m_backgroundAction->setColor(m_formEditorView->rootModelNode().auxiliaryData("formeditorColor").value()); + m_backgroundAction->setColor( + m_formEditorView->rootModelNode().auxiliaryData("formeditorColor").value()); else m_backgroundAction->setColor(Qt::transparent); - if (m_formEditorView->rootModelNode().hasAuxiliaryData("formeditorZoom")) - m_zoomAction->setZoomLevel(m_formEditorView->rootModelNode().auxiliaryData("formeditorZoom").toDouble()); - else - m_zoomAction->setZoomLevel(1.0); - } else { m_rootWidthAction->clearLineEditText(); m_rootHeightAction->clearLineEditText(); } } - void FormEditorWidget::resetView() { setRootItemRect(QRectF()); @@ -371,8 +403,8 @@ void FormEditorWidget::hideErrorMessageBox() void FormEditorWidget::showWarningMessageBox(const QList &warnings) { - if (!errorWidget()->warningsEnabled()) - return; + if (!errorWidget()->warningsEnabled()) + return; errorWidget()->setWarnings(warnings); errorWidget()->setVisible(true); @@ -408,20 +440,6 @@ QAction *FormEditorWidget::snappingAndAnchoringAction() const return m_snappingAndAnchoringAction.data(); } -void FormEditorWidget::setZoomLevel(double zoomLevel) -{ - m_graphicsView->resetTransform(); - - m_graphicsView->scale(zoomLevel, zoomLevel); - - if (zoomLevel == 1.0) { - if (m_formEditorView->rootModelNode().hasAuxiliaryData("formeditorZoom")) - m_formEditorView->rootModelNode().setAuxiliaryData("formeditorZoom", {}); - } else { - m_formEditorView->rootModelNode().setAuxiliaryData("formeditorZoom", zoomLevel); - } -} - void FormEditorWidget::setScene(FormEditorScene *scene) { m_graphicsView->setScene(scene); @@ -434,7 +452,7 @@ QActionGroup *FormEditorWidget::toolActionGroup() const ToolBox *FormEditorWidget::toolBox() const { - return m_toolBox.data(); + return m_toolBox.data(); } double FormEditorWidget::spacing() const @@ -510,10 +528,11 @@ DocumentWarningWidget *FormEditorWidget::errorWidget() { if (m_documentErrorWidget.isNull()) { m_documentErrorWidget = new DocumentWarningWidget(this); - connect(m_documentErrorWidget.data(), &DocumentWarningWidget::gotoCodeClicked, [=] - (const QString &, int codeLine, int codeColumn) { - m_formEditorView->gotoError(codeLine, codeColumn); - }); + connect(m_documentErrorWidget.data(), + &DocumentWarningWidget::gotoCodeClicked, + [=](const QString &, int codeLine, int codeColumn) { + m_formEditorView->gotoError(codeLine, codeColumn); + }); } return m_documentErrorWidget; } diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h index 8cd8278da47..d0c1fa7c5ee 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h @@ -28,8 +28,8 @@ #include -#include #include +#include QT_BEGIN_NAMESPACE class QActionGroup; @@ -70,6 +70,7 @@ public: void setRootItemRect(const QRectF &rect); QRectF rootItemRect() const; + void initialize(); void updateActions(); void resetView(); @@ -88,7 +89,6 @@ public: FormEditorGraphicsView *graphicsView() const; protected: - void wheelEvent(QWheelEvent *event) override; QActionGroup *toolActionGroup() const; DocumentWarningWidget *errorWidget(); void hideEvent(QHideEvent *event) override; @@ -96,7 +96,6 @@ protected: private: void changeTransformTool(bool checked); - void setZoomLevel(double zoomLevel); void changeRootItemWidth(const QString &widthText); void changeRootItemHeight(const QString &heightText); void changeBackgound(const QColor &color); diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index 466d304955b..c14599c204d 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -32,6 +32,7 @@ #include "openuiqmlfiledialog.h" #include "generateresource.h" #include "nodeinstanceview.h" +#include "gestures.h" #include #include @@ -221,6 +222,8 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e if (QFontDatabase::addApplicationFont(fontPath) < 0) qCWarning(qmldesignerLog) << "Could not add font " << fontPath << "to font database"; + TwoFingerSwipe::registerRecognizer(); + return true; } diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index dd7a95c9700..a0c919b91b3 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.qbs +++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs @@ -452,6 +452,8 @@ Project { "componentcore/designeractionmanagerview.h", "componentcore/findimplementation.cpp", "componentcore/findimplementation.h", + "componentcore/gestures.cpp", + "componentcore/gestures.h", "componentcore/layoutingridlayout.cpp", "componentcore/layoutingridlayout.h", "componentcore/theme.cpp",