Merge remote-tracking branch 'origin/5.14' into 5.15

Conflicts:
	tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
	tests/auto/quick/qquickloader/tst_qquickloader.cpp

Change-Id: I85fd38cfa00cd60197a1c981bfcc16fcb896cfe9
This commit is contained in:
Liang Qi 2019-11-07 07:17:40 +01:00
commit 50bce248ab
18 changed files with 276 additions and 29 deletions

63
dist/changes-5.13.2 vendored Normal file
View File

@ -0,0 +1,63 @@
Qt 5.13.2 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.13.0 through 5.13.1.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qt-5/index.html
The Qt version 5.13 series is binary compatible with the 5.12.x series.
Applications compiled for 5.12 will continue to run with 5.13.
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.
****************************************************************************
* QtQml *
****************************************************************************
- [QTBUG-77761] EcmaScript modules are loaded correctly now when using the
Qt Quick Compiler.
- [QTBUG-74087] Various JavaScript list-like constructs are parsed
iteratively rather than recursively now, avoiding stack overflows.
- [QTBUG-78554] Exceptions thrown from a promise's resolve or reject
handler are forwarded correctly now.
- [QTBUG-78996] MakeDay() and getDay() now behave more correctly.
****************************************************************************
* QtQuick *
****************************************************************************
- [QTBUG-79084] The QQuickWindow::afterAnimating signal is now emitted
properly when using QQuickRenderControl.
- [QTBUG-79011] Fix an odd 1px offset when rendering an Image with
fillMode: PreserveAspectFit.
- [QTBUG-78468] Fixed the hanging native pictures dialog on iOS.
- Item Views:
* [QTBUG-77074] Fixed a bug when TableView columnWidthProvider calculates
the widths of columns after a previously-hidden row is shown again.
* [QTBUG-77173] If you click or tap a PathView while it's moving,
it will come to rest with the nearest delegate aligned properly.
* [QTBUG-77418] ListView highlightRangeMode works correctly after
currentIndex is changed.
- Text:
* If the alpha of a text background is 0, the background rectangle node
is now omitted from the scene graph.
* [QTBUG-77389] Fixed TextEdit paragraph-selection triple click feature.
- OpenVG rendering:
* [QTBUG-77019] Fixed sprites leaking textures.
* [QTBUG-76526] Fixed per-frame delivery of touch events.
* [QTBUG-76806] The sceneGraphInitialized and sceneGraphInvalidated
signals are now emitted properly.
* [QTBUG-76589] Fixed rendering of non-affine transformed rectangles.

View File

@ -283,8 +283,11 @@ Qt::LayoutDirection QQuickGridLayoutBase::layoutDirection() const
void QQuickGridLayoutBase::setLayoutDirection(Qt::LayoutDirection dir)
{
Q_D(QQuickGridLayoutBase);
if (d->m_layoutDirection == dir)
return;
d->m_layoutDirection = dir;
invalidate();
emit layoutDirectionChanged();
}
Qt::LayoutDirection QQuickGridLayoutBase::effectiveLayoutDirection() const
@ -524,6 +527,7 @@ void QQuickGridLayout::setColumnSpacing(qreal spacing)
d->engine.setSpacing(spacing, Qt::Horizontal);
invalidate();
emit columnSpacingChanged();
}
/*!
@ -546,6 +550,7 @@ void QQuickGridLayout::setRowSpacing(qreal spacing)
d->engine.setSpacing(spacing, Qt::Vertical);
invalidate();
emit rowSpacingChanged();
}
/*!
@ -817,6 +822,7 @@ void QQuickLinearLayout::setSpacing(qreal space)
d->engine.setSpacing(space, Qt::Horizontal | Qt::Vertical);
invalidate();
emit spacingChanged();
}
void QQuickLinearLayout::insertLayoutItems()

View File

@ -63,6 +63,7 @@
#include <private/qqmlvaluetypewrapper_p.h>
#include <QtCore/qdebug.h>
#include <cmath>
#include <QtQml/QQmlPropertyMap>
Q_DECLARE_METATYPE(QList<int>)
Q_DECLARE_METATYPE(QList<qreal>)
@ -331,10 +332,15 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
return;
} else {
if (!property->isQObject())
return; // Not an object property
if (!property->isQObject()) {
if (auto asPropertyMap = qobject_cast<QQmlPropertyMap*>(currentObject))
currentObject = asPropertyMap->value(path.at(ii).toString()).value<QObject*>();
else
return; // Not an object property, and not a property map
} else {
property->readProperty(currentObject, &currentObject);
}
property->readProperty(currentObject, &currentObject);
if (!currentObject) return; // No value
}

View File

@ -442,7 +442,7 @@ void QQuickDragAttached::setImageSource(const QUrl &url)
if (url.isEmpty()) {
d->pixmapLoader.clear();
} else {
d->pixmapLoader.load(qmlEngine(this), url);
d->pixmapLoader.load(qmlEngine(parent()), url);
}
Q_EMIT imageSourceChanged();

View File

@ -1942,6 +1942,10 @@ Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerEvent *e
{
QDebugStateSaver saver(dbg);
dbg.nospace();
if (!event) {
dbg << "QQuickPointerEvent(0)";
return dbg;
}
dbg << "QQuickPointerEvent(";
dbg << event->timestamp();
dbg << " dev:";
@ -1962,6 +1966,10 @@ Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickEventPoint *eve
{
QDebugStateSaver saver(dbg);
dbg.nospace();
if (!event) {
dbg << "QQuickEventPoint(0)";
return dbg;
}
dbg << "QQuickEventPoint(accepted:" << event->isAccepted()
<< " state:";
QtDebugUtils::formatQEnum(dbg, event->state());

View File

@ -2748,22 +2748,36 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
}
QQuickWindow *parentWindow = parentItem ? QQuickItemPrivate::get(parentItem)->window : nullptr;
bool alreadyAddedChild = false;
if (d->window == parentWindow) {
// Avoid freeing and reallocating resources if the window stays the same.
d->parentItem = parentItem;
} else {
if (d->window)
d->derefWindow();
auto oldParentItem = d->parentItem;
d->parentItem = parentItem;
if (d->parentItem) {
QQuickItemPrivate::get(d->parentItem)->addChild(this);
alreadyAddedChild = true;
}
if (d->window) {
d->derefWindow();
// as we potentially changed d->parentWindow above
// the check in derefWindow could not work
// thus, we redo it here with the old parent
// Also, the window may have been deleted by derefWindow()
if (!oldParentItem && d->window) {
QQuickWindowPrivate::get(d->window)->parentlessItems.remove(this);
}
}
if (parentWindow)
d->refWindow(parentWindow);
}
d->dirty(QQuickItemPrivate::ParentChanged);
if (d->parentItem)
if (d->parentItem && !alreadyAddedChild)
QQuickItemPrivate::get(d->parentItem)->addChild(this);
else if (d->window)
else if (d->window && !alreadyAddedChild)
QQuickWindowPrivate::get(d->window)->parentlessItems.insert(this);
d->setEffectiveVisibleRecur(d->calcEffectiveVisible());

View File

@ -1581,9 +1581,7 @@ FxViewItem *QQuickItemViewPrivate::visibleItem(int modelIndex) const {
return nullptr;
}
// should rename to firstItemInView() to avoid confusion with other "*visible*" methods
// that don't look at the view position and size
FxViewItem *QQuickItemViewPrivate::firstVisibleItem() const {
FxViewItem *QQuickItemViewPrivate::firstItemInView() const {
const qreal pos = isContentFlowReversed() ? -position()-size() : position();
for (FxViewItem *item : visibleItems) {
if (item->index != -1 && item->endPosition() > pos)
@ -1955,22 +1953,22 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
bool viewportChanged = !currentChanges.pendingChanges.removes().isEmpty()
|| !currentChanges.pendingChanges.inserts().isEmpty();
FxViewItem *prevFirstVisible = firstVisibleItem();
QQmlNullableValue<qreal> prevViewPos;
int prevFirstVisibleIndex = -1;
if (prevFirstVisible) {
prevViewPos = prevFirstVisible->position();
prevFirstVisibleIndex = prevFirstVisible->index;
FxViewItem *prevFirstItemInView = firstItemInView();
QQmlNullableValue<qreal> prevFirstItemInViewPos;
int prevFirstItemInViewIndex = -1;
if (prevFirstItemInView) {
prevFirstItemInViewPos = prevFirstItemInView->position();
prevFirstItemInViewIndex = prevFirstItemInView->index;
}
qreal prevVisibleItemsFirstPos = visibleItems.count() ? visibleItems.constFirst()->position() : 0.0;
totalInsertionResult->visiblePos = prevViewPos;
totalRemovalResult->visiblePos = prevViewPos;
totalInsertionResult->visiblePos = prevFirstItemInViewPos;
totalRemovalResult->visiblePos = prevFirstItemInViewPos;
const QVector<QQmlChangeSet::Change> &removals = currentChanges.pendingChanges.removes();
const QVector<QQmlChangeSet::Change> &insertions = currentChanges.pendingChanges.inserts();
ChangeResult insertionResult(prevViewPos);
ChangeResult removalResult(prevViewPos);
ChangeResult insertionResult(prevFirstItemInViewPos);
ChangeResult removalResult(prevFirstItemInViewPos);
int removedCount = 0;
for (const QQmlChangeSet::Change &r : removals) {
@ -1979,7 +1977,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
visibleAffected = true;
if (!visibleAffected && needsRefillForAddedOrRemovedIndex(r.index))
visibleAffected = true;
const int correctedFirstVisibleIndex = prevFirstVisibleIndex - removalResult.countChangeBeforeVisible;
const int correctedFirstVisibleIndex = prevFirstItemInViewIndex - removalResult.countChangeBeforeVisible;
if (correctedFirstVisibleIndex >= 0 && r.index < correctedFirstVisibleIndex) {
if (r.index + r.count < correctedFirstVisibleIndex)
removalResult.countChangeBeforeVisible += r.count;
@ -2006,7 +2004,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
// set positions correctly for the next insertion
if (!insertions.isEmpty()) {
repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, &insertionResult, &removalResult);
repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
layoutVisibleItems(removals.first().index);
}
}
@ -2026,7 +2024,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
// set positions correctly for the next insertion
if (i < insertions.count() - 1) {
repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, &insertionResult, &removalResult);
repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
layoutVisibleItems(insertions[i].index);
}
itemCount += insertions[i].count;
@ -2043,7 +2041,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
for (const MovedItem &m : qAsConst(movingIntoView)) {
int fromIndex = findMoveKeyIndex(m.moveKey, removals);
if (fromIndex >= 0) {
if (prevFirstVisibleIndex >= 0 && fromIndex < prevFirstVisibleIndex)
if (prevFirstItemInViewIndex >= 0 && fromIndex < prevFirstItemInViewIndex)
repositionItemAt(m.item, fromIndex, -totalInsertionResult->sizeChangesAfterVisiblePos);
else
repositionItemAt(m.item, fromIndex, totalInsertionResult->sizeChangesAfterVisiblePos);
@ -2054,7 +2052,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
// reposition visibleItems.first() correctly so that the content y doesn't jump
if (removedCount != prevVisibleItemsCount)
repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, &insertionResult, &removalResult);
repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
// Whatever removed/moved items remain are no longer visible items.
prepareRemoveTransitions(&currentChanges.removedItems);

View File

@ -158,7 +158,7 @@ public:
qreal contentStartOffset() const;
int findLastVisibleIndex(int defaultValue = -1) const;
FxViewItem *visibleItem(int modelIndex) const;
FxViewItem *firstVisibleItem() const;
FxViewItem *firstItemInView() const;
int findLastIndexInView() const;
int mapFromModel(int modelIndex) const;

View File

@ -591,8 +591,8 @@ void QQuickLoader::setSource(QQmlV4Function *args)
d->clear();
QUrl sourceUrl = d->resolveSourceUrl(args);
d->disposeInitialPropertyValues();
if (!ipv->isUndefined()) {
d->disposeInitialPropertyValues();
d->initialPropertyValues.set(args->v4engine(), ipv);
}
d->qmlCallingContext.set(scope.engine, scope.engine->qmlContext());
@ -602,6 +602,7 @@ void QQuickLoader::setSource(QQmlV4Function *args)
void QQuickLoaderPrivate::disposeInitialPropertyValues()
{
initialPropertyValues.clear();
}
void QQuickLoaderPrivate::load()

View File

@ -885,7 +885,9 @@ void QQuickWidgetPrivate::createContext()
context = new QOpenGLContext;
context->setFormat(offscreenWindow->requestedFormat());
const QWindow *win = q->window()->windowHandle();
if (win && win->screen())
context->setScreen(win->screen());
QOpenGLContext *shareContext = qt_gl_global_share_context();
if (!shareContext)
shareContext = QWidgetPrivate::get(q->window())->shareContext();

View File

@ -41,6 +41,7 @@
#include <QtCore/private/qobject_p.h>
#include "../../shared/util.h"
#include "qobject.h"
#include <QtQml/QQmlPropertyMap>
#include <QDebug>
class MyQmlObject : public QObject
@ -157,6 +158,8 @@ private slots:
void copy();
void bindingToAlias();
void nestedQQmlPropertyMap();
private:
QQmlEngine engine;
};
@ -2218,6 +2221,24 @@ void tst_qqmlproperty::bindingToAlias()
QVERIFY(!o.isNull());
}
void tst_qqmlproperty::nestedQQmlPropertyMap()
{
QQmlPropertyMap mainPropertyMap;
QQmlPropertyMap nestedPropertyMap;
QQmlPropertyMap deeplyNestedPropertyMap;
mainPropertyMap.insert("nesting1", QVariant::fromValue(&nestedPropertyMap));
nestedPropertyMap.insert("value", 42);
nestedPropertyMap.insert("nesting2", QVariant::fromValue(&deeplyNestedPropertyMap));
deeplyNestedPropertyMap.insert("value", "success");
QQmlProperty value{&mainPropertyMap, "nesting1.value"};
QCOMPARE(value.read().toInt(), 42);
QQmlProperty success{&mainPropertyMap, "nesting1.nesting2.value"};
QCOMPARE(success.read().toString(), QLatin1String("success"));
}
QTEST_MAIN(tst_qqmlproperty)
#include "tst_qqmlproperty.moc"

View File

@ -143,6 +143,7 @@ private slots:
void source();
void recursion_data();
void recursion();
void noCrashWithImageProvider();
private:
QQmlEngine engine;
@ -1279,6 +1280,30 @@ void tst_QQuickDrag::recursion()
}
}
void tst_QQuickDrag::noCrashWithImageProvider()
{
// QTBUG-72045
QQmlComponent component(&engine);
component.setData(
R"(
import QtQuick 2.9
Item {
Rectangle {
id: item
width: 50
height: 50
anchors.centerIn: parent
color: "orange"
Component.onCompleted: {
item.Drag.imageSource = "image://kill/me"
}
}
})", QUrl());
QScopedPointer<QObject> object(component.create());
QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
QVERIFY(item);
}
QTEST_MAIN(tst_QQuickDrag)

View File

@ -0,0 +1,12 @@
import QtQuick 2.12
Rectangle {
width: 800
height: 600
Item {
id: it
onWindowChanged: () => it.parent = newParent
}
Item { id: newParent }
}

View File

@ -197,6 +197,8 @@ private slots:
void qtBug60123();
#endif
void setParentCalledInOnWindowChanged();
private:
enum PaintOrderOp {
@ -2146,6 +2148,12 @@ void tst_qquickitem::qtBug60123()
activateWindowAndTestPress(&window);
}
#endif
void tst_qquickitem::setParentCalledInOnWindowChanged()
{
QQuickView view;
view.setSource(testFileUrl("setParentInWindowChange.qml"));
QVERIFY(ensureFocus(&view)); // should not crash
}
QTEST_MAIN(tst_qquickitem)

View File

@ -1019,5 +1019,59 @@ Item {
waitForRendering(layout);
verify(layout.children[1].visible == false);
}
Component {
id: gridlayout_propertyChanges_Component
GridLayout {
columns: 1
property alias spy : signalSpy
SignalSpy {
id: signalSpy
target: parent
}
}
}
Component {
id: rowlayout_propertyChanges_Component
RowLayout {
property alias spy : signalSpy
SignalSpy {
id: signalSpy
target: parent
}
}
}
function test_propertyChanges_data()
{
let data = [
{ tag: "columnSpacing", value: 9 },
{ tag: "rowSpacing", value: 9 },
{ tag: "columns", value: 2 },
{ tag: "rows", value: 2 },
{ tag: "flow", value: GridLayout.TopToBottom},
{ tag: "layoutDirection", value: Qt.RightToLeft },
{ tag: "spacing", value: 9 }
]
return data
}
function test_propertyChanges(data)
{
var propName = data.tag
var layout = createTemporaryObject(propName === "spacing"
? rowlayout_propertyChanges_Component
: gridlayout_propertyChanges_Component
, container)
layout.spy.signalName = propName + "Changed"
verify(layout.spy.valid)
layout[propName] = data.value
compare(layout.spy.count, 1)
}
}
}

View File

@ -0,0 +1,4 @@
import QtQml 2.12
QtObject {
property int i: 42
}

View File

@ -0,0 +1,20 @@
import QtQuick 2.0
Item {
id: root
property int oldi: 0
property int i: 0
Loader {
id: loader
objectName: "loader"
active: true
}
Component.onCompleted: {
loader.setSource("CacheClearTest.qml", {i: 12})
root.oldi = loader.item.i
loader.setSource("CacheClearTest.qml")
root.i = loader.item.i // should be 42
}
}

View File

@ -691,6 +691,11 @@ void tst_QQuickLoader::initialPropertyValues_data()
<< (QStringList() << QString(testFileUrl("RequiredPropertyValuesComponent.qml").toString() + QLatin1String(":6:5: Required property s was not initialized")))
<< (QStringList() << "i" << "s")
<< (QVariantList() << 0 << QLatin1String(""));
QTest::newRow("source url changed, previously initial properties are discared") << testFileUrl("initialPropertyValues.11.qml")
<< QStringList()
<< (QStringList() << "oldi" << "i")
<< (QVariantList() << 12 << 42);
}
void tst_QQuickLoader::initialPropertyValues()