diff options
22 files changed, 353 insertions, 239 deletions
diff --git a/.qmake.conf b/.qmake.conf index e174a856..8a589b4e 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -5,4 +5,4 @@ DEFINES += QT_NO_FOREACH QT_NO_JAVA_STYLE_ITERATORS QT_NO_LINKED_LIST QQC2_SOURCE_TREE = $$PWD -MODULE_VERSION = 5.15.5 +MODULE_VERSION = 5.15.6 diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp index 903de676..bb1b9b15 100644 --- a/src/quicktemplates2/qquickapplicationwindow.cpp +++ b/src/quicktemplates2/qquickapplicationwindow.cpp @@ -48,6 +48,7 @@ #include "qquickdeferredpointer_p_p.h" #include <QtCore/private/qobject_p.h> +#include <QtCore/qscopedvaluerollback.h> #include <QtQuick/private/qquickitem_p.h> #include <QtQuick/private/qquickitemchangelistener_p.h> @@ -174,6 +175,7 @@ public: QPalette palette; QQuickItem *activeFocusControl = nullptr; QQuickApplicationWindow *q_ptr = nullptr; + bool insideRelayout = false; }; static void layoutItem(QQuickItem *item, qreal y, qreal width) @@ -192,9 +194,10 @@ static void layoutItem(QQuickItem *item, qreal y, qreal width) void QQuickApplicationWindowPrivate::relayout() { Q_Q(QQuickApplicationWindow); - if (!complete) + if (!complete || insideRelayout) return; + QScopedValueRollback<bool> guard(insideRelayout, true); QQuickItem *content = q->contentItem(); qreal hh = header && header->isVisible() ? header->height() : 0; qreal fh = footer && footer->isVisible() ? footer->height() : 0; diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index b715659f..e7d99a5d 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -234,6 +234,7 @@ public: void updateCurrentText(); void updateCurrentValue(); void updateCurrentTextAndValue(); + void updateAcceptableInput(); bool isValidIndex(int index) const; @@ -290,6 +291,7 @@ public: QQmlComponent *delegate = nullptr; QQuickDeferredPointer<QQuickItem> indicator; QQuickDeferredPointer<QQuickPopup> popup; + bool m_acceptableInput = true; struct ExtraData { bool editable = false; @@ -478,6 +480,26 @@ void QQuickComboBoxPrivate::updateCurrentTextAndValue() updateCurrentValue(); } +void QQuickComboBoxPrivate::updateAcceptableInput() +{ + Q_Q(QQuickComboBox); + + if (!contentItem) + return; + + const QQuickTextInput *textInputContentItem = qobject_cast<QQuickTextInput *>(contentItem); + + if (!textInputContentItem) + return; + + const bool newValue = textInputContentItem->hasAcceptableInput(); + + if (m_acceptableInput != newValue) { + m_acceptableInput = newValue; + emit q->acceptableInputChanged(); + } +} + bool QQuickComboBoxPrivate::isValidIndex(int index) const { return delegateModel && index >= 0 && index < delegateModel->count(); @@ -1485,7 +1507,7 @@ bool QQuickComboBox::isInputMethodComposing() const bool QQuickComboBox::hasAcceptableInput() const { Q_D(const QQuickComboBox); - return d->contentItem && d->contentItem->property("acceptableInput").toBool(); + return d->m_acceptableInput; } /*! @@ -1926,7 +1948,7 @@ void QQuickComboBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) QObjectPrivate::disconnect(oldInput, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput); QObjectPrivate::disconnect(oldInput, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText); disconnect(oldInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickComboBox::inputMethodComposingChanged); - disconnect(oldInput, &QQuickTextInput::acceptableInputChanged, this, &QQuickComboBox::acceptableInputChanged); + QObjectPrivate::disconnect(oldInput, &QQuickTextInput::acceptableInputChanged, d, &QQuickComboBoxPrivate::updateAcceptableInput); } } if (newItem && isEditable()) { @@ -1935,12 +1957,14 @@ void QQuickComboBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) QObjectPrivate::connect(newInput, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput); QObjectPrivate::connect(newInput, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText); connect(newInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickComboBox::inputMethodComposingChanged); - connect(newInput, &QQuickTextInput::acceptableInputChanged, this, &QQuickComboBox::acceptableInputChanged); + QObjectPrivate::connect(newInput, &QQuickTextInput::acceptableInputChanged, d, &QQuickComboBoxPrivate::updateAcceptableInput); } #if QT_CONFIG(cursor) newItem->setCursor(Qt::IBeamCursor); #endif } + + d->updateAcceptableInput(); } void QQuickComboBox::localeChange(const QLocale &newLocale, const QLocale &oldLocale) diff --git a/src/quicktemplates2/qquickmenu.cpp b/src/quicktemplates2/qquickmenu.cpp index a934fa8a..0043dddd 100644 --- a/src/quicktemplates2/qquickmenu.cpp +++ b/src/quicktemplates2/qquickmenu.cpp @@ -222,7 +222,6 @@ QQuickMenuPrivate::QQuickMenuPrivate() void QQuickMenuPrivate::init() { Q_Q(QQuickMenu); - QQuickPopupPrivate::init(); contentModel = new QQmlObjectModel(q); } diff --git a/src/quicktemplates2/qquickmenu_p_p.h b/src/quicktemplates2/qquickmenu_p_p.h index b1fbb1ef..63553f8a 100644 --- a/src/quicktemplates2/qquickmenu_p_p.h +++ b/src/quicktemplates2/qquickmenu_p_p.h @@ -73,7 +73,7 @@ public: return menu->d_func(); } - void init() override; + void init(); QQuickItem *itemAt(int index) const; void insertItem(int index, QQuickItem *item); diff --git a/src/quicktemplates2/qquickpage.cpp b/src/quicktemplates2/qquickpage.cpp index 0a72bad7..bc27740b 100644 --- a/src/quicktemplates2/qquickpage.cpp +++ b/src/quicktemplates2/qquickpage.cpp @@ -244,6 +244,9 @@ QQuickPage::~QQuickPage() The title is often displayed at the top of a page to give the user context about the page they are viewing. + Page does not render the title itself, but instead relies + on the application to do so. For example: + \code ApplicationWindow { visible: true diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index 8a03198e..bdc6dff2 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -275,21 +275,9 @@ QQuickPopupPrivate::QQuickPopupPrivate() void QQuickPopupPrivate::init() { Q_Q(QQuickPopup); - createPopupItem(); + popupItem = new QQuickPopupItem(q); popupItem->setVisible(false); q->setParentItem(qobject_cast<QQuickItem *>(parent)); - connectToPopupItem(); -} - -void QQuickPopupPrivate::createPopupItem() -{ - Q_Q(QQuickPopup); - popupItem = new QQuickPopupItem(q); -} - -void QQuickPopupPrivate::connectToPopupItem() -{ - Q_Q(QQuickPopup); QObject::connect(popupItem, &QQuickControl::paddingChanged, q, &QQuickPopup::paddingChanged); QObject::connect(popupItem, &QQuickControl::backgroundChanged, q, &QQuickPopup::backgroundChanged); QObject::connect(popupItem, &QQuickControl::contentItemChanged, q, &QQuickPopup::contentItemChanged); @@ -854,7 +842,8 @@ QQuickPopup::QQuickPopup(QObject *parent) QQuickPopup::QQuickPopup(QQuickPopupPrivate &dd, QObject *parent) : QObject(dd, parent) { - dd.init(); + Q_D(QQuickPopup); + d->init(); } QQuickPopup::~QQuickPopup() diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h index 2fc0f133..ef4b112e 100644 --- a/src/quicktemplates2/qquickpopup_p_p.h +++ b/src/quicktemplates2/qquickpopup_p_p.h @@ -96,9 +96,7 @@ public: QQmlListProperty<QObject> contentData(); QQmlListProperty<QQuickItem> contentChildren(); - virtual void init(); - void createPopupItem(); - void connectToPopupItem(); + void init(); void closeOrReject(); bool tryClose(const QPointF &pos, QQuickPopup::ClosePolicy flags); diff --git a/src/quicktemplates2/qquickpopupitem.cpp b/src/quicktemplates2/qquickpopupitem.cpp index 992d7457..0069b9fc 100644 --- a/src/quicktemplates2/qquickpopupitem.cpp +++ b/src/quicktemplates2/qquickpopupitem.cpp @@ -53,33 +53,38 @@ QT_BEGIN_NAMESPACE +class QQuickPopupItemPrivate : public QQuickPagePrivate +{ + Q_DECLARE_PUBLIC(QQuickPopupItem) + +public: + QQuickPopupItemPrivate(QQuickPopup *popup); + + void implicitWidthChanged() override; + void implicitHeightChanged() override; + + void resolveFont() override; + void resolvePalette() override; + + QQuickItem *getContentItem() override; + + void cancelContentItem() override; + void executeContentItem(bool complete = false) override; + + void cancelBackground() override; + void executeBackground(bool complete = false) override; + + int backId = 0; + int escapeId = 0; + QQuickPopup *popup = nullptr; +}; + QQuickPopupItemPrivate::QQuickPopupItemPrivate(QQuickPopup *popup) : popup(popup) { isTabFence = true; } -void QQuickPopupItemPrivate::init() -{ - Q_Q(QQuickPopupItem); - q->setParent(popup); - q->setFlag(QQuickItem::ItemIsFocusScope); - q->setAcceptedMouseButtons(Qt::AllButtons); -#if QT_CONFIG(quicktemplates2_multitouch) - q->setAcceptTouchEvents(true); -#endif -#if QT_CONFIG(cursor) - q->setCursor(Qt::ArrowCursor); -#endif - -#if QT_CONFIG(quicktemplates2_hover) - // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8 - q->setHoverEnabled(true); - // setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects()); - // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, this, &QQuickItem::setAcceptHoverEvents); -#endif -} - void QQuickPopupItemPrivate::implicitWidthChanged() { QQuickPagePrivate::implicitWidthChanged(); @@ -156,15 +161,22 @@ void QQuickPopupItemPrivate::executeBackground(bool complete) QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup) : QQuickPage(*(new QQuickPopupItemPrivate(popup)), nullptr) { - Q_D(QQuickPopupItem); - d->init(); -} + setParent(popup); + setFlag(ItemIsFocusScope); + setAcceptedMouseButtons(Qt::AllButtons); +#if QT_CONFIG(quicktemplates2_multitouch) + setAcceptTouchEvents(true); +#endif +#if QT_CONFIG(cursor) + setCursor(Qt::ArrowCursor); +#endif -QQuickPopupItem::QQuickPopupItem(QQuickPopupItemPrivate &dd) : - QQuickPage(dd, nullptr) -{ - Q_D(QQuickPopupItem); - d->init(); +#if QT_CONFIG(quicktemplates2_hover) + // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8 + setHoverEnabled(true); + // setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects()); + // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, this, &QQuickItem::setAcceptHoverEvents); +#endif } void QQuickPopupItem::grabShortcut() diff --git a/src/quicktemplates2/qquickpopupitem_p.h b/src/quicktemplates2/qquickpopupitem_p.h deleted file mode 100644 index df67e745..00000000 --- a/src/quicktemplates2/qquickpopupitem_p.h +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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. -** -** $QT_END_LICENSE$ -** -** -** -** -** -** -** -** -** -** -** -** -** -** -** -** -****************************************************************************/ - -#ifndef QQUICKPOPUPITEM_P_H -#define QQUICKPOPUPITEM_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtQuickTemplates2/private/qquickpage_p.h> -#include <QtQuickTemplates2/private/qquickpage_p_p.h> - -QT_BEGIN_NAMESPACE - -class QQuickPopup; -class QQuickPopupItemPrivate; - -class QQuickPopupItem : public QQuickPage -{ - Q_OBJECT - -public: - explicit QQuickPopupItem(QQuickPopup *popup); - - void grabShortcut(); - void ungrabShortcut(); - -protected: - void updatePolish() override; - - bool event(QEvent *event) override; - bool childMouseEventFilter(QQuickItem *child, QEvent *event) override; - void focusInEvent(QFocusEvent *event) override; - void focusOutEvent(QFocusEvent *event) override; - void keyPressEvent(QKeyEvent *event) override; - void keyReleaseEvent(QKeyEvent *event) override; - void mousePressEvent(QMouseEvent *event) override; - void mouseMoveEvent(QMouseEvent *event) override; - void mouseReleaseEvent(QMouseEvent *event) override; - void mouseDoubleClickEvent(QMouseEvent *event) override; - void mouseUngrabEvent() override; -#if QT_CONFIG(quicktemplates2_multitouch) - void touchEvent(QTouchEvent *event) override; - void touchUngrabEvent() override; -#endif -#if QT_CONFIG(wheelevent) - void wheelEvent(QWheelEvent *event) override; -#endif - - void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override; - void contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize) override; - void fontChange(const QFont &newFont, const QFont &oldFont) override; - void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; - void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override; - void mirrorChange() override; - void itemChange(ItemChange change, const ItemChangeData &data) override; - void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override; - void paletteChange(const QPalette &newPalette, const QPalette &oldPalette) override; - void enabledChange() override; - - QFont defaultFont() const override; - QPalette defaultPalette() const override; - -#if QT_CONFIG(accessibility) - QAccessible::Role accessibleRole() const override; - void accessibilityActiveChanged(bool active) override; -#endif - -protected: - QQuickPopupItem(QQuickPopupItemPrivate &dd); - -private: - Q_DISABLE_COPY(QQuickPopupItem) - Q_DECLARE_PRIVATE(QQuickPopupItem) - friend class QQuickPopup; -}; - -QT_END_NAMESPACE - -#endif // QQUICKPOPUPITEM_P_H diff --git a/src/quicktemplates2/qquickpopupitem_p_p.h b/src/quicktemplates2/qquickpopupitem_p_p.h index 65b33b21..a12e43e0 100644 --- a/src/quicktemplates2/qquickpopupitem_p_p.h +++ b/src/quicktemplates2/qquickpopupitem_p_p.h @@ -48,39 +48,67 @@ // We mean it. // -#include <QtQuickTemplates2/private/qquickpopupitem_p.h> -#include <QtQuickTemplates2/private/qquickpalette_p.h> +#include <QtQuickTemplates2/private/qquickpage_p.h> QT_BEGIN_NAMESPACE class QQuickPopup; - -class QQuickPopupItemPrivate : public QQuickPagePrivate +class QQuickPopupItemPrivate; +class QQuickPopupItem : public QQuickPage { - Q_DECLARE_PUBLIC(QQuickPopupItem) + Q_OBJECT public: - QQuickPopupItemPrivate(QQuickPopup *popup); - - void init(); - - void implicitWidthChanged() override; - void implicitHeightChanged() override; - - void resolveFont() override; - void resolvePalette() override; - - QQuickItem *getContentItem() override; - - void cancelContentItem() override; - void executeContentItem(bool complete = false) override; - - void cancelBackground() override; - void executeBackground(bool complete = false) override; - - int backId = 0; - int escapeId = 0; - QQuickPopup *popup = nullptr; + explicit QQuickPopupItem(QQuickPopup *popup); + + void grabShortcut(); + void ungrabShortcut(); + +protected: + void updatePolish() override; + + bool event(QEvent *event) override; + bool childMouseEventFilter(QQuickItem *child, QEvent *event) override; + void focusInEvent(QFocusEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + void keyReleaseEvent(QKeyEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseDoubleClickEvent(QMouseEvent *event) override; + void mouseUngrabEvent() override; +#if QT_CONFIG(quicktemplates2_multitouch) + void touchEvent(QTouchEvent *event) override; + void touchUngrabEvent() override; +#endif +#if QT_CONFIG(wheelevent) + void wheelEvent(QWheelEvent *event) override; +#endif + + void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override; + void contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize) override; + void fontChange(const QFont &newFont, const QFont &oldFont) override; + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; + void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override; + void mirrorChange() override; + void itemChange(ItemChange change, const ItemChangeData &data) override; + void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override; + void paletteChange(const QPalette &newPalette, const QPalette &oldPalette) override; + void enabledChange() override; + + QFont defaultFont() const override; + QPalette defaultPalette() const override; + +#if QT_CONFIG(accessibility) + QAccessible::Role accessibleRole() const override; + void accessibilityActiveChanged(bool active) override; +#endif + +private: + Q_DISABLE_COPY(QQuickPopupItem) + Q_DECLARE_PRIVATE(QQuickPopupItem) + friend class QQuickPopup; }; QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickswipedelegate.cpp b/src/quicktemplates2/qquickswipedelegate.cpp index b2627f32..629bf23d 100644 --- a/src/quicktemplates2/qquickswipedelegate.cpp +++ b/src/quicktemplates2/qquickswipedelegate.cpp @@ -801,9 +801,10 @@ bool QQuickSwipeDelegatePrivate::handleMouseMoveEvent(QQuickItem *item, QMouseEv const QPointF mappedEventPos = item->mapToItem(q, event->pos()); const qreal distance = (mappedEventPos - pressPoint).x(); if (!q->keepMouseGrab()) { - // Taken from QQuickDrawerPrivate::grabMouse; see comments there. - int threshold = qMax(20, QGuiApplication::styleHints()->startDragDistance() + 5); - const bool overThreshold = QQuickWindowPrivate::dragOverThreshold(distance, Qt::XAxis, event, threshold); + // We used to use the custom threshold that QQuickDrawerPrivate::grabMouse used, + // but since it's larger than what Flickable uses, it results in Flickable + // stealing events from us (QTBUG-50045), so now we use the default. + const bool overThreshold = QQuickWindowPrivate::dragOverThreshold(distance, Qt::XAxis, event); if (window && overThreshold) { QQuickItem *grabber = q->window()->mouseGrabberItem(); if (!grabber || !grabber->keepMouseGrab()) { diff --git a/src/quicktemplates2/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri index ba09591b..fa6929f9 100644 --- a/src/quicktemplates2/quicktemplates2.pri +++ b/src/quicktemplates2/quicktemplates2.pri @@ -60,7 +60,6 @@ HEADERS += \ $$PWD/qquickpopup_p_p.h \ $$PWD/qquickpopupanchors_p.h \ $$PWD/qquickpopupanchors_p_p.h \ - $$PWD/qquickpopupitem_p.h \ $$PWD/qquickpopupitem_p_p.h \ $$PWD/qquickpopuppositioner_p_p.h \ $$PWD/qquickpresshandler_p_p.h \ diff --git a/tests/auto/controls/data/tst_combobox.qml b/tests/auto/controls/data/tst_combobox.qml index eaf9b3c6..9bbea26d 100644 --- a/tests/auto/controls/data/tst_combobox.qml +++ b/tests/auto/controls/data/tst_combobox.qml @@ -157,6 +157,7 @@ TestCase { verify(control.delegate) verify(control.indicator) verify(control.popup) + verify(control.acceptableInput) compare(control.inputMethodHints, Qt.ImhNoPredictiveText) } @@ -2062,4 +2063,43 @@ TestCase { verify(control.activeFocus) verify(control.contentItem.focus) } + + Component { + id: intValidatorComponent + IntValidator { + bottom: 0 + top: 255 + } + } + + function test_acceptableInput_QTBUG_94307() { + let items = [ + { text: "A" }, + { text: "2" }, + { text: "3" } + ] + let control = createTemporaryObject(comboBox, testCase, {model: items, editable: true}) + verify(control) + + verify(control.acceptableInput) + compare(control.displayText, "A") + + let acceptableInputSpy = signalSpy.createObject(control, {target: control, signalName: "acceptableInputChanged"}) + verify(acceptableInputSpy.valid) + + let intValidator = intValidatorComponent.createObject(testCase) + verify(intValidator) + + control.validator = intValidator + + compare(acceptableInputSpy.count, 1) + compare(control.displayText, "A") + compare(control.acceptableInput, false) + + control.currentIndex = 1 + + compare(acceptableInputSpy.count, 2) + compare(control.displayText, "2") + compare(control.acceptableInput, true) + } } diff --git a/tests/auto/controls/data/tst_rangeslider.qml b/tests/auto/controls/data/tst_rangeslider.qml index 24f8a207..d645ec70 100644 --- a/tests/auto/controls/data/tst_rangeslider.qml +++ b/tests/auto/controls/data/tst_rangeslider.qml @@ -612,7 +612,7 @@ TestCase { } function test_overlappingHandles() { - var control = createTemporaryObject(sliderComponent, testCase, { orientation: data.orientation }) + var control = createTemporaryObject(sliderComponent, testCase) verify(control) // By default, we force the second handle to be after the first in @@ -1064,17 +1064,16 @@ TestCase { function test_valueAt_data() { return [ - { tag: "0.0..1.0", from: 0.0, to: 1.0, values: [0.0, 0.2, 0.5, 1.0] }, - { tag: "0..100", from: 0, to: 100, values: [0, 20, 50, 100] }, - { tag: "100..-100", from: 100, to: -100, values: [100, 60, 0, -100] }, - { tag: "-7..7", from: -7, to: 7, stepSize: 1.0, values: [-7.0, -4.0, 0.0, 7.0] }, - { tag: "-3..7", from: -3, to: 7, stepSize: 5.0, values: [-3.0, -3.0, 2.0, 7.0] }, + { tag: "0.0..1.0", properties: { from: 0.0, to: 1.0 }, values: [0.0, 0.2, 0.5, 1.0] }, + { tag: "0..100", properties: { from: 0, to: 100 }, values: [0, 20, 50, 100] }, + { tag: "100..-100", properties: { from: 100, to: -100 }, values: [100, 60, 0, -100] }, + { tag: "-7..7", properties: { from: -7, to: 7, stepSize: 1.0 }, values: [-7.0, -4.0, 0.0, 7.0] }, + { tag: "-3..7", properties: { from: -3, to: 7, stepSize: 5.0 }, values: [-3.0, -3.0, 2.0, 7.0] }, ] } function test_valueAt(data) { - var control = createTemporaryObject(sliderComponent, testCase, - { from: data.from, to: data.to, stepSize: data.stepSize }) + var control = createTemporaryObject(sliderComponent, testCase, data.properties) verify(control) compare(control.valueAt(0.0), data.values[0]) diff --git a/tests/auto/controls/data/tst_slider.qml b/tests/auto/controls/data/tst_slider.qml index 280138c5..e1e1ed97 100644 --- a/tests/auto/controls/data/tst_slider.qml +++ b/tests/auto/controls/data/tst_slider.qml @@ -831,16 +831,16 @@ TestCase { function test_valueAt_data() { return [ - { tag: "0.0..1.0", from: 0.0, to: 1.0, values: [0.0, 0.2, 0.5, 1.0] }, - { tag: "0..100", from: 0, to: 100, values: [0, 20, 50, 100] }, - { tag: "100..-100", from: 100, to: -100, values: [100, 60, 0, -100] }, - { tag: "-7..7", from: -7, to: 7, stepSize: 1.0, values: [-7.0, -4.0, 0.0, 7.0] }, - { tag: "-3..7", from: -3, to: 7, stepSize: 5.0, values: [-3.0, -3.0, 2.0, 7.0] }, + { tag: "0.0..1.0", properties: { from: 0.0, to: 1.0 }, values: [0.0, 0.2, 0.5, 1.0] }, + { tag: "0..100", properties: { from: 0, to: 100 }, values: [0, 20, 50, 100] }, + { tag: "100..-100", properties: { from: 100, to: -100 }, values: [100, 60, 0, -100] }, + { tag: "-7..7", properties: { from: -7, to: 7, stepSize: 1.0 }, values: [-7.0, -4.0, 0.0, 7.0] }, + { tag: "-3..7", properties: { from: -3, to: 7, stepSize: 5.0 }, values: [-3.0, -3.0, 2.0, 7.0] }, ] } function test_valueAt(data) { - var control = createTemporaryObject(slider, testCase, {from: data.from, to: data.to, stepSize: data.stepSize}) + let control = createTemporaryObject(slider, testCase, data.properties) verify(control) compare(control.valueAt(0.0), data.values[0]) diff --git a/tests/auto/controls/data/tst_spinbox.qml b/tests/auto/controls/data/tst_spinbox.qml index adb70a30..14ebba21 100644 --- a/tests/auto/controls/data/tst_spinbox.qml +++ b/tests/auto/controls/data/tst_spinbox.qml @@ -244,17 +244,17 @@ TestCase { function test_keys_data() { return [ - { tag: "1", from: 1, to: 10, value: 1, stepSize: 1, upSteps: [2,3,4], downSteps: [3,2,1,1] }, - { tag: "2", from: 1, to: 10, value: 10, stepSize: 2, upSteps: [10,10], downSteps: [8,6,4] }, - { tag: "25", from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,100], downSteps: [75,50,25,0,0] }, - { tag: "wrap1", wrap: true, from: 1, to: 10, value: 1, stepSize: 1, upSteps: [2,3], downSteps: [2,1,10,9] }, - { tag: "wrap2", wrap: true, from: 1, to: 10, value: 10, stepSize: 2, upSteps: [1,3,5], downSteps: [3,1,10,8,6] }, - { tag: "wrap25", wrap: true, from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,0,25], downSteps: [0,100,75] } + { tag: "1", properties: { from: 1, to: 10, value: 1, stepSize: 1 }, upSteps: [2,3,4], downSteps: [3,2,1,1] }, + { tag: "2", properties: { from: 1, to: 10, value: 10, stepSize: 2 }, upSteps: [10,10], downSteps: [8,6,4] }, + { tag: "25", properties: { from: 0, to: 100, value: 50, stepSize: 25 }, upSteps: [75,100,100], downSteps: [75,50,25,0,0] }, + { tag: "wrap1", properties: { wrap: true, from: 1, to: 10, value: 1, stepSize: 1 }, upSteps: [2,3], downSteps: [2,1,10,9] }, + { tag: "wrap2", properties: { wrap: true, from: 1, to: 10, value: 10, stepSize: 2 }, upSteps: [1,3,5], downSteps: [3,1,10,8,6] }, + { tag: "wrap25", properties: { wrap: true, from: 0, to: 100, value: 50, stepSize: 25 }, upSteps: [75,100,0,25], downSteps: [0,100,75] } ] } function test_keys(data) { - var control = createTemporaryObject(spinBox, testCase, {wrap: data.wrap, from: data.from, to: data.to, value: data.value, stepSize: data.stepSize}) + var control = createTemporaryObject(spinBox, testCase, data.properties) verify(control) var upPressedCount = 0 @@ -396,12 +396,12 @@ TestCase { function test_wheel_data() { return [ - { tag: "1", from: 1, to: 10, value: 1, stepSize: 1, upSteps: [2,3,4], downSteps: [3,2,1,1] }, - { tag: "2", from: 1, to: 10, value: 10, stepSize: 2, upSteps: [10,10], downSteps: [8,6,4] }, - { tag: "25", from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,100], downSteps: [75,50,25,0,0] }, - { tag: "wrap1", wrap: true, from: 1, to: 10, value: 1, stepSize: 1, upSteps: [2,3], downSteps: [2,1,10,9] }, - { tag: "wrap2", wrap: true, from: 1, to: 10, value: 10, stepSize: 2, upSteps: [1,3,5], downSteps: [3,1,10,8,6] }, - { tag: "wrap25", wrap: true, from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,0,25], downSteps: [0,100,75] } + { tag: "1", properties: { from: 1, to: 10, value: 1, stepSize: 1 }, upSteps: [2,3,4], downSteps: [3,2,1,1] }, + { tag: "2", properties: { from: 1, to: 10, value: 10, stepSize: 2 }, upSteps: [10,10], downSteps: [8,6,4] }, + { tag: "25", properties: { from: 0, to: 100, value: 50, stepSize: 25 }, upSteps: [75,100,100], downSteps: [75,50,25,0,0] }, + { tag: "wrap1", properties: { wrap: true, from: 1, to: 10, value: 1, stepSize: 1 }, upSteps: [2,3], downSteps: [2,1,10,9] }, + { tag: "wrap2", properties: { wrap: true, from: 1, to: 10, value: 10, stepSize: 2 }, upSteps: [1,3,5], downSteps: [3,1,10,8,6] }, + { tag: "wrap25", properties: { wrap: true, from: 0, to: 100, value: 50, stepSize: 25 }, upSteps: [75,100,0,25], downSteps: [0,100,75] } ] } @@ -409,7 +409,8 @@ TestCase { var ma = createTemporaryObject(mouseArea, testCase, {width: 100, height: 100}) verify(ma) - var control = spinBox.createObject(ma, {wrap: data.wrap, from: data.from, to: data.to, value: data.value, stepSize: data.stepSize, wheelEnabled: true}) + data.properties.wheelEnabled = true + var control = spinBox.createObject(ma, data.properties) verify(control) var valueModifiedCount = 0 diff --git a/tests/auto/controls/data/tst_splitview.qml b/tests/auto/controls/data/tst_splitview.qml index ae8179b2..aa167472 100644 --- a/tests/auto/controls/data/tst_splitview.qml +++ b/tests/auto/controls/data/tst_splitview.qml @@ -1838,8 +1838,7 @@ TestCase { var flickable = createTemporaryObject(flickableComponent, testCase) verify(flickable) - var control = threeSizedItemsComponent.createObject(flickable.contentItem, - { "orientation": data.orientation }) + var control = threeSizedItemsComponent.createObject(flickable.contentItem) verify(control) control.anchors.fill = undefined diff --git a/tests/auto/controls/data/tst_swipedelegate.qml b/tests/auto/controls/data/tst_swipedelegate.qml index 85cb8092..255dd881 100644 --- a/tests/auto/controls/data/tst_swipedelegate.qml +++ b/tests/auto/controls/data/tst_swipedelegate.qml @@ -702,7 +702,9 @@ TestCase { property alias removeAnimation: onRemoveAnimation - ListView.onRemove: SequentialAnimation { + ListView.onRemove: onRemoveAnimation.start() + + SequentialAnimation { id: onRemoveAnimation PropertyAction { @@ -1273,10 +1275,10 @@ TestCase { // When this happens, it will grab the mouse and hence we must clear // that action's pressed state so that it doesn't stay pressed after releasing. function test_dragSideAction() { - var listView = createTemporaryObject(removableDelegatesComponent, testCase); + let listView = createTemporaryObject(removableDelegatesComponent, testCase); verify(listView); - var control = listView.itemAt(0, 0); + let control = listView.itemAt(0, 0); verify(control); // Expose the side action. @@ -1284,15 +1286,43 @@ TestCase { verify(control.swipe.leftItem); tryCompare(control.swipe, "complete", true); - var pressedSpy = signalSpyComponent.createObject(control, + let pressedSpy = signalSpyComponent.createObject(control, { target: control.swipe.leftItem.SwipeDelegate, signalName: "pressedChanged" }); verify(pressedSpy); verify(pressedSpy.valid); + let movingHorizontallySpy = createTemporaryObject(signalSpyComponent, testCase, + { target: listView, signalName: "movingHorizontallyChanged" }) + verify(movingHorizontallySpy) + verify(movingHorizontallySpy.valid) + + let movingVerticallySpy = createTemporaryObject(signalSpyComponent, testCase, + { target: listView, signalName: "movingVerticallyChanged" }) + verify(movingVerticallySpy) + verify(movingVerticallySpy.valid) + + let flickingHorizontallySpy = createTemporaryObject(signalSpyComponent, testCase, + { target: listView, signalName: "flickingHorizontallyChanged" }) + verify(flickingHorizontallySpy) + verify(flickingHorizontallySpy.valid) + + let flickingVerticallySpy = createTemporaryObject(signalSpyComponent, testCase, + { target: listView, signalName: "flickingVerticallyChanged" }) + verify(flickingVerticallySpy) + verify(flickingVerticallySpy.valid) + + // Drag the ListView vertically; its contentY should change. mouseDrag(listView, 20, 20, 0, listView.height); compare(pressedSpy.count, 2); - verify(listView.contentY !== 0); + // Wait for it to stop moving. + tryCompare(listView, "flickingVertically", false) + + // 2 because it should change to true then false. + compare(movingHorizontallySpy.count, 0) + compare(movingVerticallySpy.count, 2) + compare(flickingHorizontallySpy.count, 0) + compare(flickingVerticallySpy.count, 2) compare(control.swipe.leftItem.SwipeDelegate.pressed, false); } diff --git a/tests/auto/qquickapplicationwindow/data/layoutLayout.qml b/tests/auto/qquickapplicationwindow/data/layoutLayout.qml new file mode 100644 index 00000000..24eeb57b --- /dev/null +++ b/tests/auto/qquickapplicationwindow/data/layoutLayout.qml @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.15 + +ApplicationWindow { + width: 200 + height: 200 + visible: true + + header: RowLayout { + Rectangle { color: "red"; implicitWidth: 20; implicitHeight: 20; Layout.fillWidth: true} + } + footer: ColumnLayout { + Rectangle { color: "green"; implicitWidth: 20; implicitHeight: 20; Layout.fillWidth: true} + } +} diff --git a/tests/auto/qquickapplicationwindow/tst_qquickapplicationwindow.cpp b/tests/auto/qquickapplicationwindow/tst_qquickapplicationwindow.cpp index 80124230..ebdc763a 100644 --- a/tests/auto/qquickapplicationwindow/tst_qquickapplicationwindow.cpp +++ b/tests/auto/qquickapplicationwindow/tst_qquickapplicationwindow.cpp @@ -76,6 +76,7 @@ private slots: void focusAfterPopupClosed(); void clearFocusOnDestruction(); void layout(); + void layoutLayout(); void componentComplete(); }; @@ -862,6 +863,42 @@ void tst_QQuickApplicationWindow::layout() QCOMPARE(content->height(), qreal(window->height())); } +void tst_QQuickApplicationWindow::layoutLayout() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("layoutLayout.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY2(!object.isNull(), qPrintable(component.errorString())); + + QQuickApplicationWindow* window = qobject_cast<QQuickApplicationWindow*>(object.data()); + QVERIFY(window); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QQuickItem *content = window->contentItem(); + QVERIFY(content); + QQuickItem *header = window->header(); + QVERIFY(header); + QQuickItem *footer = window->footer(); + QVERIFY(footer); + + QQuickItem *headerChild = header->findChild<QQuickItem*>(); + QVERIFY(headerChild); + QCOMPARE(header->x(), 0.0); + QCOMPARE(header->y(), -header->height()); + QCOMPARE(header->width(), qreal(window->width())); + QCOMPARE(headerChild->width(), qreal(window->width())); + QVERIFY(header->height() > 0); + + QQuickItem *footerChild = header->findChild<QQuickItem*>(); + QVERIFY(footerChild); + QCOMPARE(footer->x(), 0.0); + QCOMPARE(footer->y(), content->height()); + QCOMPARE(footer->width(), qreal(window->width())); + QCOMPARE(footerChild->width(), qreal(window->width())); + QVERIFY(footer->height() > 0.0); +} + class FriendlyApplicationWindow : public QQuickApplicationWindow { friend class tst_QQuickApplicationWindow; diff --git a/tests/auto/qquickdrawer/BLACKLIST b/tests/auto/qquickdrawer/BLACKLIST new file mode 100644 index 00000000..9f3f96be --- /dev/null +++ b/tests/auto/qquickdrawer/BLACKLIST @@ -0,0 +1,8 @@ +# See qtbase/src/testlib/qtestblacklist.cpp for format + +# QTBUG-77946 +[slider] +opensuse-leap + +[position] +opensuse-leap |