Merge remote-tracking branch 'origin/dev' into wip/scenegraphng
Conflicts: src/quick/items/qquickopenglshadereffectnode.cpp src/quick/items/qquickshadereffect.cpp src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h src/quick/scenegraph/qsgdefaultglyphnode_p.h Change-Id: I3d6874b4e4231a89d2836c04fe8e7f2ef2d698c4
This commit is contained in:
commit
9ff09fb283
|
@ -141,7 +141,7 @@ MinuteTimer *TimeModel::timer=0;
|
|||
class QExampleQmlPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
|
||||
public:
|
||||
void registerTypes(const char *uri)
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
TARGET = chapter6-plugins
|
||||
QT += qml quick
|
||||
|
||||
# Avoid going to debug/release subdirectory
|
||||
# so that our application will see the
|
||||
# import path for the Charts module.
|
||||
# Ensure that the application will see the import path for the Charts module:
|
||||
# * On Windows, do not build into a debug/release subdirectory.
|
||||
# * On OS X, add the plugin files into the bundle.
|
||||
win32: DESTDIR = ./
|
||||
osx {
|
||||
charts.files = $$OUT_PWD/Charts
|
||||
charts.path = Contents/PlugIns
|
||||
QMAKE_BUNDLE_DATA += charts
|
||||
}
|
||||
|
||||
SOURCES += main.cpp
|
||||
RESOURCES += app.qrc
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
class ChartsPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
|
||||
public:
|
||||
void registerTypes(const char *uri);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the documentation of the Qt Toolkit.
|
||||
|
@ -37,17 +37,21 @@
|
|||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
//![0]
|
||||
#include <QtQuick/QQuickView>
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlEngine>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
//![0]
|
||||
QQuickView view;
|
||||
#ifdef Q_OS_OSX
|
||||
view.engine()->addImportPath(app.applicationDirPath() + "/../PlugIns");
|
||||
#endif
|
||||
//![0]
|
||||
view.setResizeMode(QQuickView::SizeRootObjectToView);
|
||||
view.setSource(QUrl("qrc:///app.qml"));
|
||||
view.show();
|
||||
return app.exec();
|
||||
}
|
||||
//![0]
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
class TextBalloonPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
public:
|
||||
void registerTypes(const char *uri)
|
||||
{
|
||||
|
|
|
@ -87,7 +87,7 @@ public:
|
|||
class ImageProviderExtensionPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
public:
|
||||
void registerTypes(const char *uri)
|
||||
{
|
||||
|
@ -103,7 +103,4 @@ public:
|
|||
};
|
||||
|
||||
|
||||
#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface"
|
||||
|
||||
|
||||
#include "imageprovider.moc"
|
||||
|
|
|
@ -102,7 +102,7 @@ private:
|
|||
class ImageProviderExtensionPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
public:
|
||||
void registerTypes(const char *uri)
|
||||
{
|
||||
|
@ -117,7 +117,4 @@ public:
|
|||
|
||||
};
|
||||
|
||||
|
||||
#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface"
|
||||
|
||||
#include "imageresponseprovider.moc"
|
||||
|
|
|
@ -74,12 +74,15 @@
|
|||
/* COMPILER(MSVC) - Microsoft Visual C++ */
|
||||
/* COMPILER(MSVC7_OR_LOWER) - Microsoft Visual C++ 2003 or lower*/
|
||||
/* COMPILER(MSVC9_OR_LOWER) - Microsoft Visual C++ 2008 or lower*/
|
||||
/* COMPILER(MSVC12_OR_LOWER) - Microsoft Visual C++ 2013 or lower*/
|
||||
#if defined(_MSC_VER)
|
||||
#define WTF_COMPILER_MSVC 1
|
||||
#if _MSC_VER < 1400
|
||||
#define WTF_COMPILER_MSVC7_OR_LOWER 1
|
||||
#elif _MSC_VER < 1600
|
||||
#define WTF_COMPILER_MSVC9_OR_LOWER 1
|
||||
#elif _MSC_VER < 1800
|
||||
#define WTF_COMPILER_MSVC12_OR_LOWER 1
|
||||
#endif
|
||||
|
||||
/* Specific compiler features */
|
||||
|
|
|
@ -173,11 +173,15 @@ inline float log2f(float num)
|
|||
inline long long abs(long long num) { return _abs64(num); }
|
||||
#endif
|
||||
|
||||
#if COMPILER(MSVC12_OR_LOWER)
|
||||
|
||||
inline double nextafter(double x, double y) { return _nextafter(x, y); }
|
||||
inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; }
|
||||
|
||||
inline double copysign(double x, double y) { return _copysign(x, y); }
|
||||
|
||||
#endif // COMPILER(MSVC12_OR_LOWER)
|
||||
|
||||
// Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values.
|
||||
inline double wtf_atan2(double x, double y)
|
||||
{
|
||||
|
@ -211,6 +215,8 @@ inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); }
|
|||
#define fmod(x, y) wtf_fmod(x, y)
|
||||
#define pow(x, y) wtf_pow(x, y)
|
||||
|
||||
#if COMPILER(MSVC12_OR_LOWER)
|
||||
|
||||
// MSVC's math functions do not bring lrint.
|
||||
inline long int lrint(double flt)
|
||||
{
|
||||
|
@ -233,6 +239,7 @@ inline long int lrint(double flt)
|
|||
return static_cast<long int>(intgr);
|
||||
}
|
||||
|
||||
#endif // COMPILER(MSVC12_OR_LOWER)
|
||||
#endif // COMPILER(MSVC)
|
||||
|
||||
inline double deg2rad(double d) { return d * piDouble / 180.0; }
|
||||
|
|
|
@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
|
|||
class QmlFolderListModelPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
|
||||
public:
|
||||
QmlFolderListModelPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
|
||||
|
|
|
@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
|
|||
class QtQuickLayoutsPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
public:
|
||||
QtQuickLayoutsPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent)
|
||||
{
|
||||
|
|
|
@ -754,7 +754,7 @@ static QObject *module_api_factory(QQmlEngine *engine, QJSEngine *scriptEngine)
|
|||
class QQmlLocalStoragePlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
|
||||
public:
|
||||
QQmlLocalStoragePlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent)
|
||||
|
|
|
@ -75,7 +75,7 @@ QT_BEGIN_NAMESPACE
|
|||
class QtQmlModelsPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
public:
|
||||
QtQmlModelsPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
|
||||
void registerTypes(const char *uri) Q_DECL_OVERRIDE
|
||||
|
|
|
@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
|
|||
class QtQuick2ParticlesPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
public:
|
||||
QtQuick2ParticlesPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
|
||||
void registerTypes(const char *uri) Q_DECL_OVERRIDE
|
||||
|
|
|
@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
|
|||
class QtQuick2Plugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
public:
|
||||
QtQuick2Plugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
|
||||
void registerTypes(const char *uri) Q_DECL_OVERRIDE
|
||||
|
|
|
@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
|
|||
class QmlSettingsPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
|
||||
public:
|
||||
QmlSettingsPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
|
||||
|
|
|
@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
|
|||
class QtQmlStateMachinePlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtQml.StateMachine/1.0")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
|
||||
public:
|
||||
QtQmlStateMachinePlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
|
||||
|
|
|
@ -147,7 +147,7 @@ QT_BEGIN_NAMESPACE
|
|||
class QTestQmlModule : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
|
||||
public:
|
||||
QTestQmlModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
|
||||
|
|
|
@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE
|
|||
class QtQuick2WindowPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
public:
|
||||
QtQuick2WindowPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
|
||||
void registerTypes(const char *uri) Q_DECL_OVERRIDE
|
||||
|
|
|
@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
|
|||
class QmlXmlListModelPlugin : public QQmlExtensionPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
|
||||
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
|
||||
|
||||
public:
|
||||
QmlXmlListModelPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
|
||||
|
|
|
@ -291,8 +291,6 @@ QQuickOpenGLShaderEffectNode *QQuickCustomParticle::prepareNextFrame(QQuickOpenG
|
|||
builder.appendSourceFile(QStringLiteral(":/particles/shaders/customparticle.vert"));
|
||||
s.sourceCode[Key::VertexShader] = builder.source() + s.sourceCode[Key::VertexShader];
|
||||
|
||||
s.className = metaObject()->className();
|
||||
|
||||
material->setProgramSource(s);
|
||||
material->attributes = m_common.attributes;
|
||||
foreach (QQuickOpenGLShaderEffectNode* node, m_nodes)
|
||||
|
|
|
@ -322,6 +322,8 @@ public:
|
|||
return m_startTime;
|
||||
}
|
||||
|
||||
void reclaculateGroupId() const;
|
||||
|
||||
protected:
|
||||
qreal m_particlesPerSecond;
|
||||
int m_particleDuration;
|
||||
|
@ -359,9 +361,6 @@ protected:
|
|||
|
||||
bool isEmitConnected();
|
||||
|
||||
private: // methods
|
||||
void reclaculateGroupId() const;
|
||||
|
||||
private: // data
|
||||
QString m_group;
|
||||
mutable bool m_groupIdNeedRecalculation;
|
||||
|
|
|
@ -597,6 +597,13 @@ void QQuickParticleSystem::initGroups()
|
|||
groupIds.clear();
|
||||
nextFreeGroupId = 0;
|
||||
|
||||
for (auto e : qAsConst(m_emitters)) {
|
||||
e->reclaculateGroupId();
|
||||
}
|
||||
foreach (QQuickParticlePainter *p, m_painters) {
|
||||
p->recalculateGroupIds();
|
||||
}
|
||||
|
||||
QQuickParticleGroupData *pd = new QQuickParticleGroupData(QString(), this); // Default group
|
||||
Q_ASSERT(pd->index == 0);
|
||||
Q_UNUSED(pd);
|
||||
|
|
|
@ -683,11 +683,13 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope
|
|||
QQmlContext *context = qmlContext(object);
|
||||
|
||||
if (object && context) {
|
||||
QString parentProperty = propertyName;
|
||||
if (propertyName.indexOf(QLatin1Char('.')) != -1)
|
||||
parentProperty = propertyName.left(propertyName.indexOf(QLatin1Char('.')));
|
||||
QStringRef parentPropertyRef(&propertyName);
|
||||
const int idx = parentPropertyRef.indexOf(QLatin1Char('.'));
|
||||
if (idx != -1)
|
||||
parentPropertyRef = parentPropertyRef.left(idx);
|
||||
|
||||
if (object->property(parentProperty.toLatin1()).isValid()) {
|
||||
const QByteArray parentProperty = parentPropertyRef.toLatin1();
|
||||
if (object->property(parentProperty).isValid()) {
|
||||
QQmlProperty property(object, propertyName);
|
||||
QQmlPropertyPrivate::removeBinding(property);
|
||||
if (property.isResettable()) {
|
||||
|
@ -700,7 +702,7 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope
|
|||
// overwrite with default value
|
||||
if (QQmlType *objType = QQmlMetaType::qmlType(object->metaObject())) {
|
||||
if (QObject *emptyObject = objType->create()) {
|
||||
if (emptyObject->property(parentProperty.toLatin1()).isValid()) {
|
||||
if (emptyObject->property(parentProperty).isValid()) {
|
||||
QVariant defaultValue = QQmlProperty(emptyObject, propertyName).read();
|
||||
if (defaultValue.isValid()) {
|
||||
setBinding(objectId, propertyName, defaultValue, true);
|
||||
|
@ -764,9 +766,14 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth
|
|||
QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(object);
|
||||
Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this
|
||||
|
||||
int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex);
|
||||
QV4::ExecutionEngine *v4 = QV8Engine::getV4(qmlEngine(object)->handle());
|
||||
QV4::Scope scope(v4);
|
||||
|
||||
int lineNumber = 0;
|
||||
QV4::ScopedFunctionObject oldMethod(scope, vmeMetaObject->vmeMethod(prop->coreIndex));
|
||||
if (oldMethod && oldMethod->d()->function) {
|
||||
lineNumber = oldMethod->d()->function->compiledFunction->location.line;
|
||||
}
|
||||
QV4::ScopedValue v(scope, QQmlJavaScriptExpression::evalFunction(contextData, object, jsfunction, contextData->urlString(), lineNumber));
|
||||
vmeMetaObject->setVmeMethod(prop->coreIndex, v);
|
||||
return true;
|
||||
|
|
|
@ -704,7 +704,7 @@ bool NativeDebugger::reallyHitTheBreakPoint(const QV4::Function *function, int l
|
|||
const BreakPoint &bp = m_service->m_breakHandler->m_breakPoints.at(i);
|
||||
if (bp.lineNumber == lineNumber) {
|
||||
const QString fileName = function->sourceFile();
|
||||
const QString base = fileName.mid(fileName.lastIndexOf('/') + 1);
|
||||
const QStringRef base = fileName.midRef(fileName.lastIndexOf('/') + 1);
|
||||
if (bp.fileName.endsWith(base)) {
|
||||
if (bp.condition.isEmpty() || checkCondition(bp.condition)) {
|
||||
BreakPoint &mbp = m_service->m_breakHandler->m_breakPoints[i];
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <QtCore/qjsonobject.h>
|
||||
#include <QtCore/qjsonvalue.h>
|
||||
#include <QtCore/qpointer.h>
|
||||
#include <QtCore/qvector.h>
|
||||
|
||||
//#define TRACE_PROTOCOL(s) qDebug() << s
|
||||
#define TRACE_PROTOCOL(s)
|
||||
|
@ -182,24 +183,21 @@ QQmlNativeDebugConnector::QQmlNativeDebugConnector()
|
|||
: m_blockingMode(false)
|
||||
{
|
||||
const QString args = commandLineArguments();
|
||||
const QStringList lstjsDebugArguments = args.split(QLatin1Char(','));
|
||||
const auto lstjsDebugArguments = args.splitRef(QLatin1Char(','));
|
||||
QStringList services;
|
||||
QStringList::const_iterator argsItEnd = lstjsDebugArguments.cend();
|
||||
QStringList::const_iterator argsIt = lstjsDebugArguments.cbegin();
|
||||
for (; argsIt != argsItEnd; ++argsIt) {
|
||||
const QString strArgument = *argsIt;
|
||||
for (const QStringRef &strArgument : lstjsDebugArguments) {
|
||||
if (strArgument == QLatin1String("block")) {
|
||||
m_blockingMode = true;
|
||||
} else if (strArgument == QLatin1String("native")) {
|
||||
// Ignore. This is used to signal that this connector
|
||||
// should be loaded and that has already happened.
|
||||
} else if (strArgument.startsWith(QLatin1String("services:"))) {
|
||||
services.append(strArgument.mid(9));
|
||||
services.append(strArgument.mid(9).toString());
|
||||
} else if (!services.isEmpty()) {
|
||||
services.append(strArgument);
|
||||
services.append(strArgument.toString());
|
||||
} else {
|
||||
qWarning("QML Debugger: Invalid argument \"%s\" detected. Ignoring the same.",
|
||||
qUtf8Printable(strArgument));
|
||||
strArgument.toUtf8().constData());
|
||||
}
|
||||
}
|
||||
setServices(services);
|
||||
|
|
|
@ -58,71 +58,81 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin
|
|||
connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
|
||||
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
|
||||
engine->profiler, SLOT(setTimer(QElapsedTimer)));
|
||||
connect(engine->profiler, SIGNAL(dataReady(QVector<QQmlProfilerData>)),
|
||||
this, SLOT(receiveData(QVector<QQmlProfilerData>)));
|
||||
connect(engine->profiler,
|
||||
SIGNAL(dataReady(QVector<QQmlProfilerData>,QQmlProfiler::LocationHash)),
|
||||
this,
|
||||
SLOT(receiveData(QVector<QQmlProfilerData>,QQmlProfiler::LocationHash)));
|
||||
}
|
||||
|
||||
// convert to QByteArrays that can be sent to the debug client
|
||||
// use of QDataStream can skew results
|
||||
// (see tst_qqmldebugtrace::trace() benchmark)
|
||||
static void qQmlProfilerDataToByteArrays(const QQmlProfilerData *d, QList<QByteArray> &messages)
|
||||
static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d,
|
||||
const QQmlProfiler::LocationHash &locations,
|
||||
QList<QByteArray> &messages)
|
||||
{
|
||||
QQmlDebugPacket ds;
|
||||
Q_ASSERT_X(((d->messageType | d->detailType) & (1 << 31)) == 0, Q_FUNC_INFO,
|
||||
"You can use at most 31 message types and 31 detail types.");
|
||||
for (uint decodedMessageType = 0; (d->messageType >> decodedMessageType) != 0;
|
||||
Q_ASSERT_X((d.messageType & (1 << 31)) == 0, Q_FUNC_INFO,
|
||||
"You can use at most 31 message types.");
|
||||
for (quint32 decodedMessageType = 0; (d.messageType >> decodedMessageType) != 0;
|
||||
++decodedMessageType) {
|
||||
if ((d->messageType & (1 << decodedMessageType)) == 0)
|
||||
if ((d.messageType & (1 << decodedMessageType)) == 0)
|
||||
continue;
|
||||
|
||||
for (uint decodedDetailType = 0; (d->detailType >> decodedDetailType) != 0;
|
||||
++decodedDetailType) {
|
||||
if ((d->detailType & (1 << decodedDetailType)) == 0)
|
||||
continue;
|
||||
//### using QDataStream is relatively expensive
|
||||
ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType);
|
||||
|
||||
//### using QDataStream is relatively expensive
|
||||
ds << d->time << decodedMessageType << decodedDetailType;
|
||||
QQmlProfiler::Location l = locations.value(d.locationId);
|
||||
|
||||
switch (decodedMessageType) {
|
||||
case QQmlProfilerDefinitions::RangeStart:
|
||||
case QQmlProfilerDefinitions::RangeEnd:
|
||||
break;
|
||||
case QQmlProfilerDefinitions::RangeData:
|
||||
ds << (d->detailString.isEmpty() ? d->detailUrl.toString() : d->detailString);
|
||||
break;
|
||||
case QQmlProfilerDefinitions::RangeLocation:
|
||||
ds << (d->detailUrl.isEmpty() ? d->detailString : d->detailUrl.toString()) << d->x
|
||||
<< d->y;
|
||||
break;
|
||||
default:
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
|
||||
break;
|
||||
}
|
||||
messages.append(ds.squeezedData());
|
||||
ds.clear();
|
||||
switch (decodedMessageType) {
|
||||
case QQmlProfilerDefinitions::RangeStart:
|
||||
case QQmlProfilerDefinitions::RangeEnd:
|
||||
break;
|
||||
case QQmlProfilerDefinitions::RangeData:
|
||||
ds << (l.location.sourceFile.isEmpty() ? l.url.toString() : l.location.sourceFile);
|
||||
break;
|
||||
case QQmlProfilerDefinitions::RangeLocation:
|
||||
ds << (l.url.isEmpty() ? l.location.sourceFile : l.url.toString())
|
||||
<< static_cast<qint32>(l.location.line) << static_cast<qint32>(l.location.column);
|
||||
break;
|
||||
default:
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
|
||||
break;
|
||||
}
|
||||
messages.append(ds.squeezedData());
|
||||
ds.clear();
|
||||
}
|
||||
}
|
||||
|
||||
qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
|
||||
{
|
||||
while (next != data.length()) {
|
||||
if (data[next].time > until || messages.length() > s_numMessagesPerBatch)
|
||||
return data[next].time;
|
||||
qQmlProfilerDataToByteArrays(&(data[next++]), messages);
|
||||
const QQmlProfilerData &nextData = data.at(next);
|
||||
if (nextData.time > until || messages.length() > s_numMessagesPerBatch)
|
||||
return nextData.time;
|
||||
qQmlProfilerDataToByteArrays(nextData, locations, messages);
|
||||
++next;
|
||||
}
|
||||
|
||||
next = 0;
|
||||
data.clear();
|
||||
locations.clear();
|
||||
return -1;
|
||||
}
|
||||
|
||||
void QQmlProfilerAdapter::receiveData(const QVector<QQmlProfilerData> &new_data)
|
||||
void QQmlProfilerAdapter::receiveData(const QVector<QQmlProfilerData> &new_data,
|
||||
const QQmlProfiler::LocationHash &new_locations)
|
||||
{
|
||||
if (data.isEmpty())
|
||||
data = new_data;
|
||||
else
|
||||
data.append(new_data);
|
||||
|
||||
if (locations.isEmpty())
|
||||
locations = new_locations;
|
||||
else
|
||||
locations.unite(new_locations);
|
||||
|
||||
service->dataReady(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,10 +63,12 @@ public:
|
|||
qint64 sendMessages(qint64 until, QList<QByteArray> &messages) Q_DECL_OVERRIDE;
|
||||
|
||||
public slots:
|
||||
void receiveData(const QVector<QQmlProfilerData> &new_data);
|
||||
void receiveData(const QVector<QQmlProfilerData> &new_data,
|
||||
const QQmlProfiler::LocationHash &locations);
|
||||
|
||||
private:
|
||||
QVector<QQmlProfilerData> data;
|
||||
QQmlProfiler::LocationHash locations;
|
||||
int next;
|
||||
};
|
||||
|
||||
|
|
|
@ -61,29 +61,35 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
|
|||
connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
|
||||
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
|
||||
engine->profiler, SLOT(setTimer(QElapsedTimer)));
|
||||
connect(engine->profiler, SIGNAL(dataReady(QVector<QV4::Profiling::FunctionCallProperties>,
|
||||
connect(engine->profiler, SIGNAL(dataReady(QV4::Profiling::FunctionLocationHash,
|
||||
QVector<QV4::Profiling::FunctionCallProperties>,
|
||||
QVector<QV4::Profiling::MemoryAllocationProperties>)),
|
||||
this, SLOT(receiveData(QVector<QV4::Profiling::FunctionCallProperties>,
|
||||
this, SLOT(receiveData(QV4::Profiling::FunctionLocationHash,
|
||||
QVector<QV4::Profiling::FunctionCallProperties>,
|
||||
QVector<QV4::Profiling::MemoryAllocationProperties>)));
|
||||
}
|
||||
|
||||
qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages,
|
||||
QQmlDebugPacket &d)
|
||||
{
|
||||
while (m_memoryData.length() > m_memoryPos && m_memoryData[m_memoryPos].timestamp <= until) {
|
||||
QV4::Profiling::MemoryAllocationProperties &props = m_memoryData[m_memoryPos];
|
||||
// Make it const, so that we cannot accidentally detach it.
|
||||
const QVector<QV4::Profiling::MemoryAllocationProperties> &memoryData = m_memoryData;
|
||||
|
||||
while (memoryData.length() > m_memoryPos && memoryData[m_memoryPos].timestamp <= until) {
|
||||
const QV4::Profiling::MemoryAllocationProperties &props = memoryData[m_memoryPos];
|
||||
d << props.timestamp << MemoryAllocation << props.type << props.size;
|
||||
++m_memoryPos;
|
||||
messages.append(d.squeezedData());
|
||||
d.clear();
|
||||
}
|
||||
return m_memoryData.length() == m_memoryPos ? -1 : m_memoryData[m_memoryPos].timestamp;
|
||||
return memoryData.length() == m_memoryPos ? -1 : memoryData[m_memoryPos].timestamp;
|
||||
}
|
||||
|
||||
qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &messages,
|
||||
qint64 callNext, QQmlDebugPacket &d)
|
||||
{
|
||||
if (callNext == -1) {
|
||||
m_functionLocations.clear();
|
||||
m_functionCallData.clear();
|
||||
m_functionCallPos = 0;
|
||||
}
|
||||
|
@ -102,10 +108,15 @@ qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &mes
|
|||
qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
|
||||
{
|
||||
QQmlDebugPacket d;
|
||||
|
||||
// Make it const, so that we cannot accidentally detach it.
|
||||
const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData = m_functionCallData;
|
||||
const QV4::Profiling::FunctionLocationHash &functionLocations = m_functionLocations;
|
||||
|
||||
while (true) {
|
||||
while (!m_stack.isEmpty() &&
|
||||
(m_functionCallPos == m_functionCallData.length() ||
|
||||
m_stack.top() <= m_functionCallData[m_functionCallPos].start)) {
|
||||
(m_functionCallPos == functionCallData.length() ||
|
||||
m_stack.top() <= functionCallData[m_functionCallPos].start)) {
|
||||
if (m_stack.top() > until || messages.length() > s_numMessagesPerBatch)
|
||||
return finalizeMessages(until, messages, m_stack.top(), d);
|
||||
|
||||
|
@ -114,39 +125,46 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
|
|||
messages.append(d.squeezedData());
|
||||
d.clear();
|
||||
}
|
||||
while (m_functionCallPos != m_functionCallData.length() &&
|
||||
(m_stack.empty() || m_functionCallData[m_functionCallPos].start < m_stack.top())) {
|
||||
while (m_functionCallPos != functionCallData.length() &&
|
||||
(m_stack.empty() || functionCallData[m_functionCallPos].start < m_stack.top())) {
|
||||
const QV4::Profiling::FunctionCallProperties &props =
|
||||
m_functionCallData[m_functionCallPos];
|
||||
functionCallData[m_functionCallPos];
|
||||
if (props.start > until || messages.length() > s_numMessagesPerBatch)
|
||||
return finalizeMessages(until, messages, props.start, d);
|
||||
|
||||
appendMemoryEvents(props.start, messages, d);
|
||||
auto location = functionLocations.constFind(props.id);
|
||||
Q_ASSERT(location != functionLocations.constEnd());
|
||||
|
||||
d << props.start << RangeStart << Javascript;
|
||||
messages.push_back(d.squeezedData());
|
||||
d.clear();
|
||||
d << props.start << RangeLocation << Javascript << props.file << props.line
|
||||
<< props.column;
|
||||
d << props.start << RangeLocation << Javascript << location->file << location->line
|
||||
<< location->column;
|
||||
messages.push_back(d.squeezedData());
|
||||
d.clear();
|
||||
d << props.start << RangeData << Javascript << props.name;
|
||||
d << props.start << RangeData << Javascript << location->name;
|
||||
messages.push_back(d.squeezedData());
|
||||
d.clear();
|
||||
m_stack.push(props.end);
|
||||
++m_functionCallPos;
|
||||
}
|
||||
if (m_stack.empty() && m_functionCallPos == m_functionCallData.length())
|
||||
if (m_stack.empty() && m_functionCallPos == functionCallData.length())
|
||||
return finalizeMessages(until, messages, -1, d);
|
||||
}
|
||||
}
|
||||
|
||||
void QV4ProfilerAdapter::receiveData(
|
||||
const QV4::Profiling::FunctionLocationHash &locations,
|
||||
const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData,
|
||||
const QVector<QV4::Profiling::MemoryAllocationProperties> &memoryData)
|
||||
{
|
||||
// In rare cases it could be that another flush or stop event is processed while data from
|
||||
// the previous one is still pending. In that case we just append the data.
|
||||
if (m_functionLocations.isEmpty())
|
||||
m_functionLocations = locations;
|
||||
else
|
||||
m_functionLocations.unite(locations);
|
||||
|
||||
if (m_functionCallData.isEmpty())
|
||||
m_functionCallData = functionCallData;
|
||||
|
|
|
@ -74,7 +74,8 @@ signals:
|
|||
void v4ProfilingEnabledWhileWaiting(quint64 v4Features);
|
||||
|
||||
public slots:
|
||||
void receiveData(const QVector<QV4::Profiling::FunctionCallProperties> &,
|
||||
void receiveData(const QV4::Profiling::FunctionLocationHash &,
|
||||
const QVector<QV4::Profiling::FunctionCallProperties> &,
|
||||
const QVector<QV4::Profiling::MemoryAllocationProperties> &);
|
||||
|
||||
private slots:
|
||||
|
@ -82,6 +83,7 @@ private slots:
|
|||
void forwardEnabledWhileWaiting(quint64 features);
|
||||
|
||||
private:
|
||||
QV4::Profiling::FunctionLocationHash m_functionLocations;
|
||||
QVector<QV4::Profiling::FunctionCallProperties> m_functionCallData;
|
||||
QVector<QV4::Profiling::MemoryAllocationProperties> m_memoryData;
|
||||
int m_functionCallPos;
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include <QtCore/QDir>
|
||||
#include <QtCore/QPluginLoader>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/qwaitcondition.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -345,40 +346,40 @@ void QQmlDebugServerImpl::parseArguments()
|
|||
QString fileName;
|
||||
QStringList services;
|
||||
|
||||
const QStringList lstjsDebugArguments = args.split(QLatin1Char(','));
|
||||
QStringList::const_iterator argsItEnd = lstjsDebugArguments.cend();
|
||||
QStringList::const_iterator argsIt = lstjsDebugArguments.cbegin();
|
||||
for (; argsIt != argsItEnd; ++argsIt) {
|
||||
const QString strArgument = *argsIt;
|
||||
const auto lstjsDebugArguments = args.splitRef(QLatin1Char(','));
|
||||
for (auto argsIt = lstjsDebugArguments.begin(), argsItEnd = lstjsDebugArguments.end(); argsIt != argsItEnd; ++argsIt) {
|
||||
const QStringRef &strArgument = *argsIt;
|
||||
if (strArgument.startsWith(QLatin1String("port:"))) {
|
||||
portFrom = strArgument.midRef(5).toInt(&ok);
|
||||
portFrom = strArgument.mid(5).toInt(&ok);
|
||||
portTo = portFrom;
|
||||
QStringList::const_iterator argsNext = argsIt + 1;
|
||||
const auto argsNext = argsIt + 1;
|
||||
if (argsNext == argsItEnd)
|
||||
break;
|
||||
const QString nextArgument = *argsNext;
|
||||
if (ok) {
|
||||
const QString nextArgument = argsNext->toString();
|
||||
|
||||
// Don't use QStringLiteral here. QRegExp has a global cache and will save an implicitly
|
||||
// shared copy of the passed string. That copy isn't properly detached when the library
|
||||
// is unloaded if the original string lives in the library's .rodata
|
||||
if (ok && nextArgument.contains(QRegExp(QLatin1String("^\\s*\\d+\\s*$")))) {
|
||||
portTo = nextArgument.toInt(&ok);
|
||||
++argsIt;
|
||||
// Don't use QStringLiteral here. QRegExp has a global cache and will save an implicitly
|
||||
// shared copy of the passed string. That copy isn't properly detached when the library
|
||||
// is unloaded if the original string lives in the library's .rodata
|
||||
if (nextArgument.contains(QRegExp(QLatin1String("^\\s*\\d+\\s*$")))) {
|
||||
portTo = nextArgument.toInt(&ok);
|
||||
++argsIt;
|
||||
}
|
||||
}
|
||||
} else if (strArgument.startsWith(QLatin1String("host:"))) {
|
||||
hostAddress = strArgument.mid(5);
|
||||
hostAddress = strArgument.mid(5).toString();
|
||||
} else if (strArgument == QLatin1String("block")) {
|
||||
block = true;
|
||||
} else if (strArgument.startsWith(QLatin1String("file:"))) {
|
||||
fileName = strArgument.mid(5);
|
||||
fileName = strArgument.mid(5).toString();
|
||||
ok = !fileName.isEmpty();
|
||||
} else if (strArgument.startsWith(QLatin1String("services:"))) {
|
||||
services.append(strArgument.mid(9));
|
||||
services.append(strArgument.mid(9).toString());
|
||||
} else if (!services.isEmpty()) {
|
||||
services.append(strArgument);
|
||||
services.append(strArgument.toString());
|
||||
} else {
|
||||
const QString message = tr("QML Debugger: Invalid argument \"%1\" detected."
|
||||
" Ignoring the same.").arg(strArgument);
|
||||
" Ignoring the same.").arg(strArgument.toString());
|
||||
qWarning("%s", qPrintable(message));
|
||||
}
|
||||
}
|
||||
|
@ -423,7 +424,7 @@ void QQmlDebugServerImpl::parseArguments()
|
|||
//: Please preserve the line breaks and formatting
|
||||
<< tr("Sends qDebug() and similar messages over the QML debug\n"
|
||||
"\t\t connection. QtCreator uses this for showing debug\n"
|
||||
"\t\t messages in the JavaScript console.") << '\n'
|
||||
"\t\t messages in the debugger console.") << '\n'
|
||||
<< tr("Other services offered by qmltooling plugins that implement "
|
||||
"QQmlDebugServiceFactory and which can be found in the standard plugin "
|
||||
"paths will also be available and can be specified. If no \"services\" "
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -80,8 +80,10 @@ void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int id, const QQm
|
|||
location.column = loc.startColumn;
|
||||
|
||||
idIndex = id;
|
||||
indexOfDefaultProperty = -1;
|
||||
indexOfDefaultPropertyOrAlias = -1;
|
||||
defaultPropertyIsAlias = false;
|
||||
properties = pool->New<PoolList<Property> >();
|
||||
aliases = pool->New<PoolList<Alias> >();
|
||||
qmlSignals = pool->New<PoolList<Signal> >();
|
||||
bindings = pool->New<PoolList<Binding> >();
|
||||
functions = pool->New<PoolList<Function> >();
|
||||
|
@ -145,15 +147,42 @@ QString Object::appendProperty(Property *prop, const QString &propertyName, bool
|
|||
|
||||
const int index = target->properties->append(prop);
|
||||
if (isDefaultProperty) {
|
||||
if (target->indexOfDefaultProperty != -1) {
|
||||
if (target->indexOfDefaultPropertyOrAlias != -1) {
|
||||
*errorLocation = defaultToken;
|
||||
return tr("Duplicate default property");
|
||||
}
|
||||
target->indexOfDefaultProperty = index;
|
||||
target->indexOfDefaultPropertyOrAlias = index;
|
||||
}
|
||||
return QString(); // no error
|
||||
}
|
||||
|
||||
QString Object::appendAlias(Alias *alias, const QString &aliasName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation)
|
||||
{
|
||||
Object *target = declarationsOverride;
|
||||
if (!target)
|
||||
target = this;
|
||||
|
||||
for (Alias *p = target->aliases->first; p; p = p->next)
|
||||
if (p->nameIndex == alias->nameIndex)
|
||||
return tr("Duplicate alias name");
|
||||
|
||||
if (aliasName.constData()->isUpper())
|
||||
return tr("Alias names cannot begin with an upper case letter");
|
||||
|
||||
const int index = target->aliases->append(alias);
|
||||
|
||||
if (isDefaultProperty) {
|
||||
if (target->indexOfDefaultPropertyOrAlias != -1) {
|
||||
*errorLocation = defaultToken;
|
||||
return tr("Duplicate default property");
|
||||
}
|
||||
target->indexOfDefaultPropertyOrAlias = index;
|
||||
target->defaultPropertyIsAlias = true;
|
||||
}
|
||||
|
||||
return QString(); // no error
|
||||
}
|
||||
|
||||
void Object::appendFunction(QmlIR::Function *f)
|
||||
{
|
||||
Object *target = declarationsOverride;
|
||||
|
@ -190,7 +219,7 @@ Binding *Object::findBinding(quint32 nameIndex) const
|
|||
|
||||
void Object::insertSorted(Binding *b)
|
||||
{
|
||||
Binding *insertionPoint = bindings->findSortedInsertionPoint<QV4::CompiledData::Location, QV4::CompiledData::Binding, &QV4::CompiledData::Binding::valueLocation>(b);
|
||||
Binding *insertionPoint = bindings->findSortedInsertionPoint<quint32, Binding, &Binding::offset>(b);
|
||||
bindings->insertAfter(insertionPoint, b);
|
||||
}
|
||||
|
||||
|
@ -249,8 +278,8 @@ void Document::collectTypeReferences()
|
|||
|
||||
void Document::removeScriptPragmas(QString &script)
|
||||
{
|
||||
const QString pragma(QLatin1String("pragma"));
|
||||
const QString library(QLatin1String("library"));
|
||||
const QLatin1String pragma("pragma");
|
||||
const QLatin1String library("library");
|
||||
|
||||
QQmlJS::Lexer l(0);
|
||||
l.setCode(script, 0);
|
||||
|
@ -268,7 +297,7 @@ void Document::removeScriptPragmas(QString &script)
|
|||
|
||||
if (token != QQmlJSGrammar::T_PRAGMA ||
|
||||
l.tokenStartLine() != startLine ||
|
||||
script.mid(l.tokenOffset(), l.tokenLength()) != pragma)
|
||||
script.midRef(l.tokenOffset(), l.tokenLength()) != pragma)
|
||||
return;
|
||||
|
||||
token = l.lex();
|
||||
|
@ -277,7 +306,7 @@ void Document::removeScriptPragmas(QString &script)
|
|||
l.tokenStartLine() != startLine)
|
||||
return;
|
||||
|
||||
QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength());
|
||||
const QStringRef pragmaValue = script.midRef(l.tokenOffset(), l.tokenLength());
|
||||
int endOffset = l.tokenLength() + l.tokenOffset();
|
||||
|
||||
token = l.lex();
|
||||
|
@ -806,130 +835,86 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
|
|||
}
|
||||
} else {
|
||||
const QStringRef &memberType = node->memberType;
|
||||
const QStringRef &name = node->name;
|
||||
|
||||
bool typeFound = false;
|
||||
QV4::CompiledData::Property::Type type;
|
||||
|
||||
if (memberType == QLatin1String("alias")) {
|
||||
type = QV4::CompiledData::Property::Alias;
|
||||
typeFound = true;
|
||||
}
|
||||
return appendAlias(node);
|
||||
} else {
|
||||
const QStringRef &name = node->name;
|
||||
|
||||
for (int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
|
||||
const TypeNameToType *t = propTypeNameToTypes + ii;
|
||||
if (memberType == QLatin1String(t->name, static_cast<int>(t->nameLength))) {
|
||||
type = t->type;
|
||||
typeFound = true;
|
||||
bool typeFound = false;
|
||||
QV4::CompiledData::Property::Type type;
|
||||
|
||||
for (int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
|
||||
const TypeNameToType *t = propTypeNameToTypes + ii;
|
||||
if (memberType == QLatin1String(t->name, static_cast<int>(t->nameLength))) {
|
||||
type = t->type;
|
||||
typeFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!typeFound && memberType.at(0).isUpper()) {
|
||||
const QStringRef &typeModifier = node->typeModifier;
|
||||
if (!typeFound && memberType.at(0).isUpper()) {
|
||||
const QStringRef &typeModifier = node->typeModifier;
|
||||
|
||||
if (typeModifier.isEmpty()) {
|
||||
type = QV4::CompiledData::Property::Custom;
|
||||
} else if (typeModifier == QLatin1String("list")) {
|
||||
type = QV4::CompiledData::Property::CustomList;
|
||||
} else {
|
||||
recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Invalid property type modifier"));
|
||||
if (typeModifier.isEmpty()) {
|
||||
type = QV4::CompiledData::Property::Custom;
|
||||
} else if (typeModifier == QLatin1String("list")) {
|
||||
type = QV4::CompiledData::Property::CustomList;
|
||||
} else {
|
||||
recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Invalid property type modifier"));
|
||||
return false;
|
||||
}
|
||||
typeFound = true;
|
||||
} else if (!node->typeModifier.isNull()) {
|
||||
recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Unexpected property type modifier"));
|
||||
return false;
|
||||
}
|
||||
typeFound = true;
|
||||
} else if (!node->typeModifier.isNull()) {
|
||||
recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Unexpected property type modifier"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!typeFound) {
|
||||
recordError(node->typeToken, QCoreApplication::translate("QQmlParser","Expected property type"));
|
||||
return false;
|
||||
}
|
||||
|
||||
Property *property = New<Property>();
|
||||
property->flags = 0;
|
||||
if (node->isReadonlyMember)
|
||||
property->flags |= QV4::CompiledData::Property::IsReadOnly;
|
||||
property->type = type;
|
||||
if (type >= QV4::CompiledData::Property::Custom)
|
||||
property->customTypeNameIndex = registerString(memberType.toString());
|
||||
else
|
||||
property->customTypeNameIndex = emptyStringIndex;
|
||||
|
||||
const QString propName = name.toString();
|
||||
property->nameIndex = registerString(propName);
|
||||
|
||||
QQmlJS::AST::SourceLocation loc = node->firstSourceLocation();
|
||||
property->location.line = loc.startLine;
|
||||
property->location.column = loc.startColumn;
|
||||
|
||||
property->aliasPropertyValueIndex = emptyStringIndex;
|
||||
|
||||
if (type == QV4::CompiledData::Property::Alias) {
|
||||
if (!node->statement && !node->binding)
|
||||
COMPILE_EXCEPTION(loc, tr("No property alias location"));
|
||||
|
||||
QQmlJS::AST::SourceLocation rhsLoc;
|
||||
if (node->binding)
|
||||
rhsLoc = node->binding->firstSourceLocation();
|
||||
else if (node->statement)
|
||||
rhsLoc = node->statement->firstSourceLocation();
|
||||
else
|
||||
rhsLoc = node->semicolonToken;
|
||||
property->aliasLocation.line = rhsLoc.startLine;
|
||||
property->aliasLocation.column = rhsLoc.startColumn;
|
||||
|
||||
QStringList alias;
|
||||
|
||||
if (QQmlJS::AST::ExpressionStatement *stmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement*>(node->statement)) {
|
||||
alias = astNodeToStringList(stmt->expression);
|
||||
if (alias.isEmpty()) {
|
||||
if (isStatementNodeScript(node->statement)) {
|
||||
COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
|
||||
} else {
|
||||
COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias location"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
|
||||
if (!typeFound) {
|
||||
recordError(node->typeToken, QCoreApplication::translate("QQmlParser","Expected property type"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (alias.count() < 1 || alias.count() > 3)
|
||||
COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
|
||||
Property *property = New<Property>();
|
||||
property->flags = 0;
|
||||
if (node->isReadonlyMember)
|
||||
property->flags |= QV4::CompiledData::Property::IsReadOnly;
|
||||
property->type = type;
|
||||
if (type >= QV4::CompiledData::Property::Custom)
|
||||
property->customTypeNameIndex = registerString(memberType.toString());
|
||||
else
|
||||
property->customTypeNameIndex = emptyStringIndex;
|
||||
|
||||
property->aliasIdValueIndex = registerString(alias.first());
|
||||
const QString propName = name.toString();
|
||||
property->nameIndex = registerString(propName);
|
||||
|
||||
QString propertyValue = alias.value(1);
|
||||
if (alias.count() == 3) {
|
||||
propertyValue += QLatin1Char('.');
|
||||
propertyValue += alias.at(2);
|
||||
}
|
||||
property->aliasPropertyValueIndex = registerString(propertyValue);
|
||||
QQmlJS::AST::SourceLocation loc = node->firstSourceLocation();
|
||||
property->location.line = loc.startLine;
|
||||
property->location.column = loc.startColumn;
|
||||
|
||||
QQmlJS::AST::SourceLocation errorLocation;
|
||||
QString error;
|
||||
|
||||
if (illegalNames.contains(propName))
|
||||
error = tr("Illegal property name");
|
||||
else
|
||||
error = _object->appendProperty(property, propName, node->isDefaultMember, node->defaultToken, &errorLocation);
|
||||
|
||||
if (!error.isEmpty()) {
|
||||
if (errorLocation.startLine == 0)
|
||||
errorLocation = node->identifierToken;
|
||||
|
||||
recordError(errorLocation, error);
|
||||
return false;
|
||||
}
|
||||
|
||||
qSwap(_propertyDeclaration, property);
|
||||
if (node->binding) {
|
||||
// process QML-like initializers (e.g. property Object o: Object {})
|
||||
QQmlJS::AST::Node::accept(node->binding, this);
|
||||
} else if (node->statement) {
|
||||
appendBinding(node->identifierToken, node->identifierToken, _propertyDeclaration->nameIndex, node->statement);
|
||||
}
|
||||
qSwap(_propertyDeclaration, property);
|
||||
}
|
||||
QQmlJS::AST::SourceLocation errorLocation;
|
||||
QString error;
|
||||
|
||||
if (illegalNames.contains(propName))
|
||||
error = tr("Illegal property name");
|
||||
else
|
||||
error = _object->appendProperty(property, propName, node->isDefaultMember, node->defaultToken, &errorLocation);
|
||||
|
||||
if (!error.isEmpty()) {
|
||||
if (errorLocation.startLine == 0)
|
||||
errorLocation = node->identifierToken;
|
||||
|
||||
recordError(errorLocation, error);
|
||||
return false;
|
||||
}
|
||||
|
||||
qSwap(_propertyDeclaration, property);
|
||||
if (node->binding) {
|
||||
// process QML-like initializers (e.g. property Object o: Object {})
|
||||
QQmlJS::AST::Node::accept(node->binding, this);
|
||||
} else if (node->statement && type != QV4::CompiledData::Property::Alias) {
|
||||
appendBinding(node->identifierToken, node->identifierToken, _propertyDeclaration->nameIndex, node->statement);
|
||||
}
|
||||
qSwap(_propertyDeclaration, property);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1084,6 +1069,7 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo
|
|||
{
|
||||
Binding *binding = New<Binding>();
|
||||
binding->propertyNameIndex = propertyNameIndex;
|
||||
binding->offset = nameLocation.offset;
|
||||
binding->location.line = nameLocation.startLine;
|
||||
binding->location.column = nameLocation.startColumn;
|
||||
binding->flags = 0;
|
||||
|
@ -1103,6 +1089,7 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo
|
|||
|
||||
Binding *binding = New<Binding>();
|
||||
binding->propertyNameIndex = propertyNameIndex;
|
||||
binding->offset = nameLocation.offset;
|
||||
binding->location.line = nameLocation.startLine;
|
||||
binding->location.column = nameLocation.startColumn;
|
||||
|
||||
|
@ -1132,6 +1119,79 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo
|
|||
}
|
||||
}
|
||||
|
||||
bool IRBuilder::appendAlias(QQmlJS::AST::UiPublicMember *node)
|
||||
{
|
||||
Alias *alias = New<Alias>();
|
||||
alias->flags = 0;
|
||||
if (node->isReadonlyMember)
|
||||
alias->flags |= QV4::CompiledData::Alias::IsReadOnly;
|
||||
|
||||
const QString propName = node->name.toString();
|
||||
alias->nameIndex = registerString(propName);
|
||||
|
||||
QQmlJS::AST::SourceLocation loc = node->firstSourceLocation();
|
||||
alias->location.line = loc.startLine;
|
||||
alias->location.column = loc.startColumn;
|
||||
|
||||
alias->propertyNameIndex = emptyStringIndex;
|
||||
|
||||
if (!node->statement && !node->binding)
|
||||
COMPILE_EXCEPTION(loc, tr("No property alias location"));
|
||||
|
||||
QQmlJS::AST::SourceLocation rhsLoc;
|
||||
if (node->binding)
|
||||
rhsLoc = node->binding->firstSourceLocation();
|
||||
else if (node->statement)
|
||||
rhsLoc = node->statement->firstSourceLocation();
|
||||
else
|
||||
rhsLoc = node->semicolonToken;
|
||||
alias->referenceLocation.line = rhsLoc.startLine;
|
||||
alias->referenceLocation.column = rhsLoc.startColumn;
|
||||
|
||||
QStringList aliasReference;
|
||||
|
||||
if (QQmlJS::AST::ExpressionStatement *stmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement*>(node->statement)) {
|
||||
aliasReference = astNodeToStringList(stmt->expression);
|
||||
if (aliasReference.isEmpty()) {
|
||||
if (isStatementNodeScript(node->statement)) {
|
||||
COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
|
||||
} else {
|
||||
COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias location"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
|
||||
}
|
||||
|
||||
if (aliasReference.count() < 1 || aliasReference.count() > 3)
|
||||
COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
|
||||
|
||||
alias->idIndex = registerString(aliasReference.first());
|
||||
|
||||
QString propertyValue = aliasReference.value(1);
|
||||
if (aliasReference.count() == 3)
|
||||
propertyValue += QLatin1Char('.') + aliasReference.at(2);
|
||||
alias->propertyNameIndex = registerString(propertyValue);
|
||||
|
||||
QQmlJS::AST::SourceLocation errorLocation;
|
||||
QString error;
|
||||
|
||||
if (illegalNames.contains(propName))
|
||||
error = tr("Illegal property name");
|
||||
else
|
||||
error = _object->appendAlias(alias, propName, node->isDefaultMember, node->defaultToken, &errorLocation);
|
||||
|
||||
if (!error.isEmpty()) {
|
||||
if (errorLocation.startLine == 0)
|
||||
errorLocation = node->identifierToken;
|
||||
|
||||
recordError(errorLocation, error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Object *IRBuilder::bindingsTarget() const
|
||||
{
|
||||
if (_propertyDeclaration && _object->declarationsOverride)
|
||||
|
@ -1201,8 +1261,7 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O
|
|||
if (import->qualifierIndex != emptyStringIndex
|
||||
&& stringAt(import->qualifierIndex) == currentName) {
|
||||
qualifiedIdElement = qualifiedIdElement->next;
|
||||
currentName += QLatin1Char('.');
|
||||
currentName += qualifiedIdElement->name;
|
||||
currentName += QLatin1Char('.') + qualifiedIdElement->name;
|
||||
|
||||
if (!qualifiedIdElement->name.unicode()->isUpper())
|
||||
COMPILE_EXCEPTION(qualifiedIdElement->firstSourceLocation(), tr("Expected type name"));
|
||||
|
@ -1228,6 +1287,7 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O
|
|||
if (!binding) {
|
||||
binding = New<Binding>();
|
||||
binding->propertyNameIndex = propertyNameIndex;
|
||||
binding->offset = qualifiedIdElement->identifierToken.offset;
|
||||
binding->location.line = qualifiedIdElement->identifierToken.startLine;
|
||||
binding->location.column = qualifiedIdElement->identifierToken.startColumn;
|
||||
binding->valueLocation.line = qualifiedIdElement->next->identifierToken.startLine;
|
||||
|
@ -1313,7 +1373,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
|
|||
int objectsSize = 0;
|
||||
foreach (Object *o, output.objects) {
|
||||
objectOffsets.insert(o, unitSize + importSize + objectOffsetTableSize + objectsSize);
|
||||
objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->signalCount(), o->bindingCount());
|
||||
objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount());
|
||||
|
||||
int signalTableSize = 0;
|
||||
for (const Signal *s = o->firstSignal(); s; s = s->next)
|
||||
|
@ -1358,7 +1418,8 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
|
|||
|
||||
QV4::CompiledData::Object *objectToWrite = reinterpret_cast<QV4::CompiledData::Object*>(objectPtr);
|
||||
objectToWrite->inheritedTypeNameIndex = o->inheritedTypeNameIndex;
|
||||
objectToWrite->indexOfDefaultProperty = o->indexOfDefaultProperty;
|
||||
objectToWrite->indexOfDefaultPropertyOrAlias = o->indexOfDefaultPropertyOrAlias;
|
||||
objectToWrite->defaultPropertyIsAlias = o->defaultPropertyIsAlias;
|
||||
objectToWrite->idIndex = o->idIndex;
|
||||
objectToWrite->location = o->location;
|
||||
objectToWrite->locationOfIdProperty = o->locationOfIdProperty;
|
||||
|
@ -1373,6 +1434,10 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
|
|||
objectToWrite->offsetToProperties = nextOffset;
|
||||
nextOffset += objectToWrite->nProperties * sizeof(QV4::CompiledData::Property);
|
||||
|
||||
objectToWrite->nAliases = o->aliasCount();
|
||||
objectToWrite->offsetToAliases = nextOffset;
|
||||
nextOffset += objectToWrite->nAliases * sizeof(QV4::CompiledData::Alias);
|
||||
|
||||
objectToWrite->nSignals = o->signalCount();
|
||||
objectToWrite->offsetToSignals = nextOffset;
|
||||
nextOffset += objectToWrite->nSignals * sizeof(quint32);
|
||||
|
@ -1392,6 +1457,13 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
|
|||
propertiesPtr += sizeof(QV4::CompiledData::Property);
|
||||
}
|
||||
|
||||
char *aliasesPtr = objectPtr + objectToWrite->offsetToAliases;
|
||||
for (const Alias *a = o->firstAlias(); a; a = a->next) {
|
||||
QV4::CompiledData::Alias *aliasToWrite = reinterpret_cast<QV4::CompiledData::Alias*>(aliasesPtr);
|
||||
*aliasToWrite = *a;
|
||||
aliasesPtr += sizeof(QV4::CompiledData::Alias);
|
||||
}
|
||||
|
||||
char *bindingPtr = objectPtr + objectToWrite->offsetToBindings;
|
||||
bindingPtr = writeBindings(bindingPtr, o, &QV4::CompiledData::Binding::isValueBindingNoAlias);
|
||||
bindingPtr = writeBindings(bindingPtr, o, &QV4::CompiledData::Binding::isSignalHandler);
|
||||
|
@ -1420,7 +1492,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
|
|||
signalPtr += size;
|
||||
}
|
||||
|
||||
objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->signalCount(), o->bindingCount());
|
||||
objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount());
|
||||
objectPtr += signalTableSize;
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ struct PoolList
|
|||
T *insertPos = 0;
|
||||
|
||||
for (T *it = first; it; it = it->next) {
|
||||
if (!(it->*sortMember < item->*sortMember))
|
||||
if (!(it->*sortMember <= item->*sortMember))
|
||||
break;
|
||||
insertPos = it;
|
||||
}
|
||||
|
@ -227,10 +227,19 @@ struct Property : public QV4::CompiledData::Property
|
|||
|
||||
struct Binding : public QV4::CompiledData::Binding
|
||||
{
|
||||
// The offset in the source file where the binding appeared. This is used for sorting to ensure
|
||||
// that assignments to list properties are done in the correct order. We use the offset here instead
|
||||
// of Binding::location as the latter has limited precision.
|
||||
quint32 offset;
|
||||
// Binding's compiledScriptIndex is index in object's functionsAndExpressions
|
||||
Binding *next;
|
||||
};
|
||||
|
||||
struct Alias : public QV4::CompiledData::Alias
|
||||
{
|
||||
Alias *next;
|
||||
};
|
||||
|
||||
struct Function
|
||||
{
|
||||
QQmlJS::AST::FunctionDeclaration *functionDeclaration;
|
||||
|
@ -266,13 +275,16 @@ struct Q_QML_PRIVATE_EXPORT Object
|
|||
public:
|
||||
quint32 inheritedTypeNameIndex;
|
||||
quint32 idIndex;
|
||||
int indexOfDefaultProperty;
|
||||
int indexOfDefaultPropertyOrAlias : 31;
|
||||
int defaultPropertyIsAlias : 1;
|
||||
|
||||
QV4::CompiledData::Location location;
|
||||
QV4::CompiledData::Location locationOfIdProperty;
|
||||
|
||||
const Property *firstProperty() const { return properties->first; }
|
||||
int propertyCount() const { return properties->count; }
|
||||
Alias *firstAlias() const { return aliases->first; }
|
||||
int aliasCount() const { return aliases->count; }
|
||||
const Signal *firstSignal() const { return qmlSignals->first; }
|
||||
int signalCount() const { return qmlSignals->count; }
|
||||
Binding *firstBinding() const { return bindings->first; }
|
||||
|
@ -290,6 +302,7 @@ public:
|
|||
|
||||
QString appendSignal(Signal *signal);
|
||||
QString appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation);
|
||||
QString appendAlias(Alias *prop, const QString &aliasName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation);
|
||||
void appendFunction(QmlIR::Function *f);
|
||||
|
||||
QString appendBinding(Binding *b, bool isListBinding);
|
||||
|
@ -305,6 +318,7 @@ private:
|
|||
friend struct IRLoader;
|
||||
|
||||
PoolList<Property> *properties;
|
||||
PoolList<Alias> *aliases;
|
||||
PoolList<Signal> *qmlSignals;
|
||||
PoolList<Binding> *bindings;
|
||||
PoolList<Function> *functions;
|
||||
|
@ -410,6 +424,8 @@ public:
|
|||
void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, QQmlJS::AST::Statement *value);
|
||||
void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, int objectIndex, bool isListItem = false, bool isOnAssignment = false);
|
||||
|
||||
bool appendAlias(QQmlJS::AST::UiPublicMember *node);
|
||||
|
||||
Object *bindingsTarget() const;
|
||||
|
||||
bool setId(const QQmlJS::AST::SourceLocation &idLocation, QQmlJS::AST::Statement *value);
|
||||
|
|
|
@ -179,16 +179,16 @@ bool QQmlTypeCompiler::compile()
|
|||
for (int scriptIndex = 0; scriptIndex < scripts.count(); ++scriptIndex) {
|
||||
const QQmlTypeData::ScriptReference &script = scripts.at(scriptIndex);
|
||||
|
||||
QString qualifier = script.qualifier;
|
||||
QStringRef qualifier(&script.qualifier);
|
||||
QString enclosingNamespace;
|
||||
|
||||
const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
|
||||
if (lastDotIndex != -1) {
|
||||
enclosingNamespace = qualifier.left(lastDotIndex);
|
||||
enclosingNamespace = qualifier.left(lastDotIndex).toString();
|
||||
qualifier = qualifier.mid(lastDotIndex+1);
|
||||
}
|
||||
|
||||
compiledData->importCache->add(qualifier, scriptIndex, enclosingNamespace);
|
||||
compiledData->importCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
|
||||
QQmlScriptData *scriptData = script.script->scriptData();
|
||||
scriptData->addref();
|
||||
compiledData->scripts << scriptData;
|
||||
|
@ -480,7 +480,7 @@ bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int r
|
|||
}
|
||||
}
|
||||
|
||||
bool needVMEMetaObject = obj->propertyCount() != 0 || obj->signalCount() != 0 || obj->functionCount() != 0;
|
||||
bool needVMEMetaObject = obj->propertyCount() != 0 || obj->aliasCount() != 0 || obj->signalCount() != 0 || obj->functionCount() != 0;
|
||||
if (!needVMEMetaObject) {
|
||||
for (const QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
|
||||
if (binding->type == QV4::CompiledData::Binding::Type_Object && (binding->flags & QV4::CompiledData::Binding::IsOnAssignment)) {
|
||||
|
@ -507,7 +507,7 @@ bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int r
|
|||
Q_ASSERT(typeRef);
|
||||
|
||||
if (typeRef->isFullyDynamicType) {
|
||||
if (obj->propertyCount() > 0) {
|
||||
if (obj->propertyCount() > 0 || obj->aliasCount() > 0) {
|
||||
recordError(obj->location, tr("Fully dynamic types cannot declare new properties."));
|
||||
return false;
|
||||
}
|
||||
|
@ -586,9 +586,9 @@ bool QQmlPropertyCacheCreator::ensureMetaObject(int objectIndex)
|
|||
|
||||
bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Object *obj, QQmlPropertyCache *baseTypeCache)
|
||||
{
|
||||
QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(obj->propertyCount(),
|
||||
obj->functionCount() + obj->propertyCount() + obj->signalCount(),
|
||||
obj->signalCount() + obj->propertyCount());
|
||||
QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(obj->propertyCount() + obj->aliasCount(),
|
||||
obj->functionCount() + obj->propertyCount() + obj->aliasCount() + obj->signalCount(),
|
||||
obj->signalCount() + obj->propertyCount() + obj->aliasCount());
|
||||
propertyCaches[objectIndex] = cache;
|
||||
|
||||
struct TypeData {
|
||||
|
@ -624,7 +624,7 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
|
|||
QString path = compiler->url().path();
|
||||
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
|
||||
if (lastSlash > -1) {
|
||||
QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
|
||||
const QStringRef nameBase = path.midRef(lastSlash + 1, path.length() - lastSlash - 5);
|
||||
if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
|
||||
newClassName = nameBase.toUtf8() + "_QMLTYPE_" +
|
||||
QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1));
|
||||
|
@ -638,30 +638,30 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
|
|||
|
||||
cache->_dynamicClassName = newClassName;
|
||||
|
||||
int aliasCount = 0;
|
||||
int varPropCount = 0;
|
||||
|
||||
QmlIR::PropertyResolver resolver(baseTypeCache);
|
||||
|
||||
for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next) {
|
||||
if (p->type == QV4::CompiledData::Property::Alias)
|
||||
aliasCount++;
|
||||
else if (p->type == QV4::CompiledData::Property::Var)
|
||||
if (p->type == QV4::CompiledData::Property::Var)
|
||||
varPropCount++;
|
||||
|
||||
// No point doing this for both the alias and non alias cases
|
||||
bool notInRevision = false;
|
||||
QQmlPropertyData *d = resolver.property(stringAt(p->nameIndex), ¬InRevision);
|
||||
if (d && d->isFinal())
|
||||
COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
|
||||
}
|
||||
|
||||
for (const QmlIR::Alias *a = obj->firstAlias(); a; a = a->next) {
|
||||
bool notInRevision = false;
|
||||
QQmlPropertyData *d = resolver.property(stringAt(a->nameIndex), ¬InRevision);
|
||||
if (d && d->isFinal())
|
||||
COMPILE_EXCEPTION(a, tr("Cannot override FINAL property"));
|
||||
}
|
||||
|
||||
typedef QQmlVMEMetaData VMD;
|
||||
|
||||
QByteArray &dynamicData = vmeMetaObjects[objectIndex] = QByteArray(sizeof(QQmlVMEMetaData)
|
||||
+ obj->propertyCount() * sizeof(VMD::PropertyData)
|
||||
+ obj->functionCount() * sizeof(VMD::MethodData)
|
||||
+ aliasCount * sizeof(VMD::AliasData), 0);
|
||||
vmeMetaObjects[objectIndex] = QByteArray(sizeof(QQmlVMEMetaData) + obj->aliasCount() * sizeof(VMD::AliasData), 0);
|
||||
|
||||
int effectivePropertyIndex = cache->propertyIndexCacheStart;
|
||||
int effectiveMethodIndex = cache->methodIndexCacheStart;
|
||||
|
@ -689,25 +689,25 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
|
|||
}
|
||||
}
|
||||
|
||||
// First set up notify signals for properties - first normal, then var, then alias
|
||||
enum { NSS_Normal = 0, NSS_Alias = 1 };
|
||||
for (int ii = NSS_Normal; ii <= NSS_Alias; ++ii) { // 0 == normal, 1 == var, 2 == alias
|
||||
// Set up notify signals for properties - first normal, then alias
|
||||
for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next) {
|
||||
quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
|
||||
QQmlPropertyData::IsVMESignal;
|
||||
|
||||
if (ii == NSS_Alias && aliasCount == 0) continue;
|
||||
QString changedSigName = stringAt(p->nameIndex) + QLatin1String("Changed");
|
||||
seenSignals.insert(changedSigName);
|
||||
|
||||
for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next) {
|
||||
if ((ii == NSS_Normal && p->type == QV4::CompiledData::Property::Alias) ||
|
||||
(ii == NSS_Alias && p->type != QV4::CompiledData::Property::Alias))
|
||||
continue;
|
||||
cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
|
||||
}
|
||||
|
||||
quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
|
||||
QQmlPropertyData::IsVMESignal;
|
||||
for (const QmlIR::Alias *a = obj->firstAlias(); a; a = a->next) {
|
||||
quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
|
||||
QQmlPropertyData::IsVMESignal;
|
||||
|
||||
QString changedSigName = stringAt(p->nameIndex) + QLatin1String("Changed");
|
||||
seenSignals.insert(changedSigName);
|
||||
QString changedSigName = stringAt(a->nameIndex) + QLatin1String("Changed");
|
||||
seenSignals.insert(changedSigName);
|
||||
|
||||
cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
|
||||
}
|
||||
cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
|
||||
}
|
||||
|
||||
// Dynamic signals
|
||||
|
@ -752,8 +752,6 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
|
|||
}
|
||||
}
|
||||
|
||||
((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
|
||||
|
||||
quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
|
||||
QQmlPropertyData::IsVMESignal;
|
||||
if (paramCount)
|
||||
|
@ -795,25 +793,18 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
|
|||
}
|
||||
|
||||
|
||||
// Dynamic properties (except var and aliases)
|
||||
// Dynamic properties
|
||||
int effectiveSignalIndex = cache->signalHandlerIndexCacheStart;
|
||||
int propertyIdx = 0;
|
||||
for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next, ++propertyIdx) {
|
||||
|
||||
if (p->type == QV4::CompiledData::Property::Alias)
|
||||
continue;
|
||||
|
||||
int propertyType = 0;
|
||||
int vmePropertyType = 0;
|
||||
quint32 propertyFlags = 0;
|
||||
|
||||
if (p->type == QV4::CompiledData::Property::Var) {
|
||||
propertyType = QMetaType::QVariant;
|
||||
vmePropertyType = QQmlVMEMetaData::VarPropertyType;
|
||||
propertyFlags = QQmlPropertyData::IsVarProperty;
|
||||
} else if (p->type < builtinTypeCount) {
|
||||
propertyType = builtinTypes[p->type].metaType;
|
||||
vmePropertyType = propertyType;
|
||||
|
||||
if (p->type == QV4::CompiledData::Property::Variant)
|
||||
propertyFlags |= QQmlPropertyData::IsQVariant;
|
||||
|
@ -836,20 +827,16 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
|
|||
|
||||
if (p->type == QV4::CompiledData::Property::Custom) {
|
||||
propertyType = data->metaTypeId;
|
||||
vmePropertyType = QMetaType::QObjectStar;
|
||||
} else {
|
||||
propertyType = data->listMetaTypeId;
|
||||
vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
|
||||
}
|
||||
|
||||
tdata->release();
|
||||
} else {
|
||||
if (p->type == QV4::CompiledData::Property::Custom) {
|
||||
propertyType = qmltype->typeId();
|
||||
vmePropertyType = QMetaType::QObjectStar;
|
||||
} else {
|
||||
propertyType = qmltype->qListTypeId();
|
||||
vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -864,38 +851,12 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
|
|||
|
||||
|
||||
QString propertyName = stringAt(p->nameIndex);
|
||||
if (propertyIdx == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
|
||||
if (!obj->defaultPropertyIsAlias && propertyIdx == obj->indexOfDefaultPropertyOrAlias)
|
||||
cache->_defaultPropertyName = propertyName;
|
||||
cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
|
||||
propertyType, effectiveSignalIndex);
|
||||
|
||||
effectiveSignalIndex++;
|
||||
|
||||
VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
|
||||
(vmd->propertyData() + vmd->propertyCount)->propertyType = vmePropertyType;
|
||||
vmd->propertyCount++;
|
||||
}
|
||||
|
||||
// Alias property count. Actual data is setup in buildDynamicMetaAliases
|
||||
((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
|
||||
|
||||
// Dynamic slot data - comes after the property data
|
||||
for (const QmlIR::Function *s = obj->firstFunction(); s; s = s->next) {
|
||||
QQmlJS::AST::FunctionDeclaration *astFunction = s->functionDeclaration;
|
||||
int formalsCount = 0;
|
||||
QQmlJS::AST::FormalParameterList *param = astFunction->formals;
|
||||
while (param) {
|
||||
formalsCount++;
|
||||
param = param->next;
|
||||
}
|
||||
|
||||
VMD::MethodData methodData = { /* runtimeFunctionIndex*/ 0, // ###
|
||||
formalsCount,
|
||||
/* s->location.start.line */0 }; // ###
|
||||
|
||||
VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
|
||||
VMD::MethodData &md = *(vmd->methodData() + vmd->methodCount);
|
||||
vmd->methodCount++;
|
||||
md = methodData;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1163,10 +1124,10 @@ struct StaticQtMetaObject : public QObject
|
|||
{ return &staticQtMetaObject; }
|
||||
};
|
||||
|
||||
bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject)
|
||||
bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QStringRef &enumName, int enumValue, bool isQtObject)
|
||||
{
|
||||
if (enumName.length() > 0 && enumName[0].isLower() && !isQtObject) {
|
||||
COMPILE_EXCEPTION(binding, tr("Invalid property assignment: Enum value \"%1\" cannot start with a lowercase letter").arg(enumName));
|
||||
COMPILE_EXCEPTION(binding, tr("Invalid property assignment: Enum value \"%1\" cannot start with a lowercase letter").arg(enumName.toString()));
|
||||
}
|
||||
binding->type = QV4::CompiledData::Binding::Type_Number;
|
||||
binding->value.d = (double)enumValue;
|
||||
|
@ -1197,7 +1158,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
|
|||
|
||||
QHashedStringRef typeName(string.constData(), dot);
|
||||
const bool isQtObject = (typeName == QLatin1String("Qt"));
|
||||
QString enumValue = string.mid(dot+1);
|
||||
const QStringRef enumValue = string.midRef(dot + 1);
|
||||
|
||||
if (isIntProp) {
|
||||
// Allow enum assignment to ints.
|
||||
|
@ -1318,7 +1279,7 @@ void QQmlAliasAnnotator::annotateBindingsToAliases()
|
|||
const QmlIR::Object *obj = qmlObjects.at(i);
|
||||
|
||||
QmlIR::PropertyResolver resolver(propertyCache);
|
||||
QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
|
||||
QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
|
||||
|
||||
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
|
||||
if (!binding->isValueBinding())
|
||||
|
@ -1350,7 +1311,7 @@ void QQmlScriptStringScanner::scan()
|
|||
const QmlIR::Object *obj = qmlObjects.at(i);
|
||||
|
||||
QmlIR::PropertyResolver resolver(propertyCache);
|
||||
QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
|
||||
QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
|
||||
|
||||
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
|
||||
if (binding->type != QV4::CompiledData::Binding::Type_Script)
|
||||
|
@ -1390,7 +1351,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
|
|||
{
|
||||
QmlIR::PropertyResolver propertyResolver(propertyCache);
|
||||
|
||||
QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
|
||||
QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
|
||||
|
||||
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
|
||||
if (binding->type != QV4::CompiledData::Binding::Type_Object)
|
||||
|
@ -1497,7 +1458,7 @@ bool QQmlComponentAndAliasResolver::resolve()
|
|||
|
||||
if (obj->functionCount() > 0)
|
||||
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions."));
|
||||
if (obj->propertyCount() > 0)
|
||||
if (obj->propertyCount() > 0 || obj->aliasCount() > 0)
|
||||
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new properties."));
|
||||
if (obj->signalCount() > 0)
|
||||
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new signals."));
|
||||
|
@ -1568,12 +1529,8 @@ bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
|
|||
_objectIndexToIdInScope->insert(objectIndex, _objectIndexToIdInScope->count());
|
||||
}
|
||||
|
||||
for (const QmlIR::Property *property = obj->firstProperty(); property; property = property->next) {
|
||||
if (property->type == QV4::CompiledData::Property::Alias) {
|
||||
_objectsWithAliases.append(objectIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (obj->aliasCount() > 0)
|
||||
_objectsWithAliases.append(objectIndex);
|
||||
|
||||
for (const QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
|
||||
if (binding->type != QV4::CompiledData::Binding::Type_Object
|
||||
|
@ -1604,21 +1561,20 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
|
|||
int effectivePropertyIndex = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.count();
|
||||
int effectiveAliasIndex = 0;
|
||||
|
||||
const QmlIR::Property *p = obj->firstProperty();
|
||||
for (int propertyIndex = 0; propertyIndex < obj->propertyCount(); ++propertyIndex, p = p->next) {
|
||||
if (p->type != QV4::CompiledData::Property::Alias)
|
||||
continue;
|
||||
|
||||
const int idIndex = p->aliasIdValueIndex;
|
||||
int aliasIndex = 0;
|
||||
for (QmlIR::Alias *alias = obj->firstAlias(); alias; alias = alias->next, ++aliasIndex) {
|
||||
const int idIndex = alias->idIndex;
|
||||
const int targetObjectIndex = _idToObjectIndex.value(idIndex, -1);
|
||||
if (targetObjectIndex == -1) {
|
||||
recordError(p->aliasLocation, tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex)));
|
||||
recordError(alias->referenceLocation, tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex)));
|
||||
return false;
|
||||
}
|
||||
const int targetId = _objectIndexToIdInScope->value(targetObjectIndex, -1);
|
||||
Q_ASSERT(targetId != -1);
|
||||
Q_ASSERT(!(alias->flags & QV4::CompiledData::Alias::Resolved));
|
||||
alias->flags |= QV4::CompiledData::Alias::Resolved;
|
||||
Q_ASSERT(_objectIndexToIdInScope->contains(targetObjectIndex));
|
||||
alias->targetObjectId = _objectIndexToIdInScope->value(targetObjectIndex);
|
||||
|
||||
const QString aliasPropertyValue = stringAt(p->aliasPropertyValueIndex);
|
||||
const QString aliasPropertyValue = stringAt(alias->propertyNameIndex);
|
||||
|
||||
QStringRef property;
|
||||
QStringRef subProperty;
|
||||
|
@ -1631,9 +1587,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
|
|||
property = QStringRef(&aliasPropertyValue, 0, aliasPropertyValue.length());
|
||||
|
||||
int propIdx = -1;
|
||||
int propType = 0;
|
||||
int notifySignal = -1;
|
||||
int flags = 0;
|
||||
int type = 0;
|
||||
bool writable = false;
|
||||
bool resettable = false;
|
||||
|
@ -1650,7 +1604,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
|
|||
else
|
||||
type = typeRef->component->metaTypeId;
|
||||
|
||||
flags |= QML_ALIAS_FLAG_PTR;
|
||||
alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject;
|
||||
propertyFlags |= QQmlPropertyData::IsQObjectDerived;
|
||||
} else {
|
||||
QQmlPropertyCache *targetCache = propertyCaches.at(targetObjectIndex);
|
||||
|
@ -1659,7 +1613,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
|
|||
|
||||
QQmlPropertyData *targetProperty = resolver.property(property.toString());
|
||||
if (!targetProperty || targetProperty->coreIndex > 0x0000FFFF) {
|
||||
recordError(p->aliasLocation, tr("Invalid alias target location: %1").arg(property.toString()));
|
||||
recordError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(property.toString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1673,16 +1627,14 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
|
|||
if (!subProperty.isEmpty()) {
|
||||
const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(type);
|
||||
if (!valueTypeMetaObject) {
|
||||
recordError(p->aliasLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
|
||||
recordError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
propType = type;
|
||||
|
||||
int valueTypeIndex =
|
||||
valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData());
|
||||
if (valueTypeIndex == -1) {
|
||||
recordError(p->aliasLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
|
||||
recordError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
|
||||
return false;
|
||||
}
|
||||
Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
|
||||
|
@ -1704,12 +1656,13 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
|
|||
propertyFlags |= QQmlPropertyData::IsQVariant;
|
||||
|
||||
if (targetProperty->isQObject())
|
||||
flags |= QML_ALIAS_FLAG_PTR;
|
||||
alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QQmlVMEMetaData::AliasData aliasData = { targetId, propIdx, propType, flags, notifySignal };
|
||||
alias->encodedMetaPropertyIndex = propIdx;
|
||||
QQmlVMEMetaData::AliasData aliasData = { notifySignal };
|
||||
|
||||
typedef QQmlVMEMetaData VMD;
|
||||
QByteArray &dynamicData = (*vmeMetaObjectData)[objectIndex];
|
||||
|
@ -1719,7 +1672,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
|
|||
|
||||
Q_ASSERT(dynamicData.isDetached());
|
||||
|
||||
if (!(p->flags & QV4::CompiledData::Property::IsReadOnly) && writable)
|
||||
if (!(alias->flags & QV4::CompiledData::Property::IsReadOnly) && writable)
|
||||
propertyFlags |= QQmlPropertyData::IsWritable;
|
||||
else
|
||||
propertyFlags &= ~QQmlPropertyData::IsWritable;
|
||||
|
@ -1729,8 +1682,11 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
|
|||
else
|
||||
propertyFlags &= ~QQmlPropertyData::IsResettable;
|
||||
|
||||
QString propertyName = stringAt(p->nameIndex);
|
||||
if (propertyIndex == obj->indexOfDefaultProperty) propertyCache->_defaultPropertyName = propertyName;
|
||||
QString propertyName = stringAt(alias->nameIndex);
|
||||
|
||||
if (obj->defaultPropertyIsAlias && aliasIndex == obj->indexOfDefaultPropertyOrAlias)
|
||||
propertyCache->_defaultPropertyName = propertyName;
|
||||
|
||||
propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
|
||||
type, effectiveSignalIndex++);
|
||||
|
||||
|
@ -1842,7 +1798,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
|
|||
|
||||
QString defaultPropertyName;
|
||||
QQmlPropertyData *defaultProperty = 0;
|
||||
if (obj->indexOfDefaultProperty != -1) {
|
||||
if (obj->indexOfDefaultPropertyOrAlias != -1) {
|
||||
QQmlPropertyCache *cache = propertyCache->parent();
|
||||
defaultPropertyName = cache->defaultPropertyName();
|
||||
defaultProperty = cache->defaultProperty();
|
||||
|
@ -2562,7 +2518,7 @@ void QQmlDefaultPropertyMerger::mergeDefaultProperties(int objectIndex)
|
|||
|
||||
QmlIR::Object *object = qmlObjects.at(objectIndex);
|
||||
|
||||
QString defaultProperty = object->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultPropertyName() : propertyCache->defaultPropertyName();
|
||||
QString defaultProperty = object->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultPropertyName() : propertyCache->defaultPropertyName();
|
||||
QmlIR::Binding *bindingsToReinsert = 0;
|
||||
QmlIR::Binding *tail = 0;
|
||||
|
||||
|
|
|
@ -196,7 +196,11 @@ public:
|
|||
bool resolveEnumBindings();
|
||||
|
||||
private:
|
||||
bool assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject);
|
||||
bool assignEnumToBinding(QmlIR::Binding *binding, const QStringRef &enumName, int enumValue, bool isQtObject);
|
||||
bool assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject)
|
||||
{
|
||||
return assignEnumToBinding(binding, QStringRef(&enumName), enumValue, isQtObject);
|
||||
}
|
||||
bool tryQualifiedEnumAssignment(const QmlIR::Object *obj, const QQmlPropertyCache *propertyCache,
|
||||
const QQmlPropertyData *prop,
|
||||
QmlIR::Binding *binding);
|
||||
|
|
|
@ -72,6 +72,9 @@ CompilationUnit::CompilationUnit()
|
|||
CompilationUnit::~CompilationUnit()
|
||||
{
|
||||
unlink();
|
||||
if (data && !(data->flags & QV4::CompiledData::Unit::StaticData))
|
||||
free(data);
|
||||
data = 0;
|
||||
}
|
||||
|
||||
QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
|
||||
|
@ -163,9 +166,6 @@ void CompilationUnit::unlink()
|
|||
if (engine)
|
||||
engine->compilationUnits.erase(engine->compilationUnits.find(this));
|
||||
engine = 0;
|
||||
if (data && !(data->flags & QV4::CompiledData::Unit::StaticData))
|
||||
free(data);
|
||||
data = 0;
|
||||
free(runtimeStrings);
|
||||
runtimeStrings = 0;
|
||||
delete [] runtimeLookups;
|
||||
|
@ -221,8 +221,8 @@ QString Binding::valueAsString(const Unit *unit) const
|
|||
// This code must match that in the qsTr() implementation
|
||||
const QString &path = unit->stringAt(unit->sourceFileIndex);
|
||||
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
|
||||
QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, path.length()-lastSlash-5) :
|
||||
QString();
|
||||
QStringRef context = (lastSlash > -1) ? path.midRef(lastSlash + 1, path.length() - lastSlash - 5)
|
||||
: QStringRef();
|
||||
QByteArray contextUtf8 = context.toUtf8();
|
||||
QByteArray comment = unit->stringAt(value.translationData.commentIndex).toUtf8();
|
||||
QByteArray text = unit->stringAt(stringIndex).toUtf8();
|
||||
|
|
|
@ -351,22 +351,42 @@ struct Property
|
|||
enum Type { Var = 0, Variant, Int, Bool, Real, String, Url, Color,
|
||||
Font, Time, Date, DateTime, Rect, Point, Size,
|
||||
Vector2D, Vector3D, Vector4D, Matrix4x4, Quaternion,
|
||||
Alias, Custom, CustomList };
|
||||
Custom, CustomList };
|
||||
|
||||
enum Flags {
|
||||
IsReadOnly = 0x1
|
||||
};
|
||||
|
||||
quint32 nameIndex;
|
||||
quint32 type;
|
||||
union {
|
||||
quint32 customTypeNameIndex; // If type >= Custom
|
||||
quint32 aliasIdValueIndex; // If type == Alias
|
||||
};
|
||||
quint32 aliasPropertyValueIndex;
|
||||
quint32 flags; // readonly
|
||||
quint32 type : 31;
|
||||
quint32 flags : 1; // readonly
|
||||
quint32 customTypeNameIndex; // If type >= Custom
|
||||
Location location;
|
||||
Location aliasLocation; // If type == Alias
|
||||
};
|
||||
|
||||
struct Alias {
|
||||
enum Flags {
|
||||
IsReadOnly = 0x1,
|
||||
Resolved = 0x2,
|
||||
AliasPointsToPointerObject = 0x4
|
||||
};
|
||||
quint32 nameIndex : 29;
|
||||
quint32 flags : 3;
|
||||
union {
|
||||
quint32 idIndex; // string index
|
||||
quint32 targetObjectId; // object id index (in QQmlContextData::idValues)
|
||||
};
|
||||
union {
|
||||
quint32 propertyNameIndex; // string index
|
||||
qint32 encodedMetaPropertyIndex;
|
||||
};
|
||||
Location location;
|
||||
Location referenceLocation;
|
||||
|
||||
bool isObjectAlias() const {
|
||||
Q_ASSERT(flags & Resolved);
|
||||
return encodedMetaPropertyIndex == -1;
|
||||
}
|
||||
};
|
||||
|
||||
struct Object
|
||||
|
@ -376,11 +396,14 @@ struct Object
|
|||
// it will be the name of the attached type.
|
||||
quint32 inheritedTypeNameIndex;
|
||||
quint32 idIndex;
|
||||
qint32 indexOfDefaultProperty; // -1 means no default property declared in this object
|
||||
qint32 indexOfDefaultPropertyOrAlias : 31; // -1 means no default property declared in this object
|
||||
quint32 defaultPropertyIsAlias : 1;
|
||||
quint32 nFunctions;
|
||||
quint32 offsetToFunctions;
|
||||
quint32 nProperties;
|
||||
quint32 offsetToProperties;
|
||||
quint32 nAliases;
|
||||
quint32 offsetToAliases;
|
||||
quint32 nSignals;
|
||||
quint32 offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
|
||||
quint32 nBindings;
|
||||
|
@ -392,11 +415,12 @@ struct Object
|
|||
// Signal[]
|
||||
// Binding[]
|
||||
|
||||
static int calculateSizeExcludingSignals(int nFunctions, int nProperties, int nSignals, int nBindings)
|
||||
static int calculateSizeExcludingSignals(int nFunctions, int nProperties, int nAliases, int nSignals, int nBindings)
|
||||
{
|
||||
return ( sizeof(Object)
|
||||
+ nFunctions * sizeof(quint32)
|
||||
+ nProperties * sizeof(Property)
|
||||
+ nAliases * sizeof(Alias)
|
||||
+ nSignals * sizeof(quint32)
|
||||
+ nBindings * sizeof(Binding)
|
||||
+ 0x7
|
||||
|
@ -413,6 +437,11 @@ struct Object
|
|||
return reinterpret_cast<const Property*>(reinterpret_cast<const char *>(this) + offsetToProperties);
|
||||
}
|
||||
|
||||
const Alias *aliasTable() const
|
||||
{
|
||||
return reinterpret_cast<const Alias*>(reinterpret_cast<const char *>(this) + offsetToAliases);
|
||||
}
|
||||
|
||||
const Binding *bindingTable() const
|
||||
{
|
||||
return reinterpret_cast<const Binding*>(reinterpret_cast<const char *>(this) + offsetToBindings);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -45,7 +45,9 @@ QT_BEGIN_NAMESPACE
|
|||
QQmlProfiler::QQmlProfiler() : featuresEnabled(0)
|
||||
{
|
||||
static int metatype = qRegisterMetaType<QVector<QQmlProfilerData> >();
|
||||
static int metatype2 = qRegisterMetaType<QQmlProfiler::LocationHash> ();
|
||||
Q_UNUSED(metatype);
|
||||
Q_UNUSED(metatype2);
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
|
@ -62,8 +64,18 @@ void QQmlProfiler::stopProfiling()
|
|||
|
||||
void QQmlProfiler::reportData()
|
||||
{
|
||||
emit dataReady(m_data);
|
||||
m_data.clear();
|
||||
LocationHash resolved;
|
||||
resolved.reserve(m_locations.size());
|
||||
for (auto it = m_locations.constBegin(), end = m_locations.constEnd(); it != end; ++it)
|
||||
resolved.insert(it.key(), it.value());
|
||||
|
||||
// This unrefs all the objects. We have to make sure we do this in the GUI thread. Also, it's
|
||||
// a good idea to release the memory before creating the packets to be sent.
|
||||
m_locations.clear();
|
||||
|
||||
QVector<QQmlProfilerData> data;
|
||||
data.swap(m_data);
|
||||
emit dataReady(data, resolved);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
@ -54,6 +54,8 @@
|
|||
#include <private/qv4function_p.h>
|
||||
#include <private/qqmlboundsignal_p.h>
|
||||
#include <private/qfinitestack_p.h>
|
||||
#include <private/qqmlbinding_p.h>
|
||||
#include <private/qqmlcompiler_p.h>
|
||||
#include "qqmlprofilerdefinitions_p.h"
|
||||
#include "qqmlabstractprofileradapter_p.h"
|
||||
|
||||
|
@ -77,40 +79,18 @@ QT_BEGIN_NAMESPACE
|
|||
// independently when converting to QByteArrays. Thus you can only pack
|
||||
// messages if their data doesn't overlap. It's up to you to figure that
|
||||
// out.
|
||||
struct Q_AUTOTEST_EXPORT QQmlProfilerData
|
||||
struct Q_AUTOTEST_EXPORT QQmlProfilerData : public QQmlProfilerDefinitions
|
||||
{
|
||||
QQmlProfilerData() {}
|
||||
|
||||
QQmlProfilerData(qint64 time, int messageType, int detailType, const QUrl &url,
|
||||
int x = 0, int y = 0) :
|
||||
time(time), messageType(messageType), detailType(detailType), detailUrl(url),
|
||||
x(x), y(y) {}
|
||||
|
||||
QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str,
|
||||
int x = 0, int y = 0) :
|
||||
time(time), messageType(messageType), detailType(detailType),detailString(str),
|
||||
x(x), y(y) {}
|
||||
|
||||
QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str,
|
||||
const QUrl &url, int x = 0, int y = 0) :
|
||||
time(time), messageType(messageType), detailType(detailType), detailString(str),
|
||||
detailUrl(url), x(x), y(y) {}
|
||||
|
||||
|
||||
QQmlProfilerData(qint64 time, int messageType, int detailType) :
|
||||
time(time), messageType(messageType), detailType(detailType) {}
|
||||
|
||||
QQmlProfilerData(qint64 time = -1, int messageType = -1,
|
||||
RangeType detailType = MaximumRangeType, quintptr locationId = 0) :
|
||||
time(time), locationId(locationId), messageType(messageType), detailType(detailType)
|
||||
{}
|
||||
|
||||
qint64 time;
|
||||
quintptr locationId;
|
||||
|
||||
int messageType; //bit field of QQmlProfilerService::Message
|
||||
int detailType;
|
||||
|
||||
// RangeData prefers detailString; RangeLocation prefers detailUrl.
|
||||
QString detailString; //used by RangeData and possibly by RangeLocation
|
||||
QUrl detailUrl; //used by RangeLocation and possibly by RangeData
|
||||
|
||||
int x; //used by RangeLocation
|
||||
int y; //used by RangeLocation
|
||||
RangeType detailType;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
|
||||
|
@ -118,58 +98,166 @@ Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
|
|||
class QQmlProfiler : public QObject, public QQmlProfilerDefinitions {
|
||||
Q_OBJECT
|
||||
public:
|
||||
void startBinding(const QQmlSourceLocation &location)
|
||||
|
||||
class BindingRefCount : public QQmlRefCount {
|
||||
public:
|
||||
BindingRefCount(QQmlBinding *binding):
|
||||
m_binding(binding)
|
||||
{
|
||||
m_binding->ref.ref();
|
||||
}
|
||||
|
||||
BindingRefCount(const BindingRefCount &other) :
|
||||
QQmlRefCount(other), m_binding(other.m_binding)
|
||||
{
|
||||
m_binding->ref.ref();
|
||||
}
|
||||
|
||||
BindingRefCount &operator=(const BindingRefCount &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
QQmlRefCount::operator=(other);
|
||||
other.m_binding->ref.ref();
|
||||
if (!m_binding->ref.deref())
|
||||
delete m_binding;
|
||||
m_binding = other.m_binding;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~BindingRefCount()
|
||||
{
|
||||
if (!m_binding->ref.deref())
|
||||
delete m_binding;
|
||||
}
|
||||
|
||||
private:
|
||||
QQmlBinding *m_binding;
|
||||
};
|
||||
|
||||
struct Location {
|
||||
Location(const QQmlSourceLocation &location = QQmlSourceLocation(),
|
||||
const QUrl &url = QUrl()) :
|
||||
location(location), url(url) {}
|
||||
QQmlSourceLocation location;
|
||||
QUrl url;
|
||||
};
|
||||
|
||||
// Unfortunately we have to resolve the locations right away because the QML context might not
|
||||
// be available anymore when we send the data.
|
||||
struct RefLocation : public Location {
|
||||
RefLocation() : Location(), locationType(MaximumRangeType), ref(nullptr)
|
||||
{}
|
||||
|
||||
RefLocation(QQmlBinding *binding, QV4::FunctionObject *function) :
|
||||
Location(function->sourceLocation()), locationType(Binding),
|
||||
ref(new BindingRefCount(binding), QQmlRefPointer<QQmlRefCount>::Adopt)
|
||||
{}
|
||||
|
||||
RefLocation(QQmlCompiledData *ref, const QUrl &url, const QV4::CompiledData::Object *obj,
|
||||
const QString &type) :
|
||||
Location(QQmlSourceLocation(type, obj->location.line, obj->location.column), url),
|
||||
locationType(Creating), ref(ref)
|
||||
{}
|
||||
|
||||
RefLocation(QQmlBoundSignalExpression *ref) :
|
||||
Location(ref->sourceLocation()), locationType(HandlingSignal), ref(ref)
|
||||
{}
|
||||
|
||||
RefLocation(QQmlDataBlob *ref) :
|
||||
Location(QQmlSourceLocation(), ref->url()), locationType(Compiling), ref(ref)
|
||||
{}
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return locationType != MaximumRangeType;
|
||||
}
|
||||
|
||||
RangeType locationType;
|
||||
QQmlRefPointer<QQmlRefCount> ref;
|
||||
};
|
||||
|
||||
typedef QHash<quintptr, Location> LocationHash;
|
||||
|
||||
void startBinding(QQmlBinding *binding, QV4::FunctionObject *function)
|
||||
{
|
||||
quintptr locationId(id(binding));
|
||||
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
|
||||
(1 << RangeStart | 1 << RangeLocation), 1 << Binding,
|
||||
location.sourceFile, qmlSourceCoordinate(location.line), qmlSourceCoordinate(location.column)));
|
||||
(1 << RangeStart | 1 << RangeLocation), Binding,
|
||||
locationId));
|
||||
|
||||
RefLocation &location = m_locations[locationId];
|
||||
if (!location.isValid())
|
||||
location = RefLocation(binding, function);
|
||||
}
|
||||
|
||||
// Have toByteArrays() construct another RangeData event from the same QString later.
|
||||
// This is somewhat pointless but important for backwards compatibility.
|
||||
void startCompiling(const QUrl &url)
|
||||
void startCompiling(QQmlDataBlob *blob)
|
||||
{
|
||||
quintptr locationId(id(blob));
|
||||
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
|
||||
(1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
|
||||
1 << Compiling, url, 1, 1));
|
||||
Compiling, locationId));
|
||||
|
||||
RefLocation &location = m_locations[locationId];
|
||||
if (!location.isValid())
|
||||
location = RefLocation(blob);
|
||||
}
|
||||
|
||||
void startHandlingSignal(const QQmlSourceLocation &location)
|
||||
void startHandlingSignal(QQmlBoundSignalExpression *expression)
|
||||
{
|
||||
quintptr locationId(id(expression));
|
||||
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
|
||||
(1 << RangeStart | 1 << RangeLocation), 1 << HandlingSignal,
|
||||
location.sourceFile, location.line, location.column));
|
||||
(1 << RangeStart | 1 << RangeLocation), HandlingSignal,
|
||||
locationId));
|
||||
|
||||
RefLocation &location = m_locations[locationId];
|
||||
if (!location.isValid())
|
||||
location = RefLocation(expression);
|
||||
}
|
||||
|
||||
void startCreating()
|
||||
{
|
||||
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, 1 << Creating));
|
||||
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, Creating));
|
||||
}
|
||||
|
||||
void startCreating(const QString &typeName, const QUrl &fileName, int line, int column)
|
||||
void startCreating(const QV4::CompiledData::Object *obj)
|
||||
{
|
||||
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
|
||||
(1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
|
||||
1 << Creating, typeName, fileName, line, column));
|
||||
Creating, id(obj)));
|
||||
}
|
||||
|
||||
void updateCreating(const QString &typeName, const QUrl &fileName, int line, int column)
|
||||
void updateCreating(const QV4::CompiledData::Object *obj, QQmlCompiledData *ref,
|
||||
const QUrl &url, const QString &type)
|
||||
{
|
||||
quintptr locationId(id(obj));
|
||||
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
|
||||
(1 << RangeLocation | 1 << RangeData),
|
||||
1 << Creating, typeName, fileName, line, column));
|
||||
Creating, locationId));
|
||||
|
||||
RefLocation &location = m_locations[locationId];
|
||||
if (!location.isValid())
|
||||
location = RefLocation(ref, url, obj, type);
|
||||
}
|
||||
|
||||
template<RangeType Range>
|
||||
void endRange()
|
||||
{
|
||||
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, 1 << Range));
|
||||
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, Range));
|
||||
}
|
||||
|
||||
QQmlProfiler();
|
||||
|
||||
quint64 featuresEnabled;
|
||||
|
||||
template<typename Object>
|
||||
static quintptr id(const Object *pointer)
|
||||
{
|
||||
return reinterpret_cast<quintptr>(pointer);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void startProfiling(quint64 features);
|
||||
void stopProfiling();
|
||||
|
@ -177,10 +265,11 @@ public slots:
|
|||
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
|
||||
|
||||
signals:
|
||||
void dataReady(const QVector<QQmlProfilerData> &);
|
||||
void dataReady(const QVector<QQmlProfilerData> &, const QQmlProfiler::LocationHash &);
|
||||
|
||||
protected:
|
||||
QElapsedTimer m_timer;
|
||||
QHash<quintptr, RefLocation> m_locations;
|
||||
QVector<QQmlProfilerData> m_data;
|
||||
};
|
||||
|
||||
|
@ -194,11 +283,12 @@ struct QQmlProfilerHelper : public QQmlProfilerDefinitions {
|
|||
};
|
||||
|
||||
struct QQmlBindingProfiler : public QQmlProfilerHelper {
|
||||
QQmlBindingProfiler(QQmlProfiler *profiler, const QV4::FunctionObject *function) :
|
||||
QQmlBindingProfiler(QQmlProfiler *profiler, QQmlBinding *binding,
|
||||
QV4::FunctionObject *function) :
|
||||
QQmlProfilerHelper(profiler)
|
||||
{
|
||||
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileBinding, profiler,
|
||||
startBinding(function->sourceLocation()));
|
||||
startBinding(binding, function));
|
||||
}
|
||||
|
||||
~QQmlBindingProfiler()
|
||||
|
@ -213,7 +303,7 @@ struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper {
|
|||
QQmlProfilerHelper(profiler)
|
||||
{
|
||||
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileHandlingSignal, profiler,
|
||||
startHandlingSignal(expression->sourceLocation()));
|
||||
startHandlingSignal(expression));
|
||||
}
|
||||
|
||||
~QQmlHandlingSignalProfiler()
|
||||
|
@ -224,10 +314,10 @@ struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper {
|
|||
};
|
||||
|
||||
struct QQmlCompilingProfiler : public QQmlProfilerHelper {
|
||||
QQmlCompilingProfiler(QQmlProfiler *profiler, const QUrl &url) :
|
||||
QQmlCompilingProfiler(QQmlProfiler *profiler, QQmlDataBlob *blob) :
|
||||
QQmlProfilerHelper(profiler)
|
||||
{
|
||||
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, startCompiling(url));
|
||||
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, startCompiling(blob));
|
||||
}
|
||||
|
||||
~QQmlCompilingProfiler()
|
||||
|
@ -239,14 +329,6 @@ struct QQmlCompilingProfiler : public QQmlProfilerHelper {
|
|||
struct QQmlVmeProfiler : public QQmlProfilerDefinitions {
|
||||
public:
|
||||
|
||||
struct Data {
|
||||
Data() : m_line(0), m_column(0) {}
|
||||
QUrl m_url;
|
||||
int m_line;
|
||||
int m_column;
|
||||
QString m_typeName;
|
||||
};
|
||||
|
||||
QQmlVmeProfiler() : profiler(0) {}
|
||||
|
||||
void init(QQmlProfiler *p, int maxDepth)
|
||||
|
@ -255,30 +337,30 @@ public:
|
|||
ranges.allocate(maxDepth);
|
||||
}
|
||||
|
||||
Data pop()
|
||||
const QV4::CompiledData::Object *pop()
|
||||
{
|
||||
if (ranges.count() > 0)
|
||||
return ranges.pop();
|
||||
else
|
||||
return Data();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void push(const Data &data)
|
||||
void push(const QV4::CompiledData::Object *object)
|
||||
{
|
||||
if (ranges.capacity() > ranges.count())
|
||||
ranges.push(data);
|
||||
ranges.push(object);
|
||||
}
|
||||
|
||||
QQmlProfiler *profiler;
|
||||
|
||||
private:
|
||||
QFiniteStack<Data> ranges;
|
||||
QFiniteStack<const QV4::CompiledData::Object *> ranges;
|
||||
};
|
||||
|
||||
#define Q_QML_OC_PROFILE(member, Code)\
|
||||
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, member.profiler, Code)
|
||||
|
||||
class QQmlObjectCreationProfiler : public QQmlVmeProfiler::Data {
|
||||
class QQmlObjectCreationProfiler {
|
||||
public:
|
||||
|
||||
QQmlObjectCreationProfiler(QQmlProfiler *profiler) : profiler(profiler)
|
||||
|
@ -291,13 +373,10 @@ public:
|
|||
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, endRange<QQmlProfilerDefinitions::Creating>());
|
||||
}
|
||||
|
||||
void update(const QString &typeName, const QUrl &url, int line, int column)
|
||||
void update(QQmlCompiledData *ref, const QV4::CompiledData::Object *obj,
|
||||
const QString &typeName, const QUrl &url)
|
||||
{
|
||||
profiler->updateCreating(typeName, url, line, column);
|
||||
m_typeName = typeName;
|
||||
m_url = url;
|
||||
m_line = line;
|
||||
m_column = column;
|
||||
profiler->updateCreating(obj, ref, url, typeName);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -310,8 +389,7 @@ public:
|
|||
profiler(parent->profiler)
|
||||
{
|
||||
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler, {
|
||||
QQmlVmeProfiler::Data data = parent->pop();
|
||||
profiler->startCreating(data.m_typeName, data.m_url, data.m_line, data.m_column);
|
||||
profiler->startCreating(parent->pop());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -326,5 +404,6 @@ private:
|
|||
|
||||
QT_END_NAMESPACE
|
||||
Q_DECLARE_METATYPE(QVector<QQmlProfilerData>)
|
||||
Q_DECLARE_METATYPE(QQmlProfiler::LocationHash)
|
||||
|
||||
#endif // QQMLPROFILER_P_H
|
||||
|
|
|
@ -112,7 +112,7 @@ when passed from C++ to QML and vice-versa:
|
|||
\li QVector2D, QVector3D, QVector4D
|
||||
\li \l vector2d, \l vector3d, \l vector4d
|
||||
\row
|
||||
\li Enums declared with Q_ENUMS()
|
||||
\li Enums declared with Q_ENUM() or Q_ENUMS()
|
||||
\li \l enumeration
|
||||
\endtable
|
||||
|
||||
|
@ -261,6 +261,9 @@ In particular, QML currently supports:
|
|||
\li \c {QList<bool>}
|
||||
\li \c {QList<QString>} and \c{QStringList}
|
||||
\li \c {QList<QUrl>}
|
||||
\li \c {QVector<int>}
|
||||
\li \c {QVector<qreal>}
|
||||
\li \c {QVector<bool>}
|
||||
\endlist
|
||||
|
||||
These sequence types are implemented directly in terms of the underlying C++
|
||||
|
@ -303,6 +306,9 @@ The default-constructed values for each sequence type are as follows:
|
|||
\row \li QList<bool> \li boolean value \c {false}
|
||||
\row \li QList<QString> and QStringList \li empty QString
|
||||
\row \li QList<QUrl> \li empty QUrl
|
||||
\row \li QVector<int> \li integer value 0
|
||||
\row \li QVector<qreal> \li real value 0.0
|
||||
\row \li QVector<bool> \li boolean value \c {false}
|
||||
\endtable
|
||||
|
||||
If you wish to remove elements from a sequence rather than simply replace
|
||||
|
@ -341,7 +347,7 @@ properties:
|
|||
\section1 Enumeration Types
|
||||
|
||||
To use a custom enumeration as a data type, its class must be registered and
|
||||
the enumeration must also be declared with Q_ENUMS() to register it with Qt's
|
||||
the enumeration must also be declared with Q_ENUM() to register it with Qt's
|
||||
meta object system. For example, the \c Message class below has a \c Status
|
||||
enum:
|
||||
|
||||
|
@ -349,7 +355,6 @@ enum:
|
|||
class Message : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(Status)
|
||||
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
|
||||
public:
|
||||
enum Status {
|
||||
|
@ -357,6 +362,7 @@ enum:
|
|||
Loading,
|
||||
Error
|
||||
};
|
||||
Q_ENUM(Status)
|
||||
Status status() const;
|
||||
signals:
|
||||
void statusChanged();
|
||||
|
|
|
@ -386,12 +386,26 @@ directory.
|
|||
|
||||
\quotefile tutorials/extending-qml/chapter6-plugins/import/import.pro
|
||||
|
||||
In this example, the \c Charts directory is located at the same level as the application
|
||||
that uses our new import module. This way, the QML engine will find our module
|
||||
as the default search path for QML imports includes the directory of the application
|
||||
executable. Alternatively, we could control what directories the \l {QML Import Path}
|
||||
{QML import path} contains, useful if there are multiple QML applications using the
|
||||
same QML imports.
|
||||
When building this example on Windows or Linux, the \c Charts directory will be
|
||||
located at the same level as the application that uses our new import module.
|
||||
This way, the QML engine will find our module as the default search path for QML
|
||||
imports includes the directory of the application executable. On OS X, the
|
||||
plugin binary is copied to \c Contents/PlugIns in the the application bundle;
|
||||
this path is set in \l {tutorials/extending-qml/chapter6-plugins/app.pro}
|
||||
{chapter6-plugins/app.pro}:
|
||||
|
||||
\quotefromfile tutorials/extending-qml/chapter6-plugins/app.pro
|
||||
\skipto osx
|
||||
\printuntil }
|
||||
|
||||
To account for this, we also need to add this location as a
|
||||
\l {QML Import Path}{QML import path} in \c main.cpp:
|
||||
|
||||
\snippet tutorials/extending-qml/chapter6-plugins/main.cpp 0
|
||||
\dots
|
||||
|
||||
Defining custom import paths is useful also when there are multiple
|
||||
applications using the same QML imports.
|
||||
|
||||
The \c .pro file also contains additional magic to ensure that the
|
||||
\l {Module Definition qmldir Files}{module definition qmldir file} is always copied
|
||||
|
|
|
@ -508,7 +508,7 @@ built-in \l {Rectangle::color} property:
|
|||
|
||||
Any object that use this type and refer to its \c color property will be
|
||||
referring to the alias rather than the ordinary \l {Rectangle::color} property.
|
||||
Internally, however, the red can correctly set its \c color
|
||||
Internally, however, the rectangle can correctly set its \c color
|
||||
property and refer to the actual defined property rather than the alias.
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -247,6 +247,11 @@ Q_DECLARE_METATYPE(QList<int>)
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static void checkForApplicationInstance()
|
||||
{
|
||||
if (!QCoreApplication::instance())
|
||||
qFatal("QJSEngine: Must construct a QCoreApplication before a QJSEngine");
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a QJSEngine object.
|
||||
|
@ -270,6 +275,8 @@ QJSEngine::QJSEngine(QObject *parent)
|
|||
: QObject(*new QJSEnginePrivate, parent)
|
||||
, d(new QV8Engine(this))
|
||||
{
|
||||
checkForApplicationInstance();
|
||||
|
||||
QJSEnginePrivate::addToDebugServer(this);
|
||||
}
|
||||
|
||||
|
@ -280,6 +287,7 @@ QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
|
|||
: QObject(dd, parent)
|
||||
, d(new QV8Engine(this))
|
||||
{
|
||||
checkForApplicationInstance();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -287,7 +287,13 @@ void SimpleArrayData::push_front(Object *o, const Value *values, uint n)
|
|||
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Simple);
|
||||
dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
|
||||
}
|
||||
dd->offset = (dd->offset - n) % dd->alloc;
|
||||
if (n <= dd->offset) {
|
||||
dd->offset -= n; // there is enough space left in front
|
||||
} else {
|
||||
// we need to wrap around, so:
|
||||
dd->offset = dd->alloc - // start at the back, but subtract:
|
||||
(n - dd->offset); // the number of items we can put in the free space at the start of the allocated array
|
||||
}
|
||||
dd->len += n;
|
||||
for (uint i = 0; i < n; ++i)
|
||||
dd->data(i) = values[i].asReturnedValue();
|
||||
|
|
|
@ -338,7 +338,7 @@ static inline double currentTime()
|
|||
|
||||
static inline double TimeClip(double t)
|
||||
{
|
||||
if (! qIsFinite(t) || fabs(t) > 8.64e15)
|
||||
if (! qt_is_finite(t) || fabs(t) > 8.64e15)
|
||||
return qt_qnan();
|
||||
return Primitive::toInteger(t);
|
||||
}
|
||||
|
|
|
@ -160,13 +160,9 @@ ReturnedValue ErrorObject::method_get_stack(CallContext *ctx)
|
|||
if (i > 0)
|
||||
trace += QLatin1Char('\n');
|
||||
const StackFrame &frame = This->d()->stackTrace[i];
|
||||
trace += frame.function;
|
||||
trace += QLatin1Char('@');
|
||||
trace += frame.source;
|
||||
if (frame.line >= 0) {
|
||||
trace += QLatin1Char(':');
|
||||
trace += QString::number(frame.line);
|
||||
}
|
||||
trace += frame.function + QLatin1Char('@') + frame.source;
|
||||
if (frame.line >= 0)
|
||||
trace += QLatin1Char(':') + QString::number(frame.line);
|
||||
}
|
||||
This->d()->stack = ctx->d()->engine->newString(trace);
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ const IdentifierHashEntry *IdentifierHashBase::lookup(const QString &str) const
|
|||
return 0;
|
||||
Q_ASSERT(d->entries);
|
||||
|
||||
uint hash = String::createHashValue(str.constData(), str.length());
|
||||
uint hash = String::createHashValue(str.constData(), str.length(), Q_NULLPTR);
|
||||
uint idx = hash % d->alloc;
|
||||
while (1) {
|
||||
if (!d->entries[idx].identifier)
|
||||
|
|
|
@ -118,7 +118,8 @@ void IdentifierTable::addEntry(Heap::String *str)
|
|||
|
||||
Heap::String *IdentifierTable::insertString(const QString &s)
|
||||
{
|
||||
uint hash = String::createHashValue(s.constData(), s.length());
|
||||
uint subtype;
|
||||
uint hash = String::createHashValue(s.constData(), s.length(), &subtype);
|
||||
uint idx = hash % alloc;
|
||||
while (Heap::String *e = entries[idx]) {
|
||||
if (e->stringHash == hash && e->toQString() == s)
|
||||
|
@ -128,6 +129,8 @@ Heap::String *IdentifierTable::insertString(const QString &s)
|
|||
}
|
||||
|
||||
Heap::String *str = engine->newString(s);
|
||||
str->stringHash = hash;
|
||||
str->subtype = subtype;
|
||||
addEntry(str);
|
||||
return str;
|
||||
}
|
||||
|
@ -178,7 +181,8 @@ Identifier *IdentifierTable::identifier(const QString &s)
|
|||
|
||||
Identifier *IdentifierTable::identifier(const char *s, int len)
|
||||
{
|
||||
uint hash = String::createHashValue(s, len);
|
||||
uint subtype;
|
||||
uint hash = String::createHashValue(s, len, &subtype);
|
||||
if (hash == UINT_MAX)
|
||||
return identifier(QString::fromUtf8(s, len));
|
||||
|
||||
|
@ -192,6 +196,8 @@ Identifier *IdentifierTable::identifier(const char *s, int len)
|
|||
}
|
||||
|
||||
Heap::String *str = engine->newString(QString::fromLatin1(s, len));
|
||||
str->stringHash = hash;
|
||||
str->subtype = subtype;
|
||||
addEntry(str);
|
||||
return str->identifier;
|
||||
}
|
||||
|
|
|
@ -429,11 +429,13 @@ InternalClass *InternalClass::propertiesFrozen() const
|
|||
|
||||
void InternalClass::destroy()
|
||||
{
|
||||
QList<InternalClass *> destroyStack;
|
||||
destroyStack.append(this);
|
||||
std::vector<InternalClass *> destroyStack;
|
||||
destroyStack.reserve(64);
|
||||
destroyStack.push_back(this);
|
||||
|
||||
while (!destroyStack.isEmpty()) {
|
||||
InternalClass *next = destroyStack.takeLast();
|
||||
while (!destroyStack.empty()) {
|
||||
InternalClass *next = destroyStack.back();
|
||||
destroyStack.pop_back();
|
||||
if (!next->engine)
|
||||
continue;
|
||||
next->engine = 0;
|
||||
|
@ -441,13 +443,13 @@ void InternalClass::destroy()
|
|||
next->nameMap.~SharedInternalClassData<Identifier *>();
|
||||
next->propertyData.~SharedInternalClassData<PropertyAttributes>();
|
||||
if (next->m_sealed)
|
||||
destroyStack.append(next->m_sealed);
|
||||
destroyStack.push_back(next->m_sealed);
|
||||
if (next->m_frozen)
|
||||
destroyStack.append(next->m_frozen);
|
||||
destroyStack.push_back(next->m_frozen);
|
||||
|
||||
for (size_t i = 0; i < next->transitions.size(); ++i) {
|
||||
Q_ASSERT(next->transitions.at(i).lookup);
|
||||
destroyStack.append(next->transitions.at(i).lookup);
|
||||
destroyStack.push_back(next->transitions.at(i).lookup);
|
||||
}
|
||||
|
||||
next->transitions.~vector<Transition>();
|
||||
|
|
|
@ -590,8 +590,7 @@ bool JsonParser::parseString(QString *string)
|
|||
return false;
|
||||
}
|
||||
if (QChar::requiresSurrogates(ch)) {
|
||||
*string += QChar(QChar::highSurrogate(ch));
|
||||
*string += QChar(QChar::lowSurrogate(ch));
|
||||
*string += QChar(QChar::highSurrogate(ch)) + QChar(QChar::lowSurrogate(ch));
|
||||
} else {
|
||||
*string += QChar(ch);
|
||||
}
|
||||
|
@ -672,8 +671,8 @@ static QString quote(const QString &str)
|
|||
default:
|
||||
if (c.unicode() <= 0x1f) {
|
||||
product += QStringLiteral("\\u00");
|
||||
product += c.unicode() > 0xf ? QLatin1Char('1') : QLatin1Char('0');
|
||||
product += QLatin1Char("0123456789abcdef"[c.unicode() & 0xf]);
|
||||
product += (c.unicode() > 0xf ? QLatin1Char('1') : QLatin1Char('0')) +
|
||||
QLatin1Char("0123456789abcdef"[c.unicode() & 0xf]);
|
||||
} else {
|
||||
product += c;
|
||||
}
|
||||
|
|
|
@ -753,9 +753,8 @@ void Object::internalPut(String *name, const Value &value)
|
|||
|
||||
reject:
|
||||
if (engine()->current->strictMode) {
|
||||
QString message = QStringLiteral("Cannot assign to read-only property \"");
|
||||
message += name->toQString();
|
||||
message += QLatin1Char('\"');
|
||||
QString message = QStringLiteral("Cannot assign to read-only property \"") +
|
||||
name->toQString() + QLatin1Char('\"');
|
||||
engine()->throwTypeError(message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,26 +46,32 @@ QT_BEGIN_NAMESPACE
|
|||
namespace QV4 {
|
||||
namespace Profiling {
|
||||
|
||||
FunctionCallProperties FunctionCall::resolve() const
|
||||
FunctionLocation FunctionCall::resolveLocation() const
|
||||
{
|
||||
return FunctionLocation(m_function->name()->toQString(),
|
||||
m_function->compilationUnit->fileName(),
|
||||
m_function->compiledFunction->location.line,
|
||||
m_function->compiledFunction->location.column);
|
||||
}
|
||||
|
||||
FunctionCallProperties FunctionCall::properties() const
|
||||
{
|
||||
FunctionCallProperties props = {
|
||||
m_start,
|
||||
m_end,
|
||||
m_function->name()->toQString(),
|
||||
m_function->compilationUnit->fileName(),
|
||||
m_function->compiledFunction->location.line,
|
||||
m_function->compiledFunction->location.column
|
||||
reinterpret_cast<quintptr>(m_function)
|
||||
};
|
||||
return props;
|
||||
}
|
||||
|
||||
|
||||
Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(engine)
|
||||
{
|
||||
static int meta = qRegisterMetaType<QVector<QV4::Profiling::FunctionCallProperties> >();
|
||||
static int meta2 = qRegisterMetaType<QVector<QV4::Profiling::MemoryAllocationProperties> >();
|
||||
Q_UNUSED(meta);
|
||||
Q_UNUSED(meta2);
|
||||
static const int metatypes[] = {
|
||||
qRegisterMetaType<QVector<QV4::Profiling::FunctionCallProperties> >(),
|
||||
qRegisterMetaType<QVector<QV4::Profiling::MemoryAllocationProperties> >(),
|
||||
qRegisterMetaType<FunctionLocationHash>()
|
||||
};
|
||||
Q_UNUSED(metatypes);
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
|
@ -85,13 +91,18 @@ bool operator<(const FunctionCall &call1, const FunctionCall &call2)
|
|||
void Profiler::reportData()
|
||||
{
|
||||
std::sort(m_data.begin(), m_data.end());
|
||||
QVector<FunctionCallProperties> resolved;
|
||||
resolved.reserve(m_data.size());
|
||||
QVector<FunctionCallProperties> properties;
|
||||
FunctionLocationHash locations;
|
||||
properties.reserve(m_data.size());
|
||||
|
||||
foreach (const FunctionCall &call, m_data)
|
||||
resolved.append(call.resolve());
|
||||
foreach (const FunctionCall &call, m_data) {
|
||||
properties.append(call.properties());
|
||||
FunctionLocation &location = locations[properties.constLast().id];
|
||||
if (!location.isValid())
|
||||
location = call.resolveLocation();
|
||||
}
|
||||
|
||||
emit dataReady(resolved, m_memory_data);
|
||||
emit dataReady(locations, properties, m_memory_data);
|
||||
m_data.clear();
|
||||
m_memory_data.clear();
|
||||
}
|
||||
|
|
|
@ -77,12 +77,28 @@ enum MemoryType {
|
|||
struct FunctionCallProperties {
|
||||
qint64 start;
|
||||
qint64 end;
|
||||
quintptr id;
|
||||
};
|
||||
|
||||
struct FunctionLocation {
|
||||
FunctionLocation(const QString &name = QString(), const QString &file = QString(),
|
||||
int line = -1, int column = -1) :
|
||||
name(name), file(file), line(line), column(column)
|
||||
{}
|
||||
|
||||
bool isValid()
|
||||
{
|
||||
return !name.isEmpty();
|
||||
}
|
||||
|
||||
QString name;
|
||||
QString file;
|
||||
int line;
|
||||
int column;
|
||||
};
|
||||
|
||||
typedef QHash<quintptr, QV4::Profiling::FunctionLocation> FunctionLocationHash;
|
||||
|
||||
struct MemoryAllocationProperties {
|
||||
qint64 timestamp;
|
||||
qint64 size;
|
||||
|
@ -118,7 +134,8 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
FunctionCallProperties resolve() const;
|
||||
FunctionLocation resolveLocation() const;
|
||||
FunctionCallProperties properties() const;
|
||||
|
||||
private:
|
||||
friend bool operator<(const FunctionCall &call1, const FunctionCall &call2);
|
||||
|
@ -173,7 +190,8 @@ public slots:
|
|||
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
|
||||
|
||||
signals:
|
||||
void dataReady(const QVector<QV4::Profiling::FunctionCallProperties> &,
|
||||
void dataReady(const QV4::Profiling::FunctionLocationHash &,
|
||||
const QVector<QV4::Profiling::FunctionCallProperties> &,
|
||||
const QVector<QV4::Profiling::MemoryAllocationProperties> &);
|
||||
|
||||
private:
|
||||
|
@ -218,8 +236,10 @@ public:
|
|||
Q_DECLARE_TYPEINFO(QV4::Profiling::MemoryAllocationProperties, Q_MOVABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionLocation, Q_MOVABLE_TYPE);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
Q_DECLARE_METATYPE(QV4::Profiling::FunctionLocationHash)
|
||||
Q_DECLARE_METATYPE(QVector<QV4::Profiling::FunctionCallProperties>)
|
||||
Q_DECLARE_METATYPE(QVector<QV4::Profiling::MemoryAllocationProperties>)
|
||||
|
||||
|
|
|
@ -1285,6 +1285,8 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
|
|||
return 10;
|
||||
} else if (conversionType == QMetaType::QJsonObject) {
|
||||
return 5;
|
||||
} else if (conversionType == qMetaTypeId<QJSValue>()) {
|
||||
return 0;
|
||||
} else {
|
||||
return 10;
|
||||
}
|
||||
|
@ -1768,17 +1770,13 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) co
|
|||
QString result;
|
||||
if (const QMetaObject *metaObject = d()->metaObject()) {
|
||||
|
||||
result += QString::fromUtf8(metaObject->className());
|
||||
result += QLatin1String("(0x");
|
||||
result += QString::number((quintptr)d()->object.data(),16);
|
||||
result += QString::fromUtf8(metaObject->className()) +
|
||||
QLatin1String("(0x") + QString::number((quintptr)d()->object.data(),16);
|
||||
|
||||
if (d()->object) {
|
||||
QString objectName = d()->object->objectName();
|
||||
if (!objectName.isEmpty()) {
|
||||
result += QLatin1String(", \"");
|
||||
result += objectName;
|
||||
result += QLatin1Char('\"');
|
||||
}
|
||||
if (!objectName.isEmpty())
|
||||
result += QLatin1String(", \"") + objectName + QLatin1Char('\"');
|
||||
}
|
||||
|
||||
result += QLatin1Char(')');
|
||||
|
|
|
@ -185,8 +185,7 @@ QRegExp RegExpObject::toQRegExp() const
|
|||
|
||||
QString RegExpObject::toString() const
|
||||
{
|
||||
QString result = QLatin1Char('/') + source();
|
||||
result += QLatin1Char('/');
|
||||
QString result = QLatin1Char('/') + source() + QLatin1Char('/');
|
||||
if (global())
|
||||
result += QLatin1Char('g');
|
||||
if (value()->ignoreCase)
|
||||
|
|
|
@ -984,10 +984,9 @@ ReturnedValue Runtime::method_callQmlScopeObjectProperty(ExecutionEngine *engine
|
|||
Scope scope(engine);
|
||||
ScopedFunctionObject o(scope, method_getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex));
|
||||
if (!o) {
|
||||
QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow());
|
||||
QString error = QStringLiteral("Property '%1' of scope object is not a function").arg(propertyIndex);
|
||||
return engine->throwTypeError(error);
|
||||
}
|
||||
|
||||
return o->call(callData);
|
||||
}
|
||||
|
||||
|
@ -996,7 +995,7 @@ ReturnedValue Runtime::method_callQmlContextObjectProperty(ExecutionEngine *engi
|
|||
Scope scope(engine);
|
||||
ScopedFunctionObject o(scope, method_getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex));
|
||||
if (!o) {
|
||||
QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow());
|
||||
QString error = QStringLiteral("Property '%1' of context object is not a function").arg(propertyIndex);
|
||||
return engine->throwTypeError(error);
|
||||
}
|
||||
|
||||
|
@ -1623,6 +1622,351 @@ void Runtime::method_convertThisToObject(ExecutionEngine *engine)
|
|||
}
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_uPlus(const Value &value)
|
||||
{
|
||||
TRACE1(value);
|
||||
|
||||
if (value.isNumber())
|
||||
return value.asReturnedValue();
|
||||
if (value.integerCompatible())
|
||||
return Encode(value.int_32());
|
||||
|
||||
double n = value.toNumberImpl();
|
||||
return Encode(n);
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_uMinus(const Value &value)
|
||||
{
|
||||
TRACE1(value);
|
||||
|
||||
// +0 != -0, so we need to convert to double when negating 0
|
||||
if (value.isInteger() && value.integerValue())
|
||||
return Encode(-value.integerValue());
|
||||
else {
|
||||
double n = RuntimeHelpers::toNumber(value);
|
||||
return Encode(-n);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_complement(const Value &value)
|
||||
{
|
||||
TRACE1(value);
|
||||
|
||||
int n = value.toInt32();
|
||||
return Encode((int)~n);
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_uNot(const Value &value)
|
||||
{
|
||||
TRACE1(value);
|
||||
|
||||
bool b = value.toBoolean();
|
||||
return Encode(!b);
|
||||
}
|
||||
|
||||
// binary operators
|
||||
ReturnedValue Runtime::method_bitOr(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
int lval = left.toInt32();
|
||||
int rval = right.toInt32();
|
||||
return Encode(lval | rval);
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_bitXor(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
int lval = left.toInt32();
|
||||
int rval = right.toInt32();
|
||||
return Encode(lval ^ rval);
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_bitAnd(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
int lval = left.toInt32();
|
||||
int rval = right.toInt32();
|
||||
return Encode(lval & rval);
|
||||
}
|
||||
|
||||
#ifndef V4_BOOTSTRAP
|
||||
ReturnedValue Runtime::method_add(ExecutionEngine *engine, const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
if (Q_LIKELY(left.isInteger() && right.isInteger()))
|
||||
return add_int32(left.integerValue(), right.integerValue());
|
||||
if (left.isNumber() && right.isNumber())
|
||||
return Primitive::fromDouble(left.asDouble() + right.asDouble()).asReturnedValue();
|
||||
|
||||
return RuntimeHelpers::addHelper(engine, left, right);
|
||||
}
|
||||
#endif // V4_BOOTSTRAP
|
||||
|
||||
ReturnedValue Runtime::method_sub(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
if (Q_LIKELY(left.isInteger() && right.isInteger()))
|
||||
return sub_int32(left.integerValue(), right.integerValue());
|
||||
|
||||
double lval = left.isNumber() ? left.asDouble() : left.toNumberImpl();
|
||||
double rval = right.isNumber() ? right.asDouble() : right.toNumberImpl();
|
||||
|
||||
return Primitive::fromDouble(lval - rval).asReturnedValue();
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_mul(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
if (Q_LIKELY(left.isInteger() && right.isInteger()))
|
||||
return mul_int32(left.integerValue(), right.integerValue());
|
||||
|
||||
double lval = left.isNumber() ? left.asDouble() : left.toNumberImpl();
|
||||
double rval = right.isNumber() ? right.asDouble() : right.toNumberImpl();
|
||||
|
||||
return Primitive::fromDouble(lval * rval).asReturnedValue();
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_div(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
if (Value::integerCompatible(left, right)) {
|
||||
int lval = left.integerValue();
|
||||
int rval = right.integerValue();
|
||||
if (rval != 0 && (lval % rval == 0))
|
||||
return Encode(int(lval / rval));
|
||||
else
|
||||
return Encode(double(lval) / rval);
|
||||
}
|
||||
|
||||
double lval = left.toNumber();
|
||||
double rval = right.toNumber();
|
||||
return Primitive::fromDouble(lval / rval).asReturnedValue();
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_mod(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
if (Value::integerCompatible(left, right) && right.integerValue() != 0) {
|
||||
int intRes = left.integerValue() % right.integerValue();
|
||||
if (intRes != 0 || left.integerValue() >= 0)
|
||||
return Encode(intRes);
|
||||
}
|
||||
|
||||
double lval = RuntimeHelpers::toNumber(left);
|
||||
double rval = RuntimeHelpers::toNumber(right);
|
||||
#ifdef fmod
|
||||
# undef fmod
|
||||
#endif
|
||||
return Primitive::fromDouble(std::fmod(lval, rval)).asReturnedValue();
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_shl(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
int lval = left.toInt32();
|
||||
int rval = right.toInt32() & 0x1f;
|
||||
return Encode((int)(lval << rval));
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_shr(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
int lval = left.toInt32();
|
||||
unsigned rval = right.toUInt32() & 0x1f;
|
||||
return Encode((int)(lval >> rval));
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_ushr(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
unsigned lval = left.toUInt32();
|
||||
unsigned rval = right.toUInt32() & 0x1f;
|
||||
uint res = lval >> rval;
|
||||
|
||||
return Encode(res);
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_greaterThan(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = method_compareGreaterThan(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_lessThan(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = method_compareLessThan(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_greaterEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = method_compareGreaterEqual(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_lessEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = method_compareLessEqual(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
Bool Runtime::method_compareEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
if (left.rawValue() == right.rawValue())
|
||||
// NaN != NaN
|
||||
return !left.isNaN();
|
||||
|
||||
if (left.type() == right.type()) {
|
||||
if (!left.isManaged())
|
||||
return false;
|
||||
if (left.isString() == right.isString())
|
||||
return left.cast<Managed>()->isEqualTo(right.cast<Managed>());
|
||||
}
|
||||
|
||||
return RuntimeHelpers::equalHelper(left, right);
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_equal(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = method_compareEqual(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_notEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = !method_compareEqual(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_strictEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = RuntimeHelpers::strictEqual(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_strictNotEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = ! RuntimeHelpers::strictEqual(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
Bool Runtime::method_compareNotEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
return !Runtime::method_compareEqual(left, right);
|
||||
}
|
||||
|
||||
Bool Runtime::method_compareStrictEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
return RuntimeHelpers::strictEqual(left, right);
|
||||
}
|
||||
|
||||
Bool Runtime::method_compareStrictNotEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
return ! RuntimeHelpers::strictEqual(left, right);
|
||||
}
|
||||
|
||||
Bool Runtime::method_toBoolean(const Value &value)
|
||||
{
|
||||
return value.toBoolean();
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_accessQmlScopeObjectQRealProperty(const Value &context,
|
||||
QQmlAccessors *accessors)
|
||||
{
|
||||
#ifndef V4_BOOTSTRAP
|
||||
const QmlContext &c = static_cast<const QmlContext &>(context);
|
||||
qreal rv = 0;
|
||||
accessors->read(c.d()->qml->scopeObject, &rv);
|
||||
return QV4::Encode(rv);
|
||||
#else
|
||||
Q_UNUSED(context);
|
||||
Q_UNUSED(accessors);
|
||||
return QV4::Encode::undefined();
|
||||
#endif
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_accessQmlScopeObjectIntProperty(const Value &context,
|
||||
QQmlAccessors *accessors)
|
||||
{
|
||||
#ifndef V4_BOOTSTRAP
|
||||
const QmlContext &c = static_cast<const QmlContext &>(context);
|
||||
int rv = 0;
|
||||
accessors->read(c.d()->qml->scopeObject, &rv);
|
||||
return QV4::Encode(rv);
|
||||
#else
|
||||
Q_UNUSED(context);
|
||||
Q_UNUSED(accessors);
|
||||
return QV4::Encode::undefined();
|
||||
#endif
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_accessQmlScopeObjectBoolProperty(const Value &context,
|
||||
QQmlAccessors *accessors)
|
||||
{
|
||||
#ifndef V4_BOOTSTRAP
|
||||
const QmlContext &c = static_cast<const QmlContext &>(context);
|
||||
bool rv = false;
|
||||
accessors->read(c.d()->qml->scopeObject, &rv);
|
||||
return QV4::Encode(rv);
|
||||
#else
|
||||
Q_UNUSED(context);
|
||||
Q_UNUSED(accessors);
|
||||
return QV4::Encode::undefined();
|
||||
#endif
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_accessQmlScopeObjectQStringProperty(ExecutionEngine *engine,
|
||||
const Value &context,
|
||||
QQmlAccessors *accessors)
|
||||
{
|
||||
#ifndef V4_BOOTSTRAP
|
||||
const QmlContext &c = static_cast<const QmlContext &>(context);
|
||||
QString rv;
|
||||
accessors->read(c.d()->qml->scopeObject, &rv);
|
||||
return QV4::Encode(engine->newString(rv));
|
||||
#else
|
||||
Q_UNUSED(engine);
|
||||
Q_UNUSED(context);
|
||||
Q_UNUSED(accessors);
|
||||
return QV4::Encode::undefined();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // V4_BOOTSTRAP
|
||||
|
||||
} // namespace QV4
|
||||
|
|
|
@ -140,349 +140,6 @@ inline double RuntimeHelpers::toNumber(const Value &value)
|
|||
{
|
||||
return value.toNumber();
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_uPlus(const Value &value)
|
||||
{
|
||||
TRACE1(value);
|
||||
|
||||
if (value.isNumber())
|
||||
return value.asReturnedValue();
|
||||
if (value.integerCompatible())
|
||||
return Encode(value.int_32());
|
||||
|
||||
double n = value.toNumberImpl();
|
||||
return Encode(n);
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_uMinus(const Value &value)
|
||||
{
|
||||
TRACE1(value);
|
||||
|
||||
// +0 != -0, so we need to convert to double when negating 0
|
||||
if (value.isInteger() && value.integerValue())
|
||||
return Encode(-value.integerValue());
|
||||
else {
|
||||
double n = RuntimeHelpers::toNumber(value);
|
||||
return Encode(-n);
|
||||
}
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_complement(const Value &value)
|
||||
{
|
||||
TRACE1(value);
|
||||
|
||||
int n = value.toInt32();
|
||||
return Encode((int)~n);
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_uNot(const Value &value)
|
||||
{
|
||||
TRACE1(value);
|
||||
|
||||
bool b = value.toBoolean();
|
||||
return Encode(!b);
|
||||
}
|
||||
|
||||
// binary operators
|
||||
inline ReturnedValue Runtime::method_bitOr(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
int lval = left.toInt32();
|
||||
int rval = right.toInt32();
|
||||
return Encode(lval | rval);
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_bitXor(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
int lval = left.toInt32();
|
||||
int rval = right.toInt32();
|
||||
return Encode(lval ^ rval);
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_bitAnd(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
int lval = left.toInt32();
|
||||
int rval = right.toInt32();
|
||||
return Encode(lval & rval);
|
||||
}
|
||||
|
||||
#ifndef V4_BOOTSTRAP
|
||||
inline ReturnedValue Runtime::method_add(ExecutionEngine *engine, const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
if (Q_LIKELY(left.isInteger() && right.isInteger()))
|
||||
return add_int32(left.integerValue(), right.integerValue());
|
||||
if (left.isNumber() && right.isNumber())
|
||||
return Primitive::fromDouble(left.asDouble() + right.asDouble()).asReturnedValue();
|
||||
|
||||
return RuntimeHelpers::addHelper(engine, left, right);
|
||||
}
|
||||
#endif // V4_BOOTSTRAP
|
||||
|
||||
inline ReturnedValue Runtime::method_sub(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
if (Q_LIKELY(left.isInteger() && right.isInteger()))
|
||||
return sub_int32(left.integerValue(), right.integerValue());
|
||||
|
||||
double lval = left.isNumber() ? left.asDouble() : left.toNumberImpl();
|
||||
double rval = right.isNumber() ? right.asDouble() : right.toNumberImpl();
|
||||
|
||||
return Primitive::fromDouble(lval - rval).asReturnedValue();
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_mul(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
if (Q_LIKELY(left.isInteger() && right.isInteger()))
|
||||
return mul_int32(left.integerValue(), right.integerValue());
|
||||
|
||||
double lval = left.isNumber() ? left.asDouble() : left.toNumberImpl();
|
||||
double rval = right.isNumber() ? right.asDouble() : right.toNumberImpl();
|
||||
|
||||
return Primitive::fromDouble(lval * rval).asReturnedValue();
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_div(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
if (Value::integerCompatible(left, right)) {
|
||||
int lval = left.integerValue();
|
||||
int rval = right.integerValue();
|
||||
if (rval != 0 && (lval % rval == 0))
|
||||
return Encode(int(lval / rval));
|
||||
else
|
||||
return Encode(double(lval) / rval);
|
||||
}
|
||||
|
||||
double lval = left.toNumber();
|
||||
double rval = right.toNumber();
|
||||
return Primitive::fromDouble(lval / rval).asReturnedValue();
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_mod(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
if (Value::integerCompatible(left, right) && right.integerValue() != 0) {
|
||||
int intRes = left.integerValue() % right.integerValue();
|
||||
if (intRes != 0 || left.integerValue() >= 0)
|
||||
return Encode(intRes);
|
||||
}
|
||||
|
||||
double lval = RuntimeHelpers::toNumber(left);
|
||||
double rval = RuntimeHelpers::toNumber(right);
|
||||
return Primitive::fromDouble(std::fmod(lval, rval)).asReturnedValue();
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_shl(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
int lval = left.toInt32();
|
||||
int rval = right.toInt32() & 0x1f;
|
||||
return Encode((int)(lval << rval));
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_shr(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
int lval = left.toInt32();
|
||||
unsigned rval = right.toUInt32() & 0x1f;
|
||||
return Encode((int)(lval >> rval));
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_ushr(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
unsigned lval = left.toUInt32();
|
||||
unsigned rval = right.toUInt32() & 0x1f;
|
||||
uint res = lval >> rval;
|
||||
|
||||
return Encode(res);
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_greaterThan(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = method_compareGreaterThan(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_lessThan(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = method_compareLessThan(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_greaterEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = method_compareGreaterEqual(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_lessEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = method_compareLessEqual(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
inline Bool Runtime::method_compareEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
if (left.rawValue() == right.rawValue())
|
||||
// NaN != NaN
|
||||
return !left.isNaN();
|
||||
|
||||
if (left.type() == right.type()) {
|
||||
if (!left.isManaged())
|
||||
return false;
|
||||
if (left.isString() == right.isString())
|
||||
return left.cast<Managed>()->isEqualTo(right.cast<Managed>());
|
||||
}
|
||||
|
||||
return RuntimeHelpers::equalHelper(left, right);
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_equal(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = method_compareEqual(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_notEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = !method_compareEqual(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_strictEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = RuntimeHelpers::strictEqual(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_strictNotEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
bool r = ! RuntimeHelpers::strictEqual(left, right);
|
||||
return Encode(r);
|
||||
}
|
||||
|
||||
inline Bool Runtime::method_compareNotEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
return !Runtime::method_compareEqual(left, right);
|
||||
}
|
||||
|
||||
inline Bool Runtime::method_compareStrictEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
return RuntimeHelpers::strictEqual(left, right);
|
||||
}
|
||||
|
||||
inline Bool Runtime::method_compareStrictNotEqual(const Value &left, const Value &right)
|
||||
{
|
||||
TRACE2(left, right);
|
||||
|
||||
return ! RuntimeHelpers::strictEqual(left, right);
|
||||
}
|
||||
|
||||
inline Bool Runtime::method_toBoolean(const Value &value)
|
||||
{
|
||||
return value.toBoolean();
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_accessQmlScopeObjectQRealProperty(const Value &context,
|
||||
QQmlAccessors *accessors)
|
||||
{
|
||||
#ifndef V4_BOOTSTRAP
|
||||
const QmlContext &c = static_cast<const QmlContext &>(context);
|
||||
qreal rv = 0;
|
||||
accessors->read(c.d()->qml->scopeObject, &rv);
|
||||
return QV4::Encode(rv);
|
||||
#else
|
||||
Q_UNUSED(context);
|
||||
Q_UNUSED(accessors);
|
||||
return QV4::Encode::undefined();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_accessQmlScopeObjectIntProperty(const Value &context,
|
||||
QQmlAccessors *accessors)
|
||||
{
|
||||
#ifndef V4_BOOTSTRAP
|
||||
const QmlContext &c = static_cast<const QmlContext &>(context);
|
||||
int rv = 0;
|
||||
accessors->read(c.d()->qml->scopeObject, &rv);
|
||||
return QV4::Encode(rv);
|
||||
#else
|
||||
Q_UNUSED(context);
|
||||
Q_UNUSED(accessors);
|
||||
return QV4::Encode::undefined();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_accessQmlScopeObjectBoolProperty(const Value &context,
|
||||
QQmlAccessors *accessors)
|
||||
{
|
||||
#ifndef V4_BOOTSTRAP
|
||||
const QmlContext &c = static_cast<const QmlContext &>(context);
|
||||
bool rv = false;
|
||||
accessors->read(c.d()->qml->scopeObject, &rv);
|
||||
return QV4::Encode(rv);
|
||||
#else
|
||||
Q_UNUSED(context);
|
||||
Q_UNUSED(accessors);
|
||||
return QV4::Encode::undefined();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline ReturnedValue Runtime::method_accessQmlScopeObjectQStringProperty(ExecutionEngine *engine,
|
||||
const Value &context,
|
||||
QQmlAccessors *accessors)
|
||||
{
|
||||
#ifndef V4_BOOTSTRAP
|
||||
const QmlContext &c = static_cast<const QmlContext &>(context);
|
||||
QString rv;
|
||||
accessors->read(c.d()->qml->scopeObject, &rv);
|
||||
return QV4::Encode(engine->newString(rv));
|
||||
#else
|
||||
Q_UNUSED(engine);
|
||||
Q_UNUSED(context);
|
||||
Q_UNUSED(accessors);
|
||||
return QV4::Encode::undefined();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace QV4
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
@ -75,6 +75,9 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description
|
|||
|
||||
// F(elementType, elementTypeName, sequenceType, defaultValue)
|
||||
#define FOREACH_QML_SEQUENCE_TYPE(F) \
|
||||
F(int, IntVector, QVector<int>, 0) \
|
||||
F(qreal, RealVector, QVector<qreal>, 0.0) \
|
||||
F(bool, BoolVector, QVector<bool>, false) \
|
||||
F(int, Int, QList<int>, 0) \
|
||||
F(qreal, Real, QList<qreal>, 0.0) \
|
||||
F(bool, Bool, QList<bool>, false) \
|
||||
|
@ -578,6 +581,15 @@ Heap::QQmlSequence<Container>::QQmlSequence(QObject *object, int propertyIndex)
|
|||
|
||||
namespace QV4 {
|
||||
|
||||
typedef QQmlSequence<QVector<int> > QQmlIntVectorList;
|
||||
template<>
|
||||
DEFINE_OBJECT_VTABLE(QQmlIntVectorList);
|
||||
typedef QQmlSequence<QVector<qreal> > QQmlRealVectorList;
|
||||
template<>
|
||||
DEFINE_OBJECT_VTABLE(QQmlRealVectorList);
|
||||
typedef QQmlSequence<QVector<bool> > QQmlBoolVectorList;
|
||||
template<>
|
||||
DEFINE_OBJECT_VTABLE(QQmlBoolVectorList);
|
||||
typedef QQmlSequence<QStringList> QQmlQStringList;
|
||||
template<>
|
||||
DEFINE_OBJECT_VTABLE(QQmlQStringList);
|
||||
|
|
|
@ -46,12 +46,19 @@
|
|||
#include "qv4stringobject_p.h"
|
||||
#endif
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/private/qnumeric_p.h>
|
||||
|
||||
using namespace QV4;
|
||||
|
||||
static uint toArrayIndex(const QChar *ch, const QChar *end)
|
||||
static inline uint toUInt(const QChar *ch) { return ch->unicode(); }
|
||||
#ifndef V4_BOOTSTRAP
|
||||
static inline uint toUInt(const char *ch) { return *ch; }
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
static inline uint toArrayIndex(const T *ch, const T *end)
|
||||
{
|
||||
uint i = ch->unicode() - '0';
|
||||
uint i = toUInt(ch) - '0';
|
||||
if (i > 9)
|
||||
return UINT_MAX;
|
||||
++ch;
|
||||
|
@ -60,14 +67,11 @@ static uint toArrayIndex(const QChar *ch, const QChar *end)
|
|||
return UINT_MAX;
|
||||
|
||||
while (ch < end) {
|
||||
uint x = ch->unicode() - '0';
|
||||
uint x = toUInt(ch) - '0';
|
||||
if (x > 9)
|
||||
return UINT_MAX;
|
||||
uint n = i*10 + x;
|
||||
if (n < i)
|
||||
// overflow
|
||||
if (mul_overflow(i, uint(10), &i) || add_overflow(i, x, &i))
|
||||
return UINT_MAX;
|
||||
i = n;
|
||||
++ch;
|
||||
}
|
||||
return i;
|
||||
|
@ -75,30 +79,26 @@ static uint toArrayIndex(const QChar *ch, const QChar *end)
|
|||
|
||||
#ifndef V4_BOOTSTRAP
|
||||
|
||||
static uint toArrayIndex(const char *ch, const char *end)
|
||||
template <typename T>
|
||||
static inline uint calculateHashValue(const T *ch, const T* end, uint *subtype)
|
||||
{
|
||||
uint i = *ch - '0';
|
||||
if (i > 9)
|
||||
return UINT_MAX;
|
||||
++ch;
|
||||
// reject "01", "001", ...
|
||||
if (i == 0 && ch != end)
|
||||
return UINT_MAX;
|
||||
// array indices get their number as hash value
|
||||
uint h = ::toArrayIndex(ch, end);
|
||||
if (h != UINT_MAX) {
|
||||
if (subtype)
|
||||
*subtype = Heap::String::StringType_ArrayIndex;
|
||||
return h;
|
||||
}
|
||||
|
||||
while (ch < end) {
|
||||
uint x = *ch - '0';
|
||||
if (x > 9)
|
||||
return UINT_MAX;
|
||||
uint n = i*10 + x;
|
||||
if (n < i)
|
||||
// overflow
|
||||
return UINT_MAX;
|
||||
i = n;
|
||||
h = 31 * h + toUInt(ch);
|
||||
++ch;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
if (subtype)
|
||||
*subtype = Heap::String::StringType_Regular;
|
||||
return h;
|
||||
}
|
||||
|
||||
DEFINE_MANAGED_VTABLE(String);
|
||||
|
||||
|
@ -198,31 +198,6 @@ void Heap::String::simplifyString() const
|
|||
mm->growUnmanagedHeapSizeUsage(size_t(text->size) * sizeof(QChar));
|
||||
}
|
||||
|
||||
void Heap::String::createHashValue() const
|
||||
{
|
||||
if (largestSubLength)
|
||||
simplifyString();
|
||||
Q_ASSERT(!largestSubLength);
|
||||
const QChar *ch = reinterpret_cast<const QChar *>(text->data());
|
||||
const QChar *end = ch + text->size;
|
||||
|
||||
// array indices get their number as hash value
|
||||
stringHash = ::toArrayIndex(ch, end);
|
||||
if (stringHash != UINT_MAX) {
|
||||
subtype = Heap::String::StringType_ArrayIndex;
|
||||
return;
|
||||
}
|
||||
|
||||
uint h = 0xffffffff;
|
||||
while (ch < end) {
|
||||
h = 31 * h + ch->unicode();
|
||||
++ch;
|
||||
}
|
||||
|
||||
stringHash = h;
|
||||
subtype = Heap::String::StringType_Regular;
|
||||
}
|
||||
|
||||
void Heap::String::append(const String *data, QChar *ch)
|
||||
{
|
||||
std::vector<const String *> worklist;
|
||||
|
@ -243,45 +218,26 @@ void Heap::String::append(const String *data, QChar *ch)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
uint String::createHashValue(const QChar *ch, int length)
|
||||
void Heap::String::createHashValue() const
|
||||
{
|
||||
const QChar *end = ch + length;
|
||||
|
||||
// array indices get their number as hash value
|
||||
uint stringHash = ::toArrayIndex(ch, end);
|
||||
if (stringHash != UINT_MAX)
|
||||
return stringHash;
|
||||
|
||||
uint h = 0xffffffff;
|
||||
while (ch < end) {
|
||||
h = 31 * h + ch->unicode();
|
||||
++ch;
|
||||
}
|
||||
|
||||
return h;
|
||||
if (largestSubLength)
|
||||
simplifyString();
|
||||
Q_ASSERT(!largestSubLength);
|
||||
const QChar *ch = reinterpret_cast<const QChar *>(text->data());
|
||||
const QChar *end = ch + text->size;
|
||||
stringHash = calculateHashValue(ch, end, &subtype);
|
||||
}
|
||||
|
||||
uint String::createHashValue(const char *ch, int length)
|
||||
uint String::createHashValue(const QChar *ch, int length, uint *subtype)
|
||||
{
|
||||
const QChar *end = ch + length;
|
||||
return calculateHashValue(ch, end, subtype);
|
||||
}
|
||||
|
||||
uint String::createHashValue(const char *ch, int length, uint *subtype)
|
||||
{
|
||||
const char *end = ch + length;
|
||||
|
||||
// array indices get their number as hash value
|
||||
uint stringHash = ::toArrayIndex(ch, end);
|
||||
if (stringHash != UINT_MAX)
|
||||
return stringHash;
|
||||
|
||||
uint h = 0xffffffff;
|
||||
while (ch < end) {
|
||||
if ((uchar)(*ch) >= 0x80)
|
||||
return UINT_MAX;
|
||||
h = 31 * h + *ch;
|
||||
++ch;
|
||||
}
|
||||
|
||||
return h;
|
||||
return calculateHashValue(ch, end, subtype);
|
||||
}
|
||||
|
||||
uint String::getLength(const Managed *m)
|
||||
|
|
|
@ -183,8 +183,8 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed {
|
|||
|
||||
void makeIdentifierImpl(ExecutionEngine *e) const;
|
||||
|
||||
static uint createHashValue(const QChar *ch, int length);
|
||||
static uint createHashValue(const char *ch, int length);
|
||||
static uint createHashValue(const QChar *ch, int length, uint *subtype);
|
||||
static uint createHashValue(const char *ch, int length, uint *subtype);
|
||||
|
||||
bool startsWithUpper() const {
|
||||
const String::Data *l = d();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -41,12 +41,12 @@
|
|||
|
||||
inline quint32 stringHash(const QChar* data, int length)
|
||||
{
|
||||
return QV4::String::createHashValue(data, length);
|
||||
return QV4::String::createHashValue(data, length, Q_NULLPTR);
|
||||
}
|
||||
|
||||
inline quint32 stringHash(const char *data, int length)
|
||||
{
|
||||
return QV4::String::createHashValue(data, length);
|
||||
return QV4::String::createHashValue(data, length, Q_NULLPTR);
|
||||
}
|
||||
|
||||
void QHashedString::computeHash() const
|
||||
|
|
|
@ -168,7 +168,7 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
|
|||
return;
|
||||
}
|
||||
|
||||
QQmlBindingProfiler prof(ep->profiler, f);
|
||||
QQmlBindingProfiler prof(ep->profiler, this, f);
|
||||
setUpdatingFlag(true);
|
||||
|
||||
QQmlJavaScriptExpression::DeleteWatcher watcher(this);
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
|
||||
#include <private/qv4value_p.h>
|
||||
|
||||
#include <QtCore/qstringbuilder.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
|
||||
|
||||
|
@ -81,9 +80,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
|
|||
// Add some leading whitespace to account for the binding's column offset.
|
||||
// It's 2 off because a, we start counting at 1 and b, the '(' below is not counted.
|
||||
function.fill(QChar(QChar::Space), qMax(column, (quint16)2) - 2);
|
||||
function += QStringLiteral("(function ");
|
||||
function += handlerName;
|
||||
function += QLatin1Char('(');
|
||||
function += QStringLiteral("(function ") + handlerName + QLatin1Char('(');
|
||||
|
||||
if (parameterString.isEmpty()) {
|
||||
QString error;
|
||||
|
@ -99,10 +96,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
|
|||
} else
|
||||
function += parameterString;
|
||||
|
||||
function += QStringLiteral(") { ");
|
||||
function += expression;
|
||||
function += QStringLiteral(" })");
|
||||
|
||||
function += QStringLiteral(") { ") + expression + QStringLiteral(" })");
|
||||
m_function.set(v4, evalFunction(context(), scopeObject(), function, fileName, line));
|
||||
|
||||
if (m_function.isNullOrUndefined())
|
||||
|
|
|
@ -89,8 +89,6 @@ public:
|
|||
|
||||
QQmlEngine *engine;
|
||||
|
||||
QString fileName() const { return compilationUnit->fileName(); }
|
||||
QUrl url() const { return compilationUnit->url(); }
|
||||
QQmlTypeNameCache *importCache;
|
||||
|
||||
int metaTypeId;
|
||||
|
|
|
@ -570,7 +570,7 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, QQmlCompiledData *cc, int start
|
|||
d->cc = cc;
|
||||
cc->addref();
|
||||
d->start = start;
|
||||
d->url = cc->url();
|
||||
d->url = cc->compilationUnit->url();
|
||||
d->progress = 1.0;
|
||||
}
|
||||
|
||||
|
|
|
@ -293,7 +293,7 @@ inline void QQmlEnginePrivate::dereferenceScarceResources()
|
|||
// if the refcount is zero, then evaluation of the "top level"
|
||||
// expression must have completed. We can safely release the
|
||||
// scarce resources.
|
||||
if (scarceResourcesRefCount == 0) {
|
||||
if (Q_LIKELY(scarceResourcesRefCount == 0)) {
|
||||
QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine());
|
||||
if (Q_UNLIKELY(!engine->scarceResources.isEmpty())) {
|
||||
cleanupScarceResources();
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qfile.h>
|
||||
#include <QtCore/qstringlist.h>
|
||||
#include <QtCore/qvector.h>
|
||||
|
||||
#include <private/qv4errorobject_p.h>
|
||||
|
||||
|
@ -288,11 +289,11 @@ QDebug operator<<(QDebug debug, const QQmlError &error)
|
|||
stream.setCodec("UTF-8");
|
||||
#endif
|
||||
const QString code = stream.readAll();
|
||||
const QStringList lines = code.split(QLatin1Char('\n'));
|
||||
const auto lines = code.splitRef(QLatin1Char('\n'));
|
||||
|
||||
if (lines.count() >= error.line()) {
|
||||
const QString &line = lines.at(error.line() - 1);
|
||||
debug << "\n " << qPrintable(line);
|
||||
const QStringRef &line = lines.at(error.line() - 1);
|
||||
debug << "\n " << line.toLocal8Bit().constData();
|
||||
|
||||
if(error.column() > 0) {
|
||||
int column = qMax(0, error.column() - 1);
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
|
||||
Q_DECLARE_INTERFACE(QQmlTypesExtensionInterface, "org.qt-project.Qt.QQmlTypesExtensionInterface/1.0")
|
||||
|
||||
#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface"
|
||||
#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface/1.0"
|
||||
|
||||
Q_DECLARE_INTERFACE(QQmlExtensionInterface, QQmlExtensionInterface_iid)
|
||||
|
||||
|
|
|
@ -605,7 +605,7 @@ QString QQmlFile::urlToLocalFileOrQrc(const QString& url)
|
|||
{
|
||||
if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
|
||||
if (url.length() > 4)
|
||||
return QLatin1Char(':') + url.mid(4);
|
||||
return QLatin1Char(':') + url.midRef(4);
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
|
|
@ -85,12 +85,11 @@ QString resolveLocalUrl(const QString &url, const QString &relative)
|
|||
} else if (relative.at(0) == Slash || !url.contains(Slash)) {
|
||||
return relative;
|
||||
} else {
|
||||
QString base(url.left(url.lastIndexOf(Slash) + 1));
|
||||
|
||||
const QStringRef baseRef = url.leftRef(url.lastIndexOf(Slash) + 1);
|
||||
if (relative == QLatin1String("."))
|
||||
return base;
|
||||
return baseRef.toString();
|
||||
|
||||
base.append(relative);
|
||||
QString base = baseRef + relative;
|
||||
|
||||
// Remove any relative directory elements in the path
|
||||
int length = base.length();
|
||||
|
@ -192,7 +191,7 @@ void qmlClearEnginePlugins()
|
|||
{
|
||||
StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
|
||||
QMutexLocker lock(&plugins->mutex);
|
||||
foreach (RegisteredPlugin plugin, plugins->values()) {
|
||||
for (auto &plugin : qAsConst(*plugins)) {
|
||||
QPluginLoader* loader = plugin.loader;
|
||||
if (loader && !loader->unload())
|
||||
qWarning("Unloading %s failed: %s", qPrintable(plugin.uri), qPrintable(loader->errorString()));
|
||||
|
@ -303,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
|
||||
};
|
||||
|
@ -483,20 +482,58 @@ QList<QQmlImports::ScriptReference> QQmlImports::resolvedScripts() const
|
|||
return scripts;
|
||||
}
|
||||
|
||||
/*!
|
||||
Form a complete path to a qmldir file, from a base URL, a module URI and version specification.
|
||||
*/
|
||||
QString QQmlImports::completeQmldirPath(const QString &uri, const QString &base, int vmaj, int vmin,
|
||||
ImportVersion version)
|
||||
static QString joinStringRefs(const QVector<QStringRef> &refs, const QChar &sep)
|
||||
{
|
||||
QString url = uri;
|
||||
url.replace(Dot, Slash);
|
||||
QString str;
|
||||
for (auto it = refs.cbegin(); it != refs.cend(); ++it) {
|
||||
if (it != refs.cbegin())
|
||||
str += sep;
|
||||
str += *it;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
QString dir = base;
|
||||
if (!dir.endsWith(Slash) && !dir.endsWith(Backslash))
|
||||
dir += Slash;
|
||||
/*!
|
||||
Forms complete paths to a qmldir file, from a base URL, a module URI and version specification.
|
||||
|
||||
return dir + url + versionString(vmaj, vmin, version) + Slash_qmldir;
|
||||
For example, QtQml.Models 2.0:
|
||||
- base/QtQml/Models.2.0/qmldir
|
||||
- base/QtQml.2.0/Models/qmldir
|
||||
- base/QtQml/Models.2/qmldir
|
||||
- base/QtQml.2/Models/qmldir
|
||||
- base/QtQml/Models/qmldir
|
||||
*/
|
||||
QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin)
|
||||
{
|
||||
const QVector<QStringRef> parts = uri.splitRef(Dot, QString::SkipEmptyParts);
|
||||
|
||||
QStringList qmlDirPathsPaths;
|
||||
// fully & partially versioned parts + 1 unversioned for each base path
|
||||
qmlDirPathsPaths.reserve(basePaths.count() * (2 * parts.count() + 1));
|
||||
|
||||
for (int version = FullyVersioned; version <= Unversioned; ++version) {
|
||||
const QString ver = versionString(vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version));
|
||||
|
||||
for (const QString &path : basePaths) {
|
||||
QString dir = path;
|
||||
if (!dir.endsWith(Slash) && !dir.endsWith(Backslash))
|
||||
dir += Slash;
|
||||
|
||||
// append to the end
|
||||
qmlDirPathsPaths += dir + joinStringRefs(parts, Slash) + ver + Slash_qmldir;
|
||||
|
||||
if (version != Unversioned) {
|
||||
// insert in the middle
|
||||
for (int index = parts.count() - 2; index >= 0; --index) {
|
||||
qmlDirPathsPaths += dir + joinStringRefs(parts.mid(0, index + 1), Slash)
|
||||
+ ver + Slash
|
||||
+ joinStringRefs(parts.mid(index + 1), Slash) + Slash_qmldir;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return qmlDirPathsPaths;
|
||||
}
|
||||
|
||||
QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version)
|
||||
|
@ -777,11 +814,11 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS
|
|||
QString u1 = import->url;
|
||||
QString u2 = import2->url;
|
||||
if (base) {
|
||||
QString b = *base;
|
||||
QStringRef b(base);
|
||||
int dot = b.lastIndexOf(Dot);
|
||||
if (dot >= 0) {
|
||||
b = b.left(dot+1);
|
||||
QString l = b.left(dot);
|
||||
QStringRef l = b.left(dot);
|
||||
if (u1.startsWith(b))
|
||||
u1 = u1.mid(b.count());
|
||||
else if (u1 == l)
|
||||
|
@ -841,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;
|
||||
|
@ -856,8 +913,8 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res
|
|||
// To avoid traversing all static plugins for all imports, we cut down
|
||||
// the list the first time called to only contain QML plugins:
|
||||
foreach (const QStaticPlugin &plugin, QPluginLoader::staticPlugins()) {
|
||||
if (qobject_cast<QQmlExtensionPlugin *>(plugin.instance()))
|
||||
plugins.append(plugin);
|
||||
if (plugin.metaData().value(QStringLiteral("IID")).toString() == QLatin1String(QQmlExtensionInterface_iid))
|
||||
plugins.append(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -877,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;
|
||||
}
|
||||
|
@ -970,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()) {
|
||||
|
@ -998,6 +1054,8 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (staticPluginsFound > 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1130,32 +1188,29 @@ bool QQmlImportsPrivate::locateQmldir(const QString &uri, int vmaj, int vmin, QQ
|
|||
QStringList localImportPaths = database->importPathList(QQmlImportDatabase::Local);
|
||||
|
||||
// Search local import paths for a matching version
|
||||
for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) {
|
||||
foreach (const QString &path, localImportPaths) {
|
||||
QString qmldirPath = QQmlImports::completeQmldirPath(uri, path, vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version));
|
||||
const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(uri, localImportPaths, vmaj, vmin);
|
||||
for (const QString &qmldirPath : qmlDirPaths) {
|
||||
QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath);
|
||||
if (!absoluteFilePath.isEmpty()) {
|
||||
QString url;
|
||||
const QStringRef absolutePath = absoluteFilePath.leftRef(absoluteFilePath.lastIndexOf(Slash) + 1);
|
||||
if (absolutePath.at(0) == Colon)
|
||||
url = QLatin1String("qrc://") + absolutePath.mid(1);
|
||||
else
|
||||
url = QUrl::fromLocalFile(absolutePath.toString()).toString();
|
||||
|
||||
QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath);
|
||||
if (!absoluteFilePath.isEmpty()) {
|
||||
QString url;
|
||||
QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(Slash)+1);
|
||||
if (absolutePath.at(0) == Colon)
|
||||
url = QLatin1String("qrc://") + absolutePath.mid(1);
|
||||
else
|
||||
url = QUrl::fromLocalFile(absolutePath).toString();
|
||||
QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache;
|
||||
cache->versionMajor = vmaj;
|
||||
cache->versionMinor = vmin;
|
||||
cache->qmldirFilePath = absoluteFilePath;
|
||||
cache->qmldirPathUrl = url;
|
||||
cache->next = cacheHead;
|
||||
database->qmldirCache.insert(uri, cache);
|
||||
|
||||
QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache;
|
||||
cache->versionMajor = vmaj;
|
||||
cache->versionMinor = vmin;
|
||||
cache->qmldirFilePath = absoluteFilePath;
|
||||
cache->qmldirPathUrl = url;
|
||||
cache->next = cacheHead;
|
||||
database->qmldirCache.insert(uri, cache);
|
||||
*outQmldirFilePath = absoluteFilePath;
|
||||
*outQmldirPathUrl = url;
|
||||
|
||||
*outQmldirFilePath = absoluteFilePath;
|
||||
*outQmldirPathUrl = url;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1647,10 +1702,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
|
|||
resolvedPath += Slash;
|
||||
|
||||
foreach (const QString &suffix, suffixes) {
|
||||
QString pluginFileName = prefix;
|
||||
|
||||
pluginFileName += baseName;
|
||||
pluginFileName += suffix;
|
||||
QString pluginFileName = prefix + baseName + suffix;
|
||||
|
||||
QString absolutePath = typeLoader->absoluteFilePath(resolvedPath + pluginFileName);
|
||||
if (!absolutePath.isEmpty())
|
||||
|
|
|
@ -130,8 +130,7 @@ public:
|
|||
|
||||
QList<CompositeSingletonReference> resolvedCompositeSingletons() const;
|
||||
|
||||
static QString completeQmldirPath(const QString &uri, const QString &base, int vmaj, int vmin,
|
||||
QQmlImports::ImportVersion version);
|
||||
static QStringList completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin);
|
||||
static QString versionString(int vmaj, int vmin, ImportVersion version);
|
||||
|
||||
static bool isLocal(const QString &url);
|
||||
|
|
|
@ -281,7 +281,7 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
|
|||
if (!compiledData)
|
||||
return;
|
||||
|
||||
QML_MEMORY_SCOPE_URL(compiledData->url());
|
||||
QML_MEMORY_SCOPE_URL(compiledData->compilationUnit->url());
|
||||
|
||||
QExplicitlySharedDataPointer<QQmlIncubatorPrivate> protectThis(this);
|
||||
|
||||
|
@ -292,7 +292,7 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
|
|||
|
||||
if (!vmeGuard.isOK()) {
|
||||
QQmlError error;
|
||||
error.setUrl(compiledData->url());
|
||||
error.setUrl(compiledData->compilationUnit->url());
|
||||
error.setDescription(QQmlComponent::tr("Object destroyed during incubation"));
|
||||
errors << error;
|
||||
progress = QQmlIncubatorPrivate::Completed;
|
||||
|
|
|
@ -1914,14 +1914,11 @@ QList<QQmlType*> QQmlMetaType::qmlSingletonTypes()
|
|||
QMutexLocker lock(metaTypeDataLock());
|
||||
QQmlMetaTypeData *data = metaTypeData();
|
||||
|
||||
QList<QQmlType*> alltypes = data->nameToType.values();
|
||||
QList<QQmlType*> retn;
|
||||
foreach (QQmlType* t, alltypes) {
|
||||
if (t->isSingleton()) {
|
||||
retn.append(t);
|
||||
}
|
||||
for (const auto type : qAsConst(data->nameToType)) {
|
||||
if (type->isSingleton())
|
||||
retn.append(type);
|
||||
}
|
||||
|
||||
return retn;
|
||||
}
|
||||
|
||||
|
@ -1929,9 +1926,9 @@ const QQmlPrivate::CachedQmlUnit *QQmlMetaType::findCachedCompilationUnit(const
|
|||
{
|
||||
QMutexLocker lock(metaTypeDataLock());
|
||||
QQmlMetaTypeData *data = metaTypeData();
|
||||
for (QVector<QQmlPrivate::QmlUnitCacheLookupFunction>::ConstIterator it = data->lookupCachedQmlUnit.constBegin(), end = data->lookupCachedQmlUnit.constEnd();
|
||||
it != end; ++it) {
|
||||
if (const QQmlPrivate::CachedQmlUnit *unit = (*it)(uri))
|
||||
|
||||
for (const auto lookup : qAsConst(data->lookupCachedQmlUnit)) {
|
||||
if (const QQmlPrivate::CachedQmlUnit *unit = lookup(uri))
|
||||
return unit;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1961,8 +1958,7 @@ QString QQmlMetaType::prettyTypeName(const QObject *object)
|
|||
|
||||
marker = typeName.indexOf(QLatin1String("_QML_"));
|
||||
if (marker != -1) {
|
||||
typeName = typeName.left(marker);
|
||||
typeName += QLatin1Char('*');
|
||||
typeName = typeName.left(marker) + QLatin1Char('*');
|
||||
type = QQmlMetaType::qmlType(QMetaType::type(typeName.toLatin1()));
|
||||
if (type) {
|
||||
typeName = type->qmlTypeName();
|
||||
|
|
|
@ -375,7 +375,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
|
|||
QString string = binding->valueAsString(qmlUnit);
|
||||
// Encoded dir-separators defeat QUrl processing - decode them first
|
||||
string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
|
||||
QUrl value = string.isEmpty() ? QUrl() : compiledData->url().resolved(QUrl(string));
|
||||
QUrl value = string.isEmpty() ? QUrl() : compiledData->compilationUnit->url().resolved(QUrl(string));
|
||||
// Apply URL interceptor
|
||||
if (engine->urlInterceptor())
|
||||
value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
|
||||
|
@ -570,7 +570,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
|
|||
} else if (property->propType == qMetaTypeId<QList<QUrl> >()) {
|
||||
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
|
||||
QString urlString = binding->valueAsString(qmlUnit);
|
||||
QUrl u = urlString.isEmpty() ? QUrl() : compiledData->url().resolved(QUrl(urlString));
|
||||
QUrl u = urlString.isEmpty() ? QUrl() : compiledData->compilationUnit->url().resolved(QUrl(urlString));
|
||||
QList<QUrl> value;
|
||||
value.append(u);
|
||||
argv[0] = reinterpret_cast<void *>(&value);
|
||||
|
@ -664,7 +664,7 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
|
|||
if (qmlTypeForObject(_bindingTarget)) {
|
||||
quint32 bindingSkipList = 0;
|
||||
|
||||
QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultProperty != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
|
||||
QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultPropertyOrAlias != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
|
||||
|
||||
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
|
||||
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
|
||||
|
@ -999,7 +999,7 @@ void QQmlObjectCreator::setupFunctions()
|
|||
void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location, const QString &description)
|
||||
{
|
||||
QQmlError error;
|
||||
error.setUrl(compiledData->url());
|
||||
error.setUrl(compiledData->compilationUnit->url());
|
||||
error.setLine(location.line);
|
||||
error.setColumn(location.column);
|
||||
error.setDescription(description);
|
||||
|
@ -1037,8 +1037,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
|
|||
if (compiledData->isComponent(index)) {
|
||||
isComponent = true;
|
||||
QQmlComponent *component = new QQmlComponent(engine, compiledData, index, parent);
|
||||
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(QStringLiteral("<component>"),
|
||||
context->url(), obj->location.line, obj->location.column));
|
||||
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
|
||||
compiledData, obj, QStringLiteral("<component>"), context->url()));
|
||||
QQmlComponentPrivate::get(component)->creationContext = context;
|
||||
instance = component;
|
||||
ddata = QQmlData::get(instance, /*create*/true);
|
||||
|
@ -1048,8 +1048,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
|
|||
installPropertyCache = !typeRef->isFullyDynamicType;
|
||||
QQmlType *type = typeRef->type;
|
||||
if (type) {
|
||||
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(type->qmlTypeName(),
|
||||
context->url(), obj->location.line, obj->location.column));
|
||||
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
|
||||
compiledData, obj, type->qmlTypeName(), context->url()));
|
||||
instance = type->create();
|
||||
if (!instance) {
|
||||
recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex)));
|
||||
|
@ -1071,8 +1071,9 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
|
|||
sharedState->allCreatedObjects.push(instance);
|
||||
} else {
|
||||
Q_ASSERT(typeRef->component);
|
||||
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(typeRef->component->fileName(),
|
||||
context->url(), obj->location.line, obj->location.column));
|
||||
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
|
||||
compiledData, obj, typeRef->component->compilationUnit->fileName(),
|
||||
context->url()));
|
||||
if (typeRef->component->compilationUnit->data->isSingleton())
|
||||
{
|
||||
recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
|
||||
|
@ -1115,7 +1116,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
|
|||
parserStatus->classBegin();
|
||||
// push() the profiler state here, together with the parserStatus, as we'll pop() them
|
||||
// together, too.
|
||||
Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(profiler));
|
||||
Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(obj));
|
||||
sharedState->allParserStatusCallbacks.push(parserStatus);
|
||||
parserStatus->d = &sharedState->allParserStatusCallbacks.top();
|
||||
}
|
||||
|
@ -1288,7 +1289,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
|
|||
if (!data.isEmpty()) {
|
||||
Q_ASSERT(!cache.isNull());
|
||||
// install on _object
|
||||
vmeMetaObject = new QQmlVMEMetaObject(_qobject, cache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()));
|
||||
vmeMetaObject = new QQmlVMEMetaObject(_qobject, cache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()), compiledData->compilationUnit, _compiledObjectIndex);
|
||||
if (_ddata->propertyCache)
|
||||
_ddata->propertyCache->release();
|
||||
_ddata->propertyCache = cache;
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include <private/qv4functionobject_p.h>
|
||||
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
#include <private/qmetaobject_p.h>
|
||||
#include <private/qqmlvaluetypewrapper_p.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
|
@ -240,14 +241,14 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
|
|||
|
||||
QQmlTypeNameCache *typeNameCache = context?context->imports:0;
|
||||
|
||||
QStringList path = name.split(QLatin1Char('.'));
|
||||
const auto path = name.splitRef(QLatin1Char('.'));
|
||||
if (path.isEmpty()) return;
|
||||
|
||||
QObject *currentObject = obj;
|
||||
|
||||
// Everything up to the last property must be an "object type" property
|
||||
for (int ii = 0; ii < path.count() - 1; ++ii) {
|
||||
const QString &pathName = path.at(ii);
|
||||
const QStringRef &pathName = path.at(ii);
|
||||
|
||||
if (typeNameCache) {
|
||||
QQmlTypeNameCache::Result r = typeNameCache->query(pathName);
|
||||
|
@ -284,7 +285,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
|
|||
|
||||
QQmlPropertyData local;
|
||||
QQmlPropertyData *property =
|
||||
QQmlPropertyCache::property(engine, currentObject, pathName, context, local);
|
||||
QQmlPropertyCache::property(engine, currentObject, pathName.toString(), context, local);
|
||||
|
||||
if (!property) return; // Not a property
|
||||
if (property->isFunction())
|
||||
|
@ -324,14 +325,14 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
|
|||
|
||||
}
|
||||
|
||||
const QString &terminal = path.last();
|
||||
const QStringRef &terminal = path.last();
|
||||
|
||||
if (terminal.count() >= 3 &&
|
||||
terminal.at(0) == QLatin1Char('o') &&
|
||||
terminal.at(1) == QLatin1Char('n') &&
|
||||
terminal.at(2).isUpper()) {
|
||||
|
||||
QString signalName = terminal.mid(2);
|
||||
QString signalName = terminal.mid(2).toString();
|
||||
signalName[0] = signalName.at(0).toLower();
|
||||
|
||||
// XXX - this code treats methods as signals
|
||||
|
@ -376,13 +377,14 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
|
|||
}
|
||||
|
||||
// Property
|
||||
const QString terminalString = terminal.toString();
|
||||
QQmlPropertyData local;
|
||||
QQmlPropertyData *property =
|
||||
QQmlPropertyCache::property(engine, currentObject, terminal, context, local);
|
||||
QQmlPropertyCache::property(engine, currentObject, terminalString, context, local);
|
||||
if (property && !property->isFunction()) {
|
||||
object = currentObject;
|
||||
core = *property;
|
||||
nameCache = terminal;
|
||||
nameCache = terminalString;
|
||||
isNameCached = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -661,7 +661,7 @@ void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
|
|||
Q_ASSERT(m_waitingFor.contains(blob));
|
||||
Q_ASSERT(blob->status() == Error || blob->status() == Complete);
|
||||
QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler,
|
||||
blob->url());
|
||||
blob);
|
||||
|
||||
m_inCallback = true;
|
||||
|
||||
|
@ -1121,6 +1121,7 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob)
|
|||
}
|
||||
|
||||
#define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16
|
||||
#define TYPELOADER_MINIMUM_TRIM_THRESHOLD 64
|
||||
|
||||
#ifndef QT_NO_NETWORK
|
||||
void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply)
|
||||
|
@ -1225,7 +1226,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, QQmlFile *file)
|
|||
void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
|
||||
{
|
||||
QML_MEMORY_SCOPE_URL(blob->url());
|
||||
QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob->url());
|
||||
QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob);
|
||||
|
||||
blob->m_inCallback = true;
|
||||
|
||||
|
@ -1245,7 +1246,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
|
|||
void QQmlTypeLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
|
||||
{
|
||||
QML_MEMORY_SCOPE_URL(blob->url());
|
||||
QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob->url());
|
||||
QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob);
|
||||
|
||||
blob->m_inCallback = true;
|
||||
|
||||
|
@ -1398,13 +1399,10 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
|
|||
|
||||
// Probe for all possible locations
|
||||
int priority = 0;
|
||||
for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) {
|
||||
foreach (const QString &path, remotePathList) {
|
||||
QString qmldirUrl = QQmlImports::completeQmldirPath(importUri, path, import->majorVersion, import->minorVersion,
|
||||
static_cast<QQmlImports::ImportVersion>(version));
|
||||
if (!fetchQmldir(QUrl(qmldirUrl), import, ++priority, errors))
|
||||
return false;
|
||||
}
|
||||
const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(importUri, remotePathList, import->majorVersion, import->minorVersion);
|
||||
for (const QString &qmldirPath : qmlDirPaths) {
|
||||
if (!fetchQmldir(QUrl(qmldirPath), import, ++priority, errors))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1602,7 +1600,8 @@ bool QQmlTypeLoader::QmldirContent::designerSupported() const
|
|||
Constructs a new type loader that uses the given \a engine.
|
||||
*/
|
||||
QQmlTypeLoader::QQmlTypeLoader(QQmlEngine *engine)
|
||||
: m_engine(engine), m_thread(new QQmlTypeLoaderThread(this))
|
||||
: m_engine(engine), m_thread(new QQmlTypeLoaderThread(this)),
|
||||
m_typeCacheTrimThreshold(TYPELOADER_MINIMUM_TRIM_THRESHOLD)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1639,6 +1638,10 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
|
|||
QQmlTypeData *typeData = m_typeCache.value(url);
|
||||
|
||||
if (!typeData) {
|
||||
// Trim before adding the new type, so that we don't immediately trim it away
|
||||
if (m_typeCache.size() >= m_typeCacheTrimThreshold)
|
||||
trimCache();
|
||||
|
||||
typeData = new QQmlTypeData(url, this);
|
||||
// TODO: if (compiledData == 0), is it safe to omit this insertion?
|
||||
m_typeCache.insert(url, typeData);
|
||||
|
@ -1943,12 +1946,22 @@ void QQmlTypeLoader::clearCache()
|
|||
qDeleteAll(m_importQmlDirCache);
|
||||
|
||||
m_typeCache.clear();
|
||||
m_typeCacheTrimThreshold = TYPELOADER_MINIMUM_TRIM_THRESHOLD;
|
||||
m_scriptCache.clear();
|
||||
m_qmldirCache.clear();
|
||||
m_importDirCache.clear();
|
||||
m_importQmlDirCache.clear();
|
||||
}
|
||||
|
||||
void QQmlTypeLoader::updateTypeCacheTrimThreshold()
|
||||
{
|
||||
int size = m_typeCache.size();
|
||||
if (size > m_typeCacheTrimThreshold)
|
||||
m_typeCacheTrimThreshold = size * 2;
|
||||
if (size < m_typeCacheTrimThreshold / 2)
|
||||
m_typeCacheTrimThreshold = qMax(size * 2, TYPELOADER_MINIMUM_TRIM_THRESHOLD);
|
||||
}
|
||||
|
||||
void QQmlTypeLoader::trimCache()
|
||||
{
|
||||
while (true) {
|
||||
|
@ -1973,6 +1986,8 @@ void QQmlTypeLoader::trimCache()
|
|||
}
|
||||
}
|
||||
|
||||
updateTypeCacheTrimThreshold();
|
||||
|
||||
// TODO: release any scripts which are no longer referenced by any types
|
||||
}
|
||||
|
||||
|
|
|
@ -374,6 +374,7 @@ private:
|
|||
NetworkReplies m_networkReplies;
|
||||
#endif
|
||||
TypeCache m_typeCache;
|
||||
int m_typeCacheTrimThreshold;
|
||||
ScriptCache m_scriptCache;
|
||||
QmldirCache m_qmldirCache;
|
||||
ImportDirCache m_importDirCache;
|
||||
|
@ -381,6 +382,7 @@ private:
|
|||
|
||||
template<typename Loader>
|
||||
void doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode);
|
||||
void updateTypeCacheTrimThreshold();
|
||||
|
||||
friend struct PlainLoader;
|
||||
friend struct CachedLoader;
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <private/qv4functionobject_p.h>
|
||||
#include <private/qv4variantobject_p.h>
|
||||
#include <private/qv4alloca_p.h>
|
||||
#include <private/qv4objectiterator_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
@ -244,6 +245,34 @@ PropertyAttributes QQmlValueTypeWrapper::query(const Managed *m, String *name)
|
|||
return result ? Attr_Data : Attr_Invalid;
|
||||
}
|
||||
|
||||
void QQmlValueTypeWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
|
||||
{
|
||||
name->setM(0);
|
||||
*index = UINT_MAX;
|
||||
|
||||
QQmlValueTypeWrapper *that = static_cast<QQmlValueTypeWrapper*>(m);
|
||||
|
||||
if (QQmlValueTypeReference *ref = that->as<QQmlValueTypeReference>()) {
|
||||
if (!ref->readReferenceValue())
|
||||
return;
|
||||
}
|
||||
|
||||
if (that->d()->propertyCache) {
|
||||
const QMetaObject *mo = that->d()->propertyCache->createMetaObject();
|
||||
const int propertyCount = mo->propertyCount();
|
||||
if (it->arrayIndex < static_cast<uint>(propertyCount)) {
|
||||
Scope scope(that->engine());
|
||||
ScopedString propName(scope, that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name())));
|
||||
name->setM(propName->d());
|
||||
++it->arrayIndex;
|
||||
*attributes = QV4::Attr_Data;
|
||||
p->value = that->QV4::Object::get(propName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
QV4::Object::advanceIterator(m, it, name, index, p, attributes);
|
||||
}
|
||||
|
||||
bool QQmlValueTypeWrapper::isEqual(const QVariant& value)
|
||||
{
|
||||
if (QQmlValueTypeReference *ref = as<QQmlValueTypeReference>())
|
||||
|
@ -302,8 +331,7 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
|
|||
if (QMetaType::convert(w->d()->gadgetPtr, w->d()->valueType->typeId, &convertResult, QMetaType::QString)) {
|
||||
result = convertResult;
|
||||
} else {
|
||||
result = QString::fromUtf8(QMetaType::typeName(w->d()->valueType->typeId));
|
||||
result += QLatin1Char('(');
|
||||
result = QString::fromUtf8(QMetaType::typeName(w->d()->valueType->typeId)) + QLatin1Char('(');
|
||||
const QMetaObject *mo = w->d()->propertyCache->metaObject();
|
||||
const int propCount = mo->propertyCount();
|
||||
for (int i = 0; i < propCount; ++i) {
|
||||
|
|
|
@ -99,6 +99,7 @@ public:
|
|||
static void put(Managed *m, String *name, const Value &value);
|
||||
static bool isEqualTo(Managed *m, Managed *other);
|
||||
static PropertyAttributes query(const Managed *, String *name);
|
||||
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
|
||||
|
||||
static QV4::ReturnedValue method_toString(CallContext *ctx);
|
||||
|
||||
|
|
|
@ -64,8 +64,6 @@
|
|||
#include <private/qqmlengine_p.h>
|
||||
#include <private/qfinitestack_p.h>
|
||||
|
||||
#include <private/qqmlprofiler_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QObject;
|
||||
|
|
|
@ -99,10 +99,10 @@ void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
|
|||
return;
|
||||
|
||||
if (m_index >= 0) {
|
||||
QV4::ExecutionEngine *v4 = m_target->properties.engine();
|
||||
QV4::ExecutionEngine *v4 = m_target->propertyAndMethodStorage.engine();
|
||||
if (v4) {
|
||||
QV4::Scope scope(v4);
|
||||
QV4::Scoped<QV4::MemberData> sp(scope, m_target->properties.value());
|
||||
QV4::Scoped<QV4::MemberData> sp(scope, m_target->propertyAndMethodStorage.value());
|
||||
if (sp)
|
||||
*(sp->data() + m_index) = QV4::Primitive::nullValue();
|
||||
}
|
||||
|
@ -140,17 +140,19 @@ void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *e, void **)
|
|||
|
||||
void QQmlVMEMetaObjectEndpoint::tryConnect()
|
||||
{
|
||||
Q_ASSERT(metaObject->compiledObject);
|
||||
int aliasId = this - metaObject->aliasEndpoints;
|
||||
|
||||
if (metaObject.flag()) {
|
||||
// This is actually notify
|
||||
int sigIdx = metaObject->methodOffset() + aliasId + metaObject->metaData->propertyCount;
|
||||
int sigIdx = metaObject->methodOffset() + aliasId + metaObject->compiledObject->nProperties;
|
||||
metaObject->activate(metaObject->object, sigIdx, 0);
|
||||
} else {
|
||||
const QV4::CompiledData::Alias *aliasData = &metaObject->compiledObject->aliasTable()[aliasId];
|
||||
QQmlVMEMetaData::AliasData *d = metaObject->metaData->aliasData() + aliasId;
|
||||
if (!d->isObjectAlias()) {
|
||||
if (!aliasData->isObjectAlias()) {
|
||||
QQmlContextData *ctxt = metaObject->ctxt;
|
||||
QObject *target = ctxt->idValues[d->contextIdx].data();
|
||||
QObject *target = ctxt->idValues[aliasData->targetObjectId].data();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
|
@ -304,135 +306,128 @@ QAbstractDynamicMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObje
|
|||
|
||||
QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
|
||||
QQmlPropertyCache *cache,
|
||||
const QQmlVMEMetaData *meta)
|
||||
const QQmlVMEMetaData *meta, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId)
|
||||
: QQmlInterceptorMetaObject(obj, cache),
|
||||
ctxt(QQmlData::get(obj, true)->outerContext), metaData(meta),
|
||||
aliasEndpoints(0),
|
||||
methods(0)
|
||||
aliasEndpoints(0), compilationUnit(qmlCompilationUnit), compiledObject(0)
|
||||
{
|
||||
cache->addref();
|
||||
|
||||
QQmlData::get(obj)->hasVMEMetaObject = true;
|
||||
|
||||
int qobject_type = qMetaTypeId<QObject*>();
|
||||
int variant_type = qMetaTypeId<QVariant>();
|
||||
// Need JS wrapper to ensure properties are marked.
|
||||
// ### FIXME: I hope that this can be removed once we have the proper scope chain
|
||||
// set up and the JS wrappers always exist.
|
||||
bool needsJSWrapper = (metaData->propertyCount > 0);
|
||||
if (compilationUnit && qmlObjectId >= 0) {
|
||||
compiledObject = compilationUnit->data->objectAt(qmlObjectId);
|
||||
|
||||
// ### Optimize
|
||||
for (int ii = 0; ii < metaData->propertyCount; ++ii) {
|
||||
int t = (metaData->propertyData() + ii)->propertyType;
|
||||
if (t == qobject_type || t == variant_type) {
|
||||
needsJSWrapper = true;
|
||||
break;
|
||||
if (compiledObject->nProperties || compiledObject->nFunctions) {
|
||||
Q_ASSERT(cache && cache->engine);
|
||||
QV4::ExecutionEngine *v4 = cache->engine;
|
||||
QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, compiledObject->nProperties + compiledObject->nFunctions);
|
||||
propertyAndMethodStorage.set(v4, data);
|
||||
std::fill(data->data, data->data + data->size, QV4::Encode::undefined());
|
||||
|
||||
// Need JS wrapper to ensure properties/methods are marked.
|
||||
ensureQObjectWrapper();
|
||||
}
|
||||
}
|
||||
|
||||
if (needsJSWrapper)
|
||||
ensureQObjectWrapper();
|
||||
}
|
||||
|
||||
QQmlVMEMetaObject::~QQmlVMEMetaObject()
|
||||
{
|
||||
if (parent.isT1()) parent.asT1()->objectDestroyed(object);
|
||||
delete [] aliasEndpoints;
|
||||
delete [] methods;
|
||||
|
||||
qDeleteAll(varObjectGuards);
|
||||
|
||||
cache->release();
|
||||
}
|
||||
|
||||
QV4::MemberData *QQmlVMEMetaObject::propertiesAsMemberData()
|
||||
QV4::MemberData *QQmlVMEMetaObject::propertyAndMethodStorageAsMemberData()
|
||||
{
|
||||
if (properties.isUndefined()) {
|
||||
if (properties.valueRef())
|
||||
if (propertyAndMethodStorage.isUndefined()) {
|
||||
if (propertyAndMethodStorage.valueRef())
|
||||
// in some situations, the QObject wrapper (and associated data,
|
||||
// such as the varProperties array) will have been cleaned up, but the
|
||||
// QObject ptr will not yet have been deleted (eg, waiting on deleteLater).
|
||||
// In this situation, return 0.
|
||||
return 0;
|
||||
allocateProperties();
|
||||
}
|
||||
|
||||
return static_cast<QV4::MemberData*>(properties.asManaged());
|
||||
return static_cast<QV4::MemberData*>(propertyAndMethodStorage.asManaged());
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::writeProperty(int id, int v)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md)
|
||||
*(md->data() + id) = QV4::Primitive::fromInt32(v);
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::writeProperty(int id, bool v)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md)
|
||||
*(md->data() + id) = QV4::Primitive::fromBoolean(v);
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::writeProperty(int id, double v)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md)
|
||||
*(md->data() + id) = QV4::Primitive::fromDouble(v);
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::writeProperty(int id, const QString& v)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md)
|
||||
*(md->data() + id) = cache->engine->newString(v);
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::writeProperty(int id, const QUrl& v)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md)
|
||||
*(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::writeProperty(int id, const QDate& v)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md)
|
||||
*(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::writeProperty(int id, const QDateTime& v)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md)
|
||||
*(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::writeProperty(int id, const QPointF& v)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md)
|
||||
*(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::writeProperty(int id, const QSizeF& v)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md)
|
||||
*(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::writeProperty(int id, const QRectF& v)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md)
|
||||
*(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::writeProperty(int id, QObject* v)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md)
|
||||
*(md->data() + id) = QV4::QObjectWrapper::wrap(cache->engine, v);
|
||||
|
||||
|
@ -447,7 +442,7 @@ void QQmlVMEMetaObject::writeProperty(int id, QObject* v)
|
|||
|
||||
int QQmlVMEMetaObject::readPropertyAsInt(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return 0;
|
||||
|
||||
|
@ -460,7 +455,7 @@ int QQmlVMEMetaObject::readPropertyAsInt(int id)
|
|||
|
||||
bool QQmlVMEMetaObject::readPropertyAsBool(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return false;
|
||||
|
||||
|
@ -473,7 +468,7 @@ bool QQmlVMEMetaObject::readPropertyAsBool(int id)
|
|||
|
||||
double QQmlVMEMetaObject::readPropertyAsDouble(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return 0.0;
|
||||
|
||||
|
@ -486,7 +481,7 @@ double QQmlVMEMetaObject::readPropertyAsDouble(int id)
|
|||
|
||||
QString QQmlVMEMetaObject::readPropertyAsString(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return QString();
|
||||
|
||||
|
@ -499,7 +494,7 @@ QString QQmlVMEMetaObject::readPropertyAsString(int id)
|
|||
|
||||
QUrl QQmlVMEMetaObject::readPropertyAsUrl(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return QUrl();
|
||||
|
||||
|
@ -513,7 +508,7 @@ QUrl QQmlVMEMetaObject::readPropertyAsUrl(int id)
|
|||
|
||||
QDate QQmlVMEMetaObject::readPropertyAsDate(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return QDate();
|
||||
|
||||
|
@ -527,7 +522,7 @@ QDate QQmlVMEMetaObject::readPropertyAsDate(int id)
|
|||
|
||||
QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return QDateTime();
|
||||
|
||||
|
@ -541,7 +536,7 @@ QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id)
|
|||
|
||||
QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return QSizeF();
|
||||
|
||||
|
@ -555,7 +550,7 @@ QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id)
|
|||
|
||||
QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return QPointF();
|
||||
|
||||
|
@ -569,7 +564,7 @@ QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id)
|
|||
|
||||
QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return 0;
|
||||
|
||||
|
@ -583,7 +578,7 @@ QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id)
|
|||
|
||||
QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return 0;
|
||||
|
||||
|
@ -599,7 +594,7 @@ QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id)
|
|||
|
||||
QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return QRectF();
|
||||
|
||||
|
@ -621,15 +616,20 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
|
|||
if (intercept(c, _id, a))
|
||||
return -1;
|
||||
|
||||
const int propertyCount = compiledObject ? int(compiledObject->nProperties) : 0;
|
||||
const int aliasCount = compiledObject ? int(compiledObject->nAliases) : 0;
|
||||
const int signalCount = compiledObject ? int(compiledObject->nSignals) : 0;
|
||||
const int methodCount = compiledObject ? int(compiledObject->nFunctions) : 0;
|
||||
|
||||
if (c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty || c == QMetaObject::ResetProperty) {
|
||||
if (id >= propOffset()) {
|
||||
id -= propOffset();
|
||||
|
||||
if (id < metaData->propertyCount) {
|
||||
int t = (metaData->propertyData() + id)->propertyType;
|
||||
if (id < propertyCount) {
|
||||
const QV4::CompiledData::Property::Type t = static_cast<QV4::CompiledData::Property::Type>(compiledObject->propertyTable()[id].type);
|
||||
bool needActivate = false;
|
||||
|
||||
if (t == QQmlVMEMetaData::VarPropertyType) {
|
||||
if (t == QV4::CompiledData::Property::Var) {
|
||||
// the context can be null if accessing var properties from cpp after re-parenting an item.
|
||||
QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine);
|
||||
QV8Engine *v8e = (ep == 0) ? 0 : ep->v8engine();
|
||||
|
@ -645,131 +645,179 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
|
|||
}
|
||||
|
||||
} else {
|
||||
int fallbackMetaType = QMetaType::UnknownType;
|
||||
switch (t) {
|
||||
case QV4::CompiledData::Property::Font:
|
||||
fallbackMetaType = QMetaType::QFont;
|
||||
break;
|
||||
case QV4::CompiledData::Property::Time:
|
||||
fallbackMetaType = QMetaType::QTime;
|
||||
break;
|
||||
case QV4::CompiledData::Property::Color:
|
||||
fallbackMetaType = QMetaType::QColor;
|
||||
break;
|
||||
case QV4::CompiledData::Property::Vector2D:
|
||||
fallbackMetaType = QMetaType::QVector2D;
|
||||
break;
|
||||
case QV4::CompiledData::Property::Vector3D:
|
||||
fallbackMetaType = QMetaType::QVector3D;
|
||||
break;
|
||||
case QV4::CompiledData::Property::Vector4D:
|
||||
fallbackMetaType = QMetaType::QVector4D;
|
||||
break;
|
||||
case QV4::CompiledData::Property::Matrix4x4:
|
||||
fallbackMetaType = QMetaType::QMatrix4x4;
|
||||
break;
|
||||
case QV4::CompiledData::Property::Quaternion:
|
||||
fallbackMetaType = QMetaType::QQuaternion;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
||||
if (c == QMetaObject::ReadProperty) {
|
||||
switch(t) {
|
||||
case QVariant::Int:
|
||||
switch (t) {
|
||||
case QV4::CompiledData::Property::Int:
|
||||
*reinterpret_cast<int *>(a[0]) = readPropertyAsInt(id);
|
||||
break;
|
||||
case QVariant::Bool:
|
||||
case QV4::CompiledData::Property::Bool:
|
||||
*reinterpret_cast<bool *>(a[0]) = readPropertyAsBool(id);
|
||||
break;
|
||||
case QVariant::Double:
|
||||
case QV4::CompiledData::Property::Real:
|
||||
*reinterpret_cast<double *>(a[0]) = readPropertyAsDouble(id);
|
||||
break;
|
||||
case QVariant::String:
|
||||
case QV4::CompiledData::Property::String:
|
||||
*reinterpret_cast<QString *>(a[0]) = readPropertyAsString(id);
|
||||
break;
|
||||
case QVariant::Url:
|
||||
case QV4::CompiledData::Property::Url:
|
||||
*reinterpret_cast<QUrl *>(a[0]) = readPropertyAsUrl(id);
|
||||
break;
|
||||
case QVariant::Date:
|
||||
case QV4::CompiledData::Property::Date:
|
||||
*reinterpret_cast<QDate *>(a[0]) = readPropertyAsDate(id);
|
||||
break;
|
||||
case QVariant::DateTime:
|
||||
case QV4::CompiledData::Property::DateTime:
|
||||
*reinterpret_cast<QDateTime *>(a[0]) = readPropertyAsDateTime(id);
|
||||
break;
|
||||
case QVariant::RectF:
|
||||
case QV4::CompiledData::Property::Rect:
|
||||
*reinterpret_cast<QRectF *>(a[0]) = readPropertyAsRectF(id);
|
||||
break;
|
||||
case QVariant::SizeF:
|
||||
case QV4::CompiledData::Property::Size:
|
||||
*reinterpret_cast<QSizeF *>(a[0]) = readPropertyAsSizeF(id);
|
||||
break;
|
||||
case QVariant::PointF:
|
||||
case QV4::CompiledData::Property::Point:
|
||||
*reinterpret_cast<QPointF *>(a[0]) = readPropertyAsPointF(id);
|
||||
break;
|
||||
case QMetaType::QObjectStar:
|
||||
case QV4::CompiledData::Property::Custom:
|
||||
*reinterpret_cast<QObject **>(a[0]) = readPropertyAsQObject(id);
|
||||
break;
|
||||
case QMetaType::QVariant:
|
||||
case QV4::CompiledData::Property::Variant:
|
||||
*reinterpret_cast<QVariant *>(a[0]) = readPropertyAsVariant(id);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (t == qMetaTypeId<QQmlListProperty<QObject> >()) {
|
||||
QList<QObject *> *list = readPropertyAsList(id);
|
||||
QQmlListProperty<QObject> *p = static_cast<QQmlListProperty<QObject> *>(a[0]);
|
||||
*p = QQmlListProperty<QObject>(object, list,
|
||||
list_append, list_count, list_at,
|
||||
list_clear);
|
||||
p->dummy1 = this;
|
||||
p->dummy2 = reinterpret_cast<void *>(quintptr(methodOffset() + id));
|
||||
} else {
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
if (md) {
|
||||
QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
|
||||
if (v)
|
||||
QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], t);
|
||||
}
|
||||
}
|
||||
case QV4::CompiledData::Property::CustomList: {
|
||||
QList<QObject *> *list = readPropertyAsList(id);
|
||||
QQmlListProperty<QObject> *p = static_cast<QQmlListProperty<QObject> *>(a[0]);
|
||||
*p = QQmlListProperty<QObject>(object, list,
|
||||
list_append, list_count, list_at,
|
||||
list_clear);
|
||||
p->dummy1 = this;
|
||||
p->dummy2 = reinterpret_cast<void *>(quintptr(methodOffset() + id));
|
||||
break;
|
||||
}
|
||||
case QV4::CompiledData::Property::Font:
|
||||
case QV4::CompiledData::Property::Time:
|
||||
case QV4::CompiledData::Property::Color:
|
||||
case QV4::CompiledData::Property::Vector2D:
|
||||
case QV4::CompiledData::Property::Vector3D:
|
||||
case QV4::CompiledData::Property::Vector4D:
|
||||
case QV4::CompiledData::Property::Matrix4x4:
|
||||
case QV4::CompiledData::Property::Quaternion:
|
||||
Q_ASSERT(fallbackMetaType != QMetaType::UnknownType);
|
||||
if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
|
||||
QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
|
||||
if (v)
|
||||
QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], fallbackMetaType);
|
||||
}
|
||||
break;
|
||||
case QV4::CompiledData::Property::Var:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
} else if (c == QMetaObject::WriteProperty) {
|
||||
|
||||
switch(t) {
|
||||
case QVariant::Int:
|
||||
case QV4::CompiledData::Property::Int:
|
||||
needActivate = *reinterpret_cast<int *>(a[0]) != readPropertyAsInt(id);
|
||||
writeProperty(id, *reinterpret_cast<int *>(a[0]));
|
||||
break;
|
||||
case QVariant::Bool:
|
||||
case QV4::CompiledData::Property::Bool:
|
||||
needActivate = *reinterpret_cast<bool *>(a[0]) != readPropertyAsBool(id);
|
||||
writeProperty(id, *reinterpret_cast<bool *>(a[0]));
|
||||
break;
|
||||
case QVariant::Double:
|
||||
case QV4::CompiledData::Property::Real:
|
||||
needActivate = *reinterpret_cast<double *>(a[0]) != readPropertyAsDouble(id);
|
||||
writeProperty(id, *reinterpret_cast<double *>(a[0]));
|
||||
break;
|
||||
case QVariant::String:
|
||||
case QV4::CompiledData::Property::String:
|
||||
needActivate = *reinterpret_cast<QString *>(a[0]) != readPropertyAsString(id);
|
||||
writeProperty(id, *reinterpret_cast<QString *>(a[0]));
|
||||
break;
|
||||
case QVariant::Url:
|
||||
case QV4::CompiledData::Property::Url:
|
||||
needActivate = *reinterpret_cast<QUrl *>(a[0]) != readPropertyAsUrl(id);
|
||||
writeProperty(id, *reinterpret_cast<QUrl *>(a[0]));
|
||||
break;
|
||||
case QVariant::Date:
|
||||
case QV4::CompiledData::Property::Date:
|
||||
needActivate = *reinterpret_cast<QDate *>(a[0]) != readPropertyAsDate(id);
|
||||
writeProperty(id, *reinterpret_cast<QDate *>(a[0]));
|
||||
break;
|
||||
case QVariant::DateTime:
|
||||
case QV4::CompiledData::Property::DateTime:
|
||||
needActivate = *reinterpret_cast<QDateTime *>(a[0]) != readPropertyAsDateTime(id);
|
||||
writeProperty(id, *reinterpret_cast<QDateTime *>(a[0]));
|
||||
break;
|
||||
case QVariant::RectF:
|
||||
case QV4::CompiledData::Property::Rect:
|
||||
needActivate = *reinterpret_cast<QRectF *>(a[0]) != readPropertyAsRectF(id);
|
||||
writeProperty(id, *reinterpret_cast<QRectF *>(a[0]));
|
||||
break;
|
||||
case QVariant::SizeF:
|
||||
case QV4::CompiledData::Property::Size:
|
||||
needActivate = *reinterpret_cast<QSizeF *>(a[0]) != readPropertyAsSizeF(id);
|
||||
writeProperty(id, *reinterpret_cast<QSizeF *>(a[0]));
|
||||
break;
|
||||
case QVariant::PointF:
|
||||
case QV4::CompiledData::Property::Point:
|
||||
needActivate = *reinterpret_cast<QPointF *>(a[0]) != readPropertyAsPointF(id);
|
||||
writeProperty(id, *reinterpret_cast<QPointF *>(a[0]));
|
||||
break;
|
||||
case QMetaType::QObjectStar:
|
||||
case QV4::CompiledData::Property::Custom:
|
||||
needActivate = *reinterpret_cast<QObject **>(a[0]) != readPropertyAsQObject(id);
|
||||
writeProperty(id, *reinterpret_cast<QObject **>(a[0]));
|
||||
break;
|
||||
case QMetaType::QVariant:
|
||||
case QV4::CompiledData::Property::Variant:
|
||||
writeProperty(id, *reinterpret_cast<QVariant *>(a[0]));
|
||||
break;
|
||||
default: {
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
if (md) {
|
||||
case QV4::CompiledData::Property::CustomList:
|
||||
// Writing such a property is not supported. Content is added through the list property
|
||||
// methods.
|
||||
break;
|
||||
case QV4::CompiledData::Property::Font:
|
||||
case QV4::CompiledData::Property::Time:
|
||||
case QV4::CompiledData::Property::Color:
|
||||
case QV4::CompiledData::Property::Vector2D:
|
||||
case QV4::CompiledData::Property::Vector3D:
|
||||
case QV4::CompiledData::Property::Vector4D:
|
||||
case QV4::CompiledData::Property::Matrix4x4:
|
||||
case QV4::CompiledData::Property::Quaternion:
|
||||
Q_ASSERT(fallbackMetaType != QMetaType::UnknownType);
|
||||
if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
|
||||
QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
|
||||
if (!v) {
|
||||
*(md->data() + id) = cache->engine->newVariantObject(QVariant());
|
||||
v = (md->data() + id)->as<QV4::VariantObject>();
|
||||
QQml_valueTypeProvider()->initValueType(t, v->d()->data);
|
||||
QQml_valueTypeProvider()->initValueType(fallbackMetaType, v->d()->data);
|
||||
}
|
||||
needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], v->d()->data);
|
||||
QQml_valueTypeProvider()->writeValueType(t, a[0], v->d()->data);
|
||||
needActivate = !QQml_valueTypeProvider()->equalValueType(fallbackMetaType, a[0], v->d()->data);
|
||||
QQml_valueTypeProvider()->writeValueType(fallbackMetaType, a[0], v->d()->data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QV4::CompiledData::Property::Var:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -782,13 +830,12 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
|
|||
return -1;
|
||||
}
|
||||
|
||||
id -= metaData->propertyCount;
|
||||
id -= propertyCount;
|
||||
|
||||
if (id < metaData->aliasCount) {
|
||||
if (id < aliasCount) {
|
||||
const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[id];
|
||||
|
||||
QQmlVMEMetaData::AliasData *d = metaData->aliasData() + id;
|
||||
|
||||
if (d->flags & QML_ALIAS_FLAG_PTR && c == QMetaObject::ReadProperty)
|
||||
if ((aliasData->flags & QV4::CompiledData::Alias::AliasPointsToPointerObject) && c == QMetaObject::ReadProperty)
|
||||
*reinterpret_cast<void **>(a[0]) = 0;
|
||||
|
||||
if (!ctxt) return -1;
|
||||
|
@ -796,42 +843,52 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
|
|||
QQmlContext *context = ctxt->asQQmlContext();
|
||||
QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(context);
|
||||
|
||||
QObject *target = ctxtPriv->data->idValues[d->contextIdx].data();
|
||||
QObject *target = ctxtPriv->data->idValues[aliasData->targetObjectId].data();
|
||||
if (!target)
|
||||
return -1;
|
||||
|
||||
connectAlias(id);
|
||||
|
||||
if (d->isObjectAlias()) {
|
||||
if (aliasData->isObjectAlias()) {
|
||||
*reinterpret_cast<QObject **>(a[0]) = target;
|
||||
return -1;
|
||||
}
|
||||
|
||||
QQmlData *targetDData = QQmlData::get(target, /*create*/false);
|
||||
if (!targetDData)
|
||||
return -1;
|
||||
|
||||
int coreIndex;
|
||||
const int valueTypePropertyIndex = QQmlPropertyData::decodeValueTypePropertyIndex(aliasData->encodedMetaPropertyIndex, &coreIndex);
|
||||
|
||||
// Remove binding (if any) on write
|
||||
if(c == QMetaObject::WriteProperty) {
|
||||
int flags = *reinterpret_cast<int*>(a[3]);
|
||||
if (flags & QQmlPropertyPrivate::RemoveBindingOnAliasWrite) {
|
||||
QQmlData *targetData = QQmlData::get(target);
|
||||
if (targetData && targetData->hasBindingBit(d->propertyIndex()))
|
||||
QQmlPropertyPrivate::removeBinding(target, d->propertyIdx);
|
||||
if (targetData && targetData->hasBindingBit(coreIndex))
|
||||
QQmlPropertyPrivate::removeBinding(target, aliasData->encodedMetaPropertyIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (d->isValueTypeAlias()) {
|
||||
if (valueTypePropertyIndex != -1) {
|
||||
if (!targetDData->propertyCache)
|
||||
return -1;
|
||||
const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
|
||||
// Value type property
|
||||
QQmlValueType *valueType = QQmlValueTypeFactory::valueType(d->valueType());
|
||||
QQmlValueType *valueType = QQmlValueTypeFactory::valueType(pd->propType);
|
||||
Q_ASSERT(valueType);
|
||||
|
||||
valueType->read(target, d->propertyIndex());
|
||||
int rv = QMetaObject::metacall(valueType, c, d->valueTypeIndex(), a);
|
||||
valueType->read(target, coreIndex);
|
||||
int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a);
|
||||
|
||||
if (c == QMetaObject::WriteProperty)
|
||||
valueType->write(target, d->propertyIndex(), 0x00);
|
||||
valueType->write(target, coreIndex, 0x00);
|
||||
|
||||
return rv;
|
||||
|
||||
} else {
|
||||
return QMetaObject::metacall(target, c, d->propertyIndex(), a);
|
||||
return QMetaObject::metacall(target, c, coreIndex, a);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -844,8 +901,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
|
|||
if (id >= methodOffset()) {
|
||||
|
||||
id -= methodOffset();
|
||||
int plainSignals = metaData->signalCount + metaData->propertyCount +
|
||||
metaData->aliasCount;
|
||||
int plainSignals = signalCount + propertyCount + aliasCount;
|
||||
if (id < plainSignals) {
|
||||
activate(object, _id, a);
|
||||
return -1;
|
||||
|
@ -853,7 +909,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
|
|||
|
||||
id -= plainSignals;
|
||||
|
||||
if (id < metaData->methodCount) {
|
||||
if (id < methodCount) {
|
||||
if (!ctxt->engine)
|
||||
return -1; // We can't run the method
|
||||
|
||||
|
@ -877,12 +933,11 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
|
|||
return -1; // The dynamic method with that id is not available.
|
||||
}
|
||||
|
||||
QQmlVMEMetaData::MethodData *data = metaData->methodData() + id;
|
||||
|
||||
QV4::ScopedCallData callData(scope, data->parameterCount);
|
||||
const unsigned int parameterCount = function->formalParameterCount();
|
||||
QV4::ScopedCallData callData(scope, parameterCount);
|
||||
callData->thisObject = ep->v8engine()->global();
|
||||
|
||||
for (int ii = 0; ii < data->parameterCount; ++ii)
|
||||
for (uint ii = 0; ii < parameterCount; ++ii)
|
||||
callData->args[ii] = scope.engine->fromVariant(*(QVariant *)a[ii + 1]);
|
||||
|
||||
QV4::ScopedValue result(scope);
|
||||
|
@ -911,22 +966,23 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
|
|||
|
||||
QV4::ReturnedValue QQmlVMEMetaObject::method(int index)
|
||||
{
|
||||
if (!ctxt || !ctxt->isValid()) {
|
||||
if (!ctxt || !ctxt->isValid() || !compiledObject) {
|
||||
qWarning("QQmlVMEMetaObject: Internal error - attempted to evaluate a function in an invalid context");
|
||||
return QV4::Encode::undefined();
|
||||
}
|
||||
|
||||
if (!methods)
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return QV4::Encode::undefined();
|
||||
|
||||
return methods[index].value();
|
||||
return (md->data() + index + compiledObject->nProperties)->asReturnedValue();
|
||||
}
|
||||
|
||||
QV4::ReturnedValue QQmlVMEMetaObject::readVarProperty(int id)
|
||||
{
|
||||
Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType);
|
||||
Q_ASSERT(compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var);
|
||||
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md)
|
||||
return (md->data() + id)->asReturnedValue();
|
||||
return QV4::Primitive::undefinedValue().asReturnedValue();
|
||||
|
@ -934,7 +990,7 @@ QV4::ReturnedValue QQmlVMEMetaObject::readVarProperty(int id)
|
|||
|
||||
QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id)
|
||||
{
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md) {
|
||||
const QV4::QObjectWrapper *wrapper = (md->data() + id)->as<QV4::QObjectWrapper>();
|
||||
if (wrapper)
|
||||
|
@ -949,9 +1005,9 @@ QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id)
|
|||
|
||||
void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value)
|
||||
{
|
||||
Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType);
|
||||
Q_ASSERT(compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var);
|
||||
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return;
|
||||
|
||||
|
@ -989,8 +1045,8 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value)
|
|||
|
||||
void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
|
||||
{
|
||||
if ((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType) {
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
if (compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var) {
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return;
|
||||
|
||||
|
@ -1020,7 +1076,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
|
|||
needActivate = readPropertyAsQObject(id) != o; // TODO: still correct?
|
||||
writeProperty(id, o);
|
||||
} else {
|
||||
QV4::MemberData *md = propertiesAsMemberData();
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (md) {
|
||||
QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
|
||||
needActivate = (!v ||
|
||||
|
@ -1039,30 +1095,16 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
|
|||
}
|
||||
}
|
||||
|
||||
quint16 QQmlVMEMetaObject::vmeMethodLineNumber(int index)
|
||||
{
|
||||
if (index < methodOffset()) {
|
||||
Q_ASSERT(parentVMEMetaObject());
|
||||
return parentVMEMetaObject()->vmeMethodLineNumber(index);
|
||||
}
|
||||
|
||||
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
|
||||
Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
|
||||
|
||||
int rawIndex = index - methodOffset() - plainSignals;
|
||||
|
||||
QQmlVMEMetaData::MethodData *data = metaData->methodData() + rawIndex;
|
||||
return data->lineNumber;
|
||||
}
|
||||
|
||||
QV4::ReturnedValue QQmlVMEMetaObject::vmeMethod(int index)
|
||||
{
|
||||
if (index < methodOffset()) {
|
||||
Q_ASSERT(parentVMEMetaObject());
|
||||
return parentVMEMetaObject()->vmeMethod(index);
|
||||
}
|
||||
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
|
||||
Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
|
||||
if (!compiledObject)
|
||||
return QV4::Primitive::undefinedValue().asReturnedValue();
|
||||
const int plainSignals = compiledObject->nSignals + compiledObject->nProperties + compiledObject->nAliases;
|
||||
Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + int(compiledObject->nFunctions)));
|
||||
return method(index - methodOffset() - plainSignals);
|
||||
}
|
||||
|
||||
|
@ -1073,14 +1115,16 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &function)
|
|||
Q_ASSERT(parentVMEMetaObject());
|
||||
return parentVMEMetaObject()->setVmeMethod(index, function);
|
||||
}
|
||||
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
|
||||
Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
|
||||
|
||||
if (!methods)
|
||||
methods = new QV4::PersistentValue[metaData->methodCount];
|
||||
if (!compiledObject)
|
||||
return;
|
||||
const int plainSignals = compiledObject->nSignals + compiledObject->nProperties + compiledObject->nAliases;
|
||||
Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + int(compiledObject->nFunctions)));
|
||||
|
||||
int methodIndex = index - methodOffset() - plainSignals;
|
||||
methods[methodIndex].set(function.as<QV4::Object>()->engine(), function);
|
||||
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
|
||||
if (!md)
|
||||
return;
|
||||
*(md->data() + methodIndex + compiledObject->nProperties) = function;
|
||||
}
|
||||
|
||||
QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index)
|
||||
|
@ -1115,25 +1159,15 @@ void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e)
|
|||
if (v4 != e)
|
||||
return;
|
||||
|
||||
properties.markOnce(e);
|
||||
propertyAndMethodStorage.markOnce(e);
|
||||
|
||||
if (QQmlVMEMetaObject *parent = parentVMEMetaObject())
|
||||
parent->mark(e);
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::allocateProperties()
|
||||
{
|
||||
Q_ASSERT(cache && cache->engine);
|
||||
Q_ASSERT(!properties.valueRef());
|
||||
QV4::ExecutionEngine *v4 = cache->engine;
|
||||
QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, metaData->propertyCount);
|
||||
properties.set(v4, data);
|
||||
std::fill(data->data, data->data + data->size, QV4::Encode::undefined());
|
||||
}
|
||||
|
||||
bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const
|
||||
{
|
||||
Q_ASSERT(index >= propOffset() + metaData->propertyCount);
|
||||
Q_ASSERT(compiledObject && (index >= propOffset() + int(compiledObject->nProperties)));
|
||||
|
||||
*target = 0;
|
||||
*coreIndex = -1;
|
||||
|
@ -1142,31 +1176,24 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex,
|
|||
if (!ctxt)
|
||||
return false;
|
||||
|
||||
QQmlVMEMetaData::AliasData *d = metaData->aliasData() + (index - propOffset() - metaData->propertyCount);
|
||||
QQmlContext *context = ctxt->asQQmlContext();
|
||||
QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(context);
|
||||
|
||||
*target = ctxtPriv->data->idValues[d->contextIdx].data();
|
||||
const int aliasId = index - propOffset() - compiledObject->nProperties;
|
||||
const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[aliasId];
|
||||
*target = ctxt->idValues[aliasData->targetObjectId].data();
|
||||
if (!*target)
|
||||
return false;
|
||||
|
||||
if (d->isObjectAlias()) {
|
||||
} else if (d->isValueTypeAlias()) {
|
||||
*coreIndex = d->propertyIndex();
|
||||
*valueTypeIndex = d->valueTypeIndex();
|
||||
} else {
|
||||
*coreIndex = d->propertyIndex();
|
||||
}
|
||||
|
||||
if (!aliasData->isObjectAlias())
|
||||
*valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(aliasData->encodedMetaPropertyIndex, coreIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::connectAlias(int aliasId)
|
||||
{
|
||||
Q_ASSERT(compiledObject);
|
||||
if (!aliasEndpoints)
|
||||
aliasEndpoints = new QQmlVMEMetaObjectEndpoint[metaData->aliasCount];
|
||||
aliasEndpoints = new QQmlVMEMetaObjectEndpoint[compiledObject->nAliases];
|
||||
|
||||
QQmlVMEMetaData::AliasData *d = metaData->aliasData() + aliasId;
|
||||
const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[aliasId];
|
||||
|
||||
QQmlVMEMetaObjectEndpoint *endpoint = aliasEndpoints + aliasId;
|
||||
if (endpoint->metaObject.data()) {
|
||||
|
@ -1176,14 +1203,15 @@ void QQmlVMEMetaObject::connectAlias(int aliasId)
|
|||
}
|
||||
|
||||
endpoint->metaObject = this;
|
||||
endpoint->connect(&ctxt->idValues[d->contextIdx].bindings);
|
||||
endpoint->connect(&ctxt->idValues[aliasData->targetObjectId].bindings);
|
||||
endpoint->tryConnect();
|
||||
}
|
||||
|
||||
void QQmlVMEMetaObject::connectAliasSignal(int index, bool indexInSignalRange)
|
||||
{
|
||||
int aliasId = (index - (indexInSignalRange ? signalOffset() : methodOffset())) - metaData->propertyCount;
|
||||
if (aliasId < 0 || aliasId >= metaData->aliasCount)
|
||||
Q_ASSERT(compiledObject);
|
||||
int aliasId = (index - (indexInSignalRange ? signalOffset() : methodOffset())) - compiledObject->nProperties;
|
||||
if (aliasId < 0 || aliasId >= int(compiledObject->nAliases))
|
||||
return;
|
||||
|
||||
connectAlias(aliasId);
|
||||
|
|
|
@ -74,69 +74,17 @@
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#define QML_ALIAS_FLAG_PTR 0x00000001
|
||||
|
||||
struct QQmlVMEMetaData
|
||||
{
|
||||
short propertyCount;
|
||||
short aliasCount;
|
||||
short signalCount;
|
||||
short methodCount;
|
||||
// Make sure this structure is always aligned to int
|
||||
int dummy;
|
||||
|
||||
struct AliasData {
|
||||
int contextIdx;
|
||||
int propertyIdx;
|
||||
int propType;
|
||||
int flags;
|
||||
int notifySignal;
|
||||
|
||||
bool isObjectAlias() const {
|
||||
return propertyIdx == -1;
|
||||
}
|
||||
bool isPropertyAlias() const {
|
||||
return !isObjectAlias() && valueTypeIndex() == -1;
|
||||
}
|
||||
bool isValueTypeAlias() const {
|
||||
return !isObjectAlias() && valueTypeIndex() != -1;
|
||||
}
|
||||
int propertyIndex() const {
|
||||
int index;
|
||||
QQmlPropertyData::decodeValueTypePropertyIndex(propertyIdx, &index);
|
||||
return index;
|
||||
}
|
||||
int valueTypeIndex() const {
|
||||
return QQmlPropertyData::decodeValueTypePropertyIndex(propertyIdx);
|
||||
}
|
||||
int valueType() const {
|
||||
return (valueTypeIndex() != -1) ? propType : 0;
|
||||
}
|
||||
};
|
||||
|
||||
enum {
|
||||
VarPropertyType = -1
|
||||
};
|
||||
|
||||
struct PropertyData {
|
||||
int propertyType;
|
||||
};
|
||||
|
||||
struct MethodData {
|
||||
int runtimeFunctionIndex;
|
||||
int parameterCount;
|
||||
quint16 lineNumber;
|
||||
};
|
||||
|
||||
PropertyData *propertyData() const {
|
||||
return (PropertyData *)(((char *)const_cast<QQmlVMEMetaData *>(this)) + sizeof(QQmlVMEMetaData));
|
||||
}
|
||||
|
||||
AliasData *aliasData() const {
|
||||
return (AliasData *)(propertyData() + propertyCount);
|
||||
}
|
||||
|
||||
MethodData *methodData() const {
|
||||
return (MethodData *)(aliasData() + aliasCount);
|
||||
return (AliasData *)(((char *)const_cast<QQmlVMEMetaData *>(this)) + sizeof(QQmlVMEMetaData));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -199,12 +147,11 @@ class QQmlVMEMetaObjectEndpoint;
|
|||
class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject
|
||||
{
|
||||
public:
|
||||
QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data);
|
||||
QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId);
|
||||
~QQmlVMEMetaObject();
|
||||
|
||||
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
|
||||
QV4::ReturnedValue vmeMethod(int index);
|
||||
quint16 vmeMethodLineNumber(int index);
|
||||
void setVmeMethod(int index, const QV4::Value &function);
|
||||
QV4::ReturnedValue vmeProperty(int index);
|
||||
void setVMEProperty(int index, const QV4::Value &v);
|
||||
|
@ -230,9 +177,8 @@ public:
|
|||
|
||||
QQmlVMEMetaObjectEndpoint *aliasEndpoints;
|
||||
|
||||
QV4::WeakValue properties;
|
||||
inline void allocateProperties();
|
||||
QV4::MemberData *propertiesAsMemberData();
|
||||
QV4::WeakValue propertyAndMethodStorage;
|
||||
QV4::MemberData *propertyAndMethodStorageAsMemberData();
|
||||
|
||||
int readPropertyAsInt(int id);
|
||||
bool readPropertyAsBool(int id);
|
||||
|
@ -265,7 +211,6 @@ public:
|
|||
|
||||
void connectAlias(int aliasId);
|
||||
|
||||
QV4::PersistentValue *methods;
|
||||
QV4::ReturnedValue method(int);
|
||||
|
||||
QV4::ReturnedValue readVarProperty(int);
|
||||
|
@ -280,6 +225,12 @@ public:
|
|||
QList<QQmlVMEVariantQObjectPtr *> varObjectGuards;
|
||||
|
||||
QQmlVMEVariantQObjectPtr *getQObjectGuardForProperty(int) const;
|
||||
|
||||
|
||||
// keep a reference to the compilation unit in order to still
|
||||
// do property access when the context has been invalidated.
|
||||
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
|
||||
const QV4::CompiledData::Object *compiledObject;
|
||||
};
|
||||
|
||||
QQmlVMEMetaObject *QQmlVMEMetaObject::get(QObject *obj)
|
||||
|
|
|
@ -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; ii < qtMetaObject->enumeratorCount(); ++ii) {
|
||||
QMetaEnum enumerator = qtMetaObject->enumerator(ii);
|
||||
for (int jj = 0; jj < enumerator.keyCount(); ++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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -156,8 +156,7 @@ QV8Engine::QV8Engine(QJSEngine* qq)
|
|||
|
||||
QV8Engine::~QV8Engine()
|
||||
{
|
||||
for (int ii = 0; ii < m_extensionData.count(); ++ii)
|
||||
delete m_extensionData[ii];
|
||||
qDeleteAll(m_extensionData);
|
||||
m_extensionData.clear();
|
||||
|
||||
#if !defined(QT_NO_XMLSTREAMREADER) && defined(QT_NO_NETWORK)
|
||||
|
|
|
@ -1040,7 +1040,7 @@ QString QQmlDelegateModelPrivate::stringValue(Compositor::Group group, int index
|
|||
return QString();
|
||||
int from = dot+1;
|
||||
dot = name.indexOf(QLatin1Char('.'), from);
|
||||
value = obj->property(name.mid(from, dot-from).toUtf8());
|
||||
value = obj->property(name.midRef(from, dot - from).toUtf8());
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
@ -1557,29 +1557,6 @@ bool QQmlDelegateModel::isDescendantOf(const QPersistentModelIndex& desc, const
|
|||
return false;
|
||||
}
|
||||
|
||||
void QQmlDelegateModel::_q_layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
|
||||
{
|
||||
Q_D(QQmlDelegateModel);
|
||||
if (!d->m_complete)
|
||||
return;
|
||||
|
||||
if (hint == QAbstractItemModel::VerticalSortHint) {
|
||||
d->m_storedPersistentIndexes.clear();
|
||||
if (!parents.isEmpty() && d->m_adaptorModel.rootIndex.isValid() && !isDescendantOf(d->m_adaptorModel.rootIndex, parents)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < d->m_count; ++i) {
|
||||
const QModelIndex index = d->m_adaptorModel.aim()->index(i, 0, d->m_adaptorModel.rootIndex);
|
||||
d->m_storedPersistentIndexes.append(index);
|
||||
}
|
||||
} else if (hint == QAbstractItemModel::HorizontalSortHint) {
|
||||
// Ignored
|
||||
} else {
|
||||
// Triggers model reset, no preparations for that are needed
|
||||
}
|
||||
}
|
||||
|
||||
void QQmlDelegateModel::_q_layoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
|
||||
{
|
||||
Q_D(QQmlDelegateModel);
|
||||
|
@ -1591,19 +1568,7 @@ void QQmlDelegateModel::_q_layoutChanged(const QList<QPersistentModelIndex> &par
|
|||
return;
|
||||
}
|
||||
|
||||
for (int i = 0, c = d->m_storedPersistentIndexes.count(); i < c; ++i) {
|
||||
const QPersistentModelIndex &index = d->m_storedPersistentIndexes.at(i);
|
||||
if (i == index.row())
|
||||
continue;
|
||||
|
||||
_q_itemsMoved(i, index.row(), 1);
|
||||
}
|
||||
|
||||
d->m_storedPersistentIndexes.clear();
|
||||
|
||||
// layoutUpdate does not necessarily have any move changes, but it can
|
||||
// also mean data changes. We can't detect what exactly has changed, so
|
||||
// just emit it for all items
|
||||
// mark all items as changed
|
||||
_q_itemsChanged(0, d->m_count, QVector<int>());
|
||||
|
||||
} else if (hint == QAbstractItemModel::HorizontalSortHint) {
|
||||
|
|
|
@ -146,7 +146,6 @@ private Q_SLOTS:
|
|||
void _q_rowsRemoved(const QModelIndex &,int,int);
|
||||
void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
|
||||
void _q_dataChanged(const QModelIndex&,const QModelIndex&,const QVector<int> &);
|
||||
void _q_layoutAboutToBeChanged(const QList<QPersistentModelIndex>&, QAbstractItemModel::LayoutChangeHint);
|
||||
void _q_layoutChanged(const QList<QPersistentModelIndex>&, QAbstractItemModel::LayoutChangeHint);
|
||||
|
||||
private:
|
||||
|
|
|
@ -337,8 +337,6 @@ public:
|
|||
};
|
||||
QQmlDelegateModelGroup *m_groups[Compositor::MaximumGroupCount];
|
||||
};
|
||||
|
||||
QList<QPersistentModelIndex> m_storedPersistentIndexes;
|
||||
};
|
||||
|
||||
class QQmlPartsModel : public QQmlInstanceModel, public QQmlDelegateModelGroupEmitter
|
||||
|
|
|
@ -470,8 +470,6 @@ public:
|
|||
vdm, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
|
||||
QObject::disconnect(aim, SIGNAL(modelReset()),
|
||||
vdm, SLOT(_q_modelReset()));
|
||||
QObject::disconnect(aim, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
|
||||
vdm, SLOT(_q_layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
|
||||
QObject::disconnect(aim, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
|
||||
vdm, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
|
||||
}
|
||||
|
@ -928,8 +926,6 @@ void QQmlAdaptorModel::setModel(const QVariant &variant, QQmlDelegateModel *vdm,
|
|||
vdm, QQmlDelegateModel, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
|
||||
qmlobject_connect(model, QAbstractItemModel, SIGNAL(modelReset()),
|
||||
vdm, QQmlDelegateModel, SLOT(_q_modelReset()));
|
||||
qmlobject_connect(model, QAbstractItemModel, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
|
||||
vdm, QQmlDelegateModel, SLOT(_q_layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
|
||||
qmlobject_connect(model, QAbstractItemModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
|
||||
vdm, QQmlDelegateModel, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
|
||||
} else {
|
||||
|
|
|
@ -352,7 +352,7 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD
|
|||
QTestRootObject::instance()->init();
|
||||
QString path = fi.absoluteFilePath();
|
||||
if (path.startsWith(QLatin1String(":/")))
|
||||
view->setSource(QUrl(QLatin1String("qrc:") + path.mid(2)));
|
||||
view->setSource(QUrl(QLatin1String("qrc:") + path.midRef(2)));
|
||||
else
|
||||
view->setSource(QUrl::fromLocalFile(path));
|
||||
|
||||
|
|
|
@ -79,23 +79,9 @@ struct MetaPropertyData {
|
|||
QVector<QPair<QVariant, bool> > m_data;
|
||||
};
|
||||
|
||||
static bool constructedMetaData(const QQmlVMEMetaData* data)
|
||||
{
|
||||
return data->propertyCount == 0
|
||||
&& data->aliasCount == 0
|
||||
&& data->signalCount == 0
|
||||
&& data->methodCount == 0;
|
||||
}
|
||||
|
||||
static QQmlVMEMetaData* fakeMetaData()
|
||||
{
|
||||
QQmlVMEMetaData* data = new QQmlVMEMetaData;
|
||||
data->propertyCount = 0;
|
||||
data->aliasCount = 0;
|
||||
data->signalCount = 0;
|
||||
data->methodCount = 0;
|
||||
|
||||
return data;
|
||||
return new QQmlVMEMetaData;
|
||||
}
|
||||
|
||||
static const QQmlVMEMetaData* vMEMetaDataForObject(QObject *object)
|
||||
|
@ -125,7 +111,15 @@ QQmlDesignerMetaObject* QQmlDesignerMetaObject::getNodeInstanceMetaObject(QObjec
|
|||
return static_cast<QQmlDesignerMetaObject *>(parent);
|
||||
|
||||
// we just create one and the ownership goes automatically to the object in nodeinstance see init method
|
||||
return new QQmlDesignerMetaObject(object, engine);
|
||||
|
||||
QQmlData *ddata = QQmlData::get(object, false);
|
||||
|
||||
const bool hadVMEMetaObject = ddata ? ddata->hasVMEMetaObject : false;
|
||||
QQmlDesignerMetaObject *mo = new QQmlDesignerMetaObject(object, engine);
|
||||
//If our parent is not a VMEMetaObject we just set the flag to false again
|
||||
if (ddata)
|
||||
ddata->hasVMEMetaObject = hadVMEMetaObject;
|
||||
return mo;
|
||||
}
|
||||
|
||||
void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine)
|
||||
|
@ -140,20 +134,20 @@ void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine)
|
|||
QObjectPrivate *op = QObjectPrivate::get(object);
|
||||
op->metaObject = this;
|
||||
|
||||
//create cache
|
||||
cache = m_cache = QQmlEnginePrivate::get(engine)->cache(this);
|
||||
cache->addref();
|
||||
m_cache = QQmlEnginePrivate::get(engine)->cache(this);
|
||||
|
||||
//If our parent is not a VMEMetaObject we just se the flag to false again
|
||||
if (constructedMetaData(metaData))
|
||||
QQmlData::get(object)->hasVMEMetaObject = false;
|
||||
if (m_cache != cache) {
|
||||
m_cache->addref();
|
||||
cache->release();
|
||||
cache = m_cache;
|
||||
}
|
||||
|
||||
nodeInstanceMetaObjectList.insert(this, true);
|
||||
hasAssignedMetaObjectData = true;
|
||||
}
|
||||
|
||||
QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine)
|
||||
: QQmlVMEMetaObject(object, cacheForObject(object, engine), vMEMetaDataForObject(object)),
|
||||
: QQmlVMEMetaObject(object, cacheForObject(object, engine), vMEMetaDataForObject(object), /*qml compilation unit*/nullptr, /*qmlObjectId*/-1),
|
||||
m_context(engine->contextForObject(object)),
|
||||
m_data(new MetaPropertyData),
|
||||
m_cache(0)
|
||||
|
@ -161,22 +155,20 @@ QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engi
|
|||
init(object, engine);
|
||||
|
||||
QQmlData *ddata = QQmlData::get(object, false);
|
||||
|
||||
//Assign cache to object
|
||||
if (ddata && ddata->propertyCache) {
|
||||
cache->setParent(ddata->propertyCache);
|
||||
cache->invalidate(engine, this);
|
||||
ddata->propertyCache->release();
|
||||
ddata->propertyCache = m_cache;
|
||||
m_cache->addref();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QQmlDesignerMetaObject::~QQmlDesignerMetaObject()
|
||||
{
|
||||
if (cache->count() > 1) // qml is crashing because the property cache is not removed from the engine
|
||||
cache->release();
|
||||
else
|
||||
m_type->release();
|
||||
m_type->release();
|
||||
|
||||
nodeInstanceMetaObjectList.remove(this);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,6 @@ public:
|
|||
static void registerNotifyPropertyChangeCallBack(void (*callback)(QObject*, const QQuickDesignerSupport::PropertyName &propertyName));
|
||||
|
||||
protected:
|
||||
QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine);
|
||||
static QQmlDesignerMetaObject* getNodeInstanceMetaObject(QObject *object, QQmlEngine *engine);
|
||||
|
||||
void createNewDynamicProperty(const QString &name);
|
||||
|
@ -95,6 +94,7 @@ protected:
|
|||
void copyTypeMetaObject();
|
||||
|
||||
private:
|
||||
QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine);
|
||||
void init(QObject *, QQmlEngine *engine);
|
||||
|
||||
QPointer<QQmlContext> m_context;
|
||||
|
|
|
@ -189,17 +189,17 @@ QTransform QQuickDesignerSupport::parentTransform(QQuickItem *referencedItem)
|
|||
return parentTransform;
|
||||
}
|
||||
|
||||
QString propertyNameForAnchorLine(const QQuickAnchorLine::AnchorLine &anchorLine)
|
||||
QString propertyNameForAnchorLine(const QQuickAnchors::Anchor &anchorLine)
|
||||
{
|
||||
switch (anchorLine) {
|
||||
case QQuickAnchorLine::Left: return QLatin1String("left");
|
||||
case QQuickAnchorLine::Right: return QLatin1String("right");
|
||||
case QQuickAnchorLine::Top: return QLatin1String("top");
|
||||
case QQuickAnchorLine::Bottom: return QLatin1String("bottom");
|
||||
case QQuickAnchorLine::HCenter: return QLatin1String("horizontalCenter");
|
||||
case QQuickAnchorLine::VCenter: return QLatin1String("verticalCenter");
|
||||
case QQuickAnchorLine::Baseline: return QLatin1String("baseline");
|
||||
case QQuickAnchorLine::Invalid:
|
||||
case QQuickAnchors::LeftAnchor: return QLatin1String("left");
|
||||
case QQuickAnchors::RightAnchor: return QLatin1String("right");
|
||||
case QQuickAnchors::TopAnchor: return QLatin1String("top");
|
||||
case QQuickAnchors::BottomAnchor: return QLatin1String("bottom");
|
||||
case QQuickAnchors::HCenterAnchor: return QLatin1String("horizontalCenter");
|
||||
case QQuickAnchors::VCenterAnchor: return QLatin1String("verticalCenter");
|
||||
case QQuickAnchors::BaselineAnchor: return QLatin1String("baseline");
|
||||
case QQuickAnchors::InvalidAnchor: // fallthrough:
|
||||
default: return QString();
|
||||
}
|
||||
}
|
||||
|
@ -345,7 +345,7 @@ QPair<QString, QObject*> QQuickDesignerSupport::anchorLineTarget(QQuickItem *ite
|
|||
return QPair<QString, QObject*>();
|
||||
|
||||
QQuickAnchorLine anchorLine = metaProperty.read().value<QQuickAnchorLine>();
|
||||
if (anchorLine.anchorLine != QQuickAnchorLine::Invalid) {
|
||||
if (anchorLine.anchorLine != QQuickAnchors::InvalidAnchor) {
|
||||
targetObject = anchorLine.item;
|
||||
targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the documentation of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
//![0]
|
||||
import QtQuick 2.8
|
||||
|
||||
Item {
|
||||
width: 200; height: 200
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: text.implicitWidth + 20; height: text.implicitHeight + 10
|
||||
color: "green"
|
||||
radius: 5
|
||||
|
||||
Drag.active: dragArea.drag.active
|
||||
Drag.dragType: Drag.Automatic
|
||||
Drag.supportedActions: Qt.CopyAction
|
||||
Drag.mimeData: {
|
||||
"text/plain": "Copied text"
|
||||
}
|
||||
|
||||
Text {
|
||||
id: text
|
||||
anchors.centerIn: parent
|
||||
text: "Drag me"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: dragArea
|
||||
anchors.fill: parent
|
||||
|
||||
drag.target: parent
|
||||
onPressed: parent.grabToImage(function(result) {
|
||||
parent.Drag.imageSource = result.url
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
//![0]
|
|
@ -66,6 +66,7 @@
|
|||
#include <private/qv4scopedvalue_p.h>
|
||||
|
||||
#include <QtCore/qmath.h>
|
||||
#include <QtCore/qvector.h>
|
||||
#include <QtCore/private/qnumeric_p.h>
|
||||
#include <QtCore/QRunnable>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
|
@ -205,7 +206,7 @@ QColor qt_color_from_string(const QV4::Value &name)
|
|||
return QColor();
|
||||
}
|
||||
|
||||
static int qParseFontSizeFromToken(const QString &fontSizeToken, bool &ok)
|
||||
static int qParseFontSizeFromToken(const QStringRef &fontSizeToken, bool &ok)
|
||||
{
|
||||
ok = false;
|
||||
float size = fontSizeToken.trimmed().toFloat(&ok);
|
||||
|
@ -221,11 +222,11 @@ static int qParseFontSizeFromToken(const QString &fontSizeToken, bool &ok)
|
|||
\c true if successful. If the font size is invalid, \c false is returned
|
||||
and a warning is printed.
|
||||
*/
|
||||
static bool qSetFontSizeFromToken(QFont &font, const QString &fontSizeToken)
|
||||
static bool qSetFontSizeFromToken(QFont &font, const QStringRef &fontSizeToken)
|
||||
{
|
||||
const QString trimmedToken = fontSizeToken.trimmed();
|
||||
const QString unitStr = trimmedToken.right(2);
|
||||
const QString value = trimmedToken.left(trimmedToken.size() - 2);
|
||||
const QStringRef trimmedToken = fontSizeToken.trimmed();
|
||||
const QStringRef unitStr = trimmedToken.right(2);
|
||||
const QStringRef value = trimmedToken.left(trimmedToken.size() - 2);
|
||||
bool ok = false;
|
||||
int size = 0;
|
||||
if (unitStr == QLatin1String("px")) {
|
||||
|
@ -251,7 +252,7 @@ static bool qSetFontSizeFromToken(QFont &font, const QString &fontSizeToken)
|
|||
each family is separated by spaces. Families with spaces in their name
|
||||
must be quoted.
|
||||
*/
|
||||
static QStringList qExtractFontFamiliesFromString(const QString &fontFamiliesString)
|
||||
static QStringList qExtractFontFamiliesFromString(const QStringRef &fontFamiliesString)
|
||||
{
|
||||
QStringList extractedFamilies;
|
||||
int quoteIndex = -1;
|
||||
|
@ -264,7 +265,7 @@ static QStringList qExtractFontFamiliesFromString(const QString &fontFamiliesStr
|
|||
} else {
|
||||
if (ch == fontFamiliesString.at(quoteIndex)) {
|
||||
// Found the matching quote. +1/-1 because we don't want the quote as part of the name.
|
||||
const QString family = fontFamiliesString.mid(quoteIndex + 1, index - quoteIndex - 1);
|
||||
const QString family = fontFamiliesString.mid(quoteIndex + 1, index - quoteIndex - 1).toString();
|
||||
extractedFamilies.push_back(family);
|
||||
currentFamily.clear();
|
||||
quoteIndex = -1;
|
||||
|
@ -395,16 +396,17 @@ static QFont qt_font_from_string(const QString& fontString, const QFont ¤t
|
|||
fontSizeEnd += 3;
|
||||
|
||||
QFont newFont;
|
||||
if (!qSetFontSizeFromToken(newFont, fontString.mid(fontSizeStart, fontSizeEnd - fontSizeStart)))
|
||||
if (!qSetFontSizeFromToken(newFont, fontString.midRef(fontSizeStart, fontSizeEnd - fontSizeStart)))
|
||||
return currentFont;
|
||||
|
||||
// We don't want to parse the size twice, so remove it now.
|
||||
QString remainingFontString = fontString;
|
||||
remainingFontString.remove(fontSizeStart, fontSizeEnd - fontSizeStart);
|
||||
QStringRef remainingFontStringRef(&remainingFontString);
|
||||
|
||||
// Next, we have to take any font families out, as QString::split() will ruin quoted family names.
|
||||
const QString fontFamiliesString = remainingFontString.mid(fontSizeStart);
|
||||
remainingFontString.chop(remainingFontString.length() - fontSizeStart);
|
||||
const QStringRef fontFamiliesString = remainingFontStringRef.mid(fontSizeStart);
|
||||
remainingFontStringRef.truncate(fontSizeStart);
|
||||
QStringList fontFamilies = qExtractFontFamiliesFromString(fontFamiliesString);
|
||||
if (fontFamilies.isEmpty()) {
|
||||
return currentFont;
|
||||
|
@ -413,16 +415,16 @@ static QFont qt_font_from_string(const QString& fontString, const QFont ¤t
|
|||
return currentFont;
|
||||
|
||||
// Now that we've removed the messy parts, we can split the font string on spaces.
|
||||
const QString trimmedTokensStr = remainingFontString.trimmed();
|
||||
const QStringRef trimmedTokensStr = remainingFontStringRef.trimmed();
|
||||
if (trimmedTokensStr.isEmpty()) {
|
||||
// No optional properties.
|
||||
return newFont;
|
||||
}
|
||||
const QStringList tokens = trimmedTokensStr.split(QLatin1Char(' '));
|
||||
const auto tokens = trimmedTokensStr.split(QLatin1Char(' '));
|
||||
|
||||
int usedTokens = NoTokens;
|
||||
// Optional properties can be in any order, but font-size and font-family must be last.
|
||||
for (const QString &token : tokens) {
|
||||
for (const QStringRef &token : tokens) {
|
||||
if (token.compare(QLatin1String("normal")) == 0) {
|
||||
if (!(usedTokens & FontStyle) || !(usedTokens & FontVariant) || !(usedTokens & FontWeight)) {
|
||||
// Could be font-style, font-variant or font-weight.
|
||||
|
@ -943,7 +945,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE
|
|||
pixelData->d()->image = QImage(w, h, QImage::Format_ARGB32);
|
||||
pixelData->d()->image.fill(0x00000000);
|
||||
} else {
|
||||
Q_ASSERT(image.width() == int(w) && image.height() == int(h));
|
||||
Q_ASSERT(image.width() == qRound(w) && image.height() == qRound(h));
|
||||
pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32);
|
||||
}
|
||||
|
||||
|
@ -1263,7 +1265,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_globalAlpha(QV4::CallContext *c
|
|||
|
||||
double globalAlpha = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
|
||||
|
||||
if (!qIsFinite(globalAlpha))
|
||||
if (!qt_is_finite(globalAlpha))
|
||||
return QV4::Encode::undefined();
|
||||
|
||||
if (globalAlpha >= 0.0 && globalAlpha <= 1.0 && r->d()->context->state.globalAlpha != globalAlpha) {
|
||||
|
@ -1547,10 +1549,10 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4::
|
|||
qreal x1 = ctx->args()[2].toNumber();
|
||||
qreal y1 = ctx->args()[3].toNumber();
|
||||
|
||||
if (!qIsFinite(x0)
|
||||
|| !qIsFinite(y0)
|
||||
|| !qIsFinite(x1)
|
||||
|| !qIsFinite(y1)) {
|
||||
if (!qt_is_finite(x0)
|
||||
|| !qt_is_finite(y0)
|
||||
|| !qt_is_finite(x1)
|
||||
|| !qt_is_finite(y1)) {
|
||||
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createLinearGradient(): Incorrect arguments")
|
||||
}
|
||||
QQuickContext2DEngineData *ed = engineData(scope.engine);
|
||||
|
@ -1592,12 +1594,12 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4::
|
|||
qreal y1 = ctx->args()[4].toNumber();
|
||||
qreal r1 = ctx->args()[5].toNumber();
|
||||
|
||||
if (!qIsFinite(x0)
|
||||
|| !qIsFinite(y0)
|
||||
|| !qIsFinite(x1)
|
||||
|| !qIsFinite(r0)
|
||||
|| !qIsFinite(r1)
|
||||
|| !qIsFinite(y1)) {
|
||||
if (!qt_is_finite(x0)
|
||||
|| !qt_is_finite(y0)
|
||||
|| !qt_is_finite(x1)
|
||||
|| !qt_is_finite(r0)
|
||||
|| !qt_is_finite(r1)
|
||||
|| !qt_is_finite(y1)) {
|
||||
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createRadialGradient(): Incorrect arguments")
|
||||
}
|
||||
|
||||
|
@ -1639,11 +1641,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4:
|
|||
qreal x = ctx->args()[0].toNumber();
|
||||
qreal y = ctx->args()[1].toNumber();
|
||||
qreal angle = DEGREES(ctx->args()[2].toNumber());
|
||||
if (!qIsFinite(x) || !qIsFinite(y)) {
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y)) {
|
||||
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createConicalGradient(): Incorrect arguments");
|
||||
}
|
||||
|
||||
if (!qIsFinite(angle)) {
|
||||
if (!qt_is_finite(angle)) {
|
||||
V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createConicalGradient(): Incorrect arguments");
|
||||
}
|
||||
|
||||
|
@ -1894,7 +1896,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineWidth(QV4::CallContext *ctx
|
|||
|
||||
qreal w = ctx->argc() ? ctx->args()[0].toNumber() : -1;
|
||||
|
||||
if (w > 0 && qIsFinite(w) && w != r->d()->context->state.lineWidth) {
|
||||
if (w > 0 && qt_is_finite(w) && w != r->d()->context->state.lineWidth) {
|
||||
r->d()->context->state.lineWidth = w;
|
||||
r->d()->context->buffer()->setLineWidth(w);
|
||||
}
|
||||
|
@ -1923,7 +1925,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(QV4::CallContext *ct
|
|||
|
||||
qreal ml = ctx->argc() ? ctx->args()[0].toNumber() : -1;
|
||||
|
||||
if (ml > 0 && qIsFinite(ml) && ml != r->d()->context->state.miterLimit) {
|
||||
if (ml > 0 && qt_is_finite(ml) && ml != r->d()->context->state.miterLimit) {
|
||||
r->d()->context->state.miterLimit = ml;
|
||||
r->d()->context->buffer()->setMiterLimit(ml);
|
||||
}
|
||||
|
@ -1952,7 +1954,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowBlur(QV4::CallContext *ct
|
|||
|
||||
qreal blur = ctx->argc() ? ctx->args()[0].toNumber() : -1;
|
||||
|
||||
if (blur > 0 && qIsFinite(blur) && blur != r->d()->context->state.shadowBlur) {
|
||||
if (blur > 0 && qt_is_finite(blur) && blur != r->d()->context->state.shadowBlur) {
|
||||
r->d()->context->state.shadowBlur = blur;
|
||||
r->d()->context->buffer()->setShadowBlur(blur);
|
||||
}
|
||||
|
@ -2012,7 +2014,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetX(QV4::CallContext
|
|||
CHECK_CONTEXT_SETTER(r)
|
||||
|
||||
qreal offsetX = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
|
||||
if (qIsFinite(offsetX) && offsetX != r->d()->context->state.shadowOffsetX) {
|
||||
if (qt_is_finite(offsetX) && offsetX != r->d()->context->state.shadowOffsetX) {
|
||||
r->d()->context->state.shadowOffsetX = offsetX;
|
||||
r->d()->context->buffer()->setShadowOffsetX(offsetX);
|
||||
}
|
||||
|
@ -2040,7 +2042,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetY(QV4::CallContext
|
|||
CHECK_CONTEXT_SETTER(r)
|
||||
|
||||
qreal offsetY = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
|
||||
if (qIsFinite(offsetY) && offsetY != r->d()->context->state.shadowOffsetY) {
|
||||
if (qt_is_finite(offsetY) && offsetY != r->d()->context->state.shadowOffsetY) {
|
||||
r->d()->context->state.shadowOffsetY = offsetY;
|
||||
r->d()->context->buffer()->setShadowOffsetY(offsetY);
|
||||
}
|
||||
|
@ -2170,7 +2172,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arc(QV4::CallContext *ctx)
|
|||
|
||||
qreal radius = ctx->args()[2].toNumber();
|
||||
|
||||
if (qIsFinite(radius) && radius < 0)
|
||||
if (qt_is_finite(radius) && radius < 0)
|
||||
V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
|
||||
|
||||
r->d()->context->arc(ctx->args()[0].toNumber(),
|
||||
|
@ -2216,7 +2218,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arcTo(QV4::CallContext *ct
|
|||
if (ctx->argc() >= 5) {
|
||||
qreal radius = ctx->args()[4].toNumber();
|
||||
|
||||
if (qIsFinite(radius) && radius < 0)
|
||||
if (qt_is_finite(radius) && radius < 0)
|
||||
V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
|
||||
|
||||
r->d()->context->arcTo(ctx->args()[0].toNumber(),
|
||||
|
@ -2279,7 +2281,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_bezierCurveTo(QV4::CallCon
|
|||
qreal x = ctx->args()[4].toNumber();
|
||||
qreal y = ctx->args()[5].toNumber();
|
||||
|
||||
if (!qIsFinite(cp1x) || !qIsFinite(cp1y) || !qIsFinite(cp2x) || !qIsFinite(cp2y) || !qIsFinite(x) || !qIsFinite(y))
|
||||
if (!qt_is_finite(cp1x) || !qt_is_finite(cp1y) || !qt_is_finite(cp2x) || !qt_is_finite(cp2y) || !qt_is_finite(x) || !qt_is_finite(y))
|
||||
return ctx->thisObject().asReturnedValue();
|
||||
|
||||
r->d()->context->bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
|
||||
|
@ -2375,7 +2377,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_lineTo(QV4::CallContext *c
|
|||
qreal x = ctx->args()[0].toNumber();
|
||||
qreal y = ctx->args()[1].toNumber();
|
||||
|
||||
if (!qIsFinite(x) || !qIsFinite(y))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y))
|
||||
return ctx->thisObject().asReturnedValue();
|
||||
|
||||
r->d()->context->lineTo(x, y);
|
||||
|
@ -2399,7 +2401,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_moveTo(QV4::CallContext *c
|
|||
qreal x = ctx->args()[0].toNumber();
|
||||
qreal y = ctx->args()[1].toNumber();
|
||||
|
||||
if (!qIsFinite(x) || !qIsFinite(y))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y))
|
||||
return ctx->thisObject().asReturnedValue();
|
||||
r->d()->context->moveTo(x, y);
|
||||
}
|
||||
|
@ -2425,7 +2427,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_quadraticCurveTo(QV4::Call
|
|||
qreal x = ctx->args()[2].toNumber();
|
||||
qreal y = ctx->args()[3].toNumber();
|
||||
|
||||
if (!qIsFinite(cpx) || !qIsFinite(cpy) || !qIsFinite(x) || !qIsFinite(y))
|
||||
if (!qt_is_finite(cpx) || !qt_is_finite(cpy) || !qt_is_finite(x) || !qt_is_finite(y))
|
||||
return ctx->thisObject().asReturnedValue();
|
||||
|
||||
r->d()->context->quadraticCurveTo(cpx, cpy, x, y);
|
||||
|
@ -2509,7 +2511,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_text(QV4::CallContext *ctx
|
|||
qreal x = ctx->args()[1].toNumber();
|
||||
qreal y = ctx->args()[2].toNumber();
|
||||
|
||||
if (!qIsFinite(x) || !qIsFinite(y))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y))
|
||||
return ctx->thisObject().asReturnedValue();
|
||||
r->d()->context->text(ctx->args()[0].toQStringNoThrow(), x, y);
|
||||
}
|
||||
|
@ -2774,7 +2776,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillText(QV4::CallContext
|
|||
if (ctx->argc() >= 3) {
|
||||
qreal x = ctx->args()[1].toNumber();
|
||||
qreal y = ctx->args()[2].toNumber();
|
||||
if (!qIsFinite(x) || !qIsFinite(y))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y))
|
||||
return ctx->thisObject().asReturnedValue();
|
||||
QPainterPath textPath = r->d()->context->createTextGlyphs(x, y, ctx->args()[0].toQStringNoThrow());
|
||||
r->d()->context->buffer()->fill(textPath);
|
||||
|
@ -2973,14 +2975,14 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext
|
|||
return ctx->thisObject().asReturnedValue();
|
||||
}
|
||||
|
||||
if (!qIsFinite(sx)
|
||||
|| !qIsFinite(sy)
|
||||
|| !qIsFinite(sw)
|
||||
|| !qIsFinite(sh)
|
||||
|| !qIsFinite(dx)
|
||||
|| !qIsFinite(dy)
|
||||
|| !qIsFinite(dw)
|
||||
|| !qIsFinite(dh))
|
||||
if (!qt_is_finite(sx)
|
||||
|| !qt_is_finite(sy)
|
||||
|| !qt_is_finite(sw)
|
||||
|| !qt_is_finite(sh)
|
||||
|| !qt_is_finite(dx)
|
||||
|| !qt_is_finite(dy)
|
||||
|| !qt_is_finite(dw)
|
||||
|| !qt_is_finite(dh))
|
||||
return ctx->thisObject().asReturnedValue();
|
||||
|
||||
if (sx < 0
|
||||
|
@ -3201,7 +3203,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::CallC
|
|||
qreal w = ctx->args()[0].toNumber();
|
||||
qreal h = ctx->args()[1].toNumber();
|
||||
|
||||
if (!qIsFinite(w) || !qIsFinite(h))
|
||||
if (!qt_is_finite(w) || !qt_is_finite(h))
|
||||
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createImageData(): invalid arguments");
|
||||
|
||||
if (w > 0 && h > 0)
|
||||
|
@ -3227,7 +3229,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData(QV4::CallCont
|
|||
qreal y = ctx->args()[1].toNumber();
|
||||
qreal w = ctx->args()[2].toNumber();
|
||||
qreal h = ctx->args()[3].toNumber();
|
||||
if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
|
||||
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "getImageData(): Invalid arguments");
|
||||
|
||||
if (w <= 0 || h <= 0)
|
||||
|
@ -3259,7 +3261,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallCont
|
|||
qreal dy = ctx->args()[2].toNumber();
|
||||
qreal w, h, dirtyX, dirtyY, dirtyWidth, dirtyHeight;
|
||||
|
||||
if (!qIsFinite(dx) || !qIsFinite(dy))
|
||||
if (!qt_is_finite(dx) || !qt_is_finite(dy))
|
||||
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
|
||||
|
||||
QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, arg0);
|
||||
|
@ -3277,7 +3279,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallCont
|
|||
dirtyWidth = ctx->args()[5].toNumber();
|
||||
dirtyHeight = ctx->args()[6].toNumber();
|
||||
|
||||
if (!qIsFinite(dirtyX) || !qIsFinite(dirtyY) || !qIsFinite(dirtyWidth) || !qIsFinite(dirtyHeight))
|
||||
if (!qt_is_finite(dirtyX) || !qt_is_finite(dirtyY) || !qt_is_finite(dirtyWidth) || !qt_is_finite(dirtyHeight))
|
||||
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
|
||||
|
||||
|
||||
|
@ -3364,7 +3366,7 @@ QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallCo
|
|||
} else {
|
||||
color = qt_color_from_string(ctx->args()[1]);
|
||||
}
|
||||
if (pos < 0.0 || pos > 1.0 || !qIsFinite(pos)) {
|
||||
if (pos < 0.0 || pos > 1.0 || !qt_is_finite(pos)) {
|
||||
V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "CanvasGradient: parameter offset out of range");
|
||||
}
|
||||
|
||||
|
@ -3384,7 +3386,7 @@ void QQuickContext2D::scale(qreal x, qreal y)
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(x) || !qIsFinite(y))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y))
|
||||
return;
|
||||
|
||||
QTransform newTransform = state.matrix;
|
||||
|
@ -3405,7 +3407,7 @@ void QQuickContext2D::rotate(qreal angle)
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(angle))
|
||||
if (!qt_is_finite(angle))
|
||||
return;
|
||||
|
||||
QTransform newTransform =state.matrix;
|
||||
|
@ -3426,7 +3428,7 @@ void QQuickContext2D::shear(qreal h, qreal v)
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(h) || !qIsFinite(v))
|
||||
if (!qt_is_finite(h) || !qt_is_finite(v))
|
||||
return ;
|
||||
|
||||
QTransform newTransform = state.matrix;
|
||||
|
@ -3447,7 +3449,7 @@ void QQuickContext2D::translate(qreal x, qreal y)
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(x) || !qIsFinite(y))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y))
|
||||
return ;
|
||||
|
||||
QTransform newTransform = state.matrix;
|
||||
|
@ -3468,7 +3470,7 @@ void QQuickContext2D::transform(qreal a, qreal b, qreal c, qreal d, qreal e, qre
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(a) || !qIsFinite(b) || !qIsFinite(c) || !qIsFinite(d) || !qIsFinite(e) || !qIsFinite(f))
|
||||
if (!qt_is_finite(a) || !qt_is_finite(b) || !qt_is_finite(c) || !qt_is_finite(d) || !qt_is_finite(e) || !qt_is_finite(f))
|
||||
return;
|
||||
|
||||
QTransform transform(a, b, c, d, e, f);
|
||||
|
@ -3485,7 +3487,7 @@ void QQuickContext2D::transform(qreal a, qreal b, qreal c, qreal d, qreal e, qre
|
|||
|
||||
void QQuickContext2D::setTransform(qreal a, qreal b, qreal c, qreal d, qreal e, qreal f)
|
||||
{
|
||||
if (!qIsFinite(a) || !qIsFinite(b) || !qIsFinite(c) || !qIsFinite(d) || !qIsFinite(e) || !qIsFinite(f))
|
||||
if (!qt_is_finite(a) || !qt_is_finite(b) || !qt_is_finite(c) || !qt_is_finite(d) || !qt_is_finite(e) || !qt_is_finite(f))
|
||||
return;
|
||||
|
||||
QTransform ctm = state.matrix;
|
||||
|
@ -3542,7 +3544,7 @@ void QQuickContext2D::fillRect(qreal x, qreal y, qreal w, qreal h)
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
|
||||
return;
|
||||
|
||||
buffer()->fillRect(QRectF(x, y, w, h));
|
||||
|
@ -3553,7 +3555,7 @@ void QQuickContext2D::strokeRect(qreal x, qreal y, qreal w, qreal h)
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
|
||||
return;
|
||||
|
||||
buffer()->strokeRect(QRectF(x, y, w, h));
|
||||
|
@ -3564,7 +3566,7 @@ void QQuickContext2D::clearRect(qreal x, qreal y, qreal w, qreal h)
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
|
||||
return;
|
||||
|
||||
buffer()->clearRect(QRectF(x, y, w, h));
|
||||
|
@ -3575,7 +3577,7 @@ void QQuickContext2D::drawText(const QString& text, qreal x, qreal y, bool fill)
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(x) || !qIsFinite(y))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y))
|
||||
return;
|
||||
|
||||
QPainterPath textPath = createTextGlyphs(x, y, text);
|
||||
|
@ -3721,7 +3723,7 @@ void QQuickContext2D::arcTo(qreal x1, qreal y1,
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(x1) || !qIsFinite(y1) || !qIsFinite(x2) || !qIsFinite(y2) || !qIsFinite(radius))
|
||||
if (!qt_is_finite(x1) || !qt_is_finite(y1) || !qt_is_finite(x2) || !qt_is_finite(y2) || !qt_is_finite(radius))
|
||||
return;
|
||||
|
||||
QPointF st(x1, y1);
|
||||
|
@ -3739,7 +3741,7 @@ void QQuickContext2D::rect(qreal x, qreal y, qreal w, qreal h)
|
|||
{
|
||||
if (!state.invertibleCTM)
|
||||
return;
|
||||
if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
|
||||
return;
|
||||
|
||||
if (!w && !h) {
|
||||
|
@ -3756,7 +3758,7 @@ void QQuickContext2D::roundedRect(qreal x, qreal y,
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h) || !qIsFinite(xr) || !qIsFinite(yr))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h) || !qt_is_finite(xr) || !qt_is_finite(yr))
|
||||
return;
|
||||
|
||||
if (!w && !h) {
|
||||
|
@ -3772,7 +3774,7 @@ void QQuickContext2D::ellipse(qreal x, qreal y,
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
|
||||
return;
|
||||
|
||||
if (!w && !h) {
|
||||
|
@ -3798,7 +3800,7 @@ void QQuickContext2D::arc(qreal xc, qreal yc, qreal radius, qreal sar, qreal ear
|
|||
if (!state.invertibleCTM)
|
||||
return;
|
||||
|
||||
if (!qIsFinite(xc) || !qIsFinite(yc) || !qIsFinite(sar) || !qIsFinite(ear) || !qIsFinite(radius))
|
||||
if (!qt_is_finite(xc) || !qt_is_finite(yc) || !qt_is_finite(sar) || !qt_is_finite(ear) || !qt_is_finite(radius))
|
||||
return;
|
||||
|
||||
if (sar == ear)
|
||||
|
@ -3937,13 +3939,13 @@ bool QQuickContext2D::isPointInPath(qreal x, qreal y) const
|
|||
if (!m_path.elementCount())
|
||||
return false;
|
||||
|
||||
if (!qIsFinite(x) || !qIsFinite(y))
|
||||
if (!qt_is_finite(x) || !qt_is_finite(y))
|
||||
return false;
|
||||
|
||||
QPointF point(x, y);
|
||||
QTransform ctm = state.matrix;
|
||||
QPointF p = ctm.inverted().map(point);
|
||||
if (!qIsFinite(p.x()) || !qIsFinite(p.y()))
|
||||
if (!qt_is_finite(p.x()) || !qt_is_finite(p.y()))
|
||||
return false;
|
||||
|
||||
const_cast<QQuickContext2D *>(this)->m_path.setFillRule(state.fillRule);
|
||||
|
|
|
@ -39,19 +39,48 @@
|
|||
|
||||
#include "qquickanchors_p_p.h"
|
||||
|
||||
#include "qquickitem.h"
|
||||
#include "qquickitem_p.h"
|
||||
|
||||
#include <qqmlinfo.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static Q_ALWAYS_INLINE QQuickItem *readParentItem(const QQuickItem *item)
|
||||
{
|
||||
return QQuickItemPrivate::get(item)->parentItem;
|
||||
}
|
||||
|
||||
static Q_ALWAYS_INLINE qreal readX(const QQuickItem *item)
|
||||
{
|
||||
return QQuickItemPrivate::get(item)->x;
|
||||
}
|
||||
|
||||
static Q_ALWAYS_INLINE qreal readY(const QQuickItem *item)
|
||||
{
|
||||
return QQuickItemPrivate::get(item)->y;
|
||||
}
|
||||
|
||||
static Q_ALWAYS_INLINE qreal readWidth(const QQuickItem *item)
|
||||
{
|
||||
return QQuickItemPrivate::get(item)->width;
|
||||
}
|
||||
|
||||
static Q_ALWAYS_INLINE qreal readHeight(const QQuickItem *item)
|
||||
{
|
||||
return QQuickItemPrivate::get(item)->height;
|
||||
}
|
||||
|
||||
static Q_ALWAYS_INLINE qreal readBaselineOffset(const QQuickItem *item)
|
||||
{
|
||||
return QQuickItemPrivate::get(item)->baselineOffset;
|
||||
}
|
||||
|
||||
//TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
|
||||
//TODO: support non-parent, non-sibling (need to find lowest common ancestor)
|
||||
|
||||
static inline qreal hcenter(QQuickItem const *item)
|
||||
static inline qreal hcenter(const QQuickItem *item)
|
||||
{
|
||||
qreal width = item->width();
|
||||
qreal width = readWidth(item);
|
||||
if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) {
|
||||
if (!QQuickAnchorsPrivate::get(anchors)->centerAligned)
|
||||
return width / 2;
|
||||
|
@ -63,9 +92,9 @@ static inline qreal hcenter(QQuickItem const *item)
|
|||
return width / 2;
|
||||
}
|
||||
|
||||
static inline qreal vcenter(QQuickItem const *item)
|
||||
static inline qreal vcenter(const QQuickItem *item)
|
||||
{
|
||||
qreal height = item->height();
|
||||
qreal height = readHeight(item);
|
||||
if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) {
|
||||
if (!QQuickAnchorsPrivate::get(anchors)->centerAligned)
|
||||
return height / 2;
|
||||
|
@ -78,30 +107,30 @@ static inline qreal vcenter(QQuickItem const *item)
|
|||
}
|
||||
|
||||
//local position
|
||||
static qreal position(QQuickItem const *item, QQuickAnchorLine::AnchorLine anchorLine)
|
||||
static inline qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
|
||||
{
|
||||
qreal ret = 0.0;
|
||||
switch (anchorLine) {
|
||||
case QQuickAnchorLine::Left:
|
||||
ret = item->x();
|
||||
case QQuickAnchors::LeftAnchor:
|
||||
ret = readX(item);
|
||||
break;
|
||||
case QQuickAnchorLine::Right:
|
||||
ret = item->x() + item->width();
|
||||
case QQuickAnchors::RightAnchor:
|
||||
ret = readX(item) + readWidth(item);
|
||||
break;
|
||||
case QQuickAnchorLine::Top:
|
||||
ret = item->y();
|
||||
case QQuickAnchors::TopAnchor:
|
||||
ret = readY(item);
|
||||
break;
|
||||
case QQuickAnchorLine::Bottom:
|
||||
ret = item->y() + item->height();
|
||||
case QQuickAnchors::BottomAnchor:
|
||||
ret = readY(item) + readHeight(item);
|
||||
break;
|
||||
case QQuickAnchorLine::HCenter:
|
||||
ret = item->x() + hcenter(item);
|
||||
case QQuickAnchors::HCenterAnchor:
|
||||
ret = readX(item) + hcenter(item);
|
||||
break;
|
||||
case QQuickAnchorLine::VCenter:
|
||||
ret = item->y() + vcenter(item);
|
||||
case QQuickAnchors::VCenterAnchor:
|
||||
ret = readY(item) + vcenter(item);
|
||||
break;
|
||||
case QQuickAnchorLine::Baseline:
|
||||
ret = item->y() + item->baselineOffset();
|
||||
case QQuickAnchors::BaselineAnchor:
|
||||
ret = readY(item) + readBaselineOffset(item);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -111,30 +140,30 @@ static qreal position(QQuickItem const *item, QQuickAnchorLine::AnchorLine ancho
|
|||
}
|
||||
|
||||
//position when origin is 0,0
|
||||
static qreal adjustedPosition(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine)
|
||||
static inline qreal adjustedPosition(QQuickItem *item, QQuickAnchors::Anchor anchorLine)
|
||||
{
|
||||
qreal ret = 0.0;
|
||||
switch (anchorLine) {
|
||||
case QQuickAnchorLine::Left:
|
||||
case QQuickAnchors::LeftAnchor:
|
||||
ret = 0.0;
|
||||
break;
|
||||
case QQuickAnchorLine::Right:
|
||||
ret = item->width();
|
||||
case QQuickAnchors::RightAnchor:
|
||||
ret = readWidth(item);
|
||||
break;
|
||||
case QQuickAnchorLine::Top:
|
||||
case QQuickAnchors::TopAnchor:
|
||||
ret = 0.0;
|
||||
break;
|
||||
case QQuickAnchorLine::Bottom:
|
||||
ret = item->height();
|
||||
case QQuickAnchors::BottomAnchor:
|
||||
ret = readHeight(item);
|
||||
break;
|
||||
case QQuickAnchorLine::HCenter:
|
||||
case QQuickAnchors::HCenterAnchor:
|
||||
ret = hcenter(item);
|
||||
break;
|
||||
case QQuickAnchorLine::VCenter:
|
||||
case QQuickAnchors::VCenterAnchor:
|
||||
ret = vcenter(item);
|
||||
break;
|
||||
case QQuickAnchorLine::Baseline:
|
||||
ret = item->baselineOffset();
|
||||
case QQuickAnchors::BaselineAnchor:
|
||||
ret = readBaselineOffset(item);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -154,13 +183,13 @@ QQuickAnchors::~QQuickAnchors()
|
|||
d->inDestructor = true;
|
||||
d->remDepend(d->fill);
|
||||
d->remDepend(d->centerIn);
|
||||
d->remDepend(d->left.item);
|
||||
d->remDepend(d->right.item);
|
||||
d->remDepend(d->top.item);
|
||||
d->remDepend(d->bottom.item);
|
||||
d->remDepend(d->vCenter.item);
|
||||
d->remDepend(d->hCenter.item);
|
||||
d->remDepend(d->baseline.item);
|
||||
d->remDepend(d->leftAnchorItem);
|
||||
d->remDepend(d->rightAnchorItem);
|
||||
d->remDepend(d->topAnchorItem);
|
||||
d->remDepend(d->bottomAnchorItem);
|
||||
d->remDepend(d->vCenterAnchorItem);
|
||||
d->remDepend(d->hCenterAnchorItem);
|
||||
d->remDepend(d->baselineAnchorItem);
|
||||
}
|
||||
|
||||
void QQuickAnchorsPrivate::fillChanged()
|
||||
|
@ -174,12 +203,13 @@ void QQuickAnchorsPrivate::fillChanged()
|
|||
|
||||
qreal horizontalMargin = q->mirrored() ? rightMargin : leftMargin;
|
||||
|
||||
if (fill == item->parentItem()) { //child-parent
|
||||
if (fill == readParentItem(item)) { //child-parent
|
||||
setItemPos(QPointF(horizontalMargin, topMargin));
|
||||
} else if (fill->parentItem() == item->parentItem()) { //siblings
|
||||
setItemPos(QPointF(fill->x()+horizontalMargin, fill->y()+topMargin));
|
||||
} else if (readParentItem(fill) == readParentItem(item)) { //siblings
|
||||
setItemPos(QPointF(readX(fill)+horizontalMargin, readY(fill) + topMargin));
|
||||
}
|
||||
setItemSize(QSizeF(fill->width()-leftMargin-rightMargin, fill->height()-topMargin-bottomMargin));
|
||||
setItemSize(QSizeF(readWidth(fill) - leftMargin - rightMargin,
|
||||
readHeight(fill) - topMargin - bottomMargin));
|
||||
|
||||
--updatingFill;
|
||||
} else {
|
||||
|
@ -199,12 +229,12 @@ void QQuickAnchorsPrivate::centerInChanged()
|
|||
++updatingCenterIn;
|
||||
|
||||
qreal effectiveHCenterOffset = q->mirrored() ? -hCenterOffset : hCenterOffset;
|
||||
if (centerIn == item->parentItem()) {
|
||||
QPointF p(hcenter(item->parentItem()) - hcenter(item) + effectiveHCenterOffset,
|
||||
vcenter(item->parentItem()) - vcenter(item) + vCenterOffset);
|
||||
if (centerIn == readParentItem(item)) {
|
||||
QPointF p(hcenter(readParentItem(item)) - hcenter(item) + effectiveHCenterOffset,
|
||||
vcenter(readParentItem(item)) - vcenter(item) + vCenterOffset);
|
||||
setItemPos(p);
|
||||
|
||||
} else if (centerIn->parentItem() == item->parentItem()) {
|
||||
} else if (readParentItem(centerIn) == readParentItem(item)) {
|
||||
QPointF p(centerIn->x() + hcenter(centerIn) - hcenter(item) + effectiveHCenterOffset,
|
||||
centerIn->y() + vcenter(centerIn) - vcenter(item) + vCenterOffset);
|
||||
setItemPos(p);
|
||||
|
@ -225,32 +255,32 @@ void QQuickAnchorsPrivate::clearItem(QQuickItem *item)
|
|||
fill = 0;
|
||||
if (centerIn == item)
|
||||
centerIn = 0;
|
||||
if (left.item == item) {
|
||||
left.item = 0;
|
||||
if (leftAnchorItem == item) {
|
||||
leftAnchorItem = 0;
|
||||
usedAnchors &= ~QQuickAnchors::LeftAnchor;
|
||||
}
|
||||
if (right.item == item) {
|
||||
right.item = 0;
|
||||
if (rightAnchorItem == item) {
|
||||
rightAnchorItem = 0;
|
||||
usedAnchors &= ~QQuickAnchors::RightAnchor;
|
||||
}
|
||||
if (top.item == item) {
|
||||
top.item = 0;
|
||||
if (topAnchorItem == item) {
|
||||
topAnchorItem = 0;
|
||||
usedAnchors &= ~QQuickAnchors::TopAnchor;
|
||||
}
|
||||
if (bottom.item == item) {
|
||||
bottom.item = 0;
|
||||
if (bottomAnchorItem == item) {
|
||||
bottomAnchorItem = 0;
|
||||
usedAnchors &= ~QQuickAnchors::BottomAnchor;
|
||||
}
|
||||
if (vCenter.item == item) {
|
||||
vCenter.item = 0;
|
||||
if (vCenterAnchorItem == item) {
|
||||
vCenterAnchorItem = 0;
|
||||
usedAnchors &= ~QQuickAnchors::VCenterAnchor;
|
||||
}
|
||||
if (hCenter.item == item) {
|
||||
hCenter.item = 0;
|
||||
if (hCenterAnchorItem == item) {
|
||||
hCenterAnchorItem = 0;
|
||||
usedAnchors &= ~QQuickAnchors::HCenterAnchor;
|
||||
}
|
||||
if (baseline.item == item) {
|
||||
baseline.item = 0;
|
||||
if (baselineAnchorItem == item) {
|
||||
baselineAnchorItem = 0;
|
||||
usedAnchors &= ~QQuickAnchors::BaselineAnchor;
|
||||
}
|
||||
}
|
||||
|
@ -263,7 +293,7 @@ int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem)
|
|||
return dependency;
|
||||
|
||||
if (fill == controlItem) {
|
||||
if (controlItem == item->parentItem())
|
||||
if (controlItem == readParentItem(item))
|
||||
dependency |= QQuickItemPrivate::SizeChange;
|
||||
else //sibling
|
||||
dependency |= QQuickItemPrivate::GeometryChange;
|
||||
|
@ -271,27 +301,27 @@ int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem)
|
|||
}
|
||||
|
||||
if (centerIn == controlItem) {
|
||||
if (controlItem == item->parentItem())
|
||||
if (controlItem == readParentItem(item))
|
||||
dependency |= QQuickItemPrivate::SizeChange;
|
||||
else //sibling
|
||||
dependency |= QQuickItemPrivate::GeometryChange;
|
||||
return dependency; //exit early
|
||||
}
|
||||
|
||||
if ((usedAnchors & QQuickAnchors::LeftAnchor && left.item == controlItem) ||
|
||||
(usedAnchors & QQuickAnchors::RightAnchor && right.item == controlItem) ||
|
||||
(usedAnchors & QQuickAnchors::HCenterAnchor && hCenter.item == controlItem)) {
|
||||
if (controlItem == item->parentItem())
|
||||
if ((usedAnchors & QQuickAnchors::LeftAnchor && leftAnchorItem == controlItem) ||
|
||||
(usedAnchors & QQuickAnchors::RightAnchor && rightAnchorItem == controlItem) ||
|
||||
(usedAnchors & QQuickAnchors::HCenterAnchor && hCenterAnchorItem == controlItem)) {
|
||||
if (controlItem == readParentItem(item))
|
||||
dependency |= QQuickItemPrivate::WidthChange;
|
||||
else //sibling
|
||||
dependency |= QFlags<QQuickItemPrivate::GeometryChangeType>(QQuickItemPrivate::XChange | QQuickItemPrivate::WidthChange);
|
||||
}
|
||||
|
||||
if ((usedAnchors & QQuickAnchors::TopAnchor && top.item == controlItem) ||
|
||||
(usedAnchors & QQuickAnchors::BottomAnchor && bottom.item == controlItem) ||
|
||||
(usedAnchors & QQuickAnchors::VCenterAnchor && vCenter.item == controlItem) ||
|
||||
(usedAnchors & QQuickAnchors::BaselineAnchor && baseline.item == controlItem)) {
|
||||
if (controlItem == item->parentItem())
|
||||
if ((usedAnchors & QQuickAnchors::TopAnchor && topAnchorItem == controlItem) ||
|
||||
(usedAnchors & QQuickAnchors::BottomAnchor && bottomAnchorItem == controlItem) ||
|
||||
(usedAnchors & QQuickAnchors::VCenterAnchor && vCenterAnchorItem == controlItem) ||
|
||||
(usedAnchors & QQuickAnchors::BaselineAnchor && baselineAnchorItem == controlItem)) {
|
||||
if (controlItem == readParentItem(item))
|
||||
dependency |= QQuickItemPrivate::HeightChange;
|
||||
else //sibling
|
||||
dependency |= QFlags<QQuickItemPrivate::GeometryChangeType>(QQuickItemPrivate::YChange | QQuickItemPrivate::HeightChange);
|
||||
|
@ -422,13 +452,13 @@ void QQuickAnchorsPrivate::updateOnComplete()
|
|||
QQuickItem *dependencies[9];
|
||||
dependencies[0] = fill;
|
||||
dependencies[1] = centerIn;
|
||||
dependencies[2] = left.item;
|
||||
dependencies[3] = right.item;
|
||||
dependencies[4] = hCenter.item;
|
||||
dependencies[5] = top.item;
|
||||
dependencies[6] = bottom.item;
|
||||
dependencies[7] = vCenter.item;
|
||||
dependencies[8] = baseline.item;
|
||||
dependencies[2] = leftAnchorItem;
|
||||
dependencies[3] = rightAnchorItem;
|
||||
dependencies[4] = hCenterAnchorItem;
|
||||
dependencies[5] = topAnchorItem;
|
||||
dependencies[6] = bottomAnchorItem;
|
||||
dependencies[7] = vCenterAnchorItem;
|
||||
dependencies[8] = baselineAnchorItem;
|
||||
|
||||
std::sort(dependencies, dependencies + 9);
|
||||
|
||||
|
@ -447,22 +477,38 @@ void QQuickAnchorsPrivate::updateOnComplete()
|
|||
|
||||
void QQuickAnchorsPrivate::update()
|
||||
{
|
||||
fillChanged();
|
||||
centerInChanged();
|
||||
if (usedAnchors & QQuickAnchorLine::Horizontal_Mask)
|
||||
updateHorizontalAnchors();
|
||||
if (usedAnchors & QQuickAnchorLine::Vertical_Mask)
|
||||
updateVerticalAnchors();
|
||||
if (!isItemComplete())
|
||||
return;
|
||||
|
||||
if (fill) {
|
||||
fillChanged();
|
||||
} else if (centerIn) {
|
||||
centerInChanged();
|
||||
} else {
|
||||
if (usedAnchors & QQuickAnchors::Horizontal_Mask)
|
||||
updateHorizontalAnchors();
|
||||
if (usedAnchors & QQuickAnchors::Vertical_Mask)
|
||||
updateVerticalAnchors();
|
||||
}
|
||||
}
|
||||
|
||||
void QQuickAnchorsPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newG, const QRectF &oldG)
|
||||
{
|
||||
fillChanged();
|
||||
centerInChanged();
|
||||
if ((usedAnchors & QQuickAnchorLine::Horizontal_Mask) && (newG.x() != oldG.x() || newG.width() != oldG.width()))
|
||||
updateHorizontalAnchors();
|
||||
if ((usedAnchors & QQuickAnchorLine::Vertical_Mask) && (newG.y() != oldG.y() || newG.height() != oldG.height()))
|
||||
updateVerticalAnchors();
|
||||
if (!isItemComplete())
|
||||
return;
|
||||
|
||||
if (fill) {
|
||||
fillChanged();
|
||||
} else if (centerIn) {
|
||||
centerInChanged();
|
||||
} else {
|
||||
if ((usedAnchors & QQuickAnchors::Horizontal_Mask)
|
||||
&& (newG.x() != oldG.x() || newG.width() != oldG.width()))
|
||||
updateHorizontalAnchors();
|
||||
if ((usedAnchors & QQuickAnchors::Vertical_Mask)
|
||||
&& (newG.y() != oldG.y() || newG.height() != oldG.height()))
|
||||
updateVerticalAnchors();
|
||||
}
|
||||
}
|
||||
|
||||
QQuickItem *QQuickAnchors::fill() const
|
||||
|
@ -484,7 +530,7 @@ void QQuickAnchors::setFill(QQuickItem *f)
|
|||
emit fillChanged();
|
||||
return;
|
||||
}
|
||||
if (f != d->item->parentItem() && f->parentItem() != d->item->parentItem()){
|
||||
if (f != readParentItem(d->item) && readParentItem(f) != readParentItem(d->item)){
|
||||
qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
|
||||
return;
|
||||
}
|
||||
|
@ -520,7 +566,7 @@ void QQuickAnchors::setCenterIn(QQuickItem* c)
|
|||
emit centerInChanged();
|
||||
return;
|
||||
}
|
||||
if (c != d->item->parentItem() && c->parentItem() != d->item->parentItem()){
|
||||
if (c != readParentItem(d->item) && readParentItem(c) != readParentItem(d->item)){
|
||||
qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
|
||||
return;
|
||||
}
|
||||
|
@ -537,29 +583,31 @@ void QQuickAnchors::resetCenterIn()
|
|||
setCenterIn(0);
|
||||
}
|
||||
|
||||
bool QQuickAnchorsPrivate::calcStretch(const QQuickAnchorLine &edge1,
|
||||
const QQuickAnchorLine &edge2,
|
||||
qreal offset1,
|
||||
qreal offset2,
|
||||
QQuickAnchorLine::AnchorLine line,
|
||||
qreal &stretch)
|
||||
bool QQuickAnchorsPrivate::calcStretch(QQuickItem *edge1Item,
|
||||
QQuickAnchors::Anchor edge1Line,
|
||||
QQuickItem *edge2Item,
|
||||
QQuickAnchors::Anchor edge2Line,
|
||||
qreal offset1,
|
||||
qreal offset2,
|
||||
QQuickAnchors::Anchor line,
|
||||
qreal &stretch)
|
||||
{
|
||||
bool edge1IsParent = (edge1.item == item->parentItem());
|
||||
bool edge2IsParent = (edge2.item == item->parentItem());
|
||||
bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem());
|
||||
bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem());
|
||||
bool edge1IsParent = (edge1Item == readParentItem(item));
|
||||
bool edge2IsParent = (edge2Item == readParentItem(item));
|
||||
bool edge1IsSibling = (readParentItem(edge1Item) == readParentItem(item));
|
||||
bool edge2IsSibling = (readParentItem(edge2Item) == readParentItem(item));
|
||||
|
||||
bool invalid = false;
|
||||
if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
|
||||
stretch = (position(edge2.item, edge2.anchorLine) + offset2)
|
||||
- (position(edge1.item, edge1.anchorLine) + offset1);
|
||||
stretch = (position(edge2Item, edge2Line) + offset2)
|
||||
- (position(edge1Item, edge1Line) + offset1);
|
||||
} else if (edge2IsParent && edge1IsSibling) {
|
||||
stretch = (position(edge2.item, edge2.anchorLine) + offset2)
|
||||
- (position(item->parentItem(), line)
|
||||
+ position(edge1.item, edge1.anchorLine) + offset1);
|
||||
stretch = (position(edge2Item, edge2Line) + offset2)
|
||||
- (position(readParentItem(item), line)
|
||||
+ position(edge1Item, edge1Line) + offset1);
|
||||
} else if (edge2IsSibling && edge1IsParent) {
|
||||
stretch = (position(item->parentItem(), line) + position(edge2.item, edge2.anchorLine) + offset2)
|
||||
- (position(edge1.item, edge1.anchorLine) + offset1);
|
||||
stretch = (position(readParentItem(item), line) + position(edge2Item, edge2Line) + offset2)
|
||||
- (position(edge1Item, edge1Line) + offset1);
|
||||
} else
|
||||
invalid = true;
|
||||
|
||||
|
@ -578,52 +626,60 @@ void QQuickAnchorsPrivate::updateVerticalAnchors()
|
|||
bool invalid = true;
|
||||
qreal height = 0.0;
|
||||
if (usedAnchors & QQuickAnchors::BottomAnchor) {
|
||||
invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QQuickAnchorLine::Top, height);
|
||||
invalid = calcStretch(topAnchorItem, topAnchorLine,
|
||||
bottomAnchorItem, bottomAnchorLine,
|
||||
topMargin, -bottomMargin, QQuickAnchors::TopAnchor, height);
|
||||
} else if (usedAnchors & QQuickAnchors::VCenterAnchor) {
|
||||
invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QQuickAnchorLine::Top, height);
|
||||
invalid = calcStretch(topAnchorItem, topAnchorLine,
|
||||
vCenterAnchorItem, vCenterAnchorLine,
|
||||
topMargin, vCenterOffset, QQuickAnchors::TopAnchor, height);
|
||||
height *= 2;
|
||||
}
|
||||
if (!invalid)
|
||||
setItemHeight(height);
|
||||
|
||||
//Handle top
|
||||
if (top.item == item->parentItem()) {
|
||||
setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin);
|
||||
} else if (top.item->parentItem() == item->parentItem()) {
|
||||
setItemY(position(top.item, top.anchorLine) + topMargin);
|
||||
if (topAnchorItem == readParentItem(item)) {
|
||||
setItemY(adjustedPosition(topAnchorItem, topAnchorLine) + topMargin);
|
||||
} else if (readParentItem(topAnchorItem) == readParentItem(item)) {
|
||||
setItemY(position(topAnchorItem, topAnchorLine) + topMargin);
|
||||
}
|
||||
} else if (usedAnchors & QQuickAnchors::BottomAnchor) {
|
||||
//Handle stretching (top + bottom case is handled above)
|
||||
if (usedAnchors & QQuickAnchors::VCenterAnchor) {
|
||||
qreal height = 0.0;
|
||||
bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin,
|
||||
QQuickAnchorLine::Top, height);
|
||||
bool invalid = calcStretch(vCenterAnchorItem, vCenterAnchorLine,
|
||||
bottomAnchorItem, bottomAnchorLine,
|
||||
vCenterOffset, -bottomMargin, QQuickAnchors::TopAnchor,
|
||||
height);
|
||||
if (!invalid)
|
||||
setItemHeight(height*2);
|
||||
}
|
||||
|
||||
//Handle bottom
|
||||
if (bottom.item == item->parentItem()) {
|
||||
setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
|
||||
} else if (bottom.item->parentItem() == item->parentItem()) {
|
||||
setItemY(position(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
|
||||
if (bottomAnchorItem == readParentItem(item)) {
|
||||
setItemY(adjustedPosition(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin);
|
||||
} else if (readParentItem(bottomAnchorItem) == readParentItem(item)) {
|
||||
setItemY(position(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin);
|
||||
}
|
||||
} else if (usedAnchors & QQuickAnchors::VCenterAnchor) {
|
||||
//(stetching handled above)
|
||||
|
||||
//Handle vCenter
|
||||
if (vCenter.item == item->parentItem()) {
|
||||
setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine)
|
||||
if (vCenterAnchorItem == readParentItem(item)) {
|
||||
setItemY(adjustedPosition(vCenterAnchorItem, vCenterAnchorLine)
|
||||
- vcenter(item) + vCenterOffset);
|
||||
} else if (vCenter.item->parentItem() == item->parentItem()) {
|
||||
setItemY(position(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset);
|
||||
} else if (readParentItem(vCenterAnchorItem) == readParentItem(item)) {
|
||||
setItemY(position(vCenterAnchorItem, vCenterAnchorLine) - vcenter(item) + vCenterOffset);
|
||||
}
|
||||
} else if (usedAnchors & QQuickAnchors::BaselineAnchor) {
|
||||
//Handle baseline
|
||||
if (baseline.item == item->parentItem()) {
|
||||
setItemY(adjustedPosition(baseline.item, baseline.anchorLine) - item->baselineOffset() + baselineOffset);
|
||||
} else if (baseline.item->parentItem() == item->parentItem()) {
|
||||
setItemY(position(baseline.item, baseline.anchorLine) - item->baselineOffset() + baselineOffset);
|
||||
if (baselineAnchorItem == readParentItem(item)) {
|
||||
setItemY(adjustedPosition(baselineAnchorItem, baselineAnchorLine)
|
||||
- readBaselineOffset(item) + baselineOffset);
|
||||
} else if (readParentItem(baselineAnchorItem) == readParentItem(item)) {
|
||||
setItemY(position(baselineAnchorItem, baselineAnchorLine)
|
||||
- readBaselineOffset(item) + baselineOffset);
|
||||
}
|
||||
}
|
||||
--updatingVerticalAnchor;
|
||||
|
@ -633,12 +689,12 @@ void QQuickAnchorsPrivate::updateVerticalAnchors()
|
|||
}
|
||||
}
|
||||
|
||||
inline QQuickAnchorLine::AnchorLine reverseAnchorLine(QQuickAnchorLine::AnchorLine anchorLine)
|
||||
static inline QQuickAnchors::Anchor reverseAnchorLine(QQuickAnchors::Anchor anchorLine)
|
||||
{
|
||||
if (anchorLine == QQuickAnchorLine::Left) {
|
||||
return QQuickAnchorLine::Right;
|
||||
} else if (anchorLine == QQuickAnchorLine::Right) {
|
||||
return QQuickAnchorLine::Left;
|
||||
if (anchorLine == QQuickAnchors::LeftAnchor) {
|
||||
return QQuickAnchors::RightAnchor;
|
||||
} else if (anchorLine == QQuickAnchors::RightAnchor) {
|
||||
return QQuickAnchors::LeftAnchor;
|
||||
} else {
|
||||
return anchorLine;
|
||||
}
|
||||
|
@ -653,26 +709,30 @@ void QQuickAnchorsPrivate::updateHorizontalAnchors()
|
|||
if (updatingHorizontalAnchor < 3) {
|
||||
++updatingHorizontalAnchor;
|
||||
qreal effectiveRightMargin, effectiveLeftMargin, effectiveHorizontalCenterOffset;
|
||||
QQuickAnchorLine effectiveLeft, effectiveRight, effectiveHorizontalCenter;
|
||||
QQuickItem *effectiveLeftItem, *effectiveRightItem, *effectiveHorizontalCenterItem;
|
||||
QQuickAnchors::Anchor effectiveLeftLine, effectiveRightLine, effectiveHorizontalCenterLine;
|
||||
QQuickAnchors::Anchor effectiveLeftAnchor, effectiveRightAnchor;
|
||||
if (q->mirrored()) {
|
||||
effectiveLeftAnchor = QQuickAnchors::RightAnchor;
|
||||
effectiveRightAnchor = QQuickAnchors::LeftAnchor;
|
||||
effectiveLeft.item = right.item;
|
||||
effectiveLeft.anchorLine = reverseAnchorLine(right.anchorLine);
|
||||
effectiveRight.item = left.item;
|
||||
effectiveRight.anchorLine = reverseAnchorLine(left.anchorLine);
|
||||
effectiveHorizontalCenter.item = hCenter.item;
|
||||
effectiveHorizontalCenter.anchorLine = reverseAnchorLine(hCenter.anchorLine);
|
||||
effectiveLeftItem = rightAnchorItem;
|
||||
effectiveLeftLine = reverseAnchorLine(rightAnchorLine);
|
||||
effectiveRightItem = leftAnchorItem;
|
||||
effectiveRightLine = reverseAnchorLine(leftAnchorLine);
|
||||
effectiveHorizontalCenterItem = hCenterAnchorItem;
|
||||
effectiveHorizontalCenterLine = reverseAnchorLine(hCenterAnchorLine);
|
||||
effectiveLeftMargin = rightMargin;
|
||||
effectiveRightMargin = leftMargin;
|
||||
effectiveHorizontalCenterOffset = -hCenterOffset;
|
||||
} else {
|
||||
effectiveLeftAnchor = QQuickAnchors::LeftAnchor;
|
||||
effectiveRightAnchor = QQuickAnchors::RightAnchor;
|
||||
effectiveLeft = left;
|
||||
effectiveRight = right;
|
||||
effectiveHorizontalCenter = hCenter;
|
||||
effectiveLeftItem = leftAnchorItem;
|
||||
effectiveLeftLine = leftAnchorLine;
|
||||
effectiveRightItem = rightAnchorItem;
|
||||
effectiveRightLine = rightAnchorLine;
|
||||
effectiveHorizontalCenterItem = hCenterAnchorItem;
|
||||
effectiveHorizontalCenterLine = hCenterAnchorLine;
|
||||
effectiveLeftMargin = leftMargin;
|
||||
effectiveRightMargin = rightMargin;
|
||||
effectiveHorizontalCenterOffset = hCenterOffset;
|
||||
|
@ -683,42 +743,53 @@ void QQuickAnchorsPrivate::updateHorizontalAnchors()
|
|||
bool invalid = true;
|
||||
qreal width = 0.0;
|
||||
if (usedAnchors & effectiveRightAnchor) {
|
||||
invalid = calcStretch(effectiveLeft, effectiveRight, effectiveLeftMargin, -effectiveRightMargin, QQuickAnchorLine::Left, width);
|
||||
invalid = calcStretch(effectiveLeftItem, effectiveLeftLine,
|
||||
effectiveRightItem, effectiveRightLine,
|
||||
effectiveLeftMargin, -effectiveRightMargin,
|
||||
QQuickAnchors::LeftAnchor, width);
|
||||
} else if (usedAnchors & QQuickAnchors::HCenterAnchor) {
|
||||
invalid = calcStretch(effectiveLeft, effectiveHorizontalCenter, effectiveLeftMargin, effectiveHorizontalCenterOffset, QQuickAnchorLine::Left, width);
|
||||
invalid = calcStretch(effectiveLeftItem, effectiveLeftLine,
|
||||
effectiveHorizontalCenterItem, effectiveHorizontalCenterLine,
|
||||
effectiveLeftMargin, effectiveHorizontalCenterOffset,
|
||||
QQuickAnchors::LeftAnchor, width);
|
||||
width *= 2;
|
||||
}
|
||||
if (!invalid)
|
||||
setItemWidth(width);
|
||||
|
||||
//Handle left
|
||||
if (effectiveLeft.item == item->parentItem()) {
|
||||
setItemX(adjustedPosition(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin);
|
||||
} else if (effectiveLeft.item->parentItem() == item->parentItem()) {
|
||||
setItemX(position(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin);
|
||||
if (effectiveLeftItem == readParentItem(item)) {
|
||||
setItemX(adjustedPosition(effectiveLeftItem, effectiveLeftLine) + effectiveLeftMargin);
|
||||
} else if (readParentItem(effectiveLeftItem) == readParentItem(item)) {
|
||||
setItemX(position(effectiveLeftItem, effectiveLeftLine) + effectiveLeftMargin);
|
||||
}
|
||||
} else if (usedAnchors & effectiveRightAnchor) {
|
||||
//Handle stretching (left + right case is handled in updateLeftAnchor)
|
||||
if (usedAnchors & QQuickAnchors::HCenterAnchor) {
|
||||
qreal width = 0.0;
|
||||
bool invalid = calcStretch(effectiveHorizontalCenter, effectiveRight, effectiveHorizontalCenterOffset, -effectiveRightMargin,
|
||||
QQuickAnchorLine::Left, width);
|
||||
bool invalid = calcStretch(effectiveHorizontalCenterItem,
|
||||
effectiveHorizontalCenterLine,
|
||||
effectiveRightItem, effectiveRightLine,
|
||||
effectiveHorizontalCenterOffset, -effectiveRightMargin,
|
||||
QQuickAnchors::LeftAnchor, width);
|
||||
if (!invalid)
|
||||
setItemWidth(width*2);
|
||||
}
|
||||
|
||||
//Handle right
|
||||
if (effectiveRight.item == item->parentItem()) {
|
||||
setItemX(adjustedPosition(effectiveRight.item, effectiveRight.anchorLine) - item->width() - effectiveRightMargin);
|
||||
} else if (effectiveRight.item->parentItem() == item->parentItem()) {
|
||||
setItemX(position(effectiveRight.item, effectiveRight.anchorLine) - item->width() - effectiveRightMargin);
|
||||
if (effectiveRightItem == readParentItem(item)) {
|
||||
setItemX(adjustedPosition(effectiveRightItem, effectiveRightLine)
|
||||
- readWidth(item) - effectiveRightMargin);
|
||||
} else if (readParentItem(effectiveRightItem) == readParentItem(item)) {
|
||||
setItemX(position(effectiveRightItem, effectiveRightLine)
|
||||
- readWidth(item) - effectiveRightMargin);
|
||||
}
|
||||
} else if (usedAnchors & QQuickAnchors::HCenterAnchor) {
|
||||
//Handle hCenter
|
||||
if (effectiveHorizontalCenter.item == item->parentItem()) {
|
||||
setItemX(adjustedPosition(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset);
|
||||
} else if (effectiveHorizontalCenter.item->parentItem() == item->parentItem()) {
|
||||
setItemX(position(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset);
|
||||
if (effectiveHorizontalCenterItem == readParentItem(item)) {
|
||||
setItemX(adjustedPosition(effectiveHorizontalCenterItem, effectiveHorizontalCenterLine) - hcenter(item) + effectiveHorizontalCenterOffset);
|
||||
} else if (readParentItem(effectiveHorizontalCenterItem) == readParentItem(item)) {
|
||||
setItemX(position(effectiveHorizontalCenterItem, effectiveHorizontalCenterLine) - hcenter(item) + effectiveHorizontalCenterOffset);
|
||||
}
|
||||
}
|
||||
--updatingHorizontalAnchor;
|
||||
|
@ -731,13 +802,14 @@ void QQuickAnchorsPrivate::updateHorizontalAnchors()
|
|||
QQuickAnchorLine QQuickAnchors::top() const
|
||||
{
|
||||
Q_D(const QQuickAnchors);
|
||||
return d->top;
|
||||
return QQuickAnchorLine(d->topAnchorItem, d->topAnchorLine);
|
||||
}
|
||||
|
||||
void QQuickAnchors::setTop(const QQuickAnchorLine &edge)
|
||||
{
|
||||
Q_D(QQuickAnchors);
|
||||
if (!d->checkVAnchorValid(edge) || d->top == edge)
|
||||
if (!d->checkVAnchorValid(edge) ||
|
||||
(d->topAnchorItem == edge.item && d->topAnchorLine == edge.anchorLine))
|
||||
return;
|
||||
|
||||
d->usedAnchors |= TopAnchor;
|
||||
|
@ -747,10 +819,11 @@ void QQuickAnchors::setTop(const QQuickAnchorLine &edge)
|
|||
return;
|
||||
}
|
||||
|
||||
QQuickItem *oldTop = d->top.item;
|
||||
d->top = edge;
|
||||
QQuickItem *oldTop = d->topAnchorItem;
|
||||
d->topAnchorItem = edge.item;
|
||||
d->topAnchorLine = edge.anchorLine;
|
||||
d->remDepend(oldTop);
|
||||
d->addDepend(d->top.item);
|
||||
d->addDepend(d->topAnchorItem);
|
||||
emit topChanged();
|
||||
d->updateVerticalAnchors();
|
||||
}
|
||||
|
@ -759,8 +832,9 @@ void QQuickAnchors::resetTop()
|
|||
{
|
||||
Q_D(QQuickAnchors);
|
||||
d->usedAnchors &= ~TopAnchor;
|
||||
d->remDepend(d->top.item);
|
||||
d->top = QQuickAnchorLine();
|
||||
d->remDepend(d->topAnchorItem);
|
||||
d->topAnchorItem = Q_NULLPTR;
|
||||
d->topAnchorLine = QQuickAnchors::InvalidAnchor;
|
||||
emit topChanged();
|
||||
d->updateVerticalAnchors();
|
||||
}
|
||||
|
@ -768,13 +842,14 @@ void QQuickAnchors::resetTop()
|
|||
QQuickAnchorLine QQuickAnchors::bottom() const
|
||||
{
|
||||
Q_D(const QQuickAnchors);
|
||||
return d->bottom;
|
||||
return QQuickAnchorLine(d->bottomAnchorItem, d->bottomAnchorLine);
|
||||
}
|
||||
|
||||
void QQuickAnchors::setBottom(const QQuickAnchorLine &edge)
|
||||
{
|
||||
Q_D(QQuickAnchors);
|
||||
if (!d->checkVAnchorValid(edge) || d->bottom == edge)
|
||||
if (!d->checkVAnchorValid(edge) ||
|
||||
(d->bottomAnchorItem == edge.item && d->bottomAnchorLine == edge.anchorLine))
|
||||
return;
|
||||
|
||||
d->usedAnchors |= BottomAnchor;
|
||||
|
@ -784,10 +859,11 @@ void QQuickAnchors::setBottom(const QQuickAnchorLine &edge)
|
|||
return;
|
||||
}
|
||||
|
||||
QQuickItem *oldBottom = d->bottom.item;
|
||||
d->bottom = edge;
|
||||
QQuickItem *oldBottom = d->bottomAnchorItem;
|
||||
d->bottomAnchorItem = edge.item;
|
||||
d->bottomAnchorLine = edge.anchorLine;
|
||||
d->remDepend(oldBottom);
|
||||
d->addDepend(d->bottom.item);
|
||||
d->addDepend(d->bottomAnchorItem);
|
||||
emit bottomChanged();
|
||||
d->updateVerticalAnchors();
|
||||
}
|
||||
|
@ -796,8 +872,9 @@ void QQuickAnchors::resetBottom()
|
|||
{
|
||||
Q_D(QQuickAnchors);
|
||||
d->usedAnchors &= ~BottomAnchor;
|
||||
d->remDepend(d->bottom.item);
|
||||
d->bottom = QQuickAnchorLine();
|
||||
d->remDepend(d->bottomAnchorItem);
|
||||
d->bottomAnchorItem = Q_NULLPTR;
|
||||
d->bottomAnchorLine = QQuickAnchors::InvalidAnchor;
|
||||
emit bottomChanged();
|
||||
d->updateVerticalAnchors();
|
||||
}
|
||||
|
@ -805,13 +882,14 @@ void QQuickAnchors::resetBottom()
|
|||
QQuickAnchorLine QQuickAnchors::verticalCenter() const
|
||||
{
|
||||
Q_D(const QQuickAnchors);
|
||||
return d->vCenter;
|
||||
return QQuickAnchorLine(d->vCenterAnchorItem, d->vCenterAnchorLine);
|
||||
}
|
||||
|
||||
void QQuickAnchors::setVerticalCenter(const QQuickAnchorLine &edge)
|
||||
{
|
||||
Q_D(QQuickAnchors);
|
||||
if (!d->checkVAnchorValid(edge) || d->vCenter == edge)
|
||||
if (!d->checkVAnchorValid(edge) ||
|
||||
(d->vCenterAnchorItem == edge.item && d->vCenterAnchorLine == edge.anchorLine))
|
||||
return;
|
||||
|
||||
d->usedAnchors |= VCenterAnchor;
|
||||
|
@ -821,10 +899,11 @@ void QQuickAnchors::setVerticalCenter(const QQuickAnchorLine &edge)
|
|||
return;
|
||||
}
|
||||
|
||||
QQuickItem *oldVCenter = d->vCenter.item;
|
||||
d->vCenter = edge;
|
||||
QQuickItem *oldVCenter = d->vCenterAnchorItem;
|
||||
d->vCenterAnchorItem = edge.item;
|
||||
d->vCenterAnchorLine = edge.anchorLine;
|
||||
d->remDepend(oldVCenter);
|
||||
d->addDepend(d->vCenter.item);
|
||||
d->addDepend(d->vCenterAnchorItem);
|
||||
emit verticalCenterChanged();
|
||||
d->updateVerticalAnchors();
|
||||
}
|
||||
|
@ -833,8 +912,9 @@ void QQuickAnchors::resetVerticalCenter()
|
|||
{
|
||||
Q_D(QQuickAnchors);
|
||||
d->usedAnchors &= ~VCenterAnchor;
|
||||
d->remDepend(d->vCenter.item);
|
||||
d->vCenter = QQuickAnchorLine();
|
||||
d->remDepend(d->vCenterAnchorItem);
|
||||
d->vCenterAnchorItem = Q_NULLPTR;
|
||||
d->vCenterAnchorLine = QQuickAnchors::InvalidAnchor;
|
||||
emit verticalCenterChanged();
|
||||
d->updateVerticalAnchors();
|
||||
}
|
||||
|
@ -842,13 +922,14 @@ void QQuickAnchors::resetVerticalCenter()
|
|||
QQuickAnchorLine QQuickAnchors::baseline() const
|
||||
{
|
||||
Q_D(const QQuickAnchors);
|
||||
return d->baseline;
|
||||
return QQuickAnchorLine(d->baselineAnchorItem, d->baselineAnchorLine);
|
||||
}
|
||||
|
||||
void QQuickAnchors::setBaseline(const QQuickAnchorLine &edge)
|
||||
{
|
||||
Q_D(QQuickAnchors);
|
||||
if (!d->checkVAnchorValid(edge) || d->baseline == edge)
|
||||
if (!d->checkVAnchorValid(edge) ||
|
||||
(d->baselineAnchorItem == edge.item && d->baselineAnchorLine == edge.anchorLine))
|
||||
return;
|
||||
|
||||
d->usedAnchors |= BaselineAnchor;
|
||||
|
@ -858,10 +939,11 @@ void QQuickAnchors::setBaseline(const QQuickAnchorLine &edge)
|
|||
return;
|
||||
}
|
||||
|
||||
QQuickItem *oldBaseline = d->baseline.item;
|
||||
d->baseline = edge;
|
||||
QQuickItem *oldBaseline = d->baselineAnchorItem;
|
||||
d->baselineAnchorItem = edge.item;
|
||||
d->baselineAnchorLine = edge.anchorLine;
|
||||
d->remDepend(oldBaseline);
|
||||
d->addDepend(d->baseline.item);
|
||||
d->addDepend(d->baselineAnchorItem);
|
||||
emit baselineChanged();
|
||||
d->updateVerticalAnchors();
|
||||
}
|
||||
|
@ -870,8 +952,9 @@ void QQuickAnchors::resetBaseline()
|
|||
{
|
||||
Q_D(QQuickAnchors);
|
||||
d->usedAnchors &= ~BaselineAnchor;
|
||||
d->remDepend(d->baseline.item);
|
||||
d->baseline = QQuickAnchorLine();
|
||||
d->remDepend(d->baselineAnchorItem);
|
||||
d->baselineAnchorItem = Q_NULLPTR;
|
||||
d->baselineAnchorLine = QQuickAnchors::InvalidAnchor;
|
||||
emit baselineChanged();
|
||||
d->updateVerticalAnchors();
|
||||
}
|
||||
|
@ -879,13 +962,14 @@ void QQuickAnchors::resetBaseline()
|
|||
QQuickAnchorLine QQuickAnchors::left() const
|
||||
{
|
||||
Q_D(const QQuickAnchors);
|
||||
return d->left;
|
||||
return QQuickAnchorLine(d->leftAnchorItem, d->leftAnchorLine);
|
||||
}
|
||||
|
||||
void QQuickAnchors::setLeft(const QQuickAnchorLine &edge)
|
||||
{
|
||||
Q_D(QQuickAnchors);
|
||||
if (!d->checkHAnchorValid(edge) || d->left == edge)
|
||||
if (!d->checkHAnchorValid(edge) ||
|
||||
(d->leftAnchorItem == edge.item && d->leftAnchorLine == edge.anchorLine))
|
||||
return;
|
||||
|
||||
d->usedAnchors |= LeftAnchor;
|
||||
|
@ -895,10 +979,11 @@ void QQuickAnchors::setLeft(const QQuickAnchorLine &edge)
|
|||
return;
|
||||
}
|
||||
|
||||
QQuickItem *oldLeft = d->left.item;
|
||||
d->left = edge;
|
||||
QQuickItem *oldLeft = d->leftAnchorItem;
|
||||
d->leftAnchorItem = edge.item;
|
||||
d->leftAnchorLine = edge.anchorLine;
|
||||
d->remDepend(oldLeft);
|
||||
d->addDepend(d->left.item);
|
||||
d->addDepend(d->leftAnchorItem);
|
||||
emit leftChanged();
|
||||
d->updateHorizontalAnchors();
|
||||
}
|
||||
|
@ -907,8 +992,9 @@ void QQuickAnchors::resetLeft()
|
|||
{
|
||||
Q_D(QQuickAnchors);
|
||||
d->usedAnchors &= ~LeftAnchor;
|
||||
d->remDepend(d->left.item);
|
||||
d->left = QQuickAnchorLine();
|
||||
d->remDepend(d->leftAnchorItem);
|
||||
d->leftAnchorItem = Q_NULLPTR;
|
||||
d->leftAnchorLine = QQuickAnchors::InvalidAnchor;
|
||||
emit leftChanged();
|
||||
d->updateHorizontalAnchors();
|
||||
}
|
||||
|
@ -916,13 +1002,14 @@ void QQuickAnchors::resetLeft()
|
|||
QQuickAnchorLine QQuickAnchors::right() const
|
||||
{
|
||||
Q_D(const QQuickAnchors);
|
||||
return d->right;
|
||||
return QQuickAnchorLine(d->rightAnchorItem, d->rightAnchorLine);
|
||||
}
|
||||
|
||||
void QQuickAnchors::setRight(const QQuickAnchorLine &edge)
|
||||
{
|
||||
Q_D(QQuickAnchors);
|
||||
if (!d->checkHAnchorValid(edge) || d->right == edge)
|
||||
if (!d->checkHAnchorValid(edge) ||
|
||||
(d->rightAnchorItem == edge.item && d->rightAnchorLine == edge.anchorLine))
|
||||
return;
|
||||
|
||||
d->usedAnchors |= RightAnchor;
|
||||
|
@ -932,10 +1019,11 @@ void QQuickAnchors::setRight(const QQuickAnchorLine &edge)
|
|||
return;
|
||||
}
|
||||
|
||||
QQuickItem *oldRight = d->right.item;
|
||||
d->right = edge;
|
||||
QQuickItem *oldRight = d->rightAnchorItem;
|
||||
d->rightAnchorItem = edge.item;
|
||||
d->rightAnchorLine = edge.anchorLine;
|
||||
d->remDepend(oldRight);
|
||||
d->addDepend(d->right.item);
|
||||
d->addDepend(d->rightAnchorItem);
|
||||
emit rightChanged();
|
||||
d->updateHorizontalAnchors();
|
||||
}
|
||||
|
@ -944,8 +1032,9 @@ void QQuickAnchors::resetRight()
|
|||
{
|
||||
Q_D(QQuickAnchors);
|
||||
d->usedAnchors &= ~RightAnchor;
|
||||
d->remDepend(d->right.item);
|
||||
d->right = QQuickAnchorLine();
|
||||
d->remDepend(d->rightAnchorItem);
|
||||
d->rightAnchorItem = Q_NULLPTR;
|
||||
d->rightAnchorLine = QQuickAnchors::InvalidAnchor;
|
||||
emit rightChanged();
|
||||
d->updateHorizontalAnchors();
|
||||
}
|
||||
|
@ -953,13 +1042,14 @@ void QQuickAnchors::resetRight()
|
|||
QQuickAnchorLine QQuickAnchors::horizontalCenter() const
|
||||
{
|
||||
Q_D(const QQuickAnchors);
|
||||
return d->hCenter;
|
||||
return QQuickAnchorLine(d->hCenterAnchorItem, d->hCenterAnchorLine);
|
||||
}
|
||||
|
||||
void QQuickAnchors::setHorizontalCenter(const QQuickAnchorLine &edge)
|
||||
{
|
||||
Q_D(QQuickAnchors);
|
||||
if (!d->checkHAnchorValid(edge) || d->hCenter == edge)
|
||||
if (!d->checkHAnchorValid(edge) ||
|
||||
(d->hCenterAnchorItem == edge.item && d->hCenterAnchorLine == edge.anchorLine))
|
||||
return;
|
||||
|
||||
d->usedAnchors |= HCenterAnchor;
|
||||
|
@ -969,10 +1059,11 @@ void QQuickAnchors::setHorizontalCenter(const QQuickAnchorLine &edge)
|
|||
return;
|
||||
}
|
||||
|
||||
QQuickItem *oldHCenter = d->hCenter.item;
|
||||
d->hCenter = edge;
|
||||
QQuickItem *oldHCenter = d->hCenterAnchorItem;
|
||||
d->hCenterAnchorItem = edge.item;
|
||||
d->hCenterAnchorLine = edge.anchorLine;
|
||||
d->remDepend(oldHCenter);
|
||||
d->addDepend(d->hCenter.item);
|
||||
d->addDepend(d->hCenterAnchorItem);
|
||||
emit horizontalCenterChanged();
|
||||
d->updateHorizontalAnchors();
|
||||
}
|
||||
|
@ -981,8 +1072,9 @@ void QQuickAnchors::resetHorizontalCenter()
|
|||
{
|
||||
Q_D(QQuickAnchors);
|
||||
d->usedAnchors &= ~HCenterAnchor;
|
||||
d->remDepend(d->hCenter.item);
|
||||
d->hCenter = QQuickAnchorLine();
|
||||
d->remDepend(d->hCenterAnchorItem);
|
||||
d->hCenterAnchorItem = Q_NULLPTR;
|
||||
d->hCenterAnchorLine = QQuickAnchors::InvalidAnchor;
|
||||
emit horizontalCenterChanged();
|
||||
d->updateHorizontalAnchors();
|
||||
}
|
||||
|
@ -1230,7 +1322,7 @@ void QQuickAnchors::setBaselineOffset(qreal offset)
|
|||
QQuickAnchors::Anchors QQuickAnchors::usedAnchors() const
|
||||
{
|
||||
Q_D(const QQuickAnchors);
|
||||
return d->usedAnchors;
|
||||
return static_cast<QQuickAnchors::Anchors>(d->usedAnchors);
|
||||
}
|
||||
|
||||
bool QQuickAnchorsPrivate::checkHValid() const
|
||||
|
@ -1250,10 +1342,11 @@ bool QQuickAnchorsPrivate::checkHAnchorValid(QQuickAnchorLine anchor) const
|
|||
if (!anchor.item) {
|
||||
qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to a null item.");
|
||||
return false;
|
||||
} else if (anchor.anchorLine & QQuickAnchorLine::Vertical_Mask) {
|
||||
} else if (anchor.anchorLine & QQuickAnchors::Vertical_Mask) {
|
||||
qmlInfo(item) << QQuickAnchors::tr("Cannot anchor a horizontal edge to a vertical edge.");
|
||||
return false;
|
||||
} else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
|
||||
} else if (anchor.item != readParentItem(item)
|
||||
&& readParentItem(anchor.item) != readParentItem(item)) {
|
||||
qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
|
||||
return false;
|
||||
} else if (anchor.item == item) {
|
||||
|
@ -1287,10 +1380,11 @@ bool QQuickAnchorsPrivate::checkVAnchorValid(QQuickAnchorLine anchor) const
|
|||
if (!anchor.item) {
|
||||
qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to a null item.");
|
||||
return false;
|
||||
} else if (anchor.anchorLine & QQuickAnchorLine::Horizontal_Mask) {
|
||||
} else if (anchor.anchorLine & QQuickAnchors::Horizontal_Mask) {
|
||||
qmlInfo(item) << QQuickAnchors::tr("Cannot anchor a vertical edge to a horizontal edge.");
|
||||
return false;
|
||||
} else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
|
||||
} else if (anchor.item != readParentItem(item)
|
||||
&& readParentItem(anchor.item) != readParentItem(item)) {
|
||||
qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
|
||||
return false;
|
||||
} else if (anchor.item == item){
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue