aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2019-01-22 10:35:09 +0100
committerLiang Qi <liang.qi@qt.io>2019-01-22 11:20:29 +0100
commit1b4d2741f90d3f4daf79940b9c8713dda0fb7f3d (patch)
tree40cee4f6af7bf9a5fc87c43f024f417a5d09e18d
parent536868fad50778ec5bf4c6c7269c721b05d8a2d5 (diff)
parent84e15a609b37a64baf82ed20f8d4f79474989226 (diff)
Merge remote-tracking branch 'origin/5.12' into dev
Conflicts: .qmake.conf tests/auto/quick/qquickpathview/tst_qquickpathview.cpp Change-Id: Ic1f5e219a255d0613f7654368a5ce3eccb8f0ee9
-rw-r--r--src/particles/qquickcustomparticle.cpp1
-rw-r--r--src/qml/compiler/qv4compileddata.cpp2
-rw-r--r--src/qml/jsapi/qjsvalue.cpp6
-rw-r--r--src/qml/jsruntime/qv4engine.cpp5
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp1
-rw-r--r--src/qml/jsruntime/qv4stackframe_p.h2
-rw-r--r--src/qml/qml/qqmlbinding.cpp13
-rw-r--r--src/qml/qml/qqmlcomponent.cpp8
-rw-r--r--src/qml/qml/qqmlengine.cpp4
-rw-r--r--src/qml/qml/qqmllist.cpp6
-rw-r--r--src/qml/qml/qqmlmetatype.cpp16
-rw-r--r--src/quick/items/qquickitem.cpp6
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp7
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h9
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp4
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h2
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp2
-rw-r--r--src/quick/util/qquickimageprovider.cpp2
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp16
-rw-r--r--tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp39
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp56
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp1
-rw-r--r--tests/manual/tableview/storagemodel/main.qml74
-rw-r--r--tests/manual/tableview/storagemodel/storagemodel.cpp82
-rw-r--r--tests/manual/tableview/storagemodel/storagemodel.h25
25 files changed, 289 insertions, 100 deletions
diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp
index 8528a6f750..85056dffa9 100644
--- a/src/particles/qquickcustomparticle.cpp
+++ b/src/particles/qquickcustomparticle.cpp
@@ -39,6 +39,7 @@
#include "qquickcustomparticle_p.h"
#include <QtCore/qrandom.h>
+#include <QtGui/qopenglcontext.h>
#include <QtQuick/private/qquickshadereffectmesh_p.h>
#include <QtQuick/private/qsgshadersourcebuilder_p.h>
#include <QtQml/qqmlinfo.h>
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 9379160a65..a69e862fb7 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -756,7 +756,7 @@ QString Binding::valueAsString(const CompilationUnit *unit) const
#if !QT_CONFIG(translation)
case Type_TranslationById:
case Type_Translation:
- return unit->stringAt(unit->unitData->translations()[value.translationDataIndex].stringIndex);
+ return unit->stringAt(unit->unitData()->translations()[value.translationDataIndex].stringIndex);
#else
case Type_TranslationById: {
const TranslationData &translation = unit->unitData()->translations()[value.translationDataIndex];
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 225a4443d9..f6fb93eab3 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -1343,11 +1343,11 @@ bool QJSValue::hasOwnProperty(const QString &name) const
/*!
* If this QJSValue is a QObject, returns the QObject pointer
- * that the QJSValue represents; otherwise, returns 0.
+ * that the QJSValue represents; otherwise, returns \nullptr.
*
* If the QObject that this QJSValue wraps has been deleted,
- * this function returns 0 (i.e. it is possible for toQObject()
- * to return 0 even when isQObject() returns true).
+ * this function returns \nullptr (i.e. it is possible for toQObject()
+ * to return \nullptr even when isQObject() returns true).
*
* \sa isQObject()
*/
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index ff7bcb63fa..a482cc6a67 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1011,6 +1011,11 @@ StackTrace ExecutionEngine::stackTrace(int frameLimit) const
frame.line = qAbs(f->lineNumber());
frame.column = -1;
stack.append(frame);
+ if (f->isTailCalling) {
+ QV4::StackFrame frame;
+ frame.function = QStringLiteral("[elided tail calls]");
+ stack.append(frame);
+ }
--frameLimit;
f = f->parent;
}
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index dfe9d35194..41a21ba379 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -518,6 +518,7 @@ ReturnedValue ArrowFunction::virtualCall(const FunctionObject *fo, const Value *
do {
frame.pendingTailCall = false;
result = Moth::VME::exec(&frame, engine);
+ frame.isTailCalling = true;
} while (frame.pendingTailCall);
frame.pop();
diff --git a/src/qml/jsruntime/qv4stackframe_p.h b/src/qml/jsruntime/qv4stackframe_p.h
index a97ae0e7c9..44cfef9173 100644
--- a/src/qml/jsruntime/qv4stackframe_p.h
+++ b/src/qml/jsruntime/qv4stackframe_p.h
@@ -125,6 +125,7 @@ struct Q_QML_EXPORT CppStackFrame {
bool yieldIsIterator;
bool callerCanHandleTailCall;
bool pendingTailCall;
+ bool isTailCalling;
void init(EngineBase *engine, Function *v4Function, const Value *argv, int argc, bool callerCanHandleTailCall = false) {
this->engine = engine;
@@ -140,6 +141,7 @@ struct Q_QML_EXPORT CppStackFrame {
yieldIsIterator = false;
this->callerCanHandleTailCall = callerCanHandleTailCall;
pendingTailCall = false;
+ isTailCalling = false;
}
void push() {
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 024ec29a56..a949df4968 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -517,11 +517,14 @@ QVariant QQmlBinding::evaluate()
QString QQmlBinding::expressionIdentifier() const
{
- auto f = function();
- QString url = f->sourceFile();
- quint16 lineNumber = f->compiledFunction->location.line;
- quint16 columnNumber = f->compiledFunction->location.column;
- return url + QString::asprintf(":%u:%u", uint(lineNumber), uint(columnNumber));
+ if (auto f = function()) {
+ QString url = f->sourceFile();
+ quint16 lineNumber = f->compiledFunction->location.line;
+ quint16 columnNumber = f->compiledFunction->location.column;
+ return url + QString::asprintf(":%u:%u", uint(lineNumber), uint(columnNumber));
+ }
+
+ return QStringLiteral("[native code]");
}
void QQmlBinding::expressionChanged()
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 5ed3cc5d6a..57ea685a5d 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -756,12 +756,12 @@ QQmlComponent::QQmlComponent(QQmlComponentPrivate &dd, QObject *parent)
}
/*!
- Create an object instance from this component. Returns 0 if creation
+ Create an object instance from this component. Returns \nullptr if creation
failed. \a context specifies the context within which to create the object
instance.
- If \a context is 0 (the default), it will create the instance in the
- engine' s \l {QQmlEngine::rootContext()}{root context}.
+ If \a context is \nullptr (the default), it will create the instance in the
+ \l {QQmlEngine::rootContext()}{root context} of the engine.
The ownership of the returned object instance is transferred to the caller.
@@ -791,7 +791,7 @@ QObject *QQmlComponent::create(QQmlContext *context)
In general, programmers should use QQmlComponent::create() to create object
instances.
- Create an object instance from this component. Returns 0 if creation
+ Create an object instance from this component. Returns \nullptr if creation
failed. \a publicContext specifies the context within which to create the object
instance.
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 6db43a50eb..5841a480fc 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -1304,9 +1304,7 @@ void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBa
}
/*!
- Returns the image provider set for \a providerId.
-
- Returns the provider if it was found; otherwise returns 0.
+ Returns the image provider set for \a providerId if found; otherwise returns \nullptr.
\sa QQuickImageProvider
*/
diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp
index 656a8a470b..5425bf498c 100644
--- a/src/qml/qml/qqmllist.cpp
+++ b/src/qml/qml/qqmllist.cpp
@@ -184,7 +184,7 @@ bool QQmlListReference::isValid() const
}
/*!
-Returns the list property's object. Returns 0 if the reference is invalid.
+Returns the list property's object. Returns \nullptr if the reference is invalid.
*/
QObject *QQmlListReference::object() const
{
@@ -193,8 +193,8 @@ QObject *QQmlListReference::object() const
}
/*!
-Returns the QMetaObject for the elements stored in the list property. Returns 0 if the reference
-is invalid.
+Returns the QMetaObject for the elements stored in the list property,
+or \nullptr if the reference is invalid.
The QMetaObject can be used ahead of time to determine whether a given instance can be added
to a list.
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index c05ae27b93..032ee7d6fc 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -497,9 +497,9 @@ QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQm
d->extraData.cd->attachedPropertiesFunc = type.attachedPropertiesFunction;
d->extraData.cd->attachedPropertiesType = type.attachedPropertiesMetaObject;
if (d->extraData.cd->attachedPropertiesType) {
- QHash<const QMetaObject *, int>::Iterator iter = d->attachedPropertyIds.find(d->baseMetaObject);
- if (iter == d->attachedPropertyIds.end())
- iter = d->attachedPropertyIds.insert(d->baseMetaObject, d->index);
+ auto iter = QQmlTypePrivate::attachedPropertyIds.find(d->baseMetaObject);
+ if (iter == QQmlTypePrivate::attachedPropertyIds.end())
+ iter = QQmlTypePrivate::attachedPropertyIds.insert(d->baseMetaObject, d->index);
d->extraData.cd->attachedPropertiesId = *iter;
} else {
d->extraData.cd->attachedPropertiesId = -1;
@@ -569,8 +569,16 @@ QQmlType::QQmlType(QQmlTypePrivate *priv)
QQmlType::~QQmlType()
{
- if (d && !d->refCount.deref())
+ if (d && !d->refCount.deref()) {
+ // If attached properties were successfully registered, deregister them.
+ // (They may not have been registered if some other type used the same baseMetaObject)
+ if (d->regType == CppType && d->extraData.cd->attachedPropertiesType) {
+ auto it = QQmlTypePrivate::attachedPropertyIds.find(d->baseMetaObject);
+ if (it != QQmlTypePrivate::attachedPropertyIds.end() && *it == d->index)
+ QQmlTypePrivate::attachedPropertyIds.erase(it);
+ }
delete d;
+ }
}
QHashedString QQmlType::module() const
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 0cd4c446d9..ec6bf5a1b8 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -4800,7 +4800,7 @@ QQuickItem *QQuickItem::nextItemInFocusChain(bool forward)
Returns the first visible child item found at point (\a x, \a y) within
the coordinate system of this item.
- Returns 0 if there is no such item.
+ Returns \nullptr if there is no such item.
*/
QQuickItem *QQuickItem::childAt(qreal x, qreal y) const
{
@@ -7224,7 +7224,7 @@ bool QQuickItem::isFocusScope() const
If this item is a focus scope, this returns the item in its focus chain
that currently has focus.
- Returns 0 if this item is not a focus scope.
+ Returns \nullptr if this item is not a focus scope.
*/
QQuickItem *QQuickItem::scopedFocusItem() const
{
@@ -8160,7 +8160,7 @@ bool QQuickItem::isTextureProvider() const
\fn QSGTextureProvider *QQuickItem::textureProvider() const
Returns the texture provider for an item. The default implementation
- returns 0.
+ returns \nullptr.
This function may only be called on the rendering thread.
*/
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index c99e149aa5..252e5a9c55 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -56,7 +56,7 @@ static QElapsedTimer qsg_render_timer;
QSGDistanceFieldGlyphCache::Texture QSGDistanceFieldGlyphCache::s_emptyTexture;
-QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QOpenGLContext *c, const QRawFont &font)
+QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(const QRawFont &font)
: m_pendingGlyphs(64)
{
Q_ASSERT(font.isValid());
@@ -71,11 +71,6 @@ QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QOpenGLContext *c, const
// this allows us to call pathForGlyph once and reuse the result.
m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(m_doubleGlyphResolution) * QT_DISTANCEFIELD_SCALE(m_doubleGlyphResolution));
Q_ASSERT(m_referenceFont.isValid());
-#if QT_CONFIG(opengl)
- m_coreProfile = (c->format().profile() == QSurfaceFormat::CoreProfile);
-#else
- Q_UNUSED(c)
-#endif
}
QSGDistanceFieldGlyphCache::~QSGDistanceFieldGlyphCache()
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index ba5c4353b2..58ecae94e7 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -62,7 +62,6 @@
#include <QtCore/qurl.h>
#include <private/qfontengine_p.h>
#include <QtGui/private/qdatabuffer_p.h>
-#include <private/qopenglcontext_p.h>
#include <private/qdistancefield_p.h>
#include <private/qintrusivelist_p.h>
@@ -75,7 +74,6 @@ class QSGNode;
class QImage;
class TextureReference;
class QSGDistanceFieldGlyphNode;
-class QOpenGLContext;
class QSGInternalImageNode;
class QSGPainterNode;
class QSGInternalRectangleNode;
@@ -413,7 +411,7 @@ typedef QIntrusiveList<QSGDistanceFieldGlyphConsumer, &QSGDistanceFieldGlyphCons
class Q_QUICK_PRIVATE_EXPORT QSGDistanceFieldGlyphCache
{
public:
- QSGDistanceFieldGlyphCache(QOpenGLContext *c, const QRawFont &font);
+ QSGDistanceFieldGlyphCache(const QRawFont &font);
virtual ~QSGDistanceFieldGlyphCache();
struct Metrics {
@@ -514,8 +512,6 @@ protected:
void saveTexture(GLuint textureId, int width, int height) const;
#endif
- inline bool isCoreProfile() const { return m_coreProfile; }
-
bool m_doubleGlyphResolution;
protected:
@@ -523,9 +519,6 @@ protected:
private:
int m_glyphCount;
-
- bool m_coreProfile;
-
QList<Texture> m_textures;
QHash<glyph_t, GlyphData> m_glyphsData;
QDataBuffer<glyph_t> m_pendingGlyphs;
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
index ccc57b0b86..8121b4559e 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -67,7 +67,7 @@ DEFINE_BOOL_CONFIG_OPTION(qsgPreferFullSizeGlyphCacheTextures, QSG_PREFER_FULLSI
QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QOpenGLContext *c,
const QRawFont &font)
- : QSGDistanceFieldGlyphCache(c, font)
+ : QSGDistanceFieldGlyphCache(font)
, m_maxTextureSize(0)
, m_maxTextureCount(3)
, m_areaAllocator(nullptr)
@@ -89,6 +89,8 @@ QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QOpenGLCont
qWarning("Buffer creation failed");
}
+ m_coreProfile = (c->format().profile() == QSurfaceFormat::CoreProfile);
+
// Load a pregenerated cache if the font contains one
loadPregeneratedCache(font);
}
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
index a0e4387af9..c64adddd91 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
@@ -88,6 +88,7 @@ public:
private:
bool loadPregeneratedCache(const QRawFont &font);
+ inline bool isCoreProfile() const { return m_coreProfile; }
struct TextureInfo {
GLuint texture;
@@ -137,6 +138,7 @@ private:
mutable int m_maxTextureSize;
int m_maxTextureCount;
+ bool m_coreProfile;
QList<TextureInfo> m_textures;
QHash<glyph_t, TextureInfo *> m_glyphsTexture;
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index 720f08f69b..042eee19f5 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -389,7 +389,7 @@ QSGTexture::~QSGTexture()
it to a shader that operates on the texture coordinates 0-1 instead
of the texture subrect inside the atlas.
- If the texture is not part of a texture atlas, this function returns 0.
+ If the texture is not part of a texture atlas, this function returns \nullptr.
Implementations of this function are recommended to return the same instance
for multiple calls to limit memory usage.
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index ced981de3e..ebcca77f17 100644
--- a/src/quick/util/qquickimageprovider.cpp
+++ b/src/quick/util/qquickimageprovider.cpp
@@ -436,7 +436,7 @@ QPixmap QQuickImageProvider::requestPixmap(const QString &id, QSize *size, const
/*!
Implement this method to return the texture with \a id. The default
- implementation returns 0.
+ implementation returns \nullptr.
The \a id is the requested image source, with the "image:" scheme and
provider identifier removed. For example, if the image \l{Image::}{source}
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index b75f069fab..94494df4c0 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -1759,6 +1759,22 @@ void tst_QJSEngine::stacktrace()
QJSValue result2 = eng.evaluate(script2, fileName);
QVERIFY(!result2.isError());
QVERIFY(result2.isString());
+
+ {
+ QString script3 = QString::fromLatin1(
+ "'use strict'\n"
+ "function throwUp() { throw new Error('up') }\n"
+ "function indirectlyThrow() { return throwUp() }\n"
+ "indirectlyThrow()\n"
+ );
+ QJSValue result3 = eng.evaluate(script3);
+ QVERIFY(result3.isError());
+ QJSValue stack = result3.property("stack");
+ QVERIFY(stack.isString());
+ QString stackTrace = stack.toString();
+ QVERIFY(!stackTrace.contains(QStringLiteral("indirectlyThrow")));
+ QVERIFY(stackTrace.contains(QStringLiteral("elide")));
+ }
}
void tst_QJSEngine::numberParsing_data()
diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
index e83dac48fb..7139a1c952 100644
--- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
+++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
@@ -35,6 +35,7 @@
#include <private/qqmlmetatype_p.h>
#include <private/qqmlpropertyvalueinterceptor_p.h>
+#include <private/qqmlengine_p.h>
#include <private/qhashedstring_p.h>
#include "../../shared/util.h"
@@ -64,6 +65,7 @@ private slots:
void unregisterCustomSingletonType();
void normalizeUrls();
+ void unregisterAttachedProperties();
};
class TestType : public QObject
@@ -533,6 +535,43 @@ void tst_qqmlmetatype::normalizeUrls()
QVERIFY(!QQmlMetaType::qmlType(url, /*includeNonFileImports=*/true).isValid());
}
+void tst_qqmlmetatype::unregisterAttachedProperties()
+{
+ qmlClearTypeRegistrations();
+
+ const QUrl dummy("qrc:///doesnotexist.qml");
+ {
+ QQmlEngine e;
+ QQmlComponent c(&e);
+ c.setData("import QtQuick 2.2\n Item { }", dummy);
+
+ const QQmlType attachedType = QQmlMetaType::qmlType("QtQuick/KeyNavigation", 2, 2);
+ QCOMPARE(attachedType.attachedPropertiesId(QQmlEnginePrivate::get(&e)),
+ attachedType.index());
+
+ QVERIFY(c.create());
+ }
+
+ qmlClearTypeRegistrations();
+ {
+ QQmlEngine e;
+ QQmlComponent c(&e);
+
+ // The extra import shuffles the type IDs around, so that we
+ // get a different ID for the attached properties. If the attached
+ // properties aren't properly cleared, this will crash.
+ c.setData("import QtQml.StateMachine 1.0 \n"
+ "import QtQuick 2.2 \n"
+ "Item { KeyNavigation.up: null }", dummy);
+
+ const QQmlType attachedType = QQmlMetaType::qmlType("QtQuick/KeyNavigation", 2, 2);
+ QCOMPARE(attachedType.attachedPropertiesId(QQmlEnginePrivate::get(&e)),
+ attachedType.index());
+
+ QVERIFY(c.create());
+ }
+}
+
QTEST_MAIN(tst_qqmlmetatype)
#include "tst_qqmlmetatype.moc"
diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
index 62027f59f4..3526eb98be 100644
--- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
+++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
@@ -88,31 +88,37 @@ void tst_qquickapplication::active()
QQuickWindow window;
item->setParentItem(window.contentItem());
- // not active
- QVERIFY(!item->property("active").toBool());
- QVERIFY(!item->property("active2").toBool());
-
- // active
- window.show();
- window.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&window));
- QCOMPARE(QGuiApplication::focusWindow(), &window);
- QVERIFY(item->property("active").toBool());
- QVERIFY(item->property("active2").toBool());
-
- QWindowSystemInterface::handleWindowActivated(nullptr);
-
-#ifdef Q_OS_OSX
- // OS X has the concept of "reactivation"
- QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
- QVERIFY(item->property("active").toBool());
- QVERIFY(item->property("active2").toBool());
-#else
- // not active again
- QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
- QVERIFY(!item->property("active").toBool());
- QVERIFY(!item->property("active2").toBool());
-#endif
+ // If the platform plugin has the ApplicationState capability, app activation originate from it
+ // as a result of a system event. We therefore have to simulate these events here.
+ if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) {
+
+ // Flush pending events, in case the platform have already queued real application state events
+ QWindowSystemInterface::flushWindowSystemEvents();
+
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
+ QWindowSystemInterface::flushWindowSystemEvents();
+ QVERIFY(item->property("active").toBool());
+ QVERIFY(item->property("active2").toBool());
+
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
+ QWindowSystemInterface::flushWindowSystemEvents();
+ QVERIFY(!item->property("active").toBool());
+ QVERIFY(!item->property("active2").toBool());
+ } else {
+ // Otherwise, app activation is triggered by window activation.
+ window.show();
+ window.requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+ QCOMPARE(QGuiApplication::focusWindow(), &window);
+ QVERIFY(item->property("active").toBool());
+ QVERIFY(item->property("active2").toBool());
+
+ // not active again
+ QWindowSystemInterface::handleWindowActivated(nullptr);
+ QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
+ QVERIFY(!item->property("active").toBool());
+ QVERIFY(!item->property("active2").toBool());
+ }
}
void tst_qquickapplication::state()
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index 8d3abb7ce3..bf38d2d926 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -1372,6 +1372,7 @@ void tst_QQuickPathView::package()
QSKIP("QTBUG-27170 view does not reliably receive polish without a running animation");
#endif
+ QQuickTest::qWaitForItemPolished(pathView);
QQuickItem *item = findItem<QQuickItem>(pathView, "pathItem");
QVERIFY(item);
QVERIFY(item->scale() != 1.0);
diff --git a/tests/manual/tableview/storagemodel/main.qml b/tests/manual/tableview/storagemodel/main.qml
index 2603fba0e2..725d7da7b0 100644
--- a/tests/manual/tableview/storagemodel/main.qml
+++ b/tests/manual/tableview/storagemodel/main.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -38,13 +38,14 @@
****************************************************************************/
import QtQuick 2.12
-import QtQuick.Window 2.3
+import QtQuick.Window 2.12
+import Qt.labs.qmlmodels 1.0
import StorageModel 0.1
Window {
id: window
- width: 640
- height: 480
+ width: 480
+ height: 300
visible: true
color: "darkgray"
title: "Storage Volumes"
@@ -57,17 +58,62 @@ Window {
model: StorageModel { }
columnSpacing: 1
rowSpacing: 1
- delegate: Rectangle {
- id: tableDelegate
- implicitWidth: displayText.implicitWidth + 8
- implicitHeight: displayText.implicitHeight + 14
+ delegate: DelegateChooser {
+ role: "type"
+ DelegateChoice {
+ roleValue: "Value"
+ delegate: Rectangle {
+ color: "tomato"
+ implicitWidth: Math.max(100, label.implicitWidth + 8)
+ implicitHeight: label.implicitHeight + 4
- Text {
- id: displayText
- anchors.bottom: parent.bottom
- anchors.left: parent.left
- anchors.leftMargin: 4
- text: display
+ Rectangle {
+ x: parent.width - width
+ width: value * parent.width / valueMax
+ height: parent.height
+ color: "white"
+ }
+
+ Text {
+ id: label
+ anchors.baseline: parent.bottom
+ anchors.baselineOffset: -4
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ text: valueDisplay + " of " + valueMaxDisplay + " " + heading
+ }
+ }
+ }
+ DelegateChoice {
+ roleValue: "Flag"
+ // We could use a checkbox here but that would be another component (e.g. from Controls)
+ delegate: Rectangle {
+ implicitWidth: checkBox.implicitWidth + 8
+ implicitHeight: checkBox.implicitHeight + 4
+ Text {
+ id: checkBox
+ anchors.baseline: parent.bottom
+ anchors.baselineOffset: -4
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ text: (checkState ? "☑ " : "☐ ") + heading
+ }
+ }
+ }
+ DelegateChoice {
+ // roleValue: "String" // default delegate
+ delegate: Rectangle {
+ implicitWidth: stringLabel.implicitWidth + 8
+ implicitHeight: stringLabel.implicitHeight + 4
+ Text {
+ id: stringLabel
+ anchors.baseline: parent.bottom
+ anchors.baselineOffset: -4
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ text: display
+ }
+ }
}
}
}
diff --git a/tests/manual/tableview/storagemodel/storagemodel.cpp b/tests/manual/tableview/storagemodel/storagemodel.cpp
index b6b861a1a8..b43454b249 100644
--- a/tests/manual/tableview/storagemodel/storagemodel.cpp
+++ b/tests/manual/tableview/storagemodel/storagemodel.cpp
@@ -63,6 +63,20 @@ StorageModel::StorageModel(QObject *parent) :
refresh();
}
+QHash<int, QByteArray> StorageModel::roleNames() const {
+ static auto roles = QHash<int, QByteArray> {
+ { int(Role::Type), "type" },
+ { int(Role::Heading), "heading" },
+ { int(Role::Value), "value" },
+ { int(Role::ValueMax), "valueMax" },
+ { int(Role::ValueDisplay), "valueDisplay" },
+ { int(Role::ValueMaxDisplay), "valueMaxDisplay" },
+ { Qt::CheckStateRole, "checkState" },
+ };
+ static auto ret = roles.unite(QAbstractTableModel::roleNames());;
+ return ret;
+}
+
void StorageModel::refresh()
{
beginResetModel();
@@ -92,7 +106,6 @@ Qt::ItemFlags StorageModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags result = QAbstractTableModel::flags(index);
switch (Column(index.column())) {
- case Column::Available:
case Column::IsReady:
case Column::IsReadOnly:
case Column::IsValid:
@@ -109,7 +122,9 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
if (!index.isValid())
return QVariant();
- if (role == Qt::DisplayRole) {
+ switch (role) {
+ case Qt::DisplayRole:
+ case int(Role::ValueDisplay): {
const QStorageInfo &volume = m_volumes.at(index.row());
switch (Column(index.column())) {
case Column::RootPath:
@@ -120,12 +135,8 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
return volume.device();
case Column::FileSystemName:
return volume.fileSystemType();
- case Column::Total:
- return QLocale().formattedDataSize(volume.bytesTotal());
case Column::Free:
return QLocale().formattedDataSize(volume.bytesFree());
- case Column::Available:
- return QLocale().formattedDataSize(volume.bytesAvailable());
case Column::IsReady:
return volume.isReady();
case Column::IsReadOnly:
@@ -135,7 +146,8 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
default:
break;
}
- } else if (role == Qt::CheckStateRole) {
+ } break;
+ case Qt::CheckStateRole: {
const QStorageInfo &volume = m_volumes.at(index.row());
switch (Column(index.column())) {
case Column::IsReady:
@@ -147,17 +159,16 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
default:
break;
}
- } else if (role == Qt::TextAlignmentRole) {
+ } break;
+ case Qt::TextAlignmentRole:
switch (Column(index.column())) {
- case Column::Total:
case Column::Free:
- case Column::Available:
return Qt::AlignTrailing;
default:
break;
}
return Qt::AlignLeading;
- } else if (role == Qt::ToolTipRole) {
+ case Qt::ToolTipRole: {
QLocale locale;
const QStorageInfo &volume = m_volumes.at(index.row());
return tr("Root path : %1\n"
@@ -186,6 +197,51 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
arg(volume.isValid() ? tr("true") : tr("false")).
arg(volume.isRoot() ? tr("true") : tr("false"));
}
+ case int(Role::Type):
+ switch (Column(index.column())) {
+ case Column::RootPath:
+ case Column::Name:
+ case Column::Device:
+ case Column::FileSystemName:
+ return QVariant::fromValue(Type::String);
+ break;
+ case Column::Free:
+ return QVariant::fromValue(Type::Value);
+ case Column::IsReady:
+ case Column::IsReadOnly:
+ case Column::IsValid:
+ return QVariant::fromValue(Type::Flag);
+ default:
+ break;
+ }
+ break;
+ case int(Role::Heading):
+ return headerData(index.column());
+ case int(Role::Value):
+ switch (Column(index.column())) {
+ case Column::Free:
+ return m_volumes.at(index.row()).bytesFree();
+ default:
+ break;
+ }
+ break;
+ case int(Role::ValueMax):
+ switch (Column(index.column())) {
+ case Column::Free:
+ return m_volumes.at(index.row()).bytesTotal();
+ default:
+ break;
+ }
+ break;
+ case int(Role::ValueMaxDisplay):
+ switch (Column(index.column())) {
+ case Column::Free:
+ return QLocale().formattedDataSize(m_volumes.at(index.row()).bytesTotal());
+ default:
+ break;
+ }
+ break;
+ } // switch (role)
return QVariant();
}
@@ -206,12 +262,8 @@ QVariant StorageModel::headerData(int section, Qt::Orientation orientation, int
return tr("Device");
case Column::FileSystemName:
return tr("File System");
- case Column::Total:
- return tr("Total");
case Column::Free:
return tr("Free");
- case Column::Available:
- return tr("Available");
case Column::IsReady:
return tr("Ready");
case Column::IsReadOnly:
diff --git a/tests/manual/tableview/storagemodel/storagemodel.h b/tests/manual/tableview/storagemodel/storagemodel.h
index 1f6f6f8b1f..6cbab3d850 100644
--- a/tests/manual/tableview/storagemodel/storagemodel.h
+++ b/tests/manual/tableview/storagemodel/storagemodel.h
@@ -65,23 +65,42 @@ public:
Name,
Device,
FileSystemName,
- Total,
Free,
- Available,
IsReady,
IsReadOnly,
IsValid,
Count
};
+ Q_ENUM(Column)
+
+ enum class Role : int {
+ Type = Qt::UserRole + 1,
+ Heading,
+ Value,
+ ValueMax, // If we had ValueMin, it would always be zero in this example
+ ValueDisplay,
+ ValueMaxDisplay,
+ Count
+ };
+ Q_ENUM(Role)
+
+ enum class Type : int {
+ String, // use Qt::DisplayRole
+ Value, // use Role::Value and Role::ValueMax
+ Flag, // use Qt::CheckStateRole
+ Count
+ };
+ Q_ENUM(Type)
explicit StorageModel(QObject *parent = nullptr);
int columnCount(const QModelIndex &parent) const override;
int rowCount(const QModelIndex &parent) const override;
+ QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex &index, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
- QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+ QVariant headerData(int section, Qt::Orientation orientation = Qt::Horizontal, int role = Qt::DisplayRole) const override;
public slots:
void refresh();