From 2ee0e8770bf43182aae7fd4420e7bd986ecdd68e Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 30 Oct 2015 16:40:07 +0100 Subject: [PATCH] Improve the hit testing of an interactive PageIndicator The Universal style has relatively large spacing between the dots. The small dots are hard to hit => select the nearest dot. Change-Id: I2207e887706be38c1a6091bd8aca13d26b9957a8 Reviewed-by: Mitch Curtis --- src/templates/qquickpageindicator.cpp | 32 ++++++++++++++++--- .../auto/controls/data/tst_pageindicator.qml | 18 +++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/templates/qquickpageindicator.cpp b/src/templates/qquickpageindicator.cpp index 31fe28dbf9..331a1d8567 100644 --- a/src/templates/qquickpageindicator.cpp +++ b/src/templates/qquickpageindicator.cpp @@ -37,6 +37,8 @@ #include "qquickpageindicator_p.h" #include "qquickcontrol_p_p.h" +#include +#include #include QT_BEGIN_NAMESPACE @@ -86,11 +88,33 @@ public: QQuickItem *QQuickPageIndicatorPrivate::itemAt(const QPoint &pos) const { Q_Q(const QQuickPageIndicator); - if (contentItem) { - QPointF mapped = q->mapToItem(contentItem, pos); - return contentItem->childAt(mapped.x(), mapped.y()); + if (!contentItem || !q->contains(pos)) + return Q_NULLPTR; + + QPointF contentPos = q->mapToItem(contentItem, pos); + QQuickItem *item = contentItem->childAt(contentPos.x(), contentPos.y()); + while (item && item->parentItem() != contentItem) + item = item->parentItem(); + if (item && !QQuickItemPrivate::get(item)->isTransparentForPositioner()) + return item; + + // find the nearest + qreal distance = qInf(); + QQuickItem *nearest = Q_NULLPTR; + foreach (QQuickItem *child, contentItem->childItems()) { + if (QQuickItemPrivate::get(child)->isTransparentForPositioner()) + continue; + + QPointF center = child->boundingRect().center(); + QPointF pt = contentItem->mapToItem(child, contentPos); + + qreal len = QLineF(center, pt).length(); + if (len < distance) { + distance = len; + nearest = child; + } } - return Q_NULLPTR; + return nearest; } void QQuickPageIndicatorPrivate::updatePressed(bool pressed, const QPoint &pos) diff --git a/tests/auto/controls/data/tst_pageindicator.qml b/tests/auto/controls/data/tst_pageindicator.qml index 3a37aa259e..11b2ec31f9 100644 --- a/tests/auto/controls/data/tst_pageindicator.qml +++ b/tests/auto/controls/data/tst_pageindicator.qml @@ -93,6 +93,24 @@ TestCase { mouseClick(control, control.width / 2, control.height / 2, Qt.LeftButton) compare(control.currentIndex, 2) + // test also clicking outside delegates => the nearest should be selected + control.padding = 10 + control.spacing = 10 + + for (var i = 0; i < control.count; ++i) { + var child = control.contentItem.children[i] + for (var x = -2; x <= child.width + 2; ++x) { + for (var y = -2; y <= child.height + 2; ++y) { + control.currentIndex = -1 + compare(control.currentIndex, -1) + + var pos = control.mapFromItem(child, x, y) + mouseClick(control, pos.x, pos.y, Qt.LeftButton) + compare(control.currentIndex, i) + } + } + } + control.destroy() } }