Merge remote-tracking branch 'origin/5.7' into dev

Conflicts:
	src/qml/qml/v8/qqmlbuiltinfunctions_p.h
	tests/auto/qml/qqmlqt/tst_qqmlqt.cpp

Change-Id: I9dd93732f4b19513576ca1dd89ae18c69de0203b
This commit is contained in:
Simon Hausmann 2016-05-18 15:17:37 +02:00
commit 5861dc4869
13 changed files with 193 additions and 30 deletions

View File

@ -72,7 +72,7 @@ protected:
{
QMutexLocker lock(&m_configMutex);
m_waitingForConfiguration = false;
foreach (QJSEngine *engine, m_waitingEngines)
for (QJSEngine *engine : qAsConst(m_waitingEngines))
emit Base::attachedToEngine(engine);
m_waitingEngines.clear();
}

View File

@ -135,7 +135,7 @@ public:
// Validate the new range
if (_end != InvalidPosition) {
Q_ASSERT(!_ranges.isEmpty());
foreach (const Range &range, _ranges) {
for (const Range &range : qAsConst(_ranges)) {
Q_ASSERT(range.start >= 0);
Q_ASSERT(range.end >= 0);
Q_ASSERT(range.start <= range.end);

View File

@ -134,7 +134,8 @@ public:
static int ebxIdx = -1;
if (ebxIdx == -1) {
int calleeSaves = 0;
foreach (const RegisterInfo &info, getRegisterInfo()) {
const auto infos = getRegisterInfo();
for (const RegisterInfo &info : infos) {
if (info.reg<JSC::X86Registers::RegisterID>() == JSC::X86Registers::ebx) {
ebxIdx = calleeSaves;
break;

View File

@ -174,7 +174,7 @@ public:
inline DiagnosticMessage diagnosticMessage() const
{
foreach (const DiagnosticMessage &d, diagnostic_messages) {
for (const DiagnosticMessage &d : diagnostic_messages) {
if (d.kind != DiagnosticMessage::Warning)
return d;
}

View File

@ -302,7 +302,7 @@ public:
int vmaj, int vmin, QV4::CompiledData::Import::ImportType type,
QList<QQmlError> *errors, bool lowPrecedence = false);
#ifndef QT_NO_LIBRARY
bool populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri,
bool populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri, const QStringList &versionUris,
const QString &qmldirPath, QList<QQmlError> *errors);
#endif
};
@ -878,14 +878,34 @@ QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QHashedStr
return 0;
}
/*!
Returns the list of possible versioned URI combinations. For example, if \a uri is
QtQml.Models, \a vmaj is 2, and \a vmin is 0, this method returns the following:
[QtQml.Models.2.0, QtQml.2.0.Models, QtQml.Models.2, QtQml.2.Models, QtQml.Models]
*/
static QStringList versionUriList(const QString &uri, int vmaj, int vmin)
{
QStringList result;
for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) {
int index = uri.length();
do {
QString versionUri = uri;
versionUri.insert(index, QQmlImports::versionString(vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version)));
result += versionUri;
index = uri.lastIndexOf(Dot, index - 1);
} while (index > 0 && version != QQmlImports::Unversioned);
}
return result;
}
#ifndef QT_NO_LIBRARY
/*!
Get all static plugins that are QML plugins and has a meta data URI that begins with \a uri.
Note that if e.g uri == "a", and different plugins have meta data "a", "a.2.1", "a.b.c", all
will be added to the result. So the result needs further version matching by the caller.
Get all static plugins that are QML plugins and has a meta data URI that matches with one of
\a versionUris, which is a list of all possible versioned URI combinations - see versionUriList()
above.
*/
bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri,
bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri, const QStringList &versionUris,
const QString &qmldirPath, QList<QQmlError> *errors)
{
static QVector<QStaticPlugin> plugins;
@ -914,7 +934,7 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res
}
// A plugin can be set up to handle multiple URIs, so go through the list:
foreach (const QJsonValue &metaTagUri, metaTagsUriList) {
if (metaTagUri.toString().startsWith(uri)) {
if (versionUris.contains(metaTagUri.toString())) {
result.append(qMakePair(plugin, metaTagsUriList));
break;
}
@ -1007,14 +1027,13 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
// versioned to unversioned, we need to compare with differnt version strings. If a module
// has several plugins, they must all have the same version. Start by populating pluginPairs
// with relevant plugins to cut the list short early on:
const QStringList versionUris = versionUriList(uri, vmaj, vmin);
QVector<StaticPluginPair> pluginPairs;
if (!populatePluginPairVector(pluginPairs, uri, qmldirFilePath, errors))
if (!populatePluginPairVector(pluginPairs, uri, versionUris, qmldirFilePath, errors))
return false;
const QString basePath = QFileInfo(qmldirPath).absoluteFilePath();
for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned && staticPluginsFound == 0; ++version) {
QString versionUri = uri + QQmlImports::versionString(vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version));
for (const QString &versionUri : versionUris) {
foreach (const StaticPluginPair &pair, pluginPairs) {
foreach (const QJsonValue &metaTagUri, pair.second) {
if (versionUri == metaTagUri.toString()) {
@ -1035,6 +1054,8 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
}
}
}
if (staticPluginsFound > 0)
break;
}
}

View File

@ -88,22 +88,18 @@ struct StaticQtMetaObject : public QObject
};
Heap::QtObject::QtObject(QQmlEngine *qmlEngine)
: enumeratorIterator(0)
, keyIterator(0)
{
Scope scope(internalClass->engine);
ScopedObject o(scope, this);
// Set all the enums from the "Qt" namespace
const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
ScopedString str(scope);
ScopedValue v(scope);
for (int ii = 0, eii = qtMetaObject->enumeratorCount(); ii < eii; ++ii) {
QMetaEnum enumerator = qtMetaObject->enumerator(ii);
for (int jj = 0, ejj = enumerator.keyCount(); jj < ejj; ++jj) {
o->put((str = scope.engine->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj))));
}
{
ScopedString str(scope);
ScopedValue v(scope);
o->put((str = scope.engine->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0)));
o->put((str = scope.engine->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1)));
}
o->put((str = scope.engine->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0)));
o->put((str = scope.engine->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1)));
o->defineDefaultProperty(QStringLiteral("include"), QV4Include::method_include);
o->defineDefaultProperty(QStringLiteral("isQtObject"), QV4::QtObject::method_isQtObject);
@ -154,6 +150,70 @@ Heap::QtObject::QtObject(QQmlEngine *qmlEngine)
o->defineDefaultProperty(QStringLiteral("callLater"), QV4::QtObject::method_callLater);
}
void QtObject::addAll()
{
bool dummy = false;
findAndAdd(nullptr, dummy);
}
ReturnedValue QtObject::findAndAdd(const QString *name, bool &foundProperty) const
{
Scope scope(engine());
ScopedObject o(scope, this);
ScopedString key(scope);
ScopedValue value(scope);
const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
for (int enumCount = qtMetaObject->enumeratorCount(); d()->enumeratorIterator < enumCount;
++d()->enumeratorIterator) {
QMetaEnum enumerator = qtMetaObject->enumerator(d()->enumeratorIterator);
for (int keyCount = enumerator.keyCount(); d()->keyIterator < keyCount; ++d()->keyIterator) {
key = scope.engine->newString(QString::fromUtf8(enumerator.key(d()->keyIterator)));
value = QV4::Primitive::fromInt32(enumerator.value(d()->keyIterator));
o->put(key, value);
if (name && key->toQString() == *name) {
++d()->keyIterator;
foundProperty = true;
return value->asReturnedValue();
}
}
d()->keyIterator = 0;
}
d()->enumeratorIterator = Heap::QtObject::Finished;
foundProperty = false;
return Encode::undefined();
}
ReturnedValue QtObject::get(const Managed *m, String *name, bool *hasProperty)
{
bool hasProp = false;
if (hasProperty == nullptr) {
hasProperty = &hasProp;
}
ReturnedValue ret = QV4::Object::get(m, name, hasProperty);
if (*hasProperty) {
return ret;
}
auto that = static_cast<const QtObject*>(m);
if (!that->d()->isComplete()) {
const QString key = name->toQString();
ret = that->findAndAdd(&key, *hasProperty);
}
return ret;
}
void QtObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{
auto that = static_cast<QtObject*>(m);
if (!that->d()->isComplete()) {
that->addAll();
}
QV4::Object::advanceIterator(m, it, name, index, p, attributes);
}
/*!
\qmlmethod bool Qt::isQtObject(object)

View File

@ -67,6 +67,13 @@ struct QtObject : Object {
QtObject(QQmlEngine *qmlEngine);
QObject *platform;
QObject *application;
enum { Finished = -1 };
int enumeratorIterator;
int keyIterator;
bool isComplete() const
{ return enumeratorIterator == Finished; }
};
struct ConsoleObject : Object {
@ -86,6 +93,9 @@ struct QtObject : Object
{
V4_OBJECT2(QtObject, Object)
static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static ReturnedValue method_isQtObject(CallContext *ctx);
static ReturnedValue method_rgba(CallContext *ctx);
static ReturnedValue method_hsla(CallContext *ctx);
@ -126,6 +136,10 @@ struct QtObject : Object
static ReturnedValue method_get_styleHints(CallContext *ctx);
static ReturnedValue method_callLater(CallContext *ctx);
private:
void addAll();
ReturnedValue findAndAdd(const QString *name, bool &foundProperty) const;
};
struct ConsoleObject : Object

View File

@ -90,9 +90,9 @@ public:
virtual ~QQuickAnchors();
enum Anchor
#if !(defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (Q_CC_GNU < 500))
#if defined(Q_CC_CLANG) || !defined(Q_CC_GNU) // meaning: clang and msvc, but NOT gcc proper (because, you know, Q_CC_CLANG implies Q_CC_GNU)
// Not specifying the enum base type will have MSVC 'interpret' it as signed instead of an unsigned bit-field.
// However, specifying the enum base type breaks GCC 4.x on OpenSUSE 13.something, where it complains that it can't store all values in a 7 bit bitfield.
// However, specifying the enum base type breaks many GCCs, which complain that it can't store all values in a 7 bit bitfield.
: uint
#endif
{

View File

@ -881,6 +881,10 @@ QQuickFlickableVisibleArea *QQuickFlickable::visibleArea()
\e contentHeight is not equal to the \e height of the Flickable.
Allows flicking horizontally if the \e contentWidth is not equal
to the \e width of the Flickable.
\li Flickable.AutoFlickIfNeeded - allows flicking vertically if the
\e contentHeight is greater than the \e height of the Flickable.
Allows flicking horizontally if the \e contentWidth is greater than
to the \e width of the Flickable.
\li Flickable.HorizontalFlick - allows flicking horizontally.
\li Flickable.VerticalFlick - allows flicking vertically.
\li Flickable.HorizontalAndVerticalFlick - allows flicking in both directions.
@ -2167,6 +2171,8 @@ qreal QQuickFlickable::vHeight() const
bool QQuickFlickable::xflick() const
{
Q_D(const QQuickFlickable);
if ((d->flickableDirection & QQuickFlickable::AutoFlickIfNeeded) && (vWidth() > width()))
return true;
if (d->flickableDirection == QQuickFlickable::AutoFlickDirection)
return std::floor(qAbs(vWidth() - width()));
return d->flickableDirection & QQuickFlickable::HorizontalFlick;
@ -2175,6 +2181,8 @@ bool QQuickFlickable::xflick() const
bool QQuickFlickable::yflick() const
{
Q_D(const QQuickFlickable);
if ((d->flickableDirection & QQuickFlickable::AutoFlickIfNeeded) && (vHeight() > height()))
return true;
if (d->flickableDirection == QQuickFlickable::AutoFlickDirection)
return std::floor(qAbs(vHeight() - height()));
return d->flickableDirection & QQuickFlickable::VerticalFlick;

View File

@ -192,7 +192,8 @@ public:
QQuickItem *contentItem();
enum FlickableDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 };
enum FlickableDirection { AutoFlickDirection=0x0, HorizontalFlick=0x1, VerticalFlick=0x2, HorizontalAndVerticalFlick=0x3,
AutoFlickIfNeeded=0xc };
Q_ENUM(FlickableDirection)
FlickableDirection flickableDirection() const;
void setFlickableDirection(FlickableDirection);

View File

@ -0,0 +1,10 @@
import QtQuick 2.0
QtObject {
property var values: Object()
Component.onCompleted: {
for (var key in Qt) {
values[key] = Qt[key]
}
}
}

View File

@ -90,6 +90,7 @@ private slots:
void resolvedUrl();
void later_data();
void later();
void qtObjectContents();
private:
QQmlEngine engine;
@ -1093,6 +1094,51 @@ void tst_qqmlqt::later()
delete root;
}
void tst_qqmlqt::qtObjectContents()
{
struct StaticQtMetaObject : public QObject
{
static const QMetaObject *get()
{ return &staticQtMetaObject; }
};
QQmlComponent component(&engine, testFileUrl("qtObjectContents.qml"));
QObject *object = component.create();
QVERIFY(object != 0);
QVERIFY(object->property("values").canConvert<QJSValue>());
QVariantMap values = object->property("values").value<QJSValue>().toVariant().toMap();
QSet<const char *> keys;
int uniqueKeys = 0;
const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) {
QMetaEnum enumerator = qtMetaObject->enumerator(ii);
for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
auto key = enumerator.key(jj);
// qDebug() << "key:" << key;
if (!keys.contains(key)) {
++uniqueKeys;
keys.insert(key);
}
QVERIFY(values.contains(key));
QVariant value = values.value(key);
QVERIFY(value.canConvert<int>());
QCOMPARE(value.toInt(), enumerator.value(jj));
}
}
QVERIFY(values.contains("Asynchronous"));
QCOMPARE(values.value("Asynchronous").toInt(), 0);
++uniqueKeys;
QVERIFY(values.contains("Synchronous"));
QCOMPARE(values.value("Synchronous").toInt(), 1);
++uniqueKeys;
QCOMPARE(values.count(), uniqueKeys);
delete object;
}
QTEST_MAIN(tst_qqmlqt)
#include "tst_qqmlqt.moc"

View File

@ -915,8 +915,10 @@ void tst_qquicktext::hAlignImplicitWidth()
// Try to check whether alignment works by checking the number of black
// pixels in the thirds of the grabbed image.
const int windowWidth = 220;
const int textWidth = qCeil(text->implicitWidth());
// QQuickWindow::grabWindow() scales the returned image by the devicePixelRatio of the screen.
const qreal devicePixelRatio = view.screen()->devicePixelRatio();
const int windowWidth = 220 * devicePixelRatio;
const int textWidth = qCeil(text->implicitWidth()) * devicePixelRatio;
QVERIFY2(textWidth < windowWidth, "System font too large.");
const int sectionWidth = textWidth / 3;
const int centeredSection1 = (windowWidth - textWidth) / 2;