diff options
author | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2022-05-19 07:05:18 +0300 |
---|---|---|
committer | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2022-05-19 07:05:18 +0300 |
commit | a970e15d7281d2d13485a486c6debadf46ed7950 (patch) | |
tree | 449e0526a803758301861c8a8ce9f4ed96385981 | |
parent | 69c1a1e86b9774fbee6958021055c899151e1955 (diff) | |
parent | f3377bd4d790fb07bdcac06ac9f803856fee07d9 (diff) |
Merge remote-tracking branch 'origin/tqtc/lts-5.15.5' into tqtc/lts-5.15-opensourcev5.15.5-lts-lgpl
Change-Id: Iec31024aafdb1785574ba6450ca754f4660c05ee
20 files changed, 383 insertions, 112 deletions
diff --git a/.qmake.conf b/.qmake.conf index 61cc6b14..e174a856 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.4 +MODULE_VERSION = 5.15.5 diff --git a/src/imports/controls/designer/RangeSliderSpecifics.qml b/src/imports/controls/designer/RangeSliderSpecifics.qml index 2324a66f..9372a4ff 100644 --- a/src/imports/controls/designer/RangeSliderSpecifics.qml +++ b/src/imports/controls/designer/RangeSliderSpecifics.qml @@ -127,7 +127,7 @@ Column { } SecondColumnLayout { ComboBox { - backendValue: backendValues.orientation + backendValue: backendValues.snapMode model: [ "NoSnap", "SnapOnRelease", "SnapAlways" ] scope: "RangeSlider" Layout.fillWidth: true diff --git a/src/imports/controls/imagine/GroupBox.qml b/src/imports/controls/imagine/GroupBox.qml index 7abdb6f0..46f9c98a 100644 --- a/src/imports/controls/imagine/GroupBox.qml +++ b/src/imports/controls/imagine/GroupBox.qml @@ -53,7 +53,6 @@ T.GroupBox { leftPadding: background ? background.leftPadding : 0 rightPadding: background ? background.rightPadding : 0 bottomPadding: background ? background.bottomPadding : 0 - padding: 12 label: Label { width: control.width @@ -88,7 +87,7 @@ T.GroupBox { x: -leftInset y: control.topPadding - control.bottomPadding - topInset width: control.width + leftInset + rightInset - height: control.height + topInset + bottomInset - control.topPadding + control.padding + height: control.height + topInset + bottomInset - control.topPadding + control.bottomPadding source: Imagine.url + "groupbox-background" NinePatchImageSelector on source { diff --git a/src/imports/controls/material/material.pro b/src/imports/controls/material/material.pro index cf08b925..ea74d277 100644 --- a/src/imports/controls/material/material.pro +++ b/src/imports/controls/material/material.pro @@ -1,4 +1,4 @@ -TARGET = qtquickcontrols2materialstyleplugin +TARGET = qqc2materialstyleplugin TARGETPATH = QtQuick/Controls.2/Material IMPORT_NAME = QtQuick.Controls.Material diff --git a/src/imports/controls/material/qmldir b/src/imports/controls/material/qmldir index 870a0382..d48b7b12 100644 --- a/src/imports/controls/material/qmldir +++ b/src/imports/controls/material/qmldir @@ -1,4 +1,4 @@ module QtQuick.Controls.Material -plugin qtquickcontrols2materialstyleplugin +plugin qqc2materialstyleplugin classname QtQuickControls2MaterialStylePlugin depends QtQuick.Controls 2.5 diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp index b64d8d6e..906f952a 100644 --- a/src/quicktemplates2/qquickdial.cpp +++ b/src/quicktemplates2/qquickdial.cpp @@ -41,6 +41,8 @@ #include <QtQuick/private/qquickflickable_p.h> #include <QtQuickTemplates2/private/qquickcontrol_p_p.h> +#include <cmath> + QT_BEGIN_NAMESPACE /*! @@ -116,25 +118,37 @@ public: void cancelHandle(); void executeHandle(bool complete = false); + void updateAllValuesAreInteger(); + qreal from = 0; qreal to = 1; qreal value = 0; qreal position = 0; qreal angle = startAngle; qreal stepSize = 0; - bool pressed = false; QPointF pressPoint; qreal positionBeforePress = 0; QQuickDial::SnapMode snapMode = QQuickDial::NoSnap; QQuickDial::InputMode inputMode = QQuickDial::Circular; + QQuickDeferredPointer<QQuickItem> handle; bool wrap = false; bool live = true; - QQuickDeferredPointer<QQuickItem> handle; + bool pressed = false; + bool allValuesAreInteger = false; }; qreal QQuickDialPrivate::valueAt(qreal position) const { - return from + (to - from) * position; + qreal value = from + (to - from) * position; + + /* play nice with users expecting that integer from, to and stepSize leads to + integer values - given that we are using floating point internally (and in + the API of value), this does not hold, but it is easy enough to handle + */ + if (allValuesAreInteger) + value = qRound(value); + + return value; } qreal QQuickDialPrivate::snapPosition(qreal position) const @@ -308,6 +322,16 @@ void QQuickDialPrivate::executeHandle(bool complete) quickCompleteDeferred(q, handleName(), handle); } +static bool areRepresentableAsInteger(qreal num1, qreal num2, qreal num3) { + auto check = [](qreal number) -> bool { return std::nearbyint(number) == number; }; + return check(num1) && check(num2) && check(num3); +} + +void QQuickDialPrivate::updateAllValuesAreInteger() +{ + allValuesAreInteger = areRepresentableAsInteger(to, from, stepSize) && stepSize != 0.0; +} + QQuickDial::QQuickDial(QQuickItem *parent) : QQuickControl(*(new QQuickDialPrivate), parent) { @@ -342,6 +366,7 @@ void QQuickDial::setFrom(qreal from) d->from = from; emit fromChanged(); + d->updateAllValuesAreInteger(); if (isComponentComplete()) { setValue(d->value); d->updatePosition(); @@ -369,6 +394,7 @@ void QQuickDial::setTo(qreal to) return; d->to = to; + d->updateAllValuesAreInteger(); emit toChanged(); if (isComponentComplete()) { setValue(d->value); @@ -468,6 +494,7 @@ void QQuickDial::setStepSize(qreal step) return; d->stepSize = step; + d->updateAllValuesAreInteger(); emit stepSizeChanged(); } diff --git a/src/quicktemplates2/qquickmenu.cpp b/src/quicktemplates2/qquickmenu.cpp index 9fd63587..a934fa8a 100644 --- a/src/quicktemplates2/qquickmenu.cpp +++ b/src/quicktemplates2/qquickmenu.cpp @@ -222,6 +222,7 @@ QQuickMenuPrivate::QQuickMenuPrivate() void QQuickMenuPrivate::init() { Q_Q(QQuickMenu); + QQuickPopupPrivate::init(); contentModel = new QQmlObjectModel(q); } @@ -295,8 +296,8 @@ QQuickItem *QQuickMenuPrivate::beginCreateItem() QQuickItem *item = qobject_cast<QQuickItem *>(object); if (!item) delete object; - - QQml_setParent_noEvent(item, q); + else + QQml_setParent_noEvent(item, q); return item; } diff --git a/src/quicktemplates2/qquickmenu_p_p.h b/src/quicktemplates2/qquickmenu_p_p.h index 63553f8a..b1fbb1ef 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(); + void init() override; QQuickItem *itemAt(int index) const; void insertItem(int index, QQuickItem *item); diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index bdc6dff2..8a03198e 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -275,9 +275,21 @@ QQuickPopupPrivate::QQuickPopupPrivate() void QQuickPopupPrivate::init() { Q_Q(QQuickPopup); - popupItem = new QQuickPopupItem(q); + createPopupItem(); 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); @@ -842,8 +854,7 @@ QQuickPopup::QQuickPopup(QObject *parent) QQuickPopup::QQuickPopup(QQuickPopupPrivate &dd, QObject *parent) : QObject(dd, parent) { - Q_D(QQuickPopup); - d->init(); + dd.init(); } QQuickPopup::~QQuickPopup() diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h index ef4b112e..2fc0f133 100644 --- a/src/quicktemplates2/qquickpopup_p_p.h +++ b/src/quicktemplates2/qquickpopup_p_p.h @@ -96,7 +96,9 @@ public: QQmlListProperty<QObject> contentData(); QQmlListProperty<QQuickItem> contentChildren(); - void init(); + virtual void init(); + void createPopupItem(); + void connectToPopupItem(); void closeOrReject(); bool tryClose(const QPointF &pos, QQuickPopup::ClosePolicy flags); diff --git a/src/quicktemplates2/qquickpopupitem.cpp b/src/quicktemplates2/qquickpopupitem.cpp index 0069b9fc..992d7457 100644 --- a/src/quicktemplates2/qquickpopupitem.cpp +++ b/src/quicktemplates2/qquickpopupitem.cpp @@ -53,38 +53,33 @@ 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(); @@ -161,22 +156,15 @@ void QQuickPopupItemPrivate::executeBackground(bool complete) QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup) : QQuickPage(*(new QQuickPopupItemPrivate(popup)), nullptr) { - setParent(popup); - setFlag(ItemIsFocusScope); - setAcceptedMouseButtons(Qt::AllButtons); -#if QT_CONFIG(quicktemplates2_multitouch) - setAcceptTouchEvents(true); -#endif -#if QT_CONFIG(cursor) - setCursor(Qt::ArrowCursor); -#endif + 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 +QQuickPopupItem::QQuickPopupItem(QQuickPopupItemPrivate &dd) : + QQuickPage(dd, nullptr) +{ + Q_D(QQuickPopupItem); + d->init(); } void QQuickPopupItem::grabShortcut() diff --git a/src/quicktemplates2/qquickpopupitem_p.h b/src/quicktemplates2/qquickpopupitem_p.h new file mode 100644 index 00000000..df67e745 --- /dev/null +++ b/src/quicktemplates2/qquickpopupitem_p.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** 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 a12e43e0..65b33b21 100644 --- a/src/quicktemplates2/qquickpopupitem_p_p.h +++ b/src/quicktemplates2/qquickpopupitem_p_p.h @@ -48,67 +48,39 @@ // We mean it. // -#include <QtQuickTemplates2/private/qquickpage_p.h> +#include <QtQuickTemplates2/private/qquickpopupitem_p.h> +#include <QtQuickTemplates2/private/qquickpalette_p.h> QT_BEGIN_NAMESPACE class QQuickPopup; -class QQuickPopupItemPrivate; -class QQuickPopupItem : public QQuickPage + +class QQuickPopupItemPrivate : public QQuickPagePrivate { - Q_OBJECT + Q_DECLARE_PUBLIC(QQuickPopupItem) 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 - -private: - Q_DISABLE_COPY(QQuickPopupItem) - Q_DECLARE_PRIVATE(QQuickPopupItem) - friend class QQuickPopup; + 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; }; QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp index 4733d665..4e2f509d 100644 --- a/src/quicktemplates2/qquickscrollbar.cpp +++ b/src/quicktemplates2/qquickscrollbar.cpp @@ -827,6 +827,16 @@ void QQuickScrollBarAttachedPrivate::cleanupHorizontal() { Q_ASSERT(flickable && horizontal); + QQuickControlPrivate::hideOldItem(horizontal); + // ScrollBar.qml has a binding to visible and ScrollView.qml has a binding to parent. + // If we just set visible to false and parent to null, these bindings will overwrite + // them upon component completion as part of the binding evaluation. + // That's why we remove the binding completely. + const QQmlProperty visibleProperty(horizontal, QStringLiteral("visible")); + const QQmlProperty parentProperty(horizontal, QStringLiteral("parent")); + QQmlPropertyPrivate::removeBinding(visibleProperty); + QQmlPropertyPrivate::removeBinding(parentProperty); + disconnect(flickable, &QQuickFlickable::movingHorizontallyChanged, this, &QQuickScrollBarAttachedPrivate::activateHorizontal); // TODO: export QQuickFlickableVisibleArea @@ -839,6 +849,12 @@ void QQuickScrollBarAttachedPrivate::cleanupVertical() { Q_ASSERT(flickable && vertical); + QQuickControlPrivate::hideOldItem(vertical); + const QQmlProperty visibleProperty(vertical, QStringLiteral("visible")); + const QQmlProperty parentProperty(vertical, QStringLiteral("parent")); + QQmlPropertyPrivate::removeBinding(visibleProperty); + QQmlPropertyPrivate::removeBinding(parentProperty); + disconnect(flickable, &QQuickFlickable::movingVerticallyChanged, this, &QQuickScrollBarAttachedPrivate::activateVertical); // TODO: export QQuickFlickableVisibleArea @@ -869,6 +885,9 @@ class QQuickFriendlyFlickable : public QQuickFlickable void QQuickScrollBarAttachedPrivate::scrollHorizontal() { + if (!flickable) + return; + QQuickFriendlyFlickable *f = reinterpret_cast<QQuickFriendlyFlickable *>(flickable); const qreal viewwidth = f->width(); @@ -881,6 +900,9 @@ void QQuickScrollBarAttachedPrivate::scrollHorizontal() void QQuickScrollBarAttachedPrivate::scrollVertical() { + if (!flickable) + return; + QQuickFriendlyFlickable *f = reinterpret_cast<QQuickFriendlyFlickable *>(flickable); const qreal viewheight = f->height(); diff --git a/src/quicktemplates2/qquickscrollview.cpp b/src/quicktemplates2/qquickscrollview.cpp index f385778d..01e19b16 100644 --- a/src/quicktemplates2/qquickscrollview.cpp +++ b/src/quicktemplates2/qquickscrollview.cpp @@ -38,6 +38,7 @@ #include "qquickpane_p_p.h" #include "qquickscrollbar_p_p.h" +#include <QtQml/qqmlinfo.h> #include <QtQuick/private/qquickflickable_p.h> QT_BEGIN_NAMESPACE @@ -575,7 +576,10 @@ void QQuickScrollView::contentItemChange(QQuickItem *newItem, QQuickItem *oldIte // assume/require that it has an explicit content size assigned. d->flickableHasExplicitContentWidth = true; d->flickableHasExplicitContentHeight = true; - d->setFlickable(qobject_cast<QQuickFlickable *>(newItem), false); + auto newItemAsFlickable = qobject_cast<QQuickFlickable *>(newItem); + if (newItem && !newItemAsFlickable) + qmlWarning(this) << "ScrollView only supports Flickable types as its contentItem"; + d->setFlickable(newItemAsFlickable, false); } QQuickPane::contentItemChange(newItem, oldItem); } diff --git a/src/quicktemplates2/qquicktextarea.cpp b/src/quicktemplates2/qquicktextarea.cpp index d0a08c47..d09d9c3b 100644 --- a/src/quicktemplates2/qquicktextarea.cpp +++ b/src/quicktemplates2/qquicktextarea.cpp @@ -358,6 +358,7 @@ void QQuickTextAreaPrivate::attachFlickable(QQuickFlickable *item) QObject::connect(flickable, &QQuickFlickable::contentYChanged, q, &QQuickItem::update); QQuickItemPrivate::get(flickable)->updateOrAddGeometryChangeListener(this, QQuickGeometryChange::Size); + QQuickItemPrivate::get(flickable)->addItemChangeListener(this, QQuickItemPrivate::Destroyed); QObjectPrivate::connect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl); QObjectPrivate::connect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl); @@ -378,6 +379,7 @@ void QQuickTextAreaPrivate::detachFlickable() QObject::disconnect(flickable, &QQuickFlickable::contentYChanged, q, &QQuickItem::update); QQuickItemPrivate::get(flickable)->updateOrRemoveGeometryChangeListener(this, QQuickGeometryChange::Nothing); + QQuickItemPrivate::get(flickable)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed); QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl); QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl); @@ -562,6 +564,8 @@ void QQuickTextAreaPrivate::itemDestroyed(QQuickItem *item) background = nullptr; emit q->implicitBackgroundWidthChanged(); emit q->implicitBackgroundHeightChanged(); + } else if (item == flickable) { + detachFlickable(); } } diff --git a/src/quicktemplates2/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri index fa6929f9..ba09591b 100644 --- a/src/quicktemplates2/quicktemplates2.pri +++ b/src/quicktemplates2/quicktemplates2.pri @@ -60,6 +60,7 @@ 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_dial.qml b/tests/auto/controls/data/tst_dial.qml index 26f30c33..e3ad2b2f 100644 --- a/tests/auto/controls/data/tst_dial.qml +++ b/tests/auto/controls/data/tst_dial.qml @@ -691,4 +691,19 @@ TestCase { compare(control.pressed, false); compare(control.position, data.expectedPosition); } + + function test_integerStepping() { + var dial = createTemporaryObject(dialComponent, testCase) + verify(dial) + + dial.from = 1 + dial.to = 8 + dial.stepSize = 1 + + for (let i = 1; i < 8; ++i) { + // compare as strings to avoid a fuzzy compare; we want an exact match + compare(""+dial.value, ""+1) + keyClick(Qt.Key_Right) + } + } } diff --git a/tests/auto/controls/data/tst_scrollbar.qml b/tests/auto/controls/data/tst_scrollbar.qml index 9d21fa8b..b018899e 100644 --- a/tests/auto/controls/data/tst_scrollbar.qml +++ b/tests/auto/controls/data/tst_scrollbar.qml @@ -189,6 +189,36 @@ TestCase { compare(horizontal.width, oldWidth) } + function test_attachTwice() { + let container = createTemporaryObject(flickable, testCase) + verify(container) + waitForRendering(container) + + container.ScrollBar.vertical = scrollBar.createObject(container, { objectName: "oldVerticalScrollBar" }) + verify(container.ScrollBar.vertical) + let oldVerticalScrollBar = findChild(container, "oldVerticalScrollBar") + verify(oldVerticalScrollBar) + verify(oldVerticalScrollBar.visible) + + container.ScrollBar.horizontal = scrollBar.createObject(container, { objectName: "oldHorizontalScrollBar" }) + verify(container.ScrollBar.horizontal) + let oldHorizontalScrollBar = findChild(container, "oldHorizontalScrollBar") + verify(oldHorizontalScrollBar) + verify(oldHorizontalScrollBar.visible) + + container.ScrollBar.vertical = scrollBar.createObject(container, { objectName: "newVerticalScrollBar" }) + let newVerticalScrollBar = findChild(container, "newVerticalScrollBar") + verify(newVerticalScrollBar) + verify(newVerticalScrollBar.visible) + verify(!oldVerticalScrollBar.visible) + + container.ScrollBar.horizontal = scrollBar.createObject(container, { objectName: "newHorizontalScrollBar" }) + let newHorizontalScrollBar = findChild(container, "newHorizontalScrollBar") + verify(newHorizontalScrollBar) + verify(newHorizontalScrollBar.visible) + verify(!oldHorizontalScrollBar.visible) + } + function test_mouse_data() { return [ { tag: "horizontal", properties: { visible: true, orientation: Qt.Horizontal, width: testCase.width } }, diff --git a/tests/auto/controls/data/tst_scrollview.qml b/tests/auto/controls/data/tst_scrollview.qml index 87c39509..0e8b0835 100644 --- a/tests/auto/controls/data/tst_scrollview.qml +++ b/tests/auto/controls/data/tst_scrollview.qml @@ -71,6 +71,11 @@ TestCase { } Component { + id: scrollBarComponent + ScrollBar {} + } + + Component { id: scrollableLabel ScrollView { Label { @@ -188,6 +193,15 @@ TestCase { } } } + Component { + id: scrollableTextAreaWithSibling + ScrollView { + Item { + } + TextArea { + } + } + } function test_scrollBars() { var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200}) @@ -502,4 +516,64 @@ TestCase { compare(control.contentWidth, flickable.contentWidth) compare(control.contentHeight, flickable.contentHeight) } + + function test_textAreaWithSibling() { + // Checks that it does not crash when the ScrollView is deleted + var control = createTemporaryObject(scrollableTextAreaWithSibling, testCase) + verify(control) + } + + Component { + id: zeroSizedContentItemComponent + ScrollView { + width: 100 + height: 100 + contentItem: Item {} + } + } + + function test_zeroSizedContentItem() { + ignoreWarning(/ScrollView only supports Flickable types as its contentItem/) + let control = createTemporaryObject(zeroSizedContentItemComponent, testCase) + verify(control) + + let verticalScrollBar = control.ScrollBar.vertical + verify(verticalScrollBar) + // Scrolling a ScrollView with a zero-sized contentItem shouldn't crash. + mouseDrag(verticalScrollBar, verticalScrollBar.width / 2, verticalScrollBar.height / 2, 0, 50) + + let horizontalScrollBar = control.ScrollBar.horizontal + verify(verticalScrollBar) + mouseDrag(horizontalScrollBar, horizontalScrollBar.width / 2, horizontalScrollBar.height / 2, 50, 0) + } + + function test_customScrollBars() { + let control = createTemporaryObject(scrollView, testCase) + verify(control) + control.ScrollBar.vertical.objectName = "oldVerticalScrollBar" + control.ScrollBar.horizontal.objectName = "oldHorizontalScrollBar" + + let oldVerticalScrollBar = control.ScrollBar.vertical + verify(oldVerticalScrollBar) + compare(oldVerticalScrollBar.objectName, "oldVerticalScrollBar") + + let oldHorizontalScrollBar = control.ScrollBar.horizontal + verify(oldHorizontalScrollBar) + compare(oldHorizontalScrollBar.objectName, "oldHorizontalScrollBar") + + // Create the new scroll bars imperatively so that we can easily access the old ones. + control.ScrollBar.vertical = scrollBarComponent.createObject(control, { objectName: "newVerticalScrollBar" }) + verify(control.ScrollBar.vertical) + let newVerticalScrollBar = findChild(control, "newVerticalScrollBar") + verify(newVerticalScrollBar) + verify(newVerticalScrollBar.visible) + verify(!oldVerticalScrollBar.visible) + + control.ScrollBar.horizontal = scrollBarComponent.createObject(control, { objectName: "newHorizontalScrollBar" }) + verify(control.ScrollBar.horizontal) + let newHorizontalScrollBar = findChild(control, "newHorizontalScrollBar") + verify(newHorizontalScrollBar) + verify(newHorizontalScrollBar.visible) + verify(!oldHorizontalScrollBar.visible) + } } |