ListView: Do not create context for section if component is bound
ListView's section needs to inject a "section" property for compatibility, unless a required property is used for this case. So far, this made it impossible to use ComponentBehavior: Bound with sections. Remedy this by not creating a separate context if we detect that required properties are used. Adjust the check in QQuickListViewPrivate::setSectionHelper: If we don't create a custom context, it might pick up the context property from somewhere else; but we can then detect that the used context is internal, and use that check to decide whether we should call setContextProperyt or setProperty. Fixes: QTBUG-111433 Pick-to: 6.5 Change-Id: Icd3c138d48f790db92d02c53613539f8f17f5c77 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
parent
de4635e253
commit
471c909a68
|
@ -1062,16 +1062,20 @@ QQuickItem * QQuickListViewPrivate::getSectionItem(const QString §ion)
|
|||
QQmlContext *context = QQmlEngine::contextForObject(sectionItem)->parentContext();
|
||||
setSectionHelper(context, sectionItem, section);
|
||||
} else {
|
||||
QQmlContext *creationContext = sectionCriteria->delegate()->creationContext();
|
||||
QQmlContext *context = new QQmlContext(
|
||||
creationContext ? creationContext : qmlContext(q));
|
||||
QQmlComponent* delegate = sectionCriteria->delegate();
|
||||
QQmlComponentPrivate* delegatePriv = QQmlComponentPrivate::get(delegate);
|
||||
const bool reuseExistingContext = delegate->isBound();
|
||||
auto delegatePriv = QQmlComponentPrivate::get(delegate);
|
||||
QQmlPropertyCache::ConstPtr rootPropertyCache;
|
||||
|
||||
QQmlContext *creationContext = sectionCriteria->delegate()->creationContext();
|
||||
auto baseContext = creationContext ? creationContext : qmlContext(q);
|
||||
// if we need to insert a context property, we need a separate context
|
||||
QQmlContext *context = reuseExistingContext ? baseContext : new QQmlContext(baseContext);
|
||||
QObject *nobj = delegate->beginCreate(context);
|
||||
if (nobj) {
|
||||
if (delegatePriv->hadTopLevelRequiredProperties()) {
|
||||
delegate->setInitialProperties(nobj, {{QLatin1String("section"), section}});
|
||||
} else {
|
||||
} else if (!reuseExistingContext) {
|
||||
context->setContextProperty(QLatin1String("section"), section);
|
||||
}
|
||||
QQml_setParent_noEvent(context, nobj);
|
||||
|
@ -1087,7 +1091,7 @@ QQuickItem * QQuickListViewPrivate::getSectionItem(const QString §ion)
|
|||
// sections are not controlled by FxListItemSG, so apply attached properties here
|
||||
QQuickItemViewAttached *attached = static_cast<QQuickItemViewAttached*>(qmlAttachedPropertiesObject<QQuickListView>(sectionItem));
|
||||
attached->setView(q);
|
||||
} else {
|
||||
} else if (!reuseExistingContext) {
|
||||
delete context;
|
||||
}
|
||||
sectionCriteria->delegate()->completeCreate();
|
||||
|
@ -1974,7 +1978,7 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
|
|||
|
||||
void QQuickListViewPrivate::setSectionHelper(QQmlContext *context, QQuickItem *sectionItem, const QString §ion)
|
||||
{
|
||||
if (context->contextProperty(QLatin1String("section")).isValid())
|
||||
if (!QQmlContextData::get(context)->isInternal() && context->contextProperty(QLatin1String("section")).isValid())
|
||||
context->setContextProperty(QLatin1String("section"), section);
|
||||
else
|
||||
sectionItem->setProperty("section", section);
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
ListView {
|
||||
id: view
|
||||
model: ListModel {
|
||||
ListElement { name: "foo"; age: 42 }
|
||||
ListElement { name: "bar"; age: 13 }
|
||||
}
|
||||
delegate: Text { required property string name; text: name}
|
||||
section.property: "age"
|
||||
section.delegate: Rectangle { color: "gray"; width: view.width; height: 20; required property string section; Text {text: parent.section} }
|
||||
}
|
|
@ -52,6 +52,7 @@ private slots:
|
|||
|
||||
void pullbackSparseList();
|
||||
void highlightWithBound();
|
||||
void sectionIsCompatibleWithBoundComponents();
|
||||
|
||||
private:
|
||||
void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to);
|
||||
|
@ -946,6 +947,19 @@ void tst_QQuickListView2::highlightWithBound()
|
|||
QCOMPARE(highlight->objectName(), QStringLiteral("highlight"));
|
||||
}
|
||||
|
||||
void tst_QQuickListView2::sectionIsCompatibleWithBoundComponents()
|
||||
{
|
||||
QTest::failOnWarning(".?");
|
||||
QQmlEngine engine;
|
||||
QQmlComponent c(&engine, testFileUrl("sectionBoundComponent.qml"));
|
||||
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
|
||||
QScopedPointer<QObject> o(c.create());
|
||||
QVERIFY(!o.isNull());
|
||||
QQuickListView *listView = qobject_cast<QQuickListView *>(o.data());
|
||||
QVERIFY(listView);
|
||||
QTRY_COMPARE(listView->currentSection(), "42");
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QQuickListView2)
|
||||
|
||||
#include "tst_qquicklistview2.moc"
|
||||
|
|
Loading…
Reference in New Issue