aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2018-06-25 10:49:57 +0200
committerLiang Qi <liang.qi@qt.io>2018-06-25 10:49:57 +0200
commit66a781692a4d21ba4c8a124cb4be84e4e2ffa742 (patch)
tree4fe9261e26281ddb5f1444563cda53c8bf39d978
parent7fec7105b7f6119135aafd6f9ee609128125d594 (diff)
parentd5fbbddd7794265f24d392d33c4874ac756cb9c9 (diff)
Merge remote-tracking branch 'origin/5.11' into dev
Conflicts: src/imports/controls/imagine/TextArea.qml src/imports/controls/imagine/TextField.qml tests/auto/controls/data/tst_tumbler.qml Change-Id: I25a8228a4299fb7a53db70b7223663a1637ed933
-rw-r--r--dist/changes-5.11.125
-rw-r--r--src/imports/controls/TextArea.qml1
-rw-r--r--src/imports/controls/TextField.qml1
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-imagine.qdoc54
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-index.qdoc9
-rw-r--r--src/imports/controls/fusion/TextArea.qml1
-rw-r--r--src/imports/controls/fusion/TextField.qml1
-rw-r--r--src/imports/controls/imagine/TextArea.qml1
-rw-r--r--src/imports/controls/imagine/TextField.qml1
-rw-r--r--src/imports/controls/material/TextArea.qml1
-rw-r--r--src/imports/controls/material/TextField.qml2
-rw-r--r--src/imports/controls/universal/TextArea.qml1
-rw-r--r--src/imports/controls/universal/TextField.qml1
-rw-r--r--src/quickcontrols2/qquicktumblerview.cpp6
-rw-r--r--src/quicktemplates2/qquickspinbox.cpp2
-rw-r--r--src/quicktemplates2/qquicktumbler.cpp149
-rw-r--r--src/quicktemplates2/qquicktumbler_p_p.h13
-rw-r--r--tests/auto/controls/data/tst_tumbler.qml66
18 files changed, 265 insertions, 70 deletions
diff --git a/dist/changes-5.11.1 b/dist/changes-5.11.1
new file mode 100644
index 00000000..5680f38b
--- /dev/null
+++ b/dist/changes-5.11.1
@@ -0,0 +1,25 @@
+Qt 5.11.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.11.0.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+http://doc.qt.io/qt-5/index.html
+
+The Qt version 5.11 series is binary compatible with the 5.10.x series.
+Applications compiled for 5.10 will continue to run with 5.11.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Qt 5.11.1 Changes *
+****************************************************************************
+
+ - [QTBUG-67684] ComboBox: don't block the escape/back key
+ - [QTBUG-67684] ComboBox: reset when hidden
diff --git a/src/imports/controls/TextArea.qml b/src/imports/controls/TextArea.qml
index 2250cb5e..ff252bba 100644
--- a/src/imports/controls/TextArea.qml
+++ b/src/imports/controls/TextArea.qml
@@ -70,5 +70,6 @@ T.TextArea {
verticalAlignment: control.verticalAlignment
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
elide: Text.ElideRight
+ renderType: control.renderType
}
}
diff --git a/src/imports/controls/TextField.qml b/src/imports/controls/TextField.qml
index 58de180e..aa57da81 100644
--- a/src/imports/controls/TextField.qml
+++ b/src/imports/controls/TextField.qml
@@ -70,6 +70,7 @@ T.TextField {
verticalAlignment: control.verticalAlignment
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
elide: Text.ElideRight
+ renderType: control.renderType
}
background: Rectangle {
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-imagine.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-imagine.qdoc
index 9f0010c4..f24f82a9 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-imagine.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-imagine.qdoc
@@ -2358,6 +2358,60 @@
\image qtquickcontrols2-imagine-9-patch-inset-boundaries.png
+ \section3 Exporting 9-Patch Images
+
+ Various vector and bitmap editors can be used to create 9-patch images
+ suitable for use with the Imagine style. The following sections briefly
+ explain the export process for each editor, and the last section explains
+ how to ensure the exported images are 9-patch-conformant.
+
+ \section4 Illustrator
+
+ See Adobe's
+ \l {https://helpx.adobe.com/in/illustrator/using/collect-assets-export-for-screens.html#panel}
+ {Asset Export panel} documentation.
+
+ \section4 Inkscape
+
+ The \l {https://github.com/mitchcurtis/inkscape-9-patch-export}
+ {Inkscape 9-Patch Export Extension} can be used to export assets with
+ Inkscape.
+
+ \section4 Photoshop
+
+ See Adobe's
+ \l {https://helpx.adobe.com/photoshop/using/generate-assets-layers.html}
+ {Generate image assets from layers} documentation.
+
+ \section4 Sketch
+
+ See Sketch's \l {https://sketchapp.com/docs/exporting/}{Exporting} documentation.
+
+ Qt Quick Controls 2 also provides a
+ \l {http://code.qt.io/cgit/qt/qtquickcontrols2.git/tree/src/imports/controls/imagine/design}
+ {plugin} for Sketch that automatically fixes the thickness of the 9-patch lines
+ after the assets are exported. To install this file, double-click on it.
+ Once Sketch has confirmed that the 9-patch export plugin has been installed,
+ the plugin will automatically process images when they are exported.
+
+ \section4 Fixing 9-Patch Lines
+
+ When exporting 9-patch images in several DPI variants (\c {@2x}, \c {@3x},
+ etc.), the 9-patch lines will typically be scaled up along with the image.
+ There are several ways to fix this, but perhaps the simplest approach is
+ to use \l {https://www.imagemagick.org/script/mogrify.php}{ImageMagick's mogrify}
+ tool. The tool has a \c -shave feature that can be used to crop the image
+ to reduce the thickness of the 9-patch lines:
+
+ \badcode
+ mogrify -shave 1x1 -path path/to/images *@2x.9.png
+ mogrify -shave 2x2 -path path/to/images *@3x.9.png
+ mogrify -shave 3x3 -path path/to/images *@4x.9.png
+ \endcode
+
+ Regular DPI images (those without the \c @Nx prefix) are not affected, so it
+ is only necessary to run the command on images intended for high DPI displays.
+
\section2 Animated Images
The \l {https://developers.google.com/speed/webp/}{WebP} and GIF animated
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc
index ba8d7527..8e3a12e7 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc
@@ -65,6 +65,15 @@
For more details, see \l {Getting Started with Qt Quick Controls 2}.
+ \section2 Building From Source
+
+ When building from source, ensure that the \l {Qt Graphical Effects} module
+ is also built, as Qt Quick Controls 2 requires it.
+
+ The \l {Qt Image Formats} module is recommended, but not
+ required. It provides support for the \c {.webp} format used by the
+ \l {Animated Images}{Imagine style}.
+
\section1 Versions
Qt Quick Controls 2.0 was introduced in Qt 5.7. Subsequent minor Qt releases
diff --git a/src/imports/controls/fusion/TextArea.qml b/src/imports/controls/fusion/TextArea.qml
index 04b25cb3..d2469d28 100644
--- a/src/imports/controls/fusion/TextArea.qml
+++ b/src/imports/controls/fusion/TextArea.qml
@@ -72,5 +72,6 @@ T.TextArea {
verticalAlignment: control.verticalAlignment
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
elide: Text.ElideRight
+ renderType: control.renderType
}
}
diff --git a/src/imports/controls/fusion/TextField.qml b/src/imports/controls/fusion/TextField.qml
index 12331dd6..6f5f49b3 100644
--- a/src/imports/controls/fusion/TextField.qml
+++ b/src/imports/controls/fusion/TextField.qml
@@ -71,6 +71,7 @@ T.TextField {
verticalAlignment: control.verticalAlignment
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
elide: Text.ElideRight
+ renderType: control.renderType
}
background: Rectangle {
diff --git a/src/imports/controls/imagine/TextArea.qml b/src/imports/controls/imagine/TextArea.qml
index c50b2f18..94fe237c 100644
--- a/src/imports/controls/imagine/TextArea.qml
+++ b/src/imports/controls/imagine/TextArea.qml
@@ -80,6 +80,7 @@ T.TextArea {
verticalAlignment: control.verticalAlignment
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
elide: Text.ElideRight
+ renderType: control.renderType
}
background: NinePatchImage {
diff --git a/src/imports/controls/imagine/TextField.qml b/src/imports/controls/imagine/TextField.qml
index 94298fbc..2943396e 100644
--- a/src/imports/controls/imagine/TextField.qml
+++ b/src/imports/controls/imagine/TextField.qml
@@ -79,6 +79,7 @@ T.TextField {
verticalAlignment: control.verticalAlignment
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
elide: Text.ElideRight
+ renderType: control.renderType
}
background: NinePatchImage {
diff --git a/src/imports/controls/material/TextArea.qml b/src/imports/controls/material/TextArea.qml
index 7fbc5cbc..ce49af53 100644
--- a/src/imports/controls/material/TextArea.qml
+++ b/src/imports/controls/material/TextArea.qml
@@ -71,6 +71,7 @@ T.TextArea {
color: control.placeholderTextColor
verticalAlignment: control.verticalAlignment
elide: Text.ElideRight
+ renderType: control.renderType
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
}
diff --git a/src/imports/controls/material/TextField.qml b/src/imports/controls/material/TextField.qml
index 40189d74..7aa612eb 100644
--- a/src/imports/controls/material/TextField.qml
+++ b/src/imports/controls/material/TextField.qml
@@ -72,8 +72,8 @@ T.TextField {
color: control.placeholderTextColor
verticalAlignment: control.verticalAlignment
elide: Text.ElideRight
+ renderType: control.renderType
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
-
}
background: Rectangle {
diff --git a/src/imports/controls/universal/TextArea.qml b/src/imports/controls/universal/TextArea.qml
index 83602426..2d5934df 100644
--- a/src/imports/controls/universal/TextArea.qml
+++ b/src/imports/controls/universal/TextArea.qml
@@ -78,6 +78,7 @@ T.TextArea {
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
verticalAlignment: control.verticalAlignment
elide: Text.ElideRight
+ renderType: control.renderType
}
background: Rectangle {
diff --git a/src/imports/controls/universal/TextField.qml b/src/imports/controls/universal/TextField.qml
index 1a181c00..04e40fa5 100644
--- a/src/imports/controls/universal/TextField.qml
+++ b/src/imports/controls/universal/TextField.qml
@@ -78,6 +78,7 @@ T.TextField {
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
verticalAlignment: control.verticalAlignment
elide: Text.ElideRight
+ renderType: control.renderType
}
background: Rectangle {
diff --git a/src/quickcontrols2/qquicktumblerview.cpp b/src/quickcontrols2/qquicktumblerview.cpp
index 59d05211..a510a1fe 100644
--- a/src/quickcontrols2/qquicktumblerview.cpp
+++ b/src/quickcontrols2/qquicktumblerview.cpp
@@ -221,9 +221,9 @@ void QQuickTumblerView::updateModel()
// Since QQuickTumbler can't know about QQuickTumblerView, we use its private API to
// inform it that it should delay setting wrap.
QQuickTumblerPrivate *tumblerPrivate = QQuickTumblerPrivate::get(m_tumbler);
- tumblerPrivate->lockWrap();
+ tumblerPrivate->beginSetModel();
m_pathView->setModel(m_model);
- tumblerPrivate->unlockWrap();
+ tumblerPrivate->endSetModel();
// The count-depends-on-wrap behavior could cause wrap to change after
// the call above, so we must check that we're still using a PathView.
@@ -234,7 +234,7 @@ void QQuickTumblerView::updateModel()
QQuickTumblerPrivate *tumblerPrivate = QQuickTumblerPrivate::get(m_tumbler);
// setModel() causes QQuickTumblerPrivate::_q_onViewCountChanged() to
- // be called called, which calls QQuickTumbler::setCurrentIndex(),
+ // be called, which calls QQuickTumbler::setCurrentIndex(),
// which results in QQuickItemViewPrivate::createHighlightItem() being
// called. When the highlight item is created,
// QQuickTumblerPrivate::itemChildAdded() is notified and
diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp
index 3ce776eb..7f4f59fa 100644
--- a/src/quicktemplates2/qquickspinbox.cpp
+++ b/src/quicktemplates2/qquickspinbox.cpp
@@ -647,7 +647,7 @@ QJSValue QQuickSpinBox::textFromValue() const
if (!d->textFromValue.isCallable()) {
QQmlEngine *engine = qmlEngine(this);
if (engine)
- d->textFromValue = engine->evaluate(QStringLiteral("function(value, locale) { return Number(value).toLocaleString(locale, 'f', 0); }"));
+ d->textFromValue = engine->evaluate(QStringLiteral("(function(value, locale) { return Number(value).toLocaleString(locale, 'f', 0); })"));
}
return d->textFromValue;
}
diff --git a/src/quicktemplates2/qquicktumbler.cpp b/src/quicktemplates2/qquicktumbler.cpp
index 941cb14d..797f2455 100644
--- a/src/quicktemplates2/qquicktumbler.cpp
+++ b/src/quicktemplates2/qquicktumbler.cpp
@@ -186,12 +186,17 @@ void QQuickTumblerPrivate::_q_updateItemWidths()
void QQuickTumblerPrivate::_q_onViewCurrentIndexChanged()
{
Q_Q(QQuickTumbler);
- if (view && !ignoreCurrentIndexChanges) {
- const int oldCurrentIndex = currentIndex;
- currentIndex = view->property("currentIndex").toInt();
- if (oldCurrentIndex != currentIndex)
- emit q->currentIndexChanged();
+ if (!view || ignoreCurrentIndexChanges || currentIndexSetDuringModelChange) {
+ // If the user set currentIndex in the onModelChanged handler,
+ // we have to respect that currentIndex by ignoring changes in the view
+ // until the model has finished being set.
+ return;
}
+
+ const int oldCurrentIndex = currentIndex;
+ currentIndex = view->property("currentIndex").toInt();
+ if (oldCurrentIndex != currentIndex)
+ emit q->currentIndexChanged();
}
void QQuickTumblerPrivate::_q_onViewCountChanged()
@@ -206,7 +211,7 @@ void QQuickTumblerPrivate::_q_onViewCountChanged()
if (pendingCurrentIndex != -1) {
// If there was an attempt to set currentIndex at creation, try to finish that attempt now.
// componentComplete() is too early, because the count might only be known sometime after completion.
- q->setCurrentIndex(pendingCurrentIndex);
+ setCurrentIndex(pendingCurrentIndex);
// If we could successfully set the currentIndex, consider it done.
// Otherwise, we'll try again later in updatePolish().
if (currentIndex == pendingCurrentIndex)
@@ -216,10 +221,10 @@ void QQuickTumblerPrivate::_q_onViewCountChanged()
} else if (currentIndex == -1) {
// If new items were added and our currentIndex was -1, we must
// enforce our rule of a non-negative currentIndex when count > 0.
- q->setCurrentIndex(0);
+ setCurrentIndex(0);
}
} else {
- q->setCurrentIndex(-1);
+ setCurrentIndex(-1);
}
}
@@ -299,17 +304,19 @@ void QQuickTumbler::setModel(const QVariant &model)
if (model == d->model)
return;
- d->lockWrap();
+ d->beginSetModel();
d->model = model;
emit modelChanged();
- d->unlockWrap();
+ d->endSetModel();
+
+ d->currentIndexSetDuringModelChange = false;
// Don't try to correct the currentIndex if count() isn't known yet.
// We can check in setupViewData() instead.
if (isComponentComplete() && d->view && count() == 0)
- setCurrentIndex(-1);
+ d->setCurrentIndex(-1);
}
/*!
@@ -343,49 +350,9 @@ int QQuickTumbler::currentIndex() const
void QQuickTumbler::setCurrentIndex(int currentIndex)
{
Q_D(QQuickTumbler);
- if (currentIndex == d->currentIndex || currentIndex < -1)
- return;
-
- if (!isComponentComplete()) {
- // Views can't set currentIndex until they're ready.
- d->pendingCurrentIndex = currentIndex;
- return;
- }
-
- // -1 doesn't make sense for a non-empty Tumbler, because unlike
- // e.g. ListView, there's always one item selected.
- // Wait until the component has finished before enforcing this rule, though,
- // because the count might not be known yet.
- if ((d->count > 0 && currentIndex == -1) || (currentIndex >= d->count)) {
- return;
- }
-
- // The view might not have been created yet, as is the case
- // if you create a Tumbler component and pass e.g. { currentIndex: 2 }
- // to createObject().
- if (d->view) {
- // Only actually set our currentIndex if the view was able to set theirs.
- bool couldSet = false;
- if (d->count == 0 && currentIndex == -1) {
- // PathView insists on using 0 as the currentIndex when there are no items.
- couldSet = true;
- } else {
- d->ignoreCurrentIndexChanges = true;
- d->ignoreSignals = true;
- d->view->setProperty("currentIndex", currentIndex);
- d->ignoreSignals = false;
- d->ignoreCurrentIndexChanges = false;
-
- couldSet = d->view->property("currentIndex").toInt() == currentIndex;
- }
-
- if (couldSet) {
- // The view's currentIndex might not have actually changed, but ours has,
- // and that's what user code sees.
- d->currentIndex = currentIndex;
- emit currentIndexChanged();
- }
- }
+ if (d->modelBeingSet)
+ d->currentIndexSetDuringModelChange = true;
+ d->setCurrentIndex(currentIndex, QQuickTumblerPrivate::UserChange);
}
/*!
@@ -690,6 +657,64 @@ void QQuickTumblerPrivate::syncCurrentIndex()
q->polish();
}
+void QQuickTumblerPrivate::setCurrentIndex(int newCurrentIndex,
+ QQuickTumblerPrivate::PropertyChangeReason changeReason)
+{
+ Q_Q(QQuickTumbler);
+ if (newCurrentIndex == currentIndex || newCurrentIndex < -1)
+ return;
+
+ if (!q->isComponentComplete()) {
+ // Views can't set currentIndex until they're ready.
+ pendingCurrentIndex = newCurrentIndex;
+ return;
+ }
+
+ if (modelBeingSet && changeReason == UserChange) {
+ // If modelBeingSet is true and the user set the currentIndex,
+ // the model is in the process of being set and the user has set
+ // the currentIndex in onModelChanged. We have to queue the currentIndex
+ // change until we're ready.
+ pendingCurrentIndex = newCurrentIndex;
+ return;
+ }
+
+ // -1 doesn't make sense for a non-empty Tumbler, because unlike
+ // e.g. ListView, there's always one item selected.
+ // Wait until the component has finished before enforcing this rule, though,
+ // because the count might not be known yet.
+ if ((count > 0 && newCurrentIndex == -1) || (newCurrentIndex >= count)) {
+ return;
+ }
+
+ // The view might not have been created yet, as is the case
+ // if you create a Tumbler component and pass e.g. { currentIndex: 2 }
+ // to createObject().
+ if (view) {
+ // Only actually set our currentIndex if the view was able to set theirs.
+ bool couldSet = false;
+ if (count == 0 && newCurrentIndex == -1) {
+ // PathView insists on using 0 as the currentIndex when there are no items.
+ couldSet = true;
+ } else {
+ ignoreCurrentIndexChanges = true;
+ ignoreSignals = true;
+ view->setProperty("currentIndex", newCurrentIndex);
+ ignoreSignals = false;
+ ignoreCurrentIndexChanges = false;
+
+ couldSet = view->property("currentIndex").toInt() == newCurrentIndex;
+ }
+
+ if (couldSet) {
+ // The view's currentIndex might not have actually changed, but ours has,
+ // and that's what user code sees.
+ currentIndex = newCurrentIndex;
+ emit q->currentIndexChanged();
+ }
+ }
+}
+
void QQuickTumblerPrivate::setCount(int newCount)
{
if (newCount == count)
@@ -705,7 +730,7 @@ void QQuickTumblerPrivate::setCount(int newCount)
void QQuickTumblerPrivate::setWrapBasedOnCount()
{
- if (count == 0 || explicitWrap || ignoreWrapChanges)
+ if (count == 0 || explicitWrap || modelBeingSet)
return;
setWrap(count >= visibleItemCount, false);
@@ -750,17 +775,17 @@ void QQuickTumblerPrivate::setWrap(bool shouldWrap, bool isExplicit)
if (q->isComponentComplete() || contentItem)
setupViewData(contentItem);
- q->setCurrentIndex(oldCurrentIndex);
+ setCurrentIndex(oldCurrentIndex);
}
-void QQuickTumblerPrivate::lockWrap()
+void QQuickTumblerPrivate::beginSetModel()
{
- ignoreWrapChanges = true;
+ modelBeingSet = true;
}
-void QQuickTumblerPrivate::unlockWrap()
+void QQuickTumblerPrivate::endSetModel()
{
- ignoreWrapChanges = false;
+ modelBeingSet = false;
setWrapBasedOnCount();
}
@@ -796,12 +821,12 @@ void QQuickTumbler::updatePolish()
// If there is a pending currentIndex at this stage, it means that
// the view wouldn't set our currentIndex in _q_onViewCountChanged
// because it wasn't ready. Try one last time here.
- setCurrentIndex(d->pendingCurrentIndex);
+ d->setCurrentIndex(d->pendingCurrentIndex);
if (d->currentIndex != d->pendingCurrentIndex && d->currentIndex == -1) {
// If we *still* couldn't set it, it's probably invalid.
// See if we can at least enforce our rule of "non-negative currentIndex when count > 0" instead.
- setCurrentIndex(0);
+ d->setCurrentIndex(0);
}
d->pendingCurrentIndex = -1;
diff --git a/src/quicktemplates2/qquicktumbler_p_p.h b/src/quicktemplates2/qquicktumbler_p_p.h
index 4d4c3bcf..2f8b1207 100644
--- a/src/quicktemplates2/qquicktumbler_p_p.h
+++ b/src/quicktemplates2/qquicktumbler_p_p.h
@@ -76,7 +76,8 @@ public:
int visibleItemCount = 5;
bool wrap = true;
bool explicitWrap = false;
- bool ignoreWrapChanges = false;
+ bool modelBeingSet = false;
+ bool currentIndexSetDuringModelChange = false;
QQuickItem *view = nullptr;
QQuickItem *viewContentItem = nullptr;
ContentItemType viewContentItemType = UnsupportedContentItemType;
@@ -104,11 +105,17 @@ public:
void warnAboutIncorrectContentItem();
void syncCurrentIndex();
+ enum PropertyChangeReason {
+ UserChange,
+ InternalChange
+ };
+
+ void setCurrentIndex(int newCurrentIndex, PropertyChangeReason changeReason = InternalChange);
void setCount(int newCount);
void setWrapBasedOnCount();
void setWrap(bool shouldWrap, bool isExplicit);
- void lockWrap();
- void unlockWrap();
+ void beginSetModel();
+ void endSetModel();
void itemChildAdded(QQuickItem *, QQuickItem *) override;
void itemChildRemoved(QQuickItem *, QQuickItem *) override;
diff --git a/tests/auto/controls/data/tst_tumbler.qml b/tests/auto/controls/data/tst_tumbler.qml
index 46c73cfc..f62c62c2 100644
--- a/tests/auto/controls/data/tst_tumbler.qml
+++ b/tests/auto/controls/data/tst_tumbler.qml
@@ -1176,4 +1176,70 @@ TestCase {
+ " to have an y pos of " + expectedPos.y + " but it was " + actualPos.y)
}
}
+
+ Component {
+ id: setCurrentIndexOnImperativeModelChangeComponent
+
+ Tumbler {
+ onModelChanged: currentIndex = model - 2
+ }
+ }
+
+ function test_setCurrentIndexOnImperativeModelChange() {
+ var tumbler = createTemporaryObject(setCurrentIndexOnImperativeModelChangeComponent, testCase);
+ verify(tumbler);
+
+ tumbler.model = 4
+ compare(tumbler.count, 4);
+ tumblerView = findView(tumbler);
+ tryCompare(tumblerView, "count", 4);
+
+ // 4 - 2 = 2
+ compare(tumbler.currentIndex, 2);
+
+ ++tumbler.model;
+ compare(tumbler.count, 5);
+ compare(tumbler.wrap, true);
+ tumblerView = findView(tumbler);
+ tryCompare(tumblerView, "count", 5);
+ // 5 - 2 = 3
+ compare(tumbler.currentIndex, 3);
+ }
+
+ Component {
+ id: setCurrentIndexOnDeclarativeModelChangeComponent
+
+ Item {
+ property alias tumbler: tumbler
+
+ property int setting: 4
+
+ Tumbler {
+ id: tumbler
+ model: setting
+ onModelChanged: currentIndex = model - 2
+ }
+ }
+ }
+
+ function test_setCurrentIndexOnDeclarativeModelChange() {
+ var root = createTemporaryObject(setCurrentIndexOnDeclarativeModelChangeComponent, testCase);
+ verify(root);
+
+ var tumbler = root.tumbler;
+ compare(tumbler.count, 4);
+ compare(tumbler.wrap, false);
+ tumblerView = findView(tumbler);
+ tryCompare(tumblerView, "count", 4);
+ // 4 - 2 = 2
+ compare(tumbler.currentIndex, 2);
+
+ ++root.setting;
+ compare(tumbler.count, 5);
+ compare(tumbler.wrap, true);
+ tumblerView = findView(tumbler);
+ tryCompare(tumblerView, "count", 5);
+ // 5 - 2 = 3
+ compare(tumbler.currentIndex, 3);
+ }
}