From c48f4bde0044bd5b23af231f3639d0779ecbdb03 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 1 Feb 2018 20:59:58 +0100 Subject: Set the ellipseDiameters back to the original size in QGraphicsView When calling setSceneRect() on a QTouchPoint it will cause the ellipseDiameters to be changed, whereas this should not be affected by the scene rectangle as it should be in logical pixels. Also add a manual test for visually checking the ellipse diameters on various devices. Change-Id: I1ee9207cb1a63cfef33fe904594c73aba221af5c Reviewed-by: Shawn Rutledge --- .../qgraphicsscene/tst_qgraphicsscene.cpp | 76 ++++++++++ tests/manual/touchGraphicsItem/main.cpp | 163 +++++++++++++++++++++ .../manual/touchGraphicsItem/touchGraphicsItem.pro | 5 + 3 files changed, 244 insertions(+) create mode 100644 tests/manual/touchGraphicsItem/main.cpp create mode 100644 tests/manual/touchGraphicsItem/touchGraphicsItem.pro (limited to 'tests') diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp index bfdb540c2b..e7cf8f17a2 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp @@ -254,6 +254,7 @@ private slots: void zeroScale(); void focusItemChangedSignal(); void minimumRenderSize(); + void checkTouchPointsEllipseDiameters(); // task specific tests below me void task139710_bspTreeCrash(); @@ -4764,6 +4765,81 @@ void tst_QGraphicsScene::minimumRenderSize() QVERIFY(smallChild->repaints > smallerGrandChild->repaints); } +class TouchItem : public QGraphicsRectItem +{ +public: + TouchItem() : QGraphicsRectItem(QRectF(-10, -10, 20, 20)), + seenTouch(false) + { + setAcceptTouchEvents(true); + setFlag(QGraphicsItem::ItemIgnoresTransformations); + } + bool seenTouch; + QList touchPoints; +protected: + bool sceneEvent(QEvent *event) override + { + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + seenTouch = true; + touchPoints = static_cast(event)->touchPoints(); + event->accept(); + return true; + default: + break; + } + return QGraphicsRectItem::sceneEvent(event); + } +}; + +void tst_QGraphicsScene::checkTouchPointsEllipseDiameters() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + scene.setSceneRect(1, 1, 198, 198); + view.scale(1.5, 1.5); + view.setFocus(); + TouchItem *rect = new TouchItem; + scene.addItem(rect); + view.show(); + QApplication::setActiveWindow(&view); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + const QSizeF ellipseDiameters(10.0, 10.0); + QTouchEvent::TouchPoint touchPoint(0); + touchPoint.setState(Qt::TouchPointPressed); + touchPoint.setPos(view.mapFromScene(rect->mapToScene(rect->boundingRect().center()))); + touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint())); + touchPoint.setEllipseDiameters(ellipseDiameters); + + QList touchPoints = { touchPoint }; + + QTouchDevice *testDevice = QTest::createTouchDevice(QTouchDevice::TouchPad); + QTouchEvent touchEvent(QEvent::TouchBegin, + testDevice, + Qt::NoModifier, + Qt::TouchPointPressed, + touchPoints); + QApplication::sendEvent(view.viewport(), &touchEvent); + QVERIFY(rect->seenTouch); + QVERIFY(rect->touchPoints.size() == 1); + QCOMPARE(ellipseDiameters, rect->touchPoints.first().ellipseDiameters()); + + rect->seenTouch = false; + rect->touchPoints.clear(); + QTouchEvent touchUpdateEvent(QEvent::TouchUpdate, + testDevice, + Qt::NoModifier, + Qt::TouchPointMoved, + touchPoints); + QApplication::sendEvent(view.viewport(), &touchEvent); + QVERIFY(rect->seenTouch); + QVERIFY(rect->touchPoints.size() == 1); + QCOMPARE(ellipseDiameters, rect->touchPoints.first().ellipseDiameters()); +} + void tst_QGraphicsScene::taskQTBUG_15977_renderWithDeviceCoordinateCache() { QGraphicsScene scene; diff --git a/tests/manual/touchGraphicsItem/main.cpp b/tests/manual/touchGraphicsItem/main.cpp new file mode 100644 index 0000000000..7afadc7edd --- /dev/null +++ b/tests/manual/touchGraphicsItem/main.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +class TouchableItem : public QGraphicsRectItem +{ +public: + TouchableItem() : QGraphicsRectItem(50, 50, 400, 400) + { + setBrush(Qt::yellow); + setAcceptTouchEvents(true); + } +protected: + bool sceneEvent(QEvent *e) + { + const bool ret = QGraphicsRectItem::sceneEvent(e); + switch (e->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + { + QTouchEvent *te = static_cast(e); + for (const QTouchEvent::TouchPoint &tp : te->touchPoints()) { + QGraphicsEllipseItem *diameterItem = nullptr; + QSizeF ellipse = tp.ellipseDiameters(); + if (ellipse.isNull()) { + ellipse = QSizeF(5, 5); + } else { + diameterItem = new QGraphicsEllipseItem(QRectF(tp.pos().x() - ellipse.width() / 2, tp.pos().y() - ellipse.height() / 2, + ellipse.width(), ellipse.height()), this); + diameterItem->setPen(QPen(Qt::red)); + diameterItem->setBrush(QBrush(Qt::red)); + if (ellipse.width() > qreal(2) && ellipse.height() > qreal(2)) + ellipse.scale(ellipse.width() - 2, ellipse.height() - 2, Qt::IgnoreAspectRatio); + } + QGraphicsItem *parent = diameterItem ? static_cast(diameterItem) : static_cast(this); + QGraphicsEllipseItem *ellipseItem = new QGraphicsEllipseItem(QRectF(tp.pos().x() - ellipse.width() / 2, + tp.pos().y() - ellipse.height() / 2, + ellipse.width(), ellipse.height()), parent); + ellipseItem->setPen(QPen(Qt::blue)); + ellipseItem->setBrush(QBrush(Qt::blue)); + } + te->accept(); + return true; + } + default: + break; + } + return ret; + } +}; + +int main(int argc, char **argv) +{ + QApplication a(argc, argv); + QMainWindow mw; + QWidget *w = new QWidget; + QVBoxLayout *vbox = new QVBoxLayout; + vbox->addWidget(new QLabel("The blue ellipses should indicate touch point contact patches")); + qDebug() << "Touch devices:"; + for (const QTouchDevice *device : QTouchDevice::devices()) { + QString result; + QTextStream str(&result); + str << (device->type() == QTouchDevice::TouchScreen ? "TouchScreen" : "TouchPad") + << " \"" << device->name() << "\", max " << device->maximumTouchPoints() + << " touch points, capabilities:"; + const QTouchDevice::Capabilities capabilities = device->capabilities(); + if (capabilities & QTouchDevice::Position) + str << " Position"; + if (capabilities & QTouchDevice::Area) + str << " Area"; + if (capabilities & QTouchDevice::Pressure) + str << " Pressure"; + if (capabilities & QTouchDevice::Velocity) + str << " Velocity"; + if (capabilities & QTouchDevice::RawPositions) + str << " RawPositions"; + if (capabilities & QTouchDevice::NormalizedPosition) + str << " NormalizedPosition"; + if (capabilities & QTouchDevice::MouseEmulation) + str << " MouseEmulation"; + vbox->addWidget(new QLabel(result)); + qDebug() << " " << result; + } + QGraphicsView *view = new QGraphicsView; + view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents); + QGraphicsScene *scene = new QGraphicsScene(0, 0, 500, 500); + TouchableItem *touchableItem = new TouchableItem; + scene->addItem(touchableItem); + view->setScene(scene); + vbox->addWidget(view); + w->setLayout(vbox); + mw.setCentralWidget(w); + QMenu *menu = mw.menuBar()->addMenu("Menu"); + QAction *clear = new QAction("Clear"); + QObject::connect(clear, &QAction::triggered, [=]() { + qDeleteAll(touchableItem->childItems()); + }); + menu->addAction(clear); + QAction *ignoreTransform = new QAction("Ignore transformations"); + QObject::connect(ignoreTransform, &QAction::triggered, [=]() { + view->scale(1.5, 1.5); + touchableItem->setFlag(QGraphicsItem::ItemIgnoresTransformations); + }); + menu->addAction(ignoreTransform); + QAction *quit = new QAction("Quit"); + quit->setShortcut(QKeySequence::Quit); + QObject::connect(quit, &QAction::triggered, &QApplication::quit); + menu->addAction(quit); + mw.show(); + + return a.exec(); +} + + diff --git a/tests/manual/touchGraphicsItem/touchGraphicsItem.pro b/tests/manual/touchGraphicsItem/touchGraphicsItem.pro new file mode 100644 index 0000000000..67799ce9c4 --- /dev/null +++ b/tests/manual/touchGraphicsItem/touchGraphicsItem.pro @@ -0,0 +1,5 @@ +QT+=widgets +TEMPLATE = app +TARGET = touchGraphicsItem +INCLUDEPATH += . +SOURCES += main.cpp -- cgit v1.2.3