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

Conflicts:
	tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
	tests/auto/quick/qquicktableview/tst_qquicktableview.cpp

Change-Id: Ib46bc1c717cf524eea2fb3d876810c8d55747c91
This commit is contained in:
Qt Forward Merge Bot 2019-12-05 01:00:07 +01:00 committed by Ulf Hermann
commit 88490da44e
12 changed files with 463 additions and 7 deletions

View File

@ -2441,7 +2441,11 @@ bool QQuickItemViewPrivate::releaseItem(FxViewItem *item, QQmlInstanceModel::Reu
flags = model->release(item->item, reusableFlag);
if (!flags) {
// item was not destroyed, and we no longer reference it.
QQuickItemPrivate::get(item->item)->setCulled(true);
if (item->item->parentItem() == contentItem) {
// Only cull the item if its parent item is still our contentItem.
// One case where this can happen is moving an item out of one ObjectModel and into another.
QQuickItemPrivate::get(item->item)->setCulled(true);
}
unrequestedItems.insert(item->item, model->indexOf(item->item, q));
} else if (flags & QQmlInstanceModel::Destroyed) {
item->item->setParentItem(nullptr);

View File

@ -1922,9 +1922,10 @@ bool QQuickPathView::childMouseEventFilter(QQuickItem *i, QEvent *e)
void QQuickPathView::mouseUngrabEvent()
{
Q_D(QQuickPathView);
if (d->stealMouse) {
if (d->stealMouse ||
(!d->flicking && d->snapMode != NoSnap && !qFuzzyCompare(qRound(d->offset), d->offset))) {
// if our mouse grab has been removed (probably by a Flickable),
// fix our state
// or if we should snap but haven't done it, fix our state
d->stealMouse = false;
setKeepMouseGrab(false);
d->timer.invalidate();

View File

@ -1249,9 +1249,9 @@ qreal QQuickTableViewPrivate::getColumnLayoutWidth(int column)
if (qIsNaN(columnWidth) || columnWidth <= 0) {
if (!layoutWarningIssued) {
layoutWarningIssued = true;
qmlWarning(q_func()) << "the delegate's implicitHeight needs to be greater than zero";
qmlWarning(q_func()) << "the delegate's implicitWidth needs to be greater than zero";
}
columnWidth = kDefaultRowHeight;
columnWidth = kDefaultColumnWidth;
}
return columnWidth;
@ -2242,6 +2242,7 @@ void QQuickTableViewPrivate::syncModel()
if (instanceModel) {
if (tableModel) {
releaseLoadedItems(QQmlTableInstanceModel::NotReusable);
delete tableModel;
tableModel = nullptr;
}

View File

@ -92,6 +92,7 @@ int main(int argc, char **argv)
int flags = 0;
if (parser.isSet(verbose))
flags |= Test262Runner::Verbose;
if (parser.isSet(parallel))
flags |= Test262Runner::Parallel;

View File

@ -0,0 +1,140 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** 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.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.14
import QtQml.Models 2.14
Item {
id: root
width: 400
height: 400
readonly property int rectCount: 3
property var rectColors: ["red", "green", "blue"]
property alias listView1: listView1
property alias listView2: listView2
function moveRedRectToModel2() {
var appItem = objectModel1.get(0)
objectModel1.remove(0, 1)
objectModel2.insert(0, appItem)
}
function moveRedRectToModel1() {
var appItem = objectModel2.get(0)
objectModel2.remove(0, 1)
objectModel1.insert(0, appItem)
}
ObjectModel {
id: objectModel1
objectName: "objectModel1"
Component.onCompleted: {
for (var i = 0; i < root.rectCount; i++) {
var outerRect = rectComponent.createObject(null, {
"objectName": root.rectColors[i] + "Rect",
"color": root.rectColors[i]
})
objectModel1.append(outerRect)
}
}
}
ObjectModel {
id: objectModel2
objectName: "objectModel2"
}
ListView {
id: listView1
objectName: "listView1"
anchors.left: parent.left
anchors.top: parent.top
height: 100
width: 100
anchors.margins: 20
clip: true
cacheBuffer: 0
model: objectModel1
orientation: ListView.Horizontal
spacing: 20
Component.onCompleted: contentItem.objectName = "listView1ContentItem"
}
ListView {
id: listView2
objectName: "listView2"
anchors.right: parent.right
anchors.top: parent.top
height: 100
width: 100
anchors.margins: 20
clip: true
cacheBuffer: 0
model: objectModel2
orientation: ListView.Horizontal
spacing: 20
Component.onCompleted: contentItem.objectName = "listView2ContentItem"
}
Component {
id: rectComponent
Rectangle {
height: 100
width: 100
opacity: 0.2
}
}
}

View File

@ -288,6 +288,7 @@ private slots:
void reuse_reuseIsOffByDefault();
void reuse_checkThatItemsAreReused();
void moveObjectModelItemToAnotherObjectModel();
private:
template <class T> void items(const QUrl &source);
@ -9376,6 +9377,40 @@ void tst_QQuickListView::dragOverFloatingHeaderOrFooter() // QTBUG-74046
releaseView(window);
}
void tst_QQuickListView::moveObjectModelItemToAnotherObjectModel()
{
QScopedPointer<QQuickView> window(createView());
window->setSource(testFileUrl("moveObjectModelItemToAnotherObjectModel.qml"));
QCOMPARE(window->status(), QQuickView::Ready);
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QObject *root = window->rootObject();
QVERIFY(root);
const QQuickListView *listView1 = root->property("listView1").value<QQuickListView*>();
QVERIFY(listView1);
const QQuickListView *listView2 = root->property("listView2").value<QQuickListView*>();
QVERIFY(listView2);
const QQuickItem *redRect = listView1->itemAtIndex(0);
QVERIFY(redRect);
QCOMPARE(redRect->objectName(), QString::fromLatin1("redRect"));
QVERIFY(QMetaObject::invokeMethod(root, "moveRedRectToModel2"));
QVERIFY(QQuickTest::qIsPolishScheduled(listView2));
QVERIFY(QQuickTest::qWaitForItemPolished(listView2));
QVERIFY(redRect->isVisible());
QVERIFY(!QQuickItemPrivate::get(redRect)->culled);
QVERIFY(QMetaObject::invokeMethod(root, "moveRedRectToModel1"));
QVERIFY(QQuickTest::qIsPolishScheduled(listView1));
QVERIFY(QQuickTest::qWaitForItemPolished(listView1));
QVERIFY(redRect->isVisible());
QVERIFY(!QQuickItemPrivate::get(redRect)->culled);
}
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"

View File

@ -0,0 +1,75 @@
import QtQuick 2.9
Flickable {
width: 480
height: 480
contentX: 0
contentWidth: width
contentHeight: height
leftMargin: 408
rightMargin: 36
maximumFlickVelocity: 0
boundsBehavior: Flickable.StopAtBounds
flickableDirection: Flickable.HorizontalFlick
PathView {
id:pathView
objectName: "pathView"
property int countclick: 0
readonly property int contentsWidth: 348
readonly property int contentsHeight: 480
width: contentsWidth
height: contentsHeight
interactive: true
cacheItemCount: 10
currentIndex: 2
pathItemCount: 4
highlightMoveDuration: 300
highlightRangeMode : PathView.StrictlyEnforceRange
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
snapMode : PathView.SnapOneItem
path: Path {
startX: pathView.contentsWidth / 2 - 800
startY: pathView.contentsHeight / 2 - 800
PathArc {
x: pathView.contentsWidth / 2 - 800
y: pathView.contentsHeight / 2 + 800
radiusX: 800
radiusY: 800
direction: PathArc.Clockwise
}
}
model: ListModel {
ListElement { objectName:"aqua"; name: "aqua" ;mycolor:"aqua"}
ListElement { objectName:"blue"; name: "blue" ;mycolor:"blue"}
ListElement { objectName:"blueviolet"; name: "blueviolet" ;mycolor:"blueviolet"}
ListElement { objectName:"brown"; name: "brown" ;mycolor:"brown"}
ListElement { objectName:"chartreuse"; name: "chartreuse" ;mycolor:"chartreuse"}
}
delegate: Item {
id: revolveritem
objectName: model.objectName
width: pathView.contentsWidth
height: pathView.contentsHeight
Rectangle
{
id:myRectangle
color: mycolor
width: pathView.contentsWidth -20
height: pathView.contentsHeight -20
}
}
}
}

View File

@ -140,6 +140,7 @@ private slots:
void cacheItemCount();
void changePathDuringRefill();
void nestedinFlickable();
void ungrabNestedinFlickable();
void flickableDelegate();
void jsArrayChange();
void qtbug37815();
@ -2413,6 +2414,40 @@ void tst_QQuickPathView::nestedinFlickable()
}
void tst_QQuickPathView::ungrabNestedinFlickable()
{
QScopedPointer<QQuickView> window(createView());
QQuickViewTestUtil::moveMouseAway(window.data());
window->setSource(testFileUrl("ungrabNestedinFlickable.qml"));
window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "pathView");
QVERIFY(pathview != nullptr);
double pathviewOffsetBefore = pathview->offset();
// Drag slowly upwards so that it does not flick, release, and let it start snapping back
QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(200, 350));
for (int i = 0; i < 4; ++i)
QTest::mouseMove(window.data(), QPoint(200, 325 - i * 25), 500);
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(200, 250));
QCOMPARE(pathview->isMoving(), true);
// Press again to stop moving
QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(200, 350));
QTRY_COMPARE(pathview->isMoving(), false);
// Cancel the grab, wait for movement to stop, and expect it to snap to
// the nearest delegate, which should be at the same offset as where we started
pathview->ungrabMouse();
QTRY_COMPARE(pathview->offset(), pathviewOffsetBefore);
QCOMPARE(pathview->isMoving(), false);
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(200, 350));
}
void tst_QQuickPathView::flickableDelegate()
{
QScopedPointer<QQuickView> window(createView());

View File

@ -0,0 +1,87 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.12
import QtQuick.Window 2.3
Item {
width: 640
height: 450
property alias tableView: tableView
property real delegateWidth: 100
property real delegateHeight: 50
property Component delegate: tableViewDelegate
property bool delegateParentSetBeforeCompleted: false
TableView {
id: tableView
width: 600
height: 400
anchors.margins: 1
clip: true
delegate: tableViewDelegate
columnSpacing: 1
rowSpacing: 1
}
Component {
id: tableViewDelegate
Rectangle {
objectName: "tableViewDelegate"
implicitWidth: delegateWidth
implicitHeight: delegateHeight
color: "lightgray"
border.width: 1
property string modelDataFromIndex: tableView.model.dataFromSerializedIndex(index)
property string modelDataBinding: modelData
Text {
anchors.centerIn: parent
text: modelData
}
Component.onCompleted: {
delegateParentSetBeforeCompleted = parent != null;
}
}
}
}

View File

@ -70,7 +70,6 @@ Item {
color: "lightgray"
border.width: 1
property string modelDataFromIndex: tableView.model.dataFromSerializedIndex(index)
property string modelDataBinding: modelData
Text {

View File

@ -0,0 +1,63 @@
import QtQuick 2.14
import QtQml.Models 2.14
Item {
id: root
visible: true
width: 640
height: 480
property alias tableView: tv
ObjectModel {
id: om
Rectangle { height: 30; width: 80; color: "red" }
Rectangle { height: 30; width: 80; color: "green" }
Rectangle { height: 30; width: 80; color: "blue" }
}
ListModel {
id: lm
ListElement { name: "1" }
ListElement { name: "44"}
}
DelegateModel {
id: dm
model: ListModel {
ListElement { name: "Apple" }
ListElement { name: "Orange" }
}
delegate: Rectangle {
height: 25
width: 100
Text { text: "Name: " + name}
}
}
TableView {
id: tv
visible: true
anchors.fill: parent
property int modelId: 0
model: {
switch (modelId) {
case 0: return lm;
case 1: return om;
case 2: return dm;
default: return null;
}
}
delegate: Rectangle {
id: dlg
implicitWidth: 40
implicitHeight: 20
color: "red"
Text {
text: qsTr("name: " + name)
}
border.color: "green"
}
}
}

View File

@ -177,6 +177,7 @@ private slots:
void checkSyncView_connect_late();
void delegateWithRequiredProperties();
void checkThatFetchMoreIsCalledWhenScrolledToTheEndOfTable();
void replaceModel();
};
tst_QQuickTableView::tst_QQuickTableView()
@ -2094,7 +2095,7 @@ void tst_QQuickTableView::checkThatWeAlwaysEmitChangedUponItemReused()
// any data referred to by the index property inside the delegate
// will change too. So we need to refresh any bindings to index.
// QTBUG-79209
LOAD_TABLEVIEW("plaintableview.qml");
LOAD_TABLEVIEW("checkalwaysemit.qml");
TestModel model(1, 1);
tableView->setModel(QVariant::fromValue(&model));
@ -2745,6 +2746,20 @@ void tst_QQuickTableView::delegateWithRequiredProperties()
}
}
void tst_QQuickTableView::replaceModel()
{
LOAD_TABLEVIEW("replaceModelTableView.qml");
tableView->setProperty("modelId", 0);
QTRY_COMPARE(tableView->rows(), 2);
tableView->setProperty("modelId", 1);
QTRY_COMPARE(tableView->rows(), 0);
tableView->setProperty("modelId", 2);
QTRY_COMPARE(tableView->rows(), 0);
tableView->setProperty("modelId", 0);
QTRY_COMPARE(tableView->rows(), 2);
}
QTEST_MAIN(tst_QQuickTableView)
#include "tst_qquicktableview.moc"