diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2017-04-06 22:13:27 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2017-04-06 22:13:27 +0200 |
commit | 2784902b9b42de127c0903c3d6b076297cf47a07 (patch) | |
tree | 3b95b5cdf61c951f7d54fccf47b14a0ccbce7e6c | |
parent | 0a96b436d9845899888f7c7d153f0d9909ce4c06 (diff) | |
parent | f8224c9c9e3dfc1fd4cc3bff915e7e2d1c411d05 (diff) |
Merge remote-tracking branch 'origin/5.9' into dev
Conflicts:
src/imports/templates/qtquicktemplates2plugin.cpp
Change-Id: I4a07d331163a85a0fb98a5f58f3970863f8da0fc
37 files changed, 916 insertions, 99 deletions
@@ -32,6 +32,7 @@ /tests/auto/controls/default/tst_default /tests/auto/controls/material/tst_material /tests/auto/controls/universal/tst_universal +/tests/auto/cursor/tst_cursor /tests/auto/drawer/tst_drawer /tests/auto/focus/tst_focus /tests/auto/menu/tst_menu diff --git a/examples/quickcontrols2/gallery/gallery.qml b/examples/quickcontrols2/gallery/gallery.qml index ed5171df..9f253ab3 100644 --- a/examples/quickcontrols2/gallery/gallery.qml +++ b/examples/quickcontrols2/gallery/gallery.qml @@ -48,7 +48,7 @@ ** ****************************************************************************/ -import QtQuick 2.6 +import QtQuick 2.9 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.1 @@ -68,7 +68,7 @@ ApplicationWindow { } Shortcut { - sequence: "Esc" + sequences: ["Esc", "Back"] enabled: stackView.depth > 1 onActivated: { stackView.pop() @@ -76,6 +76,11 @@ ApplicationWindow { } } + Shortcut { + sequence: "Menu" + onActivated: optionsMenu.open() + } + header: ToolBar { Material.foreground: "white" diff --git a/src/imports/calendar/qquickmonthgrid.cpp b/src/imports/calendar/qquickmonthgrid.cpp index 5eb0798c..9621f49a 100644 --- a/src/imports/calendar/qquickmonthgrid.cpp +++ b/src/imports/calendar/qquickmonthgrid.cpp @@ -195,6 +195,9 @@ QQuickMonthGrid::QQuickMonthGrid(QQuickItem *parent) : setFlag(ItemIsFocusScope); setActiveFocusOnTab(true); setAcceptedMouseButtons(Qt::LeftButton); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif d->model = new QQuickMonthModel(this); d->source = QVariant::fromValue(d->model); diff --git a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc index 99b6c2ea..4f0771a6 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc @@ -35,6 +35,36 @@ to build complete interfaces in Qt Quick. The module was introduced in Qt 5.7. + Qt Quick Controls 2 comes with a selection customizable styles. + See \l {Styling Qt Quick Controls 2} for more details. + + \raw HTML + <table style="background:transparent; border:0px" width="66%"> + <tr> + <td style="border:0px; padding-right:25px;"> + <a href="qtquickcontrols2-default.html"> + <img src="images/qtquickcontrols2-default.png" alt="Default" width="100%"/> + </a> + </td> + <td style="border:0px; padding-right:25px;"> + <a href="qtquickcontrols2-material.html"> + <img src="images/qtquickcontrols2-material.png" alt="Material" width="100%"/> + </a> + </td> + <td style="border:0px;"> + <a href="qtquickcontrols2-universal.html"> + <img src="images/qtquickcontrols2-universal.png" alt="Universal" width="100%"/> + </a> + </td> + </tr> + <tr> + <td style="border:0px">Default</td> + <td style="border:0px">Material</td> + <td style="border:0px">Universal</td> + </tr> + </table> + \endraw + \section1 Prerequisites The \l{Qt Quick Controls 2 QML Types}{QML types} can be imported into your @@ -62,7 +92,7 @@ \section1 Versions - Qt Quick Controls 2.0 was released in Qt 5.7. Subsequent minor Qt releases + Qt Quick Controls 2.0 was introduced in Qt 5.7. Subsequent minor Qt releases increment the import version of the Qt Quick Controls 2 modules by one. The experimental Qt Labs modules use import version 1.0. @@ -71,35 +101,31 @@ \li \c Qt \li \l {Qt Quick QML Types}{\c QtQuick} \li \l {Qt Quick Controls 2 QML Types}{\c QtQuick.Controls},\br - \l {Qt Quick Templates 2 QML Types}{\c QtQuick.Templates}, - \li \l {Material Style}{\c QtQuick.Controls.Material},\br - \l {Universal Style}{\c QtQuick.Controls.Universal} + \l {Material Style}{\c QtQuick.Controls.Material},\br + \l {Universal Style}{\c QtQuick.Controls.Universal},\br + \l {Qt Quick Templates 2 QML Types}{\c QtQuick.Templates} \li \l {Qt Labs Calendar QML Types}{\c Qt.labs.calendar},\br \l {Qt Labs Platform QML Types}{\c Qt.labs.platform} \row \li 5.7 \li 2.7 \li 2.0 - \li 2.0 \li 1.0 \row \li 5.8 \li 2.8 \li 2.1 - \li 2.1 \li 1.0 \row \li 5.9 \li 2.9 \li 2.2 - \li 2.2 \li 1.0 \row \li ... \li ... \li ... \li ... - \li ... \endtable \section1 Important Concepts in Qt Quick Controls 2 @@ -129,6 +155,7 @@ \li \l{Qt Quick Controls 2 - Gallery}{Gallery} \li \l{Qt Quick Controls 2 - Chat Tutorial}{Chat Tutorial} \li \l{Qt Quick Controls 2 - Text Editor}{Text Editor} + \li \l{Qt Quick Controls 2 - Wearable Demo}{Wearable Demo} \li \l{Qt Quick Controls 2 Examples}{All Examples} \endlist diff --git a/src/imports/controls/material/qquickmaterialbusyindicator.cpp b/src/imports/controls/material/qquickmaterialbusyindicator.cpp index 7bc96505..9df8f5d2 100644 --- a/src/imports/controls/material/qquickmaterialbusyindicator.cpp +++ b/src/imports/controls/material/qquickmaterialbusyindicator.cpp @@ -178,7 +178,7 @@ void QQuickMaterialBusyIndicatorNode::sync(QQuickItem *item) } QQuickMaterialBusyIndicator::QQuickMaterialBusyIndicator(QQuickItem *parent) : - QQuickItem(parent) + QQuickItem(parent), m_elapsed(0), m_color(Qt::black) { setFlag(ItemHasContents); } diff --git a/src/imports/templates/qtquicktemplates2plugin.cpp b/src/imports/templates/qtquicktemplates2plugin.cpp index a43d5baf..becea232 100644 --- a/src/imports/templates/qtquicktemplates2plugin.cpp +++ b/src/imports/templates/qtquicktemplates2plugin.cpp @@ -252,6 +252,7 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri) // NOTE: register the latest revisions of all template/control base classes to // make revisioned properties available to their subclasses (synced with Qt 5.9) qmlRegisterRevision<QQuickText, 9>(uri, 2, 2); + qmlRegisterRevision<QQuickTextInput, 9>(uri, 2, 2); // QtQuick.Templates 2.3 (new types and revisions in Qt 5.10) qmlRegisterType<QQuickIcon>(); diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp index c0d8101e..9b1a51fb 100644 --- a/src/quicktemplates2/qquickabstractbutton.cpp +++ b/src/quicktemplates2/qquickabstractbutton.cpp @@ -342,6 +342,9 @@ QQuickAbstractButton::QQuickAbstractButton(QQuickItem *parent) setActiveFocusOnTab(true); setFocusPolicy(Qt::StrongFocus); setAcceptedMouseButtons(Qt::LeftButton); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif } QQuickAbstractButton::QQuickAbstractButton(QQuickAbstractButtonPrivate &dd, QQuickItem *parent) @@ -350,6 +353,9 @@ QQuickAbstractButton::QQuickAbstractButton(QQuickAbstractButtonPrivate &dd, QQui setActiveFocusOnTab(true); setFocusPolicy(Qt::StrongFocus); setAcceptedMouseButtons(Qt::LeftButton); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif } QQuickAbstractButton::~QQuickAbstractButton() diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index 786db55b..85c577b4 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -628,6 +628,9 @@ QQuickComboBox::QQuickComboBox(QQuickItem *parent) setFocusPolicy(Qt::StrongFocus); setFlag(QQuickItem::ItemIsFocusScope); setAcceptedMouseButtons(Qt::LeftButton); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif setInputMethodHints(Qt::ImhNoPredictiveText); } @@ -737,12 +740,18 @@ void QQuickComboBox::setEditable(bool editable) QObjectPrivate::connect(input, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText); QObjectPrivate::connect(input, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput); } +#if QT_CONFIG(cursor) + d->contentItem->setCursor(Qt::IBeamCursor); +#endif } else { d->contentItem->removeEventFilter(this); if (QQuickTextInput *input = qobject_cast<QQuickTextInput *>(d->contentItem)) { QObjectPrivate::disconnect(input, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText); QObjectPrivate::disconnect(input, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput); } +#if QT_CONFIG(cursor) + d->contentItem->unsetCursor(); +#endif } } @@ -1542,6 +1551,9 @@ void QQuickComboBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) connect(newInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickComboBox::inputMethodComposingChanged); connect(newInput, &QQuickTextInput::acceptableInputChanged, this, &QQuickComboBox::acceptableInputChanged); } +#if QT_CONFIG(cursor) + newItem->setCursor(Qt::IBeamCursor); +#endif } } diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp index 24a8df01..5b98992b 100644 --- a/src/quicktemplates2/qquickdial.cpp +++ b/src/quicktemplates2/qquickdial.cpp @@ -207,8 +207,6 @@ void QQuickDialPrivate::handlePress(const QPointF &point) void QQuickDialPrivate::handleMove(const QPointF &point) { Q_Q(QQuickDial); - if (!q->keepMouseGrab() && !q->keepTouchGrab()) - return; const qreal oldPos = position; qreal pos = positionAt(point); if (snapMode == QQuickDial::SnapAlways) @@ -260,6 +258,9 @@ QQuickDial::QQuickDial(QQuickItem *parent) { setActiveFocusOnTab(true); setAcceptedMouseButtons(Qt::LeftButton); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif } /*! @@ -648,6 +649,7 @@ void QQuickDial::mousePressEvent(QMouseEvent *event) Q_D(QQuickDial); QQuickControl::mousePressEvent(event); d->handlePress(event->localPos()); + d->handleMove(event->localPos()); } void QQuickDial::mouseMoveEvent(QMouseEvent *event) @@ -708,7 +710,8 @@ void QQuickDial::touchEvent(QTouchEvent *event) setKeepTouchGrab(overYDragThreshold); } } - d->handleMove(point.pos()); + if (keepTouchGrab()) + d->handleMove(point.pos()); } break; diff --git a/src/quicktemplates2/qquickdialog.cpp b/src/quicktemplates2/qquickdialog.cpp index fbb612b3..3ac99caa 100644 --- a/src/quicktemplates2/qquickdialog.cpp +++ b/src/quicktemplates2/qquickdialog.cpp @@ -257,6 +257,8 @@ void QQuickDialog::setFooter(QQuickItem *footer) \snippet qtquickcontrols2-dialog.qml 1 + The buttons will be positioned in the appropriate order for the user's platform. + Possible flags: \value Dialog.Ok An "OK" button defined with the \c AcceptRole. \value Dialog.Open An "Open" button defined with the \c AcceptRole. diff --git a/src/quicktemplates2/qquickdialogbuttonbox.cpp b/src/quicktemplates2/qquickdialogbuttonbox.cpp index f1971635..386577da 100644 --- a/src/quicktemplates2/qquickdialogbuttonbox.cpp +++ b/src/quicktemplates2/qquickdialogbuttonbox.cpp @@ -437,6 +437,8 @@ void QQuickDialogButtonBox::resetAlignment() \snippet qtquickcontrols2-dialogbuttonbox.qml 1 + The buttons will be positioned in the appropriate order for the user's platform. + Possible flags: \value DialogButtonBox.Ok An "OK" button defined with the \c AcceptRole. \value DialogButtonBox.Open An "Open" button defined with the \c AcceptRole. diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp index c72979ae..d31186cd 100644 --- a/src/quicktemplates2/qquickoverlay.cpp +++ b/src/quicktemplates2/qquickoverlay.cpp @@ -97,6 +97,9 @@ static QQuickItem *createDimmer(QQmlComponent *component, QQuickPopup *popup, QQ item->setZ(popup->z()); if (popup->isModal()) { item->setAcceptedMouseButtons(Qt::AllButtons); +#if QT_CONFIG(cursor) + item->setCursor(Qt::ArrowCursor); +#endif #if QT_CONFIG(quicktemplates2_hover) // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8 item->setAcceptHoverEvents(true); diff --git a/src/quicktemplates2/qquickpage.cpp b/src/quicktemplates2/qquickpage.cpp index 701916b6..6b0b3a38 100644 --- a/src/quicktemplates2/qquickpage.cpp +++ b/src/quicktemplates2/qquickpage.cpp @@ -117,6 +117,9 @@ QQuickPage::QQuickPage(QQuickItem *parent) Q_D(QQuickPage); setFlag(ItemIsFocusScope); setAcceptedMouseButtons(Qt::AllButtons); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif d->layout.reset(new QQuickPageLayout(this)); } diff --git a/src/quicktemplates2/qquickpageindicator.cpp b/src/quicktemplates2/qquickpageindicator.cpp index 92b6c0c0..b4c9c14c 100644 --- a/src/quicktemplates2/qquickpageindicator.cpp +++ b/src/quicktemplates2/qquickpageindicator.cpp @@ -247,7 +247,17 @@ void QQuickPageIndicator::setInteractive(bool interactive) return; d->interactive = interactive; - setAcceptedMouseButtons(interactive ? Qt::LeftButton : Qt::NoButton); + if (interactive) { + setAcceptedMouseButtons(Qt::LeftButton); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif + } else { + setAcceptedMouseButtons(Qt::NoButton); +#if QT_CONFIG(cursor) + unsetCursor(); +#endif + } emit interactiveChanged(); } diff --git a/src/quicktemplates2/qquickpane.cpp b/src/quicktemplates2/qquickpane.cpp index 6cb81316..efa85e0c 100644 --- a/src/quicktemplates2/qquickpane.cpp +++ b/src/quicktemplates2/qquickpane.cpp @@ -123,6 +123,9 @@ QQuickPane::QQuickPane(QQuickItem *parent) { setFlag(QQuickItem::ItemIsFocusScope); setAcceptedMouseButtons(Qt::AllButtons); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif } QQuickPane::QQuickPane(QQuickPanePrivate &dd, QQuickItem *parent) @@ -130,6 +133,9 @@ QQuickPane::QQuickPane(QQuickPanePrivate &dd, QQuickItem *parent) { setFlag(QQuickItem::ItemIsFocusScope); setAcceptedMouseButtons(Qt::AllButtons); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif } /*! diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index 9b541803..8c37ea84 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -176,7 +176,7 @@ QT_BEGIN_NAMESPACE This signal is emitted when the popup is opened. - \sa closed + \sa aboutToShow() */ /*! @@ -184,7 +184,23 @@ QT_BEGIN_NAMESPACE This signal is emitted when the popup is closed. - \sa opened + \sa aboutToHide() +*/ + +/*! + \qmlsignal void QtQuick.Controls::Popup::aboutToShow() + + This signal is emitted when the popup is about to show. + + \sa opened() +*/ + +/*! + \qmlsignal void QtQuick.Controls::Popup::aboutToHide() + + This signal is emitted when the popup is about to hide. + + \sa closed() */ QQuickPopupPrivate::QQuickPopupPrivate() diff --git a/src/quicktemplates2/qquickrangeslider.cpp b/src/quicktemplates2/qquickrangeslider.cpp index 175ca06e..9996d041 100644 --- a/src/quicktemplates2/qquickrangeslider.cpp +++ b/src/quicktemplates2/qquickrangeslider.cpp @@ -456,8 +456,6 @@ void QQuickRangeSliderPrivate::handlePress(const QPointF &point, int touchId) void QQuickRangeSliderPrivate::handleMove(const QPointF &point, int touchId) { Q_Q(QQuickRangeSlider); - if (!q->keepMouseGrab() && !q->keepTouchGrab()) - return; QQuickRangeSliderNode *pressedNode = QQuickRangeSliderPrivate::pressedNode(touchId); if (pressedNode) { qreal pos = positionAt(q, pressedNode->handle(), point); @@ -521,8 +519,11 @@ QQuickRangeSlider::QQuickRangeSlider(QQuickItem *parent) d->first = new QQuickRangeSliderNode(0.0, this); d->second = new QQuickRangeSliderNode(1.0, this); - setAcceptedMouseButtons(Qt::LeftButton); setFlag(QQuickItem::ItemIsFocusScope); + setAcceptedMouseButtons(Qt::LeftButton); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif } /*! @@ -982,6 +983,7 @@ void QQuickRangeSlider::mousePressEvent(QMouseEvent *event) Q_D(QQuickRangeSlider); QQuickControl::mousePressEvent(event); d->handlePress(event->localPos()); + d->handleMove(event->localPos()); } void QQuickRangeSlider::mouseMoveEvent(QMouseEvent *event) @@ -994,7 +996,8 @@ void QQuickRangeSlider::mouseMoveEvent(QMouseEvent *event) else setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->localPos().y() - d->pressPoint.y(), Qt::YAxis, event)); } - d->handleMove(event->localPos()); + if (keepMouseGrab()) + d->handleMove(event->localPos()); } void QQuickRangeSlider::mouseReleaseEvent(QMouseEvent *event) diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp index 9aeec74f..6050149e 100644 --- a/src/quicktemplates2/qquickscrollbar.cpp +++ b/src/quicktemplates2/qquickscrollbar.cpp @@ -196,9 +196,18 @@ void QQuickScrollBarPrivate::setInteractive(bool enabled) return; interactive = enabled; - q->setAcceptedMouseButtons(interactive ? Qt::LeftButton : Qt::NoButton); - if (!interactive) + if (interactive) { + q->setAcceptedMouseButtons(Qt::LeftButton); +#if QT_CONFIG(cursor) + q->setCursor(Qt::ArrowCursor); +#endif + } else { + q->setAcceptedMouseButtons(Qt::NoButton); +#if QT_CONFIG(cursor) + q->unsetCursor(); +#endif q->ungrabMouse(); + } emit q->interactiveChanged(); } @@ -274,6 +283,9 @@ QQuickScrollBar::QQuickScrollBar(QQuickItem *parent) { setKeepMouseGrab(true); setAcceptedMouseButtons(Qt::LeftButton); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif } QQuickScrollBarAttached *QQuickScrollBar::qmlAttachedProperties(QObject *object) diff --git a/src/quicktemplates2/qquickslider.cpp b/src/quicktemplates2/qquickslider.cpp index 47f51cf2..7c64957b 100644 --- a/src/quicktemplates2/qquickslider.cpp +++ b/src/quicktemplates2/qquickslider.cpp @@ -194,8 +194,6 @@ void QQuickSliderPrivate::handlePress(const QPointF &point) void QQuickSliderPrivate::handleMove(const QPointF &point) { Q_Q(QQuickSlider); - if (!q->keepMouseGrab() && !q->keepTouchGrab()) - return; const qreal oldPos = position; qreal pos = positionAt(point); if (snapMode == QQuickSlider::SnapAlways) @@ -243,6 +241,9 @@ QQuickSlider::QQuickSlider(QQuickItem *parent) setActiveFocusOnTab(true); setFocusPolicy(Qt::StrongFocus); setAcceptedMouseButtons(Qt::LeftButton); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif } /*! @@ -650,6 +651,7 @@ void QQuickSlider::mousePressEvent(QMouseEvent *event) Q_D(QQuickSlider); QQuickControl::mousePressEvent(event); d->handlePress(event->localPos()); + d->handleMove(event->localPos()); } void QQuickSlider::mouseMoveEvent(QMouseEvent *event) @@ -704,7 +706,8 @@ void QQuickSlider::touchEvent(QTouchEvent *event) else setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().y() - d->pressPoint.y(), Qt::YAxis, &point)); } - d->handleMove(point.pos()); + if (keepTouchGrab()) + d->handleMove(point.pos()); } break; diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp index 657102c3..b70366ea 100644 --- a/src/quicktemplates2/qquickspinbox.cpp +++ b/src/quicktemplates2/qquickspinbox.cpp @@ -351,6 +351,9 @@ QQuickSpinBox::QQuickSpinBox(QQuickItem *parent) setFlag(ItemIsFocusScope); setFiltersChildMouseEvents(true); setAcceptedMouseButtons(Qt::LeftButton); +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif } /*! @@ -470,6 +473,15 @@ void QQuickSpinBox::setEditable(bool editable) if (d->editable == editable) return; +#if QT_CONFIG(cursor) + if (d->contentItem) { + if (editable) + d->contentItem->setCursor(Qt::IBeamCursor); + else + d->contentItem->unsetCursor(); + } +#endif + d->editable = editable; emit editableChanged(); } @@ -905,11 +917,16 @@ void QQuickSpinBox::itemChange(ItemChange change, const ItemChangeData &value) void QQuickSpinBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) { + Q_D(QQuickSpinBox); if (QQuickTextInput *oldInput = qobject_cast<QQuickTextInput *>(oldItem)) disconnect(oldInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickSpinBox::inputMethodComposingChanged); if (newItem) { newItem->setActiveFocusOnTab(true); +#if QT_CONFIG(cursor) + if (d->editable) + newItem->setCursor(Qt::IBeamCursor); +#endif if (QQuickTextInput *newInput = qobject_cast<QQuickTextInput *>(newItem)) connect(newInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickSpinBox::inputMethodComposingChanged); diff --git a/src/quicktemplates2/qquickstackview_p.cpp b/src/quicktemplates2/qquickstackview_p.cpp index c6f9291d..3c983d6b 100644 --- a/src/quicktemplates2/qquickstackview_p.cpp +++ b/src/quicktemplates2/qquickstackview_p.cpp @@ -93,6 +93,7 @@ static bool initProperties(QQuickStackElement *element, const QV4::Value &props, QList<QQuickStackElement *> QQuickStackViewPrivate::parseElements(int from, QQmlV4Function *args, QStringList *errors) { QV4::ExecutionEngine *v4 = args->v4engine(); + QQmlContextData *context = v4->callingQmlContext(); QV4::Scope scope(v4); QList<QQuickStackElement *> elements; @@ -105,7 +106,7 @@ QList<QQuickStackElement *> QQuickStackViewPrivate::parseElements(int from, QQml for (int j = 0; j < len; ++j) { QString error; QV4::ScopedValue value(scope, array->getIndexed(j)); - QQuickStackElement *element = createElement(value, &error); + QQuickStackElement *element = createElement(value, context, &error); if (element) { if (j < len - 1) { QV4::ScopedValue props(scope, array->getIndexed(j + 1)); @@ -119,7 +120,7 @@ QList<QQuickStackElement *> QQuickStackViewPrivate::parseElements(int from, QQml } } else { QString error; - QQuickStackElement *element = createElement(arg, &error); + QQuickStackElement *element = createElement(arg, context, &error); if (element) { if (i < argc - 1) { QV4::ScopedValue props(scope, (*args)[i + 1]); @@ -153,11 +154,19 @@ QQuickStackElement *QQuickStackViewPrivate::findElement(const QV4::Value &value) return nullptr; } -QQuickStackElement *QQuickStackViewPrivate::createElement(const QV4::Value &value, QString *error) +static QString resolvedUrl(const QString &str, QQmlContextData *context) +{ + QUrl url(str); + if (url.isRelative()) + return context->resolvedUrl(url).toString(); + return str; +} + +QQuickStackElement *QQuickStackViewPrivate::createElement(const QV4::Value &value, QQmlContextData *context, QString *error) { Q_Q(QQuickStackView); if (const QV4::String *s = value.as<QV4::String>()) - return QQuickStackElement::fromString(s->toQString(), q, error); + return QQuickStackElement::fromString(resolvedUrl(s->toQString(), context), q, error); if (const QV4::QObjectWrapper *o = value.as<QV4::QObjectWrapper>()) return QQuickStackElement::fromObject(o->object(), q, error); return nullptr; diff --git a/src/quicktemplates2/qquickstackview_p_p.h b/src/quicktemplates2/qquickstackview_p_p.h index 26d741f8..81ca9164 100644 --- a/src/quicktemplates2/qquickstackview_p_p.h +++ b/src/quicktemplates2/qquickstackview_p_p.h @@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE +class QQmlContextData; class QQuickStackElement; struct QQuickStackTransition; @@ -79,7 +80,7 @@ public: QList<QQuickStackElement *> parseElements(int from, QQmlV4Function *args, QStringList *errors); QQuickStackElement *findElement(QQuickItem *item) const; QQuickStackElement *findElement(const QV4::Value &value) const; - QQuickStackElement *createElement(const QV4::Value &value, QString *error); + QQuickStackElement *createElement(const QV4::Value &value, QQmlContextData *context, QString *error); bool pushElements(const QList<QQuickStackElement *> &elements); bool pushElement(QQuickStackElement *element); bool popElements(QQuickStackElement *element); diff --git a/src/quicktemplates2/qquicktabbar_p.h b/src/quicktemplates2/qquicktabbar_p.h index bc228346..0ffd53d5 100644 --- a/src/quicktemplates2/qquicktabbar_p.h +++ b/src/quicktemplates2/qquicktabbar_p.h @@ -83,8 +83,8 @@ public: Q_SIGNALS: void positionChanged(); - void contentWidthChanged(); - void contentHeightChanged(); + Q_REVISION(2) void contentWidthChanged(); + Q_REVISION(2) void contentHeightChanged(); protected: void updatePolish() override; diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 38f098c9..0162c38f 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -4,6 +4,7 @@ SUBDIRS += \ applicationwindow \ calendar \ controls \ + cursor \ drawer \ menu \ platform \ diff --git a/tests/auto/controls/data/tst_combobox.qml b/tests/auto/controls/data/tst_combobox.qml index fb4dc57c..05eb2de1 100644 --- a/tests/auto/controls/data/tst_combobox.qml +++ b/tests/auto/controls/data/tst_combobox.qml @@ -55,8 +55,8 @@ import QtQuick.Controls 2.2 TestCase { id: testCase - width: 200 - height: 200 + width: 400 + height: 400 visible: true when: windowShown name: "ComboBox" @@ -724,6 +724,8 @@ TestCase { compare(downSpy.count, 3) compare(pressedSpy.count, 2) + compare(control.popup.y, control.height) + control.down = false compare(control.down, false) compare(downSpy.count, 4) diff --git a/tests/auto/controls/data/tst_dial.qml b/tests/auto/controls/data/tst_dial.qml index 98c3a002..3b20e91d 100644 --- a/tests/auto/controls/data/tst_dial.qml +++ b/tests/auto/controls/data/tst_dial.qml @@ -465,7 +465,7 @@ TestCase { compare(dial.value, dial.to); } - function test_snapMode_data() { + function test_snapMode_data(immediate) { return [ { tag: "NoSnap", snapMode: Slider.NoSnap, from: 0, to: 2, values: [0, 0, 1], positions: [0, 0.5, 0.5] }, { tag: "SnapAlways (0..2)", snapMode: Slider.SnapAlways, from: 0, to: 2, values: [0.0, 0.0, 1.0], positions: [0.0, 0.5, 0.5] }, @@ -474,13 +474,13 @@ TestCase { { tag: "SnapAlways (1..-1)", snapMode: Slider.SnapAlways, from: 1, to: -1, values: [1.0, 1.0, 0.0], positions: [0.0, 0.5, 0.5] }, { tag: "SnapOnRelease (0..2)", snapMode: Slider.SnapOnRelease, from: 0, to: 2, values: [0.0, 0.0, 1.0], positions: [0.0, 0.5, 0.5] }, { tag: "SnapOnRelease (1..3)", snapMode: Slider.SnapOnRelease, from: 1, to: 3, values: [1.0, 1.0, 2.0], positions: [0.0, 0.5, 0.5] }, - { tag: "SnapOnRelease (-1..1)", snapMode: Slider.SnapOnRelease, from: -1, to: 1, values: [0.0, 0.0, 0.0], positions: [0.5, 0.5, 0.5] }, + { tag: "SnapOnRelease (-1..1)", snapMode: Slider.SnapOnRelease, from: -1, to: 1, values: [0.0, 0.0, 0.0], positions: [immediate ? 0.0 : 0.5, 0.5, 0.5] }, { tag: "SnapOnRelease (1..-1)", snapMode: Slider.SnapOnRelease, from: 1, to: -1, values: [1.0, 1.0, 0.0], positions: [0.0, 0.5, 0.5] } ] } function test_snapMode_mouse_data() { - return test_snapMode_data() + return test_snapMode_data(true) } function test_snapMode_mouse(data) { @@ -492,11 +492,11 @@ TestCase { dial.to = data.to; dial.stepSize = 0.2; - var fuzz = 0.05; + var fuzz = 0.055; mousePress(dial, dial.width * 0.25, dial.height * 0.75); - compare(dial.value, data.values[0]); - compare(dial.position, data.positions[0]); + fuzzyCompare(dial.value, data.values[0], fuzz); + fuzzyCompare(dial.position, data.positions[0], fuzz); mouseMove(dial, dial.width * 0.5, dial.height * 0.25); fuzzyCompare(dial.value, data.values[1], fuzz); @@ -508,7 +508,7 @@ TestCase { } function test_snapMode_touch_data() { - return test_snapMode_data() + return test_snapMode_data(false) } function test_snapMode_touch(data) { diff --git a/tests/auto/controls/data/tst_rangeslider.qml b/tests/auto/controls/data/tst_rangeslider.qml index 867bb70a..bc3ce515 100644 --- a/tests/auto/controls/data/tst_rangeslider.qml +++ b/tests/auto/controls/data/tst_rangeslider.qml @@ -294,7 +294,7 @@ TestCase { var secondPressedSpy = signalSpy.createObject(control, {target: control.second, signalName: "pressedChanged"}) verify(secondPressedSpy.valid) - mousePress(control, control.width * 0.25, control.height * 0.75, Qt.LeftButton) + mousePress(control, control.leftPadding, control.height - control.bottomPadding, Qt.LeftButton) compare(firstPressedSpy.count, 1) compare(secondPressedSpy.count, 0) compare(control.first.pressed, true) @@ -304,7 +304,7 @@ TestCase { compare(control.second.value, 1.0) compare(control.second.position, 1.0) - mouseRelease(control, control.width * 0.25, control.height * 0.75, Qt.LeftButton) + mouseRelease(control, control.leftPadding, control.height - control.bottomPadding, Qt.LeftButton) compare(firstPressedSpy.count, 2) compare(secondPressedSpy.count, 0) compare(control.first.pressed, false) @@ -314,7 +314,7 @@ TestCase { compare(control.second.value, 1.0) compare(control.second.position, 1.0) - mousePress(control, control.width * 0.75, control.height * 0.25, Qt.LeftButton) + mousePress(control, control.width - control.rightPadding, control.topPadding, Qt.LeftButton) compare(firstPressedSpy.count, 2) compare(secondPressedSpy.count, 1) compare(control.first.pressed, false) @@ -324,7 +324,7 @@ TestCase { compare(control.second.value, 1.0) compare(control.second.position, 1.0) - mouseRelease(control, control.width * 0.75, control.height * 0.25, Qt.LeftButton) + mouseRelease(control, control.width - control.rightPadding, control.topPadding, Qt.LeftButton) compare(firstPressedSpy.count, 2) compare(secondPressedSpy.count, 2) compare(control.first.pressed, false) @@ -354,7 +354,7 @@ TestCase { compare(control.second.value, 1.0) compare(control.second.position, 1.0) - mousePress(control, control.first.handle.x, control.first.handle.y, Qt.LeftButton) + mousePress(control, control.leftPadding, control.height - control.bottomPadding, Qt.LeftButton) compare(firstPressedSpy.count, 5) compare(secondPressedSpy.count, 2) compare(control.first.pressed, true) @@ -745,7 +745,8 @@ TestCase { control.first.value = 0 control.locale = Qt.locale("ar_EG") - mousePress(control, control.first.handle.x, control.first.handle.y, Qt.LeftButton) + mousePress(control, control.first.handle.x + control.first.handle.width / 2, + control.first.handle.y + control.first.handle.height / 2, Qt.LeftButton) compare(firstPressedSpy.count, 3) compare(control.first.pressed, true) compare(control.first.value, 0.0) @@ -774,22 +775,22 @@ TestCase { compare(control.first.visualPosition, 0.5) } - function test_snapMode_data() { + function test_snapMode_data(immediate) { return [ { tag: "NoSnap", snapMode: RangeSlider.NoSnap, from: 0, to: 2, values: [0, 0, 0.25], positions: [0, 0.1, 0.1] }, { tag: "SnapAlways (0..2)", snapMode: RangeSlider.SnapAlways, from: 0, to: 2, values: [0.0, 0.0, 0.2], positions: [0.0, 0.1, 0.1] }, { tag: "SnapAlways (1..3)", snapMode: RangeSlider.SnapAlways, from: 1, to: 3, values: [1.0, 1.0, 1.2], positions: [0.0, 0.1, 0.1] }, - { tag: "SnapAlways (-1..1)", snapMode: RangeSlider.SnapAlways, from: -1, to: 1, values: [0.0, 0.0, -0.8], positions: [0.5, 0.1, 0.1] }, - { tag: "SnapAlways (1..-1)", snapMode: RangeSlider.SnapAlways, from: 1, to: -1, values: [0.0, 0.0, 0.8], positions: [0.5, 0.1, 0.1] }, + { tag: "SnapAlways (-1..1)", snapMode: RangeSlider.SnapAlways, from: -1, to: 1, values: [0.0, 0.0, -0.8], positions: [immediate ? 0.0 : 0.5, 0.1, 0.1] }, + { tag: "SnapAlways (1..-1)", snapMode: RangeSlider.SnapAlways, from: 1, to: -1, values: [0.0, 0.0, 0.8], positions: [immediate ? 0.0 : 0.5, 0.1, 0.1] }, { tag: "SnapOnRelease (0..2)", snapMode: RangeSlider.SnapOnRelease, from: 0, to: 2, values: [0.0, 0.0, 0.2], positions: [0.0, 0.1, 0.1] }, { tag: "SnapOnRelease (1..3)", snapMode: RangeSlider.SnapOnRelease, from: 1, to: 3, values: [1.0, 1.0, 1.2], positions: [0.0, 0.1, 0.1] }, - { tag: "SnapOnRelease (-1..1)", snapMode: RangeSlider.SnapOnRelease, from: -1, to: 1, values: [0.0, 0.0, -0.8], positions: [0.5, 0.1, 0.1] }, - { tag: "SnapOnRelease (1..-1)", snapMode: RangeSlider.SnapOnRelease, from: 1, to: -1, values: [0.0, 0.0, 0.8], positions: [0.5, 0.1, 0.1] } + { tag: "SnapOnRelease (-1..1)", snapMode: RangeSlider.SnapOnRelease, from: -1, to: 1, values: [0.0, 0.0, -0.8], positions: [immediate ? 0.0 : 0.5, 0.1, 0.1] }, + { tag: "SnapOnRelease (1..-1)", snapMode: RangeSlider.SnapOnRelease, from: 1, to: -1, values: [0.0, 0.0, 0.8], positions: [immediate ? 0.0 : 0.5, 0.1, 0.1] } ] } function test_snapMode_mouse_data() { - return test_snapMode_data() + return test_snapMode_data(true) } function test_snapMode_mouse(data) { @@ -799,28 +800,26 @@ TestCase { control.first.value = 0 control.second.value = data.to - function sliderCompare(left, right) { - return Math.abs(left - right) < 0.05 - } + var fuzz = 0.05 - mousePress(control, control.first.handle.x, control.first.handle.y) + mousePress(control, control.leftPadding) compare(control.first.pressed, true) compare(control.first.value, data.values[0]) compare(control.first.position, data.positions[0]) mouseMove(control, control.leftPadding + 0.15 * (control.availableWidth + control.first.handle.width / 2)) compare(control.first.pressed, true) - verify(sliderCompare(control.first.value, data.values[1])) - verify(sliderCompare(control.first.position, data.positions[1])) + fuzzyCompare(control.first.value, data.values[1], fuzz) + fuzzyCompare(control.first.position, data.positions[1], fuzz) mouseRelease(control, control.leftPadding + 0.15 * (control.availableWidth + control.first.handle.width / 2)) compare(control.first.pressed, false) - verify(sliderCompare(control.first.value, data.values[2])) - verify(sliderCompare(control.first.position, data.positions[2])) + fuzzyCompare(control.first.value, data.values[2], fuzz) + fuzzyCompare(control.first.position, data.positions[2], fuzz) } function test_snapMode_touch_data() { - return test_snapMode_data() + return test_snapMode_data(false) } function test_snapMode_touch(data) { @@ -830,9 +829,7 @@ TestCase { control.first.value = 0 control.second.value = data.to - function sliderCompare(left, right) { - return Math.abs(left - right) < 0.05 - } + var fuzz = 0.05 var touch = touchEvent(control) touch.press(0, control, control.first.handle.x, control.first.handle.y).commit() @@ -842,13 +839,13 @@ TestCase { touch.move(0, control, control.leftPadding + 0.15 * (control.availableWidth + control.first.handle.width / 2)).commit() compare(control.first.pressed, true) - verify(sliderCompare(control.first.value, data.values[1])) - verify(sliderCompare(control.first.position, data.positions[1])) + fuzzyCompare(control.first.value, data.values[1], fuzz) + fuzzyCompare(control.first.position, data.positions[1], fuzz) touch.release(0, control, control.leftPadding + 0.15 * (control.availableWidth + control.first.handle.width / 2)).commit() compare(control.first.pressed, false) - verify(sliderCompare(control.first.value, data.values[2])) - verify(sliderCompare(control.first.position, data.positions[2])) + fuzzyCompare(control.first.value, data.values[2], fuzz) + fuzzyCompare(control.first.position, data.positions[2], fuzz) } function test_focus() { diff --git a/tests/auto/controls/data/tst_slider.qml b/tests/auto/controls/data/tst_slider.qml index 26cb305e..240f734f 100644 --- a/tests/auto/controls/data/tst_slider.qml +++ b/tests/auto/controls/data/tst_slider.qml @@ -236,7 +236,7 @@ TestCase { var movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"}) verify(movedSpy.valid) - mousePress(control, 0, 0, Qt.LeftButton) + mousePress(control, 0, control.height, Qt.LeftButton) compare(pressedSpy.count, ++pressedCount) compare(movedSpy.count, movedCount) compare(control.pressed, true) @@ -265,17 +265,17 @@ TestCase { compare(control.value, 0.5) compare(control.position, 0.5) - mousePress(control, control.width, control.height, Qt.LeftButton) + mousePress(control, control.width, 0, Qt.LeftButton) compare(pressedSpy.count, ++pressedCount) - compare(movedSpy.count, movedCount) + compare(movedSpy.count, ++movedCount) compare(control.pressed, true) - compare(control.value, 0.5) - compare(control.position, 0.5) + compare(control.value, data.live ? 1.0 : 0.5) + compare(control.position, 1.0) // maximum on the right in horizontal vs. at the top in vertical mouseMove(control, control.width * 2, -control.height, 0) compare(pressedSpy.count, pressedCount) - compare(movedSpy.count, ++movedCount) + compare(movedSpy.count, movedCount) compare(control.pressed, true) compare(control.value, data.live ? 1.0 : 0.5) compare(control.position, 1.0) @@ -624,8 +624,8 @@ TestCase { compare(pressedSpy.count, 3) compare(control.pressed, true) compare(control.value, 0.0) - compare(control.position, 0.0) - compare(control.visualPosition, 1.0) + compare(control.position, 1.0) + compare(control.visualPosition, 0.0) mouseMove(control, control.leftPadding + control.availableWidth * 0.5, control.height * 0.5, 0) compare(pressedSpy.count, 3) @@ -649,31 +649,29 @@ TestCase { compare(control.visualPosition, 0.5) } - function test_snapMode_data() { + function test_snapMode_data(immediate) { return [ { tag: "NoSnap", snapMode: Slider.NoSnap, from: 0, to: 2, values: [0, 0, 0.25], positions: [0, 0.1, 0.1] }, { tag: "SnapAlways (0..2)", snapMode: Slider.SnapAlways, from: 0, to: 2, values: [0.0, 0.0, 0.2], positions: [0.0, 0.1, 0.1] }, { tag: "SnapAlways (1..3)", snapMode: Slider.SnapAlways, from: 1, to: 3, values: [1.0, 1.0, 1.2], positions: [0.0, 0.1, 0.1] }, - { tag: "SnapAlways (-1..1)", snapMode: Slider.SnapAlways, from: -1, to: 1, values: [0.0, 0.0, -0.8], positions: [0.5, 0.1, 0.1] }, - { tag: "SnapAlways (1..-1)", snapMode: Slider.SnapAlways, from: 1, to: -1, values: [0.0, 0.0, 0.8], positions: [0.5, 0.1, 0.1] }, + { tag: "SnapAlways (-1..1)", snapMode: Slider.SnapAlways, from: -1, to: 1, values: [0.0, 0.0, -0.8], positions: [immediate ? 0.0 : 0.5, 0.1, 0.1] }, + { tag: "SnapAlways (1..-1)", snapMode: Slider.SnapAlways, from: 1, to: -1, values: [0.0, 0.0, 0.8], positions: [immediate ? 0.0 : 0.5, 0.1, 0.1] }, { tag: "SnapOnRelease (0..2)", snapMode: Slider.SnapOnRelease, from: 0, to: 2, values: [0.0, 0.0, 0.2], positions: [0.0, 0.1, 0.1] }, { tag: "SnapOnRelease (1..3)", snapMode: Slider.SnapOnRelease, from: 1, to: 3, values: [1.0, 1.0, 1.2], positions: [0.0, 0.1, 0.1] }, - { tag: "SnapOnRelease (-1..1)", snapMode: Slider.SnapOnRelease, from: -1, to: 1, values: [0.0, 0.0, -0.8], positions: [0.5, 0.1, 0.1] }, - { tag: "SnapOnRelease (1..-1)", snapMode: Slider.SnapOnRelease, from: 1, to: -1, values: [0.0, 0.0, 0.8], positions: [0.5, 0.1, 0.1] } + { tag: "SnapOnRelease (-1..1)", snapMode: Slider.SnapOnRelease, from: -1, to: 1, values: [0.0, 0.0, -0.8], positions: [immediate ? 0.0 : 0.5, 0.1, 0.1] }, + { tag: "SnapOnRelease (1..-1)", snapMode: Slider.SnapOnRelease, from: 1, to: -1, values: [0.0, 0.0, 0.8], positions: [immediate ? 0.0 : 0.5, 0.1, 0.1] } ] } function test_snapMode_mouse_data() { - return test_snapMode_data() + return test_snapMode_data(true) } function test_snapMode_mouse(data) { var control = createTemporaryObject(slider, testCase, {live: false, snapMode: data.snapMode, from: data.from, to: data.to, stepSize: 0.2}) verify(control) - function sliderCompare(left, right) { - return Math.abs(left - right) < 0.05 - } + var fuzz = 0.05 mousePress(control, control.leftPadding) compare(control.value, data.values[0]) @@ -681,25 +679,23 @@ TestCase { mouseMove(control, control.leftPadding + 0.15 * (control.availableWidth + control.handle.width / 2)) - verify(sliderCompare(control.value, data.values[1])) - verify(sliderCompare(control.position, data.positions[1])) + fuzzyCompare(control.value, data.values[1], fuzz) + fuzzyCompare(control.position, data.positions[1], fuzz) mouseRelease(control, control.leftPadding + 0.15 * (control.availableWidth + control.handle.width / 2)) - verify(sliderCompare(control.value, data.values[2])) - verify(sliderCompare(control.position, data.positions[2])) + fuzzyCompare(control.value, data.values[2], fuzz) + fuzzyCompare(control.position, data.positions[2], fuzz) } function test_snapMode_touch_data() { - return test_snapMode_data() + return test_snapMode_data(false) } function test_snapMode_touch(data) { var control = createTemporaryObject(slider, testCase, {live: false, snapMode: data.snapMode, from: data.from, to: data.to, stepSize: 0.2}) verify(control) - function sliderCompare(left, right) { - return Math.abs(left - right) < 0.05 - } + var fuzz = 0.05 var touch = touchEvent(control) touch.press(0, control, control.leftPadding).commit() @@ -708,12 +704,12 @@ TestCase { touch.move(0, control, control.leftPadding + 0.15 * (control.availableWidth + control.handle.width / 2)).commit() - verify(sliderCompare(control.value, data.values[1])) - verify(sliderCompare(control.position, data.positions[1])) + fuzzyCompare(control.value, data.values[1], fuzz) + fuzzyCompare(control.position, data.positions[1], fuzz) touch.release(0, control, control.leftPadding + 0.15 * (control.availableWidth + control.handle.width / 2)).commit() - verify(sliderCompare(control.value, data.values[2])) - verify(sliderCompare(control.position, data.positions[2])) + fuzzyCompare(control.value, data.values[2], fuzz) + fuzzyCompare(control.position, data.positions[2], fuzz) } function test_wheel_data() { diff --git a/tests/auto/controls/data/tst_stackview.qml b/tests/auto/controls/data/tst_stackview.qml index c56a04de..37bd5222 100644 --- a/tests/auto/controls/data/tst_stackview.qml +++ b/tests/auto/controls/data/tst_stackview.qml @@ -1101,4 +1101,13 @@ TestCase { control.destroy() } + + function test_resolve() { + var control = createTemporaryObject(stackView, testCase) + verify(control) + + var item = control.push("TestItem.qml") + compare(control.depth, 1) + verify(item) + } } diff --git a/tests/auto/cursor/cursor.pro b/tests/auto/cursor/cursor.pro new file mode 100644 index 00000000..4948e943 --- /dev/null +++ b/tests/auto/cursor/cursor.pro @@ -0,0 +1,14 @@ +CONFIG += testcase +TARGET = tst_cursor +SOURCES += tst_cursor.cpp + +macos:CONFIG -= app_bundle + +QT += core-private gui-private qml-private quick-private testlib quicktemplates2-private + +include (../shared/util.pri) + +TESTDATA = data/* + +OTHER_FILES += \ + data/*.qml diff --git a/tests/auto/cursor/data/buttons.qml b/tests/auto/cursor/data/buttons.qml new file mode 100644 index 00000000..21226ef5 --- /dev/null +++ b/tests/auto/cursor/data/buttons.qml @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +import QtQuick 2.6 +import QtQuick.Controls 2.2 + +MouseArea { + width: column.width + height: column.height + cursorShape: Qt.ForbiddenCursor + + Column { + id: column + padding: 10 + spacing: 10 + + Button { + text: "Button" + } + CheckBox { + text: "CheckBox" + } + CheckDelegate { + text: "CheckDelegate" + } + ItemDelegate { + text: "ItemDelegate" + } + MenuItem { + text: "MenuItem" + } + RadioButton { + text: "RadioButton" + } + RadioDelegate { + text: "RadioDelegate" + } + RoundButton { + text: "X" + } + SwipeDelegate { + text: "SwipeDelegate" + } + Switch { + text: "Switch" + } + SwitchDelegate { + text: "SwitchDelegate" + } + TabButton { + text: "TabButton" + } + ToolButton { + text: "ToolButton" + } + } +} diff --git a/tests/auto/cursor/data/containers.qml b/tests/auto/cursor/data/containers.qml new file mode 100644 index 00000000..09fbbc18 --- /dev/null +++ b/tests/auto/cursor/data/containers.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +import QtQuick 2.6 +import QtQuick.Controls 2.2 + +MouseArea { + width: column.width + height: column.height + cursorShape: Qt.ForbiddenCursor + + Column { + id: column + padding: 10 + spacing: 10 + + Page { + width: 200 + height: 20 + } + Pane { + width: 200 + height: 20 + } + ToolBar { + width: 200 + height: 20 + } + } +} diff --git a/tests/auto/cursor/data/editable.qml b/tests/auto/cursor/data/editable.qml new file mode 100644 index 00000000..1956889b --- /dev/null +++ b/tests/auto/cursor/data/editable.qml @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +import QtQuick 2.6 +import QtQuick.Controls 2.2 + +MouseArea { + width: column.width + height: column.height + cursorShape: Qt.ForbiddenCursor + + Column { + id: column + padding: 10 + spacing: 10 + + ComboBox { + editable: true + model: "ComboBox" + } + SpinBox { + editable: true + } + } +} diff --git a/tests/auto/cursor/data/pageindicator.qml b/tests/auto/cursor/data/pageindicator.qml new file mode 100644 index 00000000..1e550a78 --- /dev/null +++ b/tests/auto/cursor/data/pageindicator.qml @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +import QtQuick 2.6 +import QtQuick.Controls 2.2 + +MouseArea { + width: 200 + height: 200 + cursorShape: Qt.ForbiddenCursor + + PageIndicator { + anchors.centerIn: parent + } +} diff --git a/tests/auto/cursor/data/scrollbar.qml b/tests/auto/cursor/data/scrollbar.qml new file mode 100644 index 00000000..01dcd2ae --- /dev/null +++ b/tests/auto/cursor/data/scrollbar.qml @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +import QtQuick 2.6 +import QtQuick.Controls 2.0 + +ApplicationWindow { + width: 400 + height: 400 + + property alias textArea: textArea + property alias scrollBar: scrollBar + + Flickable { + anchors.fill: parent + TextArea.flickable: TextArea { + id: textArea + } + ScrollBar.vertical: ScrollBar { + id: scrollBar + } + } +} diff --git a/tests/auto/cursor/data/sliders.qml b/tests/auto/cursor/data/sliders.qml new file mode 100644 index 00000000..408e8947 --- /dev/null +++ b/tests/auto/cursor/data/sliders.qml @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +import QtQuick 2.6 +import QtQuick.Controls 2.2 + +MouseArea { + width: column.width + height: column.height + cursorShape: Qt.ForbiddenCursor + + Column { + id: column + padding: 10 + spacing: 10 + + Dial { + } + Slider { + } + RangeSlider { + } + } +} diff --git a/tests/auto/cursor/tst_cursor.cpp b/tests/auto/cursor/tst_cursor.cpp new file mode 100644 index 00000000..6256112d --- /dev/null +++ b/tests/auto/cursor/tst_cursor.cpp @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/qtest.h> +#include "../shared/visualtestutil.h" + +#include <QtQuick/qquickview.h> +#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h> +#include <QtQuickTemplates2/private/qquickcontrol_p.h> +#include <QtQuickTemplates2/private/qquickpageindicator_p.h> +#include <QtQuickTemplates2/private/qquickscrollbar_p.h> +#include <QtQuickTemplates2/private/qquicktextarea_p.h> + +using namespace QQuickVisualTestUtil; + +class tst_cursor : public QQmlDataTest +{ + Q_OBJECT + +private slots: + void controls_data(); + void controls(); + void editable(); + void pageIndicator(); + void scrollBar(); +}; + +void tst_cursor::controls_data() +{ + QTest::addColumn<QString>("testFile"); + + QTest::newRow("buttons") << "buttons.qml"; + QTest::newRow("containers") << "containers.qml"; + QTest::newRow("sliders") << "sliders.qml"; +} + +void tst_cursor::controls() +{ + QFETCH(QString, testFile); + + QQuickView view(testFileUrl(testFile)); + view.show(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickItem *mouseArea = view.rootObject(); + QVERIFY(mouseArea); + QCOMPARE(mouseArea->cursor().shape(), Qt::ForbiddenCursor); + + QQuickItem *column = mouseArea->childItems().value(0); + QVERIFY(column); + + const auto controls = column->childItems(); + for (QQuickItem *control : controls) { + QCOMPARE(control->cursor().shape(), Qt::ArrowCursor); + + QTest::mouseMove(&view, control->mapToScene(QPointF(-1, -1)).toPoint()); + QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor); + + QTest::mouseMove(&view, control->mapToScene(QPointF(0, 0)).toPoint()); + QCOMPARE(view.cursor().shape(), Qt::ArrowCursor); + + QTest::mouseMove(&view, control->mapToScene(QPointF(control->width() + 1, control->height() + 1)).toPoint()); + QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor); + } +} + +void tst_cursor::editable() +{ + QQuickView view(testFileUrl("editable.qml")); + view.show(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickItem *mouseArea = view.rootObject(); + QVERIFY(mouseArea); + QCOMPARE(mouseArea->cursor().shape(), Qt::ForbiddenCursor); + + QQuickItem *column = mouseArea->childItems().value(0); + QVERIFY(column); + + const auto children = column->childItems(); + for (QQuickItem *child : children) { + QQuickControl *control = qobject_cast<QQuickControl *>(child); + QVERIFY(control); + QCOMPARE(control->cursor().shape(), Qt::ArrowCursor); + QCOMPARE(control->contentItem()->cursor().shape(), Qt::IBeamCursor); + + QTest::mouseMove(&view, control->mapToScene(QPointF(-1, -1)).toPoint()); + QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor); + + QTest::mouseMove(&view, control->mapToScene(QPointF(control->width() / 2, control->height() / 2)).toPoint()); + QCOMPARE(view.cursor().shape(), Qt::IBeamCursor); + + control->setProperty("editable", false); + QCOMPARE(control->cursor().shape(), Qt::ArrowCursor); + QCOMPARE(control->contentItem()->cursor().shape(), Qt::ArrowCursor); + QCOMPARE(view.cursor().shape(), Qt::ArrowCursor); + + QTest::mouseMove(&view, control->mapToScene(QPointF(control->width() + 1, control->height() + 1)).toPoint()); + QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor); + } +} + +void tst_cursor::pageIndicator() +{ + QQuickView view(testFileUrl("pageindicator.qml")); + view.show(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickItem *mouseArea = view.rootObject(); + QVERIFY(mouseArea); + QCOMPARE(mouseArea->cursor().shape(), Qt::ForbiddenCursor); + + QQuickPageIndicator *indicator = qobject_cast<QQuickPageIndicator *>(mouseArea->childItems().value(0)); + QVERIFY(indicator); + + QTest::mouseMove(&view, indicator->mapToScene(QPointF(-1, -1)).toPoint()); + QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor); + + QTest::mouseMove(&view, indicator->mapToScene(QPointF(0, 0)).toPoint()); + QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor); + + indicator->setInteractive(true); + QCOMPARE(view.cursor().shape(), Qt::ArrowCursor); + + QTest::mouseMove(&view, indicator->mapToScene(QPointF(indicator->width() + 1, indicator->height() + 1)).toPoint()); + QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor); +} + +// QTBUG-59629 +void tst_cursor::scrollBar() +{ + // Ensure that the mouse cursor has the correct shape when over a scrollbar + // which is itself over a text area with IBeamCursor. + QQuickApplicationHelper helper(this, QStringLiteral("scrollbar.qml")); + QQuickApplicationWindow *window = helper.appWindow; + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickScrollBar *scrollBar = helper.appWindow->property("scrollBar").value<QQuickScrollBar*>(); + QVERIFY(scrollBar); + + QQuickTextArea *textArea = helper.appWindow->property("textArea").value<QQuickTextArea*>(); + QVERIFY(textArea); + + textArea->setText(QString("\n").repeated(100)); + + const QPoint textAreaPos(window->width() / 2, window->height() / 2); + QTest::mouseMove(window, textAreaPos); + QCOMPARE(window->cursor().shape(), textArea->cursor().shape()); + QCOMPARE(textArea->cursor().shape(), Qt::CursorShape::IBeamCursor); + + const QPoint scrollBarPos(window->width() - scrollBar->width() / 2, window->height() / 2); + QTest::mouseMove(window, scrollBarPos); + QVERIFY(scrollBar->isActive()); + QCOMPARE(window->cursor().shape(), scrollBar->cursor().shape()); + QCOMPARE(scrollBar->cursor().shape(), Qt::CursorShape::ArrowCursor); + + scrollBar->setInteractive(false); + QCOMPARE(window->cursor().shape(), textArea->cursor().shape()); +} + +QTEST_MAIN(tst_cursor) + +#include "tst_cursor.moc" |