aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates2/qquicktumbler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktemplates2/qquicktumbler.cpp')
-rw-r--r--src/quicktemplates2/qquicktumbler.cpp149
1 files changed, 87 insertions, 62 deletions
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;