aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2016-02-19 12:49:16 +0100
committerLiang Qi <liang.qi@theqtcompany.com>2016-02-19 12:59:04 +0100
commit4e7f570f921671c627040537b4dd8cdb77bda3d1 (patch)
tree7d82e1b6536d5274ab29a3e6307fedcbefd3ce78
parent72447b6dbf98ace65ec46559337243970a668d26 (diff)
parent39df6760e4db6af700c46a420286b51113b5dadb (diff)
Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts: src/quick/items/qquickitem.cpp tests/auto/quick/qquickgridview/tst_qquickgridview.cpp tests/auto/quick/qquicklistview/tst_qquicklistview.cpp Change-Id: I3cf47faa2fe567d62fffd985aeecbefe5811cc42
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--src/qml/qml/qqmlengine.cpp4
-rw-r--r--src/qml/qml/qqmlengine_p.h3
-rw-r--r--src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc2
-rw-r--r--src/quick/items/qquickgridview.cpp80
-rw-r--r--src/quick/items/qquickitem.cpp30
-rw-r--r--src/quick/items/qquickitem.h3
-rw-r--r--src/quick/items/qquicktext.cpp19
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp7
-rw-r--r--src/quick/items/qquickwindow.cpp39
-rw-r--r--src/quick/items/qquickwindow.h1
-rw-r--r--src/quick/items/qquickwindow_p.h3
-rw-r--r--src/quick/quick.pro2
-rw-r--r--src/quick/util/qquickpixmapcache.cpp2
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp26
-rw-r--r--tests/auto/quick/qquickgridview/data/qtbug48870.qml30
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp38
-rw-r--r--tests/auto/quick/qquickitem2/data/qtbug_50516_2_1.qml13
-rw-r--r--tests/auto/quick/qquickitem2/data/qtbug_50516_2_2.qml12
-rw-r--r--tests/auto/quick/qquickitem2/data/qtbug_50516_2_3.qml16
-rw-r--r--tests/auto/quick/qquickitem2/data/qtbug_50516_2_4.qml15
-rw-r--r--tests/auto/quick/qquickitem2/data/qtbug_50516_2_5.qml16
-rw-r--r--tests/auto/quick/qquickitem2/data/qtbug_50516_2_6.qml17
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp64
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp92
-rw-r--r--tests/auto/quick/shared/viewtestutil.cpp80
-rw-r--r--tests/auto/quick/shared/viewtestutil.h22
27 files changed, 500 insertions, 138 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 8aae4dff1e..f529b4bc7d 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -336,6 +336,8 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
} else if (property->isV4Function()) {
Scope scope(engine);
ScopedContext global(scope, engine->qmlContext());
+ if (!global)
+ global = engine->rootContext();
return QV4::QObjectMethod::create(global, object, property->coreIndex);
} else if (property->isSignalHandler()) {
QmlSignalHandler::initProto(engine);
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 0e99e4ca89..1348151b0d 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -606,8 +606,8 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
workerScriptEngine(0),
activeObjectCreator(0),
networkAccessManager(0), networkAccessManagerFactory(0), urlInterceptor(0),
- scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
- incubatorCount(0), incubationController(0)
+ scarceResourcesRefCount(0), importDatabase(e), typeLoader(e),
+ uniqueId(1), incubatorCount(0), incubationController(0)
{
}
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index e56a3fc57f..88518ac749 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -172,9 +172,8 @@ public:
void referenceScarceResources();
void dereferenceScarceResources();
- QQmlTypeLoader typeLoader;
QQmlImportDatabase importDatabase;
-
+ QQmlTypeLoader typeLoader;
QString offlineStoragePath;
diff --git a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
index dffcabbd5b..cb281a2d4a 100644
--- a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
+++ b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
@@ -102,7 +102,7 @@ has changed. If the QList changes, it is necessary to reset
the model by calling QQmlContext::setContextProperty() again.
-\section2 QAbstractItemModel
+\section2 QAbstractItemModel subclass
A model can be defined by subclassing QAbstractItemModel. This is the
best approach if you have a more complex model that cannot be supported
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index 421c9762ff..da48fd869d 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -182,6 +182,8 @@ public:
bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) Q_DECL_OVERRIDE;
bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) Q_DECL_OVERRIDE;
+ void removeItem(FxViewItem *item);
+
FxViewItem *newViewItem(int index, QQuickItem *item) Q_DECL_OVERRIDE;
void initializeViewItem(FxViewItem *item) Q_DECL_OVERRIDE;
void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) Q_DECL_OVERRIDE;
@@ -567,6 +569,17 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
return changed;
}
+void QQuickGridViewPrivate::removeItem(FxViewItem *item)
+{
+ if (item->transitionScheduledOrRunning()) {
+ qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item:" << item->index << item->item->objectName();
+ item->releaseAfterTransition = true;
+ releasePendingTransition.append(item);
+ } else {
+ releaseItem(item);
+ }
+}
+
bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
{
FxGridItemSG *item = 0;
@@ -581,13 +594,7 @@ bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
if (item->index != -1)
visibleIndex++;
visibleItems.removeFirst();
- if (item->transitionScheduledOrRunning()) {
- qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item:" << item->index << item->item->objectName();
- item->releaseAfterTransition = true;
- releasePendingTransition.append(item);
- } else {
- releaseItem(item);
- }
+ removeItem(item);
changed = true;
}
while (visibleItems.count() > 1
@@ -597,13 +604,7 @@ bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
break;
qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.count()-1;
visibleItems.removeLast();
- if (item->transitionScheduledOrRunning()) {
- qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item:" << item->index << item->item->objectName();
- item->releaseAfterTransition = true;
- releasePendingTransition.append(item);
- } else {
- releaseItem(item);
- }
+ removeItem(item);
changed = true;
}
@@ -2406,11 +2407,12 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
int i = count - 1;
int from = tempPos - buffer - displayMarginBeginning;
- while (i >= 0) {
- if (rowPos > from && insertionIdx < visibleIndex) {
- // item won't be visible, just note the size for repositioning
- insertResult->countChangeBeforeVisible++;
- } else {
+ if (rowPos > from && insertionIdx < visibleIndex) {
+ // items won't be visible, just note the size for repositioning
+ insertResult->countChangeBeforeVisible += count;
+ insertResult->sizeChangesBeforeVisiblePos += ((count + columns - 1) / columns) * rowSize();
+ } else {
+ while (i >= 0) {
// item is before first visible e.g. in cache buffer
FxViewItem *item = 0;
if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
@@ -2426,19 +2428,40 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
insertResult->changedFirstItem = true;
if (!change.isMove()) {
addedItems->append(item);
- item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
+ if (transitioner)
+ item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
+ else
+ item->moveTo(QPointF(colPos, rowPos), true);
}
insertResult->sizeChangesBeforeVisiblePos += rowSize();
+
+ if (--colNum < 0 ) {
+ colNum = columns - 1;
+ rowPos -= rowSize();
+ }
+ colPos = colNum * colSize();
+ index++;
+ i--;
}
+ }
- if (--colNum < 0 ) {
- colNum = columns - 1;
- rowPos -= rowSize();
+ // There may be gaps in the index sequence of visibleItems because
+ // of the index shift/update done before the insertion just above.
+ // Find if there is any...
+ int firstOkIdx = -1;
+ for (int i = 0; i <= insertionIdx && i < visibleItems.count() - 1; i++) {
+ if (visibleItems.at(i)->index + 1 != visibleItems.at(i + 1)->index) {
+ firstOkIdx = i + 1;
+ break;
}
- colPos = colNum * colSize();
- index++;
- i--;
}
+ // ... and remove all the items before that one
+ for (int i = 0; i < firstOkIdx; i++) {
+ FxViewItem *nvItem = visibleItems.takeFirst();
+ addedItems->removeOne(nvItem);
+ removeItem(nvItem);
+ }
+
} else {
int i = 0;
int to = buffer+displayMarginEnd+tempPos+size()-1;
@@ -2463,7 +2486,10 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
movingIntoView->append(MovedItem(item, change.moveKey(item->index)));
} else {
addedItems->append(item);
- item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
+ if (transitioner)
+ item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
+ else
+ item->moveTo(QPointF(colPos, rowPos), true);
}
insertResult->sizeChangesAfterVisiblePos += rowSize();
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 8715fa2772..4bd95d5520 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -2074,6 +2074,10 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
\value ItemRotationHasChanged The item's rotation has changed.
ItemChangeData::realValue contains the new rotation.
+
+ \value ItemDevicePixelRatioHasChanged The device pixel ratio of the screen
+ the item is on has changed. ItemChangedData::realValue contains the new
+ device pixel ratio.
*/
/*!
@@ -2477,6 +2481,7 @@ QQuickItem *QQuickItemPrivate::prevTabChildItem(const QQuickItem *item, int star
QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, bool forward)
{
Q_ASSERT(item);
+ qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: item:" << item << ", forward:" << forward;
if (!item->window())
return item;
@@ -2487,19 +2492,25 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
bool all = QGuiApplication::styleHints()->tabFocusBehavior() == Qt::TabFocusAllControls;
QQuickItem *from = 0;
+ bool isTabFence = item->d_func()->isTabFence;
if (forward) {
- from = item->parentItem();
+ if (!isTabFence)
+ from = item->parentItem();
} else {
if (!item->childItems().isEmpty())
from = item->d_func()->childItems.constFirst();
- else
+ else if (!isTabFence)
from = item->parentItem();
}
bool skip = false;
QQuickItem * startItem = item;
QQuickItem * firstFromItem = from;
QQuickItem *current = item;
+ qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: startItem:" << startItem;
+ qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: firstFromItem:" << firstFromItem;
do {
+ qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: current:" << current;
+ qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: from:" << from;
skip = false;
QQuickItem *last = current;
@@ -2513,7 +2524,7 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
else
lastChild = prevTabChildItem(current, -1);
}
- bool isTabFence = current->d_func()->isTabFence;
+ isTabFence = current->d_func()->isTabFence;
if (isTabFence && !hasChildren)
return current;
@@ -2568,9 +2579,14 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
return startItem;
}
}
- if (!firstFromItem) { //start from root
- startItem = current;
- firstFromItem = from;
+ if (!firstFromItem) {
+ if (startItem->d_func()->isTabFence) {
+ if (current == startItem)
+ firstFromItem = from;
+ } else { //start from root
+ startItem = current;
+ firstFromItem = from;
+ }
}
} while (skip || !current->activeFocusOnTab() || !current->isEnabled() || !current->isVisible()
|| !(all || QQuickItemPrivate::canAcceptTabFocus(current)));
@@ -5968,6 +5984,8 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
}
break;
case QQuickItem::ItemAntialiasingHasChanged:
+ // fall through
+ case QQuickItem::ItemDevicePixelRatioHasChanged:
q->itemChange(change, data);
break;
}
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index 8795c71b38..b33f3d8b6a 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -172,7 +172,8 @@ public:
ItemOpacityHasChanged, // value.realValue
ItemActiveFocusHasChanged, // value.boolValue
ItemRotationHasChanged, // value.realValue
- ItemAntialiasingHasChanged // value.boolValue
+ ItemAntialiasingHasChanged, // value.boolValue
+ ItemDevicePixelRatioHasChanged // value.realValue
};
union ItemChangeData {
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 0f7f1961a1..f3254cf8d7 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -1465,7 +1465,8 @@ void QQuickText::itemChange(ItemChange change, const ItemChangeData &value)
{
Q_D(QQuickText);
Q_UNUSED(value);
- if (change == ItemAntialiasingHasChanged) {
+ switch (change) {
+ case ItemAntialiasingHasChanged:
if (!antialiasing())
d->font.setStyleStrategy(QFont::NoAntialias);
else
@@ -1473,6 +1474,22 @@ void QQuickText::itemChange(ItemChange change, const ItemChangeData &value)
d->implicitWidthValid = false;
d->implicitHeightValid = false;
d->updateLayout();
+ break;
+
+ case ItemDevicePixelRatioHasChanged:
+ if (d->renderType == NativeRendering) {
+ // Native rendering optimizes for a given pixel grid, so its results must not be scaled.
+ // Text layout code respects the current device pixel ratio automatically, we only need
+ // to rerun layout after the ratio changed.
+ // Changes of implicit size should be minimal; they are hard to avoid.
+ d->implicitWidthValid = false;
+ d->implicitHeightValid = false;
+ d->updateLayout();
+ }
+ break;
+
+ default:
+ break;
}
QQuickItem::itemChange(change, value);
}
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index 34b9d6efa2..2872c3e230 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -828,14 +828,15 @@ void QQuickTextNodeEngine::addToSceneGraph(QQuickTextNode *parentNode,
for (int i = 0; i < node->ranges.size(); ++i) {
const QPair<int, int> &range = node->ranges.at(i);
- int rangeLength = range.second - range.first;
+ int rangeLength = range.second - range.first + 1;
if (previousNode != 0) {
for (int j = 0; j < previousNode->ranges.size(); ++j) {
const QPair<int, int> &otherRange = previousNode->ranges.at(j);
+
if (range.first < otherRange.second && range.second > otherRange.first) {
int start = qMax(range.first, otherRange.first);
int end = qMin(range.second, otherRange.second);
- rangeLength -= end - start;
+ rangeLength -= end - start + 1;
if (rangeLength == 0)
break;
}
@@ -849,7 +850,7 @@ void QQuickTextNodeEngine::addToSceneGraph(QQuickTextNode *parentNode,
if (range.first < otherRange.second && range.second > otherRange.first) {
int start = qMax(range.first, otherRange.first);
int end = qMin(range.second, otherRange.second);
- rangeLength -= end - start;
+ rangeLength -= end - start + 1;
if (rangeLength == 0)
break;
}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 10f4fb20fc..44ff9aef81 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -294,10 +294,43 @@ void QQuickWindow::update()
QQuickRenderControlPrivate::get(d->renderControl)->update();
}
+static void updatePixelRatioHelper(QQuickItem *item, float pixelRatio)
+{
+ if (item->flags() & QQuickItem::ItemHasContents) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->itemChange(QQuickItem::ItemDevicePixelRatioHasChanged, pixelRatio);
+ }
+
+ QList <QQuickItem *> items = item->childItems();
+ for (int i = 0; i < items.size(); ++i)
+ updatePixelRatioHelper(items.at(i), pixelRatio);
+}
+
+void QQuickWindow::physicalDpiChanged()
+{
+ Q_D(QQuickWindow);
+ const qreal newPixelRatio = screen()->devicePixelRatio();
+ if (qFuzzyCompare(newPixelRatio, d->devicePixelRatio))
+ return;
+ d->devicePixelRatio = newPixelRatio;
+ if (d->contentItem)
+ updatePixelRatioHelper(d->contentItem, newPixelRatio);
+}
+
void QQuickWindow::handleScreenChanged(QScreen *screen)
{
Q_D(QQuickWindow);
- Q_UNUSED(screen)
+ if (screen) {
+ physicalDpiChanged();
+ // When physical DPI changes on the same screen, either the resolution or the device pixel
+ // ratio changed. We must check what it is. Device pixel ratio does not have its own
+ // ...Changed() signal.
+ d->physicalDpiChangedConnection = connect(screen, SIGNAL(physicalDotsPerInchChanged(qreal)),
+ this, SLOT(physicalDpiChanged()));
+ } else {
+ disconnect(d->physicalDpiChangedConnection);
+ }
+
d->forcePolish();
}
@@ -416,6 +449,7 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, touchMouseId(-1)
, touchMousePressTimestamp(0)
, dirtyItemList(0)
+ , devicePixelRatio(0)
, context(0)
, renderer(0)
, windowManager(0)
@@ -470,6 +504,9 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
Q_ASSERT(windowManager || renderControl);
+ if (QScreen *screen = q->screen())
+ devicePixelRatio = screen->devicePixelRatio();
+
QSGContext *sg;
if (renderControl) {
QQuickRenderControlPrivate *renderControlPriv = QQuickRenderControlPrivate::get(renderControl);
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 262828ad1d..e04a4a1ce2 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -202,6 +202,7 @@ protected:
private Q_SLOTS:
void maybeUpdate();
void cleanupSceneGraph();
+ void physicalDpiChanged();
void handleScreenChanged(QScreen *screen);
void setTransientParent_helper(QQuickWindow *window);
void runJobsAfterSwap();
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 652320c1c9..1064be7178 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -211,6 +211,9 @@ public:
QVector<QQuickItem *> itemsToPolish;
+ qreal devicePixelRatio;
+ QMetaObject::Connection physicalDpiChangedConnection;
+
void updateDirtyNodes();
void cleanupNodes();
void cleanupNodesOnShutdown();
diff --git a/src/quick/quick.pro b/src/quick/quick.pro
index 4ff2d76a09..c8aa47d939 100644
--- a/src/quick/quick.pro
+++ b/src/quick/quick.pro
@@ -29,7 +29,7 @@ load(qt_module)
include(util/util.pri)
include(scenegraph/scenegraph.pri)
include(items/items.pri)
-include(designer/designer.pri)
+!wince:include(designer/designer.pri)
contains(QT_CONFIG, accessibility) {
include(accessible/accessible.pri)
}
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index d669a7feda..7d9997b9c8 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -1194,8 +1194,6 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
*ok = true;
return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, autoTransform, appliedTransform);
}
- errorString = QQuickPixmap::tr("Invalid image data: %1").arg(url.toString());
-
} else {
errorString = QQuickPixmap::tr("Cannot open: %1").arg(url.toString());
}
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index fe3efcd948..253b050b15 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -185,6 +185,8 @@ private slots:
void argumentEvaluationOrder();
+ void v4FunctionWithoutQML();
+
signals:
void testSignal();
};
@@ -3794,6 +3796,30 @@ void tst_QJSEngine::argumentEvaluationOrder()
}
+class TestObject : public QObject
+{
+ Q_OBJECT
+public:
+ TestObject() : called(false) {}
+
+ bool called;
+
+ Q_INVOKABLE void callMe(QQmlV4Function *) {
+ called = true;
+ }
+};
+
+void tst_QJSEngine::v4FunctionWithoutQML()
+{
+ TestObject obj;
+ QJSEngine engine;
+ QJSValue wrapper = engine.newQObject(&obj);
+ QQmlEngine::setObjectOwnership(&obj, QQmlEngine::CppOwnership);
+ QVERIFY(!obj.called);
+ wrapper.property("callMe").call();
+ QVERIFY(obj.called);
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/quick/qquickgridview/data/qtbug48870.qml b/tests/auto/quick/qquickgridview/data/qtbug48870.qml
new file mode 100644
index 0000000000..7c0783fbb5
--- /dev/null
+++ b/tests/auto/quick/qquickgridview/data/qtbug48870.qml
@@ -0,0 +1,30 @@
+import QtQuick 2.6
+
+Rectangle {
+ width: 500
+ height: 500
+ color: "blue"
+
+ GridView {
+ id: view
+ objectName: "view"
+ anchors.fill: parent
+ model: testModel
+ cellWidth: 150
+ cellHeight: 150
+ readonly property int columns: Math.floor(width / cellWidth)
+
+ delegate: Rectangle {
+ width: GridView.view.cellWidth
+ height: GridView.view.cellHeight
+ color: (row & 1) != (col & 1) ? "green" : "red"
+ readonly property int row: index / view.columns
+ readonly property int col: index % view.columns
+
+ Text {
+ anchors.centerIn: parent
+ text: "Item " + index
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index b3474db7de..07c03a57d7 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -36,6 +36,7 @@
#include <QtQml/qqmlincubator.h>
#include <QtQml/qqmlcontext.h>
#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qquickitemview_p_p.h>
#include <QtQuick/private/qquickgridview_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQml/private/qqmllistmodel_p.h>
@@ -205,6 +206,7 @@ private slots:
void contentHeightWithDelayRemove();
void QTBUG_45640();
+ void QTBUG_48870_fastModelUpdates();
void keyNavigationEnabled();
@@ -6628,6 +6630,42 @@ void tst_QQuickGridView::keyNavigationEnabled()
QCOMPARE(gridView->currentIndex(), 1);
}
+void tst_QQuickGridView::QTBUG_48870_fastModelUpdates()
+{
+ StressTestModel model;
+
+ QScopedPointer<QQuickView> window(createView());
+ QQmlContext *ctxt = window->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ window->setSource(testFileUrl("qtbug48870.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickGridView *view = findItem<QQuickGridView>(window->rootObject(), "view");
+ QTRY_VERIFY(view != 0);
+
+ QQuickItemViewPrivate *priv = QQuickItemViewPrivate::get(view);
+ bool nonUnique;
+ FxViewItem *item = Q_NULLPTR;
+ int expectedIdx;
+ QVERIFY(testVisibleItems(priv, &nonUnique, &item, &expectedIdx));
+
+ for (int i = 0; i < 10; i++) {
+ QTest::qWait(100);
+ QVERIFY2(testVisibleItems(priv, &nonUnique, &item, &expectedIdx),
+ qPrintable(!item ? QString("Unexpected null item")
+ : nonUnique ? QString("Non-unique item at %1 and %2").arg(item->index).arg(expectedIdx)
+ : QString("Found index %1, expected index is %3").arg(item->index).arg(expectedIdx)));
+ if (i % 3 != 0) {
+ if (i & 1)
+ flick(window.data(), QPoint(100, 200), QPoint(100, 0), 100);
+ else
+ flick(window.data(), QPoint(100, 200), QPoint(100, 400), 100);
+ }
+ }
+}
+
QTEST_MAIN(tst_QQuickGridView)
#include "tst_qquickgridview.moc"
diff --git a/tests/auto/quick/qquickitem2/data/qtbug_50516_2_1.qml b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_1.qml
new file mode 100644
index 0000000000..d8b7833467
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_1.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.1
+import Test 1.0
+
+TabFence2 {
+ objectName: "root"
+ focus: true
+ width: 800
+ height: 600
+ Item {
+ objectName: "item"
+ focus: true
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/qtbug_50516_2_2.qml b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_2.qml
new file mode 100644
index 0000000000..445dc6d2a1
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_2.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.1
+import Test 1.0
+
+TabFence2 {
+ objectName: "root"
+ focus: true
+ width: 800
+ height: 600
+ Item {
+ objectName: "item"
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/qtbug_50516_2_3.qml b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_3.qml
new file mode 100644
index 0000000000..806d48ebeb
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_3.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.1
+import Test 1.0
+
+TabFence2 {
+ objectName: "root"
+ focus: true
+ width: 800
+ height: 600
+ Item {
+ objectName: "item2"
+ focus: true
+ }
+ Item {
+ objectName: "item2"
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/qtbug_50516_2_4.qml b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_4.qml
new file mode 100644
index 0000000000..6fcf513b51
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_4.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.1
+import Test 1.0
+
+TabFence2 {
+ objectName: "root"
+ focus: true
+ width: 800
+ height: 600
+ Item {
+ objectName: "item2"
+ }
+ Item {
+ objectName: "item2"
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/qtbug_50516_2_5.qml b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_5.qml
new file mode 100644
index 0000000000..4f7b68a8de
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_5.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.1
+import Test 1.0
+
+TabFence2 {
+ objectName: "root"
+ focus: true
+ width: 800
+ height: 600
+ TextInput {
+ objectName: "item1"
+ activeFocusOnTab: true
+ }
+ Item {
+ objectName: "item2"
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/qtbug_50516_2_6.qml b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_6.qml
new file mode 100644
index 0000000000..223476327a
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/qtbug_50516_2_6.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.1
+import Test 1.0
+
+TabFence2 {
+ objectName: "root"
+ focus: true
+ width: 800
+ height: 600
+ TextInput {
+ objectName: "item1"
+ activeFocusOnTab: true
+ }
+ TextInput {
+ objectName: "item2"
+ activeFocusOnTab: true
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index 607dbccaed..b4131a2df8 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -70,6 +70,8 @@ private slots:
void tabFence();
void qtbug_50516();
+ void qtbug_50516_2_data();
+ void qtbug_50516_2();
void keys();
void standardKeys_data();
@@ -305,6 +307,22 @@ public:
QML_DECLARE_TYPE(TabFenceItem);
+class TabFenceItem2 : public QQuickItem
+{
+ Q_OBJECT
+
+public:
+ TabFenceItem2(QQuickItem *parent = Q_NULLPTR)
+ : QQuickItem(parent)
+ {
+ QQuickItemPrivate *d = QQuickItemPrivate::get(this);
+ d->isTabFence = true;
+ setFlag(ItemIsFocusScope);
+ }
+};
+
+QML_DECLARE_TYPE(TabFenceItem2);
+
tst_QQuickItem::tst_QQuickItem()
{
}
@@ -315,6 +333,7 @@ void tst_QQuickItem::initTestCase()
qmlRegisterType<KeyTestItem>("Test",1,0,"KeyTestItem");
qmlRegisterType<HollowTestItem>("Test", 1, 0, "HollowTestItem");
qmlRegisterType<TabFenceItem>("Test", 1, 0, "TabFence");
+ qmlRegisterType<TabFenceItem2>("Test", 1, 0, "TabFence2");
}
void tst_QQuickItem::cleanup()
@@ -1212,6 +1231,51 @@ void tst_QQuickItem::qtbug_50516()
delete window;
}
+void tst_QQuickItem::qtbug_50516_2_data()
+{
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<QString>("item1");
+ QTest::addColumn<QString>("item2");
+
+ QTest::newRow("FocusScope TabFence with one Item(focused)")
+ << QStringLiteral("qtbug_50516_2_1.qml") << QStringLiteral("root") << QStringLiteral("root");
+ QTest::newRow("FocusScope TabFence with one Item(unfocused)")
+ << QStringLiteral("qtbug_50516_2_2.qml") << QStringLiteral("root") << QStringLiteral("root");
+ QTest::newRow("FocusScope TabFence with two Items(focused)")
+ << QStringLiteral("qtbug_50516_2_3.qml") << QStringLiteral("root") << QStringLiteral("root");
+ QTest::newRow("FocusScope TabFence with two Items(unfocused)")
+ << QStringLiteral("qtbug_50516_2_4.qml") << QStringLiteral("root") << QStringLiteral("root");
+ QTest::newRow("FocusScope TabFence with one Item and one TextInput(unfocused)")
+ << QStringLiteral("qtbug_50516_2_5.qml") << QStringLiteral("item1") << QStringLiteral("item1");
+ QTest::newRow("FocusScope TabFence with two TextInputs(unfocused)")
+ << QStringLiteral("qtbug_50516_2_6.qml") << QStringLiteral("item1") << QStringLiteral("item2");
+}
+
+void tst_QQuickItem::qtbug_50516_2()
+{
+ QFETCH(QString, filename);
+ QFETCH(QString, item1);
+ QFETCH(QString, item2);
+
+ QQuickView *window = new QQuickView(0);
+ window->setBaseSize(QSize(800,600));
+
+ window->setSource(testFileUrl(filename));
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+ QVERIFY(QGuiApplication::focusWindow() == window);
+ QVERIFY(window->rootObject()->hasActiveFocus());
+
+ QQuickItem *contentItem = window->rootObject();
+ QQuickItem *next = contentItem->nextItemInFocusChain(true);
+ QCOMPARE(next->objectName(), item1);
+ next = contentItem->nextItemInFocusChain(false);
+ QCOMPARE(next->objectName(), item2);
+
+ delete window;
+}
+
void tst_QQuickItem::keys()
{
QQuickView *window = new QQuickView(0);
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 405acad165..658ffa1f57 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -8264,99 +8264,9 @@ void tst_QQuickListView::keyNavigationEnabled()
QCOMPARE(listView->currentIndex(), 1);
}
-static bool testVisibleItems(const QQuickItemViewPrivate *priv, bool *nonUnique, FxViewItem **failItem, int *expectedIdx)
-{
- QHash<QQuickItem*, int> uniqueItems;
-
- int skip = 0;
- for (int i = 0; i < priv->visibleItems.count(); ++i) {
- FxViewItem *item = priv->visibleItems.at(i);
- if (!item) {
- *failItem = Q_NULLPTR;
- return false;
- }
-#if 0
- qDebug() << "\t" << item->index
- << item->item
- << item->position()
- << (!item->item || QQuickItemPrivate::get(item->item)->culled ? "hidden" : "visible");
-#endif
- if (item->index == -1) {
- ++skip;
- } else if (item->index != priv->visibleIndex + i - skip) {
- *nonUnique = false;
- *failItem = item;
- *expectedIdx = priv->visibleIndex + i - skip;
- return false;
- } else if (uniqueItems.contains(item->item)) {
- *nonUnique = true;
- *failItem = item;
- *expectedIdx = uniqueItems.find(item->item).value();
- return false;
- }
-
- uniqueItems.insert(item->item, item->index);
- }
-
- return true;
-}
-
-class QTBUG_48870_Model : public QAbstractListModel
-{
- Q_OBJECT
-
-public:
-
- QTBUG_48870_Model()
- : QAbstractListModel()
- , m_rowCount(20)
- {
- QTimer *t = new QTimer(this);
- t->setInterval(500);
- t->start();
-
- qsrand(qHash(QDateTime::currentDateTime()));
- connect(t, &QTimer::timeout, this, &QTBUG_48870_Model::updateModel);
- }
-
- int rowCount(const QModelIndex &) const
- {
- return m_rowCount;
- }
-
- QVariant data(const QModelIndex &, int) const
- {
- return QVariant();
- }
-
-public Q_SLOTS:
- void updateModel()
- {
- if (m_rowCount > 10) {
- for (int i = 0; i < 10; ++i) {
- int rnum = qrand() % m_rowCount;
- beginRemoveRows(QModelIndex(), rnum, rnum);
- m_rowCount--;
- endRemoveRows();
- }
- }
- if (m_rowCount < 20) {
- for (int i = 0; i < 10; ++i) {
- int rnum = qrand() % m_rowCount;
- beginInsertRows(QModelIndex(), rnum, rnum);
- m_rowCount++;
- endInsertRows();
- }
- }
- }
-
-private:
- int m_rowCount;
-};
-
void tst_QQuickListView::QTBUG_48870_fastModelUpdates()
{
- QTBUG_48870_Model model;
+ StressTestModel model;
QScopedPointer<QQuickView> window(createView());
QQmlContext *ctxt = window->rootContext();
diff --git a/tests/auto/quick/shared/viewtestutil.cpp b/tests/auto/quick/shared/viewtestutil.cpp
index 09c88acbe6..ab58aee648 100644
--- a/tests/auto/quick/shared/viewtestutil.cpp
+++ b/tests/auto/quick/shared/viewtestutil.cpp
@@ -35,6 +35,7 @@
#include <QtTest/QTest>
#include <private/qquickwindow_p.h>
+#include <private/qquickitemview_p_p.h>
QQuickView *QQuickViewTestUtil::createView()
@@ -347,6 +348,85 @@ QList<QPair<QString,QString> > QQuickViewTestUtil::ListRange::getModelDataValues
return data;
}
+QQuickViewTestUtil::StressTestModel::StressTestModel()
+ : QAbstractListModel()
+ , m_rowCount(20)
+{
+ QTimer *t = new QTimer(this);
+ t->setInterval(500);
+ t->start();
+
+ qsrand(qHash(QDateTime::currentDateTime()));
+ connect(t, &QTimer::timeout, this, &StressTestModel::updateModel);
+}
+
+int QQuickViewTestUtil::StressTestModel::rowCount(const QModelIndex &) const
+{
+ return m_rowCount;
+}
+
+QVariant QQuickViewTestUtil::StressTestModel::data(const QModelIndex &, int) const
+{
+ return QVariant();
+}
+
+void QQuickViewTestUtil::StressTestModel::updateModel()
+{
+ if (m_rowCount > 10) {
+ for (int i = 0; i < 10; ++i) {
+ int rnum = qrand() % m_rowCount;
+ beginRemoveRows(QModelIndex(), rnum, rnum);
+ m_rowCount--;
+ endRemoveRows();
+ }
+ }
+ if (m_rowCount < 20) {
+ for (int i = 0; i < 10; ++i) {
+ int rnum = qrand() % m_rowCount;
+ beginInsertRows(QModelIndex(), rnum, rnum);
+ m_rowCount++;
+ endInsertRows();
+ }
+ }
+}
+
+bool QQuickViewTestUtil::testVisibleItems(const QQuickItemViewPrivate *priv, bool *nonUnique, FxViewItem **failItem, int *expectedIdx)
+{
+ QHash<QQuickItem*, int> uniqueItems;
+
+ int skip = 0;
+ for (int i = 0; i < priv->visibleItems.count(); ++i) {
+ FxViewItem *item = priv->visibleItems.at(i);
+ if (!item) {
+ *failItem = Q_NULLPTR;
+ return false;
+ }
+#if 0
+ qDebug() << "\t" << item->index
+ << item->item
+ << item->position()
+ << (!item->item || QQuickItemPrivate::get(item->item)->culled ? "hidden" : "visible");
+#endif
+ if (item->index == -1) {
+ ++skip;
+ } else if (item->index != priv->visibleIndex + i - skip) {
+ *nonUnique = false;
+ *failItem = item;
+ *expectedIdx = priv->visibleIndex + i - skip;
+ return false;
+ } else if (uniqueItems.contains(item->item)) {
+ *nonUnique = true;
+ *failItem = item;
+ *expectedIdx = uniqueItems.find(item->item).value();
+ return false;
+ }
+
+ uniqueItems.insert(item->item, item->index);
+ }
+
+ return true;
+}
+
namespace QQuickTouchUtils {
/* QQuickWindow does event compression and only delivers events just
diff --git a/tests/auto/quick/shared/viewtestutil.h b/tests/auto/quick/shared/viewtestutil.h
index 0f50180809..b11d5e4859 100644
--- a/tests/auto/quick/shared/viewtestutil.h
+++ b/tests/auto/quick/shared/viewtestutil.h
@@ -34,6 +34,8 @@
#include <QtCore/QAbstractListModel>
QT_FORWARD_DECLARE_CLASS(QQuickView)
+QT_FORWARD_DECLARE_CLASS(QQuickItemViewPrivate)
+QT_FORWARD_DECLARE_CLASS(FxViewItem)
namespace QQuickViewTestUtil
{
@@ -154,6 +156,26 @@ namespace QQuickViewTestUtil
for (; f != replaced.end(); ++f, ++t)
*t = *f;
}
+
+ class StressTestModel : public QAbstractListModel
+ {
+ Q_OBJECT
+
+ public:
+
+ StressTestModel();
+
+ int rowCount(const QModelIndex &) const;
+ QVariant data(const QModelIndex &, int) const;
+
+ public Q_SLOTS:
+ void updateModel();
+
+ private:
+ int m_rowCount;
+ };
+
+ bool testVisibleItems(const QQuickItemViewPrivate *priv, bool *nonUnique, FxViewItem **failItem, int *expectedIdx);
}
namespace QQuickTouchUtils {