From bf6bda9487ce63275264eff66e609a89bacb6416 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 25 Jan 2016 21:57:29 +0100 Subject: Update the item when the DevicePixelRatio changes Since the rendering of the item depends on the device pixel ratio then it needs to be updated whenever this changes. [ChangeLog][QQuickPaintedItem] When the device pixel ratio is changed for the screen the item is rendered on then the item will be updated. Change-Id: Idf3c73faf0c13573c570fe22b5fb9e97fe1e66e2 Reviewed-by: Robin Burchell --- src/quick/items/qquickpainteditem.cpp | 7 +++++++ src/quick/items/qquickpainteditem.h | 1 + 2 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp index ad8d94d240..63e90a5cce 100644 --- a/src/quick/items/qquickpainteditem.cpp +++ b/src/quick/items/qquickpainteditem.cpp @@ -657,4 +657,11 @@ QSGTextureProvider *QQuickPaintedItem::textureProvider() const return d->textureProvider; } +void QQuickPaintedItem::itemChange(ItemChange change, const ItemChangeData &value) +{ + if (change == ItemDevicePixelRatioHasChanged) + update(); + QQuickItem::itemChange(change, value); +} + QT_END_NAMESPACE diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h index bb4e7f1f85..ff559cd10e 100644 --- a/src/quick/items/qquickpainteditem.h +++ b/src/quick/items/qquickpainteditem.h @@ -115,6 +115,7 @@ protected: QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent = Q_NULLPTR); QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; void releaseResources() Q_DECL_OVERRIDE; + void itemChange(ItemChange, const ItemChangeData &) Q_DECL_OVERRIDE; private Q_SLOTS: void invalidateSceneGraph(); -- cgit v1.2.3 From 07b7c6efaa75b79b0625de81dc8f7e6ca264e16e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 7 Apr 2016 11:22:33 +0200 Subject: QQuickText,QQuickTextInput: Fully qualify enumerations in changed() signals. Similar to change 85b64e701b2eaecdd30a7e0e079e2c80dd846fec. Fixes test warnings: QWARN : tst_qquicktextinput::mouseSelectionMode_accessors() QSignalSpy: Unable to handle parameter 'mode' of type 'SelectionMode' of method 'mouseSelectionModeChanged', use qRegisterMetaType to register it. QWARN : tst_qquicktext::textFormat() QSignalSpy: Unable to handle parameter 'textFormat' of type 'TextFormat' of method 'textFormatChanged', use qRegisterMetaType to register it. Change-Id: I9105eb31ce3d6203602649e24835f4fb0ddb25fd Reviewed-by: Robin Burchell --- src/quick/items/qquicktext_p.h | 10 +++++----- src/quick/items/qquicktextinput_p.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h index ea69aea3f9..ff36ae48b4 100644 --- a/src/quick/items/qquicktext_p.h +++ b/src/quick/items/qquicktext_p.h @@ -248,16 +248,16 @@ Q_SIGNALS: void fontChanged(const QFont &font); void colorChanged(); void linkColorChanged(); - void styleChanged(TextStyle style); + void styleChanged(QQuickText::TextStyle style); void styleColorChanged(); - void horizontalAlignmentChanged(HAlignment alignment); - void verticalAlignmentChanged(VAlignment alignment); + void horizontalAlignmentChanged(QQuickText::HAlignment alignment); + void verticalAlignmentChanged(QQuickText::VAlignment alignment); void wrapModeChanged(); void lineCountChanged(); void truncatedChanged(); void maximumLineCountChanged(); - void textFormatChanged(TextFormat textFormat); - void elideModeChanged(TextElideMode mode); + void textFormatChanged(QQuickText::TextFormat textFormat); + void elideModeChanged(QQuickText::TextElideMode mode); void contentSizeChanged(); void lineHeightChanged(qreal lineHeight); void lineHeightModeChanged(LineHeightMode mode); diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h index 8733b31960..e2d7193d35 100644 --- a/src/quick/items/qquicktextinput_p.h +++ b/src/quick/items/qquicktextinput_p.h @@ -311,8 +311,8 @@ Q_SIGNALS: void selectionColorChanged(); void selectedTextColorChanged(); void fontChanged(const QFont &font); - void horizontalAlignmentChanged(HAlignment alignment); - void verticalAlignmentChanged(VAlignment alignment); + void horizontalAlignmentChanged(QQuickTextInput::HAlignment alignment); + void verticalAlignmentChanged(QQuickTextInput::VAlignment alignment); void wrapModeChanged(); void readOnlyChanged(bool isReadOnly); void cursorVisibleChanged(bool isCursorVisible); @@ -320,14 +320,14 @@ Q_SIGNALS: void maximumLengthChanged(int maximumLength); void validatorChanged(); void inputMaskChanged(const QString &inputMask); - void echoModeChanged(EchoMode echoMode); + void echoModeChanged(QQuickTextInput::EchoMode echoMode); void passwordCharacterChanged(); Q_REVISION(3) void passwordMaskDelayChanged(int delay); void displayTextChanged(); void activeFocusOnPressChanged(bool activeFocusOnPress); void autoScrollChanged(bool autoScroll); void selectByMouseChanged(bool selectByMouse); - void mouseSelectionModeChanged(SelectionMode mode); + void mouseSelectionModeChanged(QQuickTextInput::SelectionMode mode); void persistentSelectionChanged(); void canPasteChanged(); void canUndoChanged(); -- cgit v1.2.3 From 392c7b99348e2a96ef11adb5712095fbd13fb780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20L=C3=B6sch?= Date: Thu, 24 Mar 2016 12:09:31 +0100 Subject: Instantiate static Qml plugins declaring QQmlExtensionInterface only When instantiating static plugins no check is done whether the QQmlExtensionInterface is declared. Therefore all user plugins are instantiated in the Qml thread, which may cause problems. Task-number: QTBUG-52012 Change-Id: Ia91ec5ec7b2a9721bd11e3648cdc161855b4454e Reviewed-by: Simon Hausmann --- src/imports/folderlistmodel/plugin.cpp | 2 +- src/imports/localstorage/plugin.cpp | 2 +- src/imports/models/plugin.cpp | 2 +- src/imports/particles/plugin.cpp | 2 +- src/imports/qtquick2/plugin.cpp | 2 +- src/imports/settings/plugin.cpp | 2 +- src/imports/statemachine/plugin.cpp | 2 +- src/imports/testlib/main.cpp | 2 +- src/imports/window/plugin.cpp | 2 +- src/imports/xmllistmodel/plugin.cpp | 2 +- src/qml/qml/qqmlimport.cpp | 4 ++-- 11 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/imports/folderlistmodel/plugin.cpp b/src/imports/folderlistmodel/plugin.cpp index a2536bdc7d..400989d3dd 100644 --- a/src/imports/folderlistmodel/plugin.cpp +++ b/src/imports/folderlistmodel/plugin.cpp @@ -42,7 +42,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: virtual void registerTypes(const char *uri) diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index ada50774a7..b8d7030763 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -741,7 +741,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() diff --git a/src/imports/models/plugin.cpp b/src/imports/models/plugin.cpp index c2b0d2ae94..0a3e96aea3 100644 --- a/src/imports/models/plugin.cpp +++ b/src/imports/models/plugin.cpp @@ -62,7 +62,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: virtual void registerTypes(const char *uri) { diff --git a/src/imports/particles/plugin.cpp b/src/imports/particles/plugin.cpp index 56b611a408..7f95b9d833 100644 --- a/src/imports/particles/plugin.cpp +++ b/src/imports/particles/plugin.cpp @@ -41,7 +41,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: virtual void registerTypes(const char *uri) { diff --git a/src/imports/qtquick2/plugin.cpp b/src/imports/qtquick2/plugin.cpp index 36a57112b2..b4caf01d10 100644 --- a/src/imports/qtquick2/plugin.cpp +++ b/src/imports/qtquick2/plugin.cpp @@ -41,7 +41,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: virtual void registerTypes(const char *uri) { diff --git a/src/imports/settings/plugin.cpp b/src/imports/settings/plugin.cpp index c32d370537..2b4b114326 100644 --- a/src/imports/settings/plugin.cpp +++ b/src/imports/settings/plugin.cpp @@ -41,7 +41,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: virtual void registerTypes(const char *uri) diff --git a/src/imports/statemachine/plugin.cpp b/src/imports/statemachine/plugin.cpp index 2d52839f68..c4947a455e 100644 --- a/src/imports/statemachine/plugin.cpp +++ b/src/imports/statemachine/plugin.cpp @@ -46,7 +46,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: void registerTypes(const char *uri) diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp index c42ece5da5..b90c671cba 100644 --- a/src/imports/testlib/main.cpp +++ b/src/imports/testlib/main.cpp @@ -134,7 +134,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: virtual void registerTypes(const char *uri) diff --git a/src/imports/window/plugin.cpp b/src/imports/window/plugin.cpp index 010e9b3eed..25383c20d5 100644 --- a/src/imports/window/plugin.cpp +++ b/src/imports/window/plugin.cpp @@ -58,7 +58,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: virtual void registerTypes(const char *uri) { diff --git a/src/imports/xmllistmodel/plugin.cpp b/src/imports/xmllistmodel/plugin.cpp index 8a9d4379c4..f28dba783b 100644 --- a/src/imports/xmllistmodel/plugin.cpp +++ b/src/imports/xmllistmodel/plugin.cpp @@ -41,7 +41,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: virtual void registerTypes(const char *uri) diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index d538199520..9fc01c8e35 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -850,8 +850,8 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector &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(plugin.instance())) - plugins.append(plugin); + if (plugin.metaData().value(QStringLiteral("IID")).toString() == QLatin1String(QQmlExtensionInterface_iid)) + plugins.append(plugin); } } -- cgit v1.2.3 From 5b9f096addaaa81aefc437020f2fdcf5fdade051 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Mon, 11 Apr 2016 17:20:24 +0200 Subject: Fix typo in QML alias documentation Change-Id: I9e8b4cb7fe2151b7b3da19dd15641bf76a69042b Reviewed-by: Venugopal Shivashankar --- src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc index 04d769e4dc..04d0d0ed2e 100644 --- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc +++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc @@ -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. -- cgit v1.2.3 From f8c53e88ee45b7b545dfa2d98419a3f6066c7e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 12 Apr 2016 13:26:46 +0200 Subject: Fix high-DPI image and svg providers Commit 834f9c76 accidentally inverted a validity test by going from !isEmpty() to !isValid(). Change to isValid() which preserves the previous logic: a set sourceSize is automatically scaled by the target devicePixelRatio. Verified with: tests/manual/highdpi/imageprovider.qml tests/manual/highdpi/svg.qml Change-Id: Ie979d566418c365d4d7fc5e5c3e6a795a891db51 Reviewed-by: Robin Burchell --- src/quick/items/qquickimagebase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index 47952d86bd..dcbb4b3ea6 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -219,7 +219,7 @@ void QQuickImageBase::load() // sourceSize is set. If sourceSize is not set then the provider default size // will be used, as usual. bool setDevicePixelRatio = false; - if (!d->sourcesize.isValid()) { + if (d->sourcesize.isValid()) { if (loadUrl.scheme() == QStringLiteral("image")) { setDevicePixelRatio = true; } else { -- cgit v1.2.3 From 81768d64fda69a7d464338660b552979b9e74b3a Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 12 Apr 2016 13:14:58 +0200 Subject: QQuickItem: Ignore NaN x and y values. These cause warnings, and incorrect rendering. We already guard width and height against NaN, so doing the same with x & y seems like a sensible idea. Change-Id: Ib33e51fe0beb9a2fa30fbf70743c8d6384a99441 Task-number: QTBUG-34489 Task-number: QTBUG-50604 Reviewed-by: Shawn Rutledge Reviewed-by: Gunnar Sletta --- src/quick/items/qquickitem.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 24e52ff65e..c363894a8b 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -6217,6 +6217,8 @@ QPointF QQuickItem::position() const void QQuickItem::setX(qreal v) { Q_D(QQuickItem); + if (qIsNaN(v)) + return; if (d->x == v) return; @@ -6232,6 +6234,8 @@ void QQuickItem::setX(qreal v) void QQuickItem::setY(qreal v) { Q_D(QQuickItem); + if (qIsNaN(v)) + return; if (d->y == v) return; -- cgit v1.2.3 From d7ca86b61e61f9375f3924397155b05e9c67d632 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 13 Apr 2016 13:36:36 +0200 Subject: Set the private active variable to true and not the one passed in Change-Id: I953370e353eb0c67f086b3a539985701723798e9 Reviewed-by: Mitch Curtis --- src/quick/items/qquickdrag.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index 279f5e5299..7e1ffb6b7e 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -304,7 +304,7 @@ void QQuickDragAttached::setActive(bool active) else if (d->dragType == QQuickDrag::Automatic) { // There are different semantics than start() since startDrag() // may be called after an internal drag is already started. - active = true; + d->active = true; emit activeChanged(); d->startDrag(d->supportedActions); } -- cgit v1.2.3 From 490ec1ff4e8eecd3abac4796fbe246411205c8d2 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 14 Apr 2016 12:40:31 +0200 Subject: Fix memory corruption when calling Array.unshift() The dequeue offset won't wrap around when n > offset. [ChangeLog][QtQml] Fix crash with Array.unshift() Task-number: QTBUG-52065 Change-Id: I5e8b89ec964cd6397100442a5239254bca989a3f Reviewed-by: Robin Burchell --- src/qml/jsruntime/qv4arraydata.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index ec0185de64..bd736d775e 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -281,7 +281,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(); } - 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(); -- cgit v1.2.3 From 35e2f29cde8dc8280b5ce1986533fca63f902d5e Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Tue, 12 Jan 2016 13:37:42 +0100 Subject: QML extensions tutorial: Add import plugin to app. bundle on OS X The application in chapter 6 of this tutorial failed to import the custom extension plugin on OS X, as it could not see it's import path outside the application bundle. Change-Id: Icdca1f0553020e0460e4efabc5461a3447b32086 Task-number: QTBUG-47003 Reviewed-by: Leena Miettinen Reviewed-by: Jake Petroules --- .../doc/src/cppintegration/extending-tutorial.qdoc | 26 +++++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc index d862b50fcb..c0cfc3e1aa 100644 --- a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc +++ b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc @@ -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 -- cgit v1.2.3 From cf28f909da1145b8f4fbb92a3bf8353d5f397f97 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 18 Apr 2016 11:52:48 +0200 Subject: QQmlDesignerMetaObject: Fixing reference counting We have to overwrite the cache of QQmlInterceptorMetaObject, but we messed up the reference counting. The same applies for QQmlData. When overwriting the old cache we have to call release on the old cache and increase the reference count on the new cache, because it is released in the destructors of QmlData and QQmlInterceptorMetaObject. Change-Id: Iecdbe8d474092906344d4e5a74278f5d8120b5ef Reviewed-by: Tim Jenssen Reviewed-by: Simon Hausmann --- src/quick/designer/qqmldesignermetaobject.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp index 76c94b242d..9ee814e1a6 100644 --- a/src/quick/designer/qqmldesignermetaobject.cpp +++ b/src/quick/designer/qqmldesignermetaobject.cpp @@ -134,9 +134,13 @@ 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 (m_cache != cache) { + m_cache->addref(); + cache->release(); + cache = m_cache; + } //If our parent is not a VMEMetaObject we just se the flag to false again if (constructedMetaData(metaData)) @@ -160,17 +164,16 @@ QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engi 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); } -- cgit v1.2.3 From 23e0e26ce652cf360310ebb1e2de8283502eba2e Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 18 Apr 2016 15:14:26 +0200 Subject: Occasionally trim the type cache As loaded components are kept in a cache, they are never removed by the garbage collector. So, if you periodically create new components, they leak. This change adds a floating threshold for the number of components. When that threshold is surpassed trimCache() is called and unneeded components are removed. Task-number: QTBUG-42055 Change-Id: I30e3e4ee287f6d34376713668009c67614a50e0c Reviewed-by: Simon Hausmann --- src/qml/qml/qqmltypeloader.cpp | 20 +++++++++++++++++++- src/qml/qml/qqmltypeloader_p.h | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 1e671542be..0e0efcf753 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -1113,6 +1113,7 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob) } #define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16 +#define TYPELOADER_MINIMUM_TRIM_THRESHOLD 64 void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply) { @@ -1592,7 +1593,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) { } @@ -1629,6 +1631,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); @@ -1933,12 +1939,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) { @@ -1963,6 +1979,8 @@ void QQmlTypeLoader::trimCache() } } + updateTypeCacheTrimThreshold(); + // TODO: release any scripts which are no longer referenced by any types } diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 6433601ba8..f565bcd31f 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -358,6 +358,7 @@ private: QQmlTypeLoaderThread *m_thread; NetworkReplies m_networkReplies; TypeCache m_typeCache; + int m_typeCacheTrimThreshold; ScriptCache m_scriptCache; QmldirCache m_qmldirCache; ImportDirCache m_importDirCache; @@ -365,6 +366,7 @@ private: template void doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode); + void updateTypeCacheTrimThreshold(); friend struct PlainLoader; friend struct CachedLoader; -- cgit v1.2.3 From 33a40e23bd7dac4a90c25e8814c9d744add23c4c Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 19 Apr 2016 13:53:40 +0200 Subject: Initialize qmlEngine in QQuickItemGrabResultPrivate Task-number: QTBUG-51878 Change-Id: If2d28bf641ed4bbd74b2d4f51f0821e93b0aa238 Reviewed-by: Robin Burchell --- src/quick/items/qquickitemgrabresult.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/quick/items/qquickitemgrabresult.cpp b/src/quick/items/qquickitemgrabresult.cpp index 93797d9ce8..939d19ea02 100644 --- a/src/quick/items/qquickitemgrabresult.cpp +++ b/src/quick/items/qquickitemgrabresult.cpp @@ -52,6 +52,7 @@ class QQuickItemGrabResultPrivate : public QObjectPrivate public: QQuickItemGrabResultPrivate() : cacheEntry(0) + , qmlEngine(0) , texture(0) { } -- cgit v1.2.3 From d142b2d212ea09a7919a0a2761ee9c04d5c9bda8 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Tue, 19 Apr 2016 10:48:49 +0200 Subject: Fix assertion in qt_create_image_data() Fix rounding of width and height parameters. Change-Id: Ib7655dafe382684340c32e2d2dc8adb445af65b0 Reviewed-by: Mitch Curtis --- src/quick/items/context2d/qquickcontext2d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 56578b5f16..734cadf49a 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -938,7 +938,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); } -- cgit v1.2.3 From fc22938dfc7b4c09f76913ac62e1f8ba345eccaf Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Mon, 18 Apr 2016 18:08:28 +0200 Subject: Make sure QQuickPathPercent::value is initialized Change-Id: I2704b417085a7956e73daed191011af594703aa9 Reviewed-by: Shawn Rutledge --- src/quick/util/qquickpath_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h index b39b6e5c01..c9a416d75a 100644 --- a/src/quick/util/qquickpath_p.h +++ b/src/quick/util/qquickpath_p.h @@ -329,7 +329,7 @@ class Q_AUTOTEST_EXPORT QQuickPathPercent : public QQuickPathElement Q_OBJECT Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged) public: - QQuickPathPercent(QObject *parent=0) : QQuickPathElement(parent) {} + QQuickPathPercent(QObject *parent=0) : QQuickPathElement(parent), _value(0) {} qreal value() const; void setValue(qreal value); -- cgit v1.2.3 From e1400b5b4d8311769ad3b9f631479ee2b0271197 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Thu, 14 Apr 2016 10:48:25 +0200 Subject: Fixed MouseArea threshold with preventStealing When preventStealing is true both keepMouseGrab() and d->stealMouse are true. This in turn enable the dragging immediately since the condition "keepMouseGrab() && d->stealMouse && !d->drag->active()" is true. Conversely when preventStealing is false the dragging is enabled in the next move event since keepMouseGrab() and d->stealMouse are set true inside the last "if" "!keepMouseGrab() && ...check threshold..". This patch adds a new boolean flag for storing if we detected a drag motion (so we exceeded the threshold) and enable the dragging iff this flag is true. With this change: - if preventStealing is true (and so keepMouseGrab() and d->stealMouse) the additional d->overThresHold prevent the start of dragging. At the same time the last if (!keepMouseGrab()) cannot be executed since keepMouseGrab is true and we still check for the threshold being exceeded. - if preventStealing is false, we still check for exceeding the threshold and if this happen we enter in the last "if" since !keepMousegrab() && d->overThreshold is true taking the mouseGrab as without this patch Task-number: QTBUG-52534 Change-Id: I2b14d3048b6f8223c90ce5e2fd26e7ca706cb56a Reviewed-by: Michael Brasser Reviewed-by: Robin Burchell Reviewed-by: Shawn Rutledge --- src/quick/items/qquickmousearea.cpp | 21 +++++++++++++-------- src/quick/items/qquickmousearea_p_p.h | 1 + 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index ef053abbd1..d66e55aa12 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -52,7 +52,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING) QQuickMouseAreaPrivate::QQuickMouseAreaPrivate() : enabled(true), scrollGestureEnabled(true), hovered(false), longPress(false), moved(false), stealMouse(false), doubleClick(false), preventStealing(false), - propagateComposedEvents(false), pressed(0) + propagateComposedEvents(false), overThreshold(false), pressed(0) #ifndef QT_NO_DRAGANDDROP , drag(0) #endif @@ -715,7 +715,7 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) curLocalPos = event->windowPos(); } - if (keepMouseGrab() && d->stealMouse && !d->drag->active()) + if (keepMouseGrab() && d->stealMouse && d->overThreshold && !d->drag->active()) d->drag->setActive(true); QPointF startPos = d->drag->target()->parentItem() @@ -741,16 +741,19 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) if (d->drag->active()) d->drag->target()->setPosition(dragPos); - if (!keepMouseGrab() - && (QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(), Qt::XAxis, event, d->drag->threshold()) - || QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), Qt::YAxis, event, d->drag->threshold()))) { - setKeepMouseGrab(true); - d->stealMouse = true; - + if (!d->overThreshold && (QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(), Qt::XAxis, event, d->drag->threshold()) + || QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), Qt::YAxis, event, d->drag->threshold()))) + { + d->overThreshold = true; if (d->drag->smoothed()) d->startScene = event->windowPos(); } + if (!keepMouseGrab() && d->overThreshold) { + setKeepMouseGrab(true); + d->stealMouse = true; + } + d->moved = true; } #endif @@ -767,6 +770,7 @@ void QQuickMouseArea::mouseReleaseEvent(QMouseEvent *event) { Q_D(QQuickMouseArea); d->stealMouse = false; + d->overThreshold = false; if (!d->enabled && !d->pressed) { QQuickItem::mouseReleaseEvent(event); } else { @@ -875,6 +879,7 @@ void QQuickMouseArea::ungrabMouse() d->pressed = 0; d->stealMouse = false; d->doubleClick = false; + d->overThreshold = false; setKeepMouseGrab(false); #ifndef QT_NO_DRAGANDDROP diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h index 014729b651..f63c5f6092 100644 --- a/src/quick/items/qquickmousearea_p_p.h +++ b/src/quick/items/qquickmousearea_p_p.h @@ -86,6 +86,7 @@ public: bool doubleClick : 1; bool preventStealing : 1; bool propagateComposedEvents : 1; + bool overThreshold : 1; Qt::MouseButtons pressed; #ifndef QT_NO_DRAGANDDROP QQuickDrag *drag; -- cgit v1.2.3 From 26ff8f9029107877bfbfdc2f099f9b11861183ed Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 22 Mar 2016 07:24:47 -0500 Subject: Allow more control over memory/speed tradeoff in the atlas. QSG_ATLAS_TRANSIENT_IMAGE_THRESHOLD can be used to define a threshold for retaining the QImage associated with an atlas texture. This gives more control to the developer on platforms where removing a texture from the atlas (e.g. for use in a ShaderEffect) can be prohibitively expensive. Change-Id: I13fd01ebbe94dd960fdcb3ee20b4ff40dcc5694f Reviewed-by: Laszlo Agocs Reviewed-by: Brett Stottlemyer Reviewed-by: Robin Burchell Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/util/qsgatlastexture.cpp | 11 ++++++++++- src/quick/scenegraph/util/qsgatlastexture_p.h | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index 8e8e870505..832510148c 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -121,6 +121,7 @@ Atlas::Atlas(const QSize &size) : m_allocator(size) , m_texture_id(0) , m_size(size) + , m_atlas_transient_image_threshold(0) , m_allocated(false) { @@ -170,6 +171,11 @@ Atlas::Atlas(const QSize &size) m_use_bgra_fallback = qEnvironmentVariableIsSet("QSG_ATLAS_USE_BGRA_FALLBACK"); m_debug_overlay = qEnvironmentVariableIsSet("QSG_ATLAS_OVERLAY"); + + // images smaller than this will retain their QImage. + // by default no images are retained (favoring memory) + // set to a very large value to retain all images (allowing quick removal from the atlas) + m_atlas_transient_image_threshold = qt_sg_envInt("QSG_ATLAS_TRANSIENT_IMAGE_THRESHOLD", 0); } Atlas::~Atlas() @@ -392,7 +398,10 @@ void Atlas::bind(QSGTexture::Filtering filtering) } else { upload(t); } - t->releaseImage(); + const QSize textureSize = t->textureSize(); + if (textureSize.width() > m_atlas_transient_image_threshold || + textureSize.height() > m_atlas_transient_image_threshold) + t->releaseImage(); qCDebug(QSG_LOG_TIME_TEXTURE).nospace() << "atlastexture uploaded in: " << qsg_renderer_timer.elapsed() << "ms (" << t->textureSize().width() << "x" diff --git a/src/quick/scenegraph/util/qsgatlastexture_p.h b/src/quick/scenegraph/util/qsgatlastexture_p.h index e77e0fa104..a9ba83b2fc 100644 --- a/src/quick/scenegraph/util/qsgatlastexture_p.h +++ b/src/quick/scenegraph/util/qsgatlastexture_p.h @@ -110,6 +110,8 @@ private: GLuint m_internalFormat; GLuint m_externalFormat; + int m_atlas_transient_image_threshold; + uint m_allocated : 1; uint m_use_bgra_fallback: 1; -- cgit v1.2.3 From d50a57f408a9cc160c187c012f51b8fa89738858 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 18 Apr 2016 18:24:53 +0200 Subject: Drop the class name from shader effect material keys Shader effects with equal program source code can use the same compiled shaders. There is no need to duplicate the data for each QML component. Task-number: QTBUG-42055 Change-Id: Iae86890ebf0ad6ef34a63565b8a01d0fcd903fbc Reviewed-by: Michael Brasser Reviewed-by: Gunnar Sletta --- src/particles/qquickcustomparticle.cpp | 2 -- src/quick/items/qquickshadereffect.cpp | 1 - src/quick/items/qquickshadereffectnode.cpp | 4 +--- src/quick/items/qquickshadereffectnode_p.h | 1 - 4 files changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp index 5e244ba02c..e62c6f556b 100644 --- a/src/particles/qquickcustomparticle.cpp +++ b/src/particles/qquickcustomparticle.cpp @@ -284,8 +284,6 @@ QQuickShaderEffectNode *QQuickCustomParticle::prepareNextFrame(QQuickShaderEffec 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 (QQuickShaderEffectNode* node, m_nodes) diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp index 47c67e0e1c..94fa7e92e3 100644 --- a/src/quick/items/qquickshadereffect.cpp +++ b/src/quick/items/qquickshadereffect.cpp @@ -1035,7 +1035,6 @@ QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa builder.appendSourceFile(QStringLiteral(":/qt-project.org/items/shaders/shadereffect.vert")); s.sourceCode[Key::VertexShader] = builder.source(); } - s.className = metaObject()->className(); material->setProgramSource(s); material->attributes = m_common.attributes; diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp index df030d15a7..b9c94af717 100644 --- a/src/quick/items/qquickshadereffectnode.cpp +++ b/src/quick/items/qquickshadereffectnode.cpp @@ -327,8 +327,6 @@ const char *QQuickCustomMaterialShader::fragmentShader() const bool QQuickShaderEffectMaterialKey::operator == (const QQuickShaderEffectMaterialKey &other) const { - if (className != other.className) - return false; for (int shaderType = 0; shaderType < ShaderTypeCount; ++shaderType) { if (sourceCode[shaderType] != other.sourceCode[shaderType]) return false; @@ -343,7 +341,7 @@ bool QQuickShaderEffectMaterialKey::operator != (const QQuickShaderEffectMateria uint qHash(const QQuickShaderEffectMaterialKey &key) { - uint hash = qHash((const void *)key.className); + uint hash = 1; typedef QQuickShaderEffectMaterialKey Key; for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) hash = hash * 31337 + qHash(key.sourceCode[shaderType]); diff --git a/src/quick/items/qquickshadereffectnode_p.h b/src/quick/items/qquickshadereffectnode_p.h index 8a7fd6c3a5..d3d3f72410 100644 --- a/src/quick/items/qquickshadereffectnode_p.h +++ b/src/quick/items/qquickshadereffectnode_p.h @@ -65,7 +65,6 @@ struct QQuickShaderEffectMaterialKey { }; QByteArray sourceCode[ShaderTypeCount]; - const char *className; bool operator == (const QQuickShaderEffectMaterialKey &other) const; bool operator != (const QQuickShaderEffectMaterialKey &other) const; -- cgit v1.2.3 From e3f1f8fa3dd26c76ee157f17f3eec970981ec368 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 20 Apr 2016 10:40:09 +0200 Subject: Minor cleanup: Remove unused forward declaration QGlyphs does not exist anywhere. It is the old name of QGlyphRun, so this forward declaration is not needed. Change-Id: I1394f3d7abf0a8bc58ff2295f41dd3779ed01901 Reviewed-by: Robin Burchell --- src/quick/scenegraph/qsgdefaultglyphnode_p.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p.h index 4efeaea373..ea4c0ff787 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.h +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.h @@ -56,7 +56,6 @@ QT_BEGIN_NAMESPACE -class QGlyphs; class QSGTextMaskMaterial; class QSGDefaultGlyphNode: public QSGGlyphNode { -- cgit v1.2.3 From 9c8dab537819f0d999e680490c2d125b8836cbbb Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Wed, 20 Apr 2016 13:32:03 +0200 Subject: Revert "Fixed MouseArea threshold with preventStealing" This reverts commit e1400b5b4d8311769ad3b9f631479ee2b0271197, which breaks qtlocation unit tests for drag support. It is no longer possible to drag markers in mapviewer. Task-number: QTBUG-52534 Change-Id: If713a8e45f64ea898f38fe3e39561ebc266403b2 Reviewed-by: Alex Blasche Reviewed-by: Liang Qi --- src/quick/items/qquickmousearea.cpp | 21 ++++++++------------- src/quick/items/qquickmousearea_p_p.h | 1 - 2 files changed, 8 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index d66e55aa12..ef053abbd1 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -52,7 +52,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING) QQuickMouseAreaPrivate::QQuickMouseAreaPrivate() : enabled(true), scrollGestureEnabled(true), hovered(false), longPress(false), moved(false), stealMouse(false), doubleClick(false), preventStealing(false), - propagateComposedEvents(false), overThreshold(false), pressed(0) + propagateComposedEvents(false), pressed(0) #ifndef QT_NO_DRAGANDDROP , drag(0) #endif @@ -715,7 +715,7 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) curLocalPos = event->windowPos(); } - if (keepMouseGrab() && d->stealMouse && d->overThreshold && !d->drag->active()) + if (keepMouseGrab() && d->stealMouse && !d->drag->active()) d->drag->setActive(true); QPointF startPos = d->drag->target()->parentItem() @@ -741,17 +741,14 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) if (d->drag->active()) d->drag->target()->setPosition(dragPos); - if (!d->overThreshold && (QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(), Qt::XAxis, event, d->drag->threshold()) - || QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), Qt::YAxis, event, d->drag->threshold()))) - { - d->overThreshold = true; - if (d->drag->smoothed()) - d->startScene = event->windowPos(); - } - - if (!keepMouseGrab() && d->overThreshold) { + if (!keepMouseGrab() + && (QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(), Qt::XAxis, event, d->drag->threshold()) + || QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), Qt::YAxis, event, d->drag->threshold()))) { setKeepMouseGrab(true); d->stealMouse = true; + + if (d->drag->smoothed()) + d->startScene = event->windowPos(); } d->moved = true; @@ -770,7 +767,6 @@ void QQuickMouseArea::mouseReleaseEvent(QMouseEvent *event) { Q_D(QQuickMouseArea); d->stealMouse = false; - d->overThreshold = false; if (!d->enabled && !d->pressed) { QQuickItem::mouseReleaseEvent(event); } else { @@ -879,7 +875,6 @@ void QQuickMouseArea::ungrabMouse() d->pressed = 0; d->stealMouse = false; d->doubleClick = false; - d->overThreshold = false; setKeepMouseGrab(false); #ifndef QT_NO_DRAGANDDROP diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h index f63c5f6092..014729b651 100644 --- a/src/quick/items/qquickmousearea_p_p.h +++ b/src/quick/items/qquickmousearea_p_p.h @@ -86,7 +86,6 @@ public: bool doubleClick : 1; bool preventStealing : 1; bool propagateComposedEvents : 1; - bool overThreshold : 1; Qt::MouseButtons pressed; #ifndef QT_NO_DRAGANDDROP QQuickDrag *drag; -- cgit v1.2.3 From 0b7c11e7c2bb457bff399fdec38d9cf266e89a86 Mon Sep 17 00:00:00 2001 From: Michael Bruning Date: Tue, 12 Apr 2016 15:14:55 +0200 Subject: Also match QJSValue conversion types in MatchScore. This had the effect that overloaded methods were always mapped to the wrong slot. [ChangeLog][QtQml][Important Behavior Changes] When matching the method signature of a invokable method to the slot in the metaobject, the matching function now assigns the best match to a QJSValue if the parameter actually is a QJSValue. This corrects the previous behavior, where QJSValue and int were given the same match score even though QJSValue would have been the best match. Task-number: QTBUG-51746 Change-Id: I906e7b006ee5af92ea760ed1625e5047aef123bf Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4qobjectwrapper.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index bcd97efee8..6be86e3bdb 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1270,6 +1270,8 @@ static int MatchScore(const QV4::Value &actual, int conversionType) return 10; } else if (conversionType == QMetaType::QJsonObject) { return 5; + } else if (conversionType == qMetaTypeId()) { + return 0; } else { return 10; } -- cgit v1.2.3 From 3b9d7ee10e2ae6565f0767219303d9a11d80f489 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 20 Apr 2016 12:52:11 +0200 Subject: QML: Remove baselineOffsetValid flag from QQuickItem. This flag was only used to return 0.0 when false, and baselineOffset when true. So initializing the baselineOffset to 0.0 does the same thing. Change-Id: Ia92b05761ea3a03175ae0078bf950a1b4da2d356 Reviewed-by: Michael Brasser Reviewed-by: Erik Verbruggen --- src/quick/items/qquickitem.cpp | 10 ++-------- src/quick/items/qquickitem_p.h | 5 ++--- 2 files changed, 4 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index c363894a8b..b15dd76f27 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3083,7 +3083,6 @@ QQuickItemPrivate::QQuickItemPrivate() , flags(0) , widthValid(false) , heightValid(false) - , baselineOffsetValid(false) , componentComplete(true) , keepMouse(false) , keepTouch(false) @@ -3157,7 +3156,7 @@ void QQuickItemPrivate::init(QQuickItem *parent) registerAccessorProperties(); - baselineOffsetValid = false; + baselineOffset = 0.0; if (parent) { q->setParentItem(parent); @@ -4207,11 +4206,7 @@ QQuickAnchorLine QQuickItemPrivate::baseline() const qreal QQuickItem::baselineOffset() const { Q_D(const QQuickItem); - if (d->baselineOffsetValid) { - return d->baselineOffset; - } else { - return 0.0; - } + return d->baselineOffset; } void QQuickItem::setBaselineOffset(qreal offset) @@ -4221,7 +4216,6 @@ void QQuickItem::setBaselineOffset(qreal offset) return; d->baselineOffset = offset; - d->baselineOffsetValid = true; for (int ii = 0; ii < d->changeListeners.count(); ++ii) { const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii); diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 634aa2b658..c5d54a390b 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -396,7 +396,6 @@ public: quint32 flags:5; bool widthValid:1; bool heightValid:1; - bool baselineOffsetValid:1; bool componentComplete:1; bool keepMouse:1; bool keepTouch:1; @@ -405,8 +404,8 @@ public: bool antialiasing:1; bool focus:1; bool activeFocus:1; - // Bit 16 bool notifiedFocus:1; + // Bit 16 bool notifiedActiveFocus:1; bool filtersChildMouseEvents:1; bool explicitVisible:1; @@ -422,8 +421,8 @@ public: bool isAccessible:1; bool culled:1; bool hasCursor:1; - // Bit 32 bool hasCursorInChild:1; + // Bit 32 bool activeFocusOnTab:1; bool implicitAntialiasing:1; bool antialiasingValid:1; -- cgit v1.2.3 From 3c5e438890db63ecde98c84d221f87a3af52e1bf Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 11 Apr 2016 17:17:19 +0200 Subject: Allow target path version in a parent module For example, the QML Engine is now able to locate QtQml.Models 2.x in both of the following target/installation paths: - QT_INSTALL_QML/QtQml/Models.2 - QT_INSTALL_QML/QtQml.2/Models This is required for QtQuick Controls 2. The target path of the module is QT_INSTALL_QML/QtQuick/Controls.2. The built-in styles are installed as sub-directories to be able to locate them from the controls module. Some of the built-in styles provide their own C++ extensions via style- specific imports (eg. the Material attached property is imported from QtQuick.Controls.Material 2.0). The problem is that the QML Engine does not find the module from QT_INSTALL_QML/QtQuick/Controls.2/Material, but requires it to be installed outside the main controls module ie. QT_INSTALL_QML/QtQuick/Controls/Material(.2). This makes it a) hard to locate the styles from the main controls module, and b) conflicts with the target path of QtQuick Controls 1. [ChangeLog][QtQml] Made the QML Engine capable of locating QML sub- modules from within a versioned parent module path. For example, QtQml.Models 2.x can be either in QT_INSTALL_QML/QtQml/Models.2 or in QT_INSTALL_QML/QtQml.2/Models. Change-Id: I2fe4bbdd6d04dd1e80cbe9b3e7e02617658a0756 Task-number: QTBUG-52556 Reviewed-by: J-P Nurmi Reviewed-by: Shawn Rutledge Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlimport.cpp | 99 ++++++++++++++++++++++++++++-------------- src/qml/qml/qqmlimport_p.h | 3 +- src/qml/qml/qqmltypeloader.cpp | 11 ++--- 3 files changed, 72 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index d6c81bcc49..ec29e600ed 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -483,20 +483,58 @@ QList QQmlImports::resolvedScripts() const return scripts; } +static QString joinStringRefs(const QVector &refs, const QChar &sep) +{ + QString str; + for (auto it = refs.cbegin(); it != refs.cend(); ++it) { + if (it != refs.cbegin()) + str += sep; + str += *it; + } + return str; +} + /*! - Form a complete path to a qmldir file, from a base URL, a module URI and version specification. + Forms complete paths to a qmldir file, from a base URL, a module URI and version specification. + + 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 */ -QString QQmlImports::completeQmldirPath(const QString &uri, const QString &base, int vmaj, int vmin, - ImportVersion version) +QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin) { - QString url = uri; - url.replace(Dot, Slash); + const QVector 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)); - QString dir = base; - if (!dir.endsWith(Slash) && !dir.endsWith(Backslash)) - dir += Slash; + for (int version = FullyVersioned; version <= Unversioned; ++version) { + const QString ver = versionString(vmaj, vmin, static_cast(version)); - return dir + url + versionString(vmaj, vmin, version) + Slash_qmldir; + 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) @@ -1130,32 +1168,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(version)); - - 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(); + const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(uri, localImportPaths, vmaj, vmin); + for (const QString &qmldirPath : qmlDirPaths) { + 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; } } diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index 628564ae34..0e7848730f 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -130,8 +130,7 @@ public: QList 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); diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 52a7562b58..7fed82f4a4 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -1380,13 +1380,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(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; } } } -- cgit v1.2.3 From 597370b36487d2d2ed438db531f2d4aad4e55744 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 18 Apr 2016 10:02:16 +0200 Subject: QQuickTextControlPrivate: Listen for changes to cursorFlashTime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cursorFlashTime will now change dynamically from QPA while platform controlled text selection (on mobile) is ongoing. This patch will therefore update QQuickTextControlPrivate so that it listens to the cursorFlashTimeChanged signal and changes the blinking rate when triggered. Change-Id: Ifea202bc9f57af8c5959594eb50f2aacff284d68 Reviewed-by: Jan Arve Sæther --- src/quick/items/qquicktextcontrol.cpp | 27 ++++++++++++++++++++++----- src/quick/items/qquicktextcontrol_p_p.h | 2 ++ 2 files changed, 24 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index e2f4d51542..0cee9c7d27 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -108,6 +108,7 @@ QQuickTextControlPrivate::QQuickTextControlPrivate() overwriteMode(false), acceptRichText(true), cursorVisible(false), + cursorBlinkingEnabled(false), hasFocus(false), hadSelectionOnMousePress(false), wordSelectionEnabled(false), @@ -462,14 +463,30 @@ void QQuickTextControlPrivate::_q_updateCursorPosChanged(const QTextCursor &some void QQuickTextControlPrivate::setBlinkingCursorEnabled(bool enable) { - Q_Q(QQuickTextControl); + if (cursorBlinkingEnabled == enable) + return; + + cursorBlinkingEnabled = enable; + updateCursorFlashTime(); - if (enable && QGuiApplication::styleHints()->cursorFlashTime() > 0) - cursorBlinkTimer.start(QGuiApplication::styleHints()->cursorFlashTime() / 2, q); + if (enable) + connect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QQuickTextControlPrivate::updateCursorFlashTime); else - cursorBlinkTimer.stop(); + disconnect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QQuickTextControlPrivate::updateCursorFlashTime); +} - cursorOn = enable; +void QQuickTextControlPrivate::updateCursorFlashTime() +{ + // Note: cursorOn represents the current blinking state controlled by a timer, and + // should not be confused with cursorVisible or cursorBlinkingEnabled. However, we + // interpretate a cursorFlashTime of 0 to mean "always on, never blink". + cursorOn = true; + int flashTime = QGuiApplication::styleHints()->cursorFlashTime(); + + if (cursorBlinkingEnabled && flashTime >= 2) + cursorBlinkTimer.start(flashTime / 2, q_func()); + else + cursorBlinkTimer.stop(); repaintCursor(); } diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h index f312fcb1ce..0f78feb5de 100644 --- a/src/quick/items/qquicktextcontrol_p_p.h +++ b/src/quick/items/qquicktextcontrol_p_p.h @@ -97,6 +97,7 @@ public: void _q_updateCursorPosChanged(const QTextCursor &someCursor); void setBlinkingCursorEnabled(bool enable); + void updateCursorFlashTime(); void extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition); void extendBlockwiseSelection(int suggestedNewPosition); @@ -156,6 +157,7 @@ public: bool overwriteMode : 1; bool acceptRichText : 1; bool cursorVisible : 1; // used to hide the cursor in the preedit area + bool cursorBlinkingEnabled : 1; bool hasFocus : 1; bool hadSelectionOnMousePress : 1; bool wordSelectionEnabled : 1; -- cgit v1.2.3 From c598d52561e048319c6c3656bedf4bb665603dc7 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 20 Apr 2016 11:35:42 +0200 Subject: QQuickTextInput: Listen for changes to cursorFlashTime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cursorFlashTime will now change dynamically from QPA while platform controlled text selection (on mobile) is ongoing. This patch will therefore update QWidgetLineControl so that it listens to the cursorFlashTimeChanged signal and changes the blinking rate when triggered. The previous code had a function setCursorBlinkPeriod, which is now changed to setBlinkingCursorEnabled (like in QQuickTextControlPrivate). This is because all callers of the function did either pass "QApplication::cursorFlashTime" or "0", which basically means enable or disable blinking. This moves the control of the blinking rate fully to updateCursorFlashTime, which simplifies the code a bit, especially when cursorFlashTime can change. Note that when setting a blink period to 0, it means "show the cursor without blinking". AFAICS, the current implementation did not guarantee that. This is now made more explicit in the code. If hiding the cursor is needed, a separate function "setCursorVisible" is already available for controlling that. Change-Id: Ie3222525474e03b485ff8585fd8d7da6fd5b26e5 Reviewed-by: Jan Arve Sæther --- src/quick/items/qquicktextinput.cpp | 71 +++++++++++++++++------------------ src/quick/items/qquicktextinput_p_p.h | 12 +++--- 2 files changed, 42 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index f93857a892..ab7a0f02dd 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -760,12 +760,8 @@ void QQuickTextInput::setCursorVisible(bool on) d->cursorVisible = on; if (on && isComponentComplete()) QQuickTextUtil::createCursor(d); - if (!d->cursorItem) { - d->setCursorBlinkPeriod(on ? QGuiApplication::styleHints()->cursorFlashTime() : 0); - d->updateType = QQuickTextInputPrivate::UpdatePaintNode; - polish(); - update(); - } + if (!d->cursorItem) + d->updateCursorBlinking(); emit cursorVisibleChanged(d->cursorVisible); } @@ -1782,7 +1778,7 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData node = new QQuickTextNode(this); d->textNode = node; - const bool showCursor = !isReadOnly() && d->cursorItem == 0 && d->cursorVisible && (d->m_blinkStatus || d->m_blinkPeriod == 0); + const bool showCursor = !isReadOnly() && d->cursorItem == 0 && d->cursorVisible && d->m_blinkStatus; if (!d->textLayoutDirty && oldNode != 0) { if (showCursor) @@ -2518,8 +2514,10 @@ void QQuickTextInputPrivate::handleFocusEvent(QFocusEvent *event) { Q_Q(QQuickTextInput); bool focus = event->gotFocus(); - if (!m_readOnly) + if (!m_readOnly) { q->setCursorVisible(focus); + setBlinkingCursorEnabled(focus); + } if (focus) { q->q_updateAlignment(); #ifndef QT_NO_IM @@ -4219,26 +4217,39 @@ bool QQuickTextInputPrivate::emitCursorPositionChanged() } -void QQuickTextInputPrivate::setCursorBlinkPeriod(int msec) +void QQuickTextInputPrivate::setBlinkingCursorEnabled(bool enable) { - Q_Q(QQuickTextInput); - if (msec == m_blinkPeriod) + if (enable == m_blinkEnabled) return; + + m_blinkEnabled = enable; + updateCursorBlinking(); + + if (enable) + connect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QQuickTextInputPrivate::updateCursorBlinking); + else + disconnect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QQuickTextInputPrivate::updateCursorBlinking); +} + +void QQuickTextInputPrivate::updateCursorBlinking() +{ + Q_Q(QQuickTextInput); + if (m_blinkTimer) { q->killTimer(m_blinkTimer); - } - if (msec) { - m_blinkTimer = q->startTimer(msec / 2); - m_blinkStatus = 1; - } else { m_blinkTimer = 0; - if (m_blinkStatus == 1) { - updateType = UpdatePaintNode; - q->polish(); - q->update(); - } } - m_blinkPeriod = msec; + + if (m_blinkEnabled && cursorVisible && !cursorItem && !m_readOnly) { + int flashTime = QGuiApplication::styleHints()->cursorFlashTime(); + if (flashTime >= 2) + m_blinkTimer = q->startTimer(flashTime / 2); + } + + m_blinkStatus = 1; + updateType = UpdatePaintNode; + q->polish(); + q->update(); } void QQuickTextInput::timerEvent(QTimerEvent *event) @@ -4275,20 +4286,8 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event) return; } - if (m_blinkPeriod > 0) { - if (m_blinkTimer) - q->killTimer(m_blinkTimer); - - m_blinkTimer = q->startTimer(m_blinkPeriod / 2); - - if (m_blinkStatus == 0) { - m_blinkStatus = 1; - - updateType = UpdatePaintNode; - q->polish(); - q->update(); - } - } + if (m_blinkEnabled) + updateCursorBlinking(); if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit && !m_passwordEchoEditing diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h index 9d3c66f04a..57a9f6413a 100644 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@ -107,7 +107,7 @@ public: #ifndef QT_NO_IM , m_preeditCursor(0) #endif - , m_blinkPeriod(0) + , m_blinkEnabled(false) , m_blinkTimer(0) , m_maxLength(32767) , m_lastCursorPos(-1) @@ -242,7 +242,7 @@ public: #ifndef QT_NO_IM int m_preeditCursor; #endif - int m_blinkPeriod; // 0 for non-blinking cursor + bool m_blinkEnabled; int m_blinkTimer; int m_maxLength; int m_lastCursorPos; @@ -307,8 +307,9 @@ public: return !tripleClickTimer.hasExpired(QGuiApplication::styleHints()->mouseDoubleClickInterval()); } - void setNativeCursorEnabled(bool enabled) { - setCursorBlinkPeriod(enabled && cursorVisible ? QGuiApplication::styleHints()->cursorFlashTime() : 0); } + void setNativeCursorEnabled(bool) { + updateCursorBlinking(); + } int nextMaskBlank(int pos) { @@ -443,7 +444,8 @@ public: #endif void processKeyEvent(QKeyEvent* ev); - void setCursorBlinkPeriod(int msec); + void setBlinkingCursorEnabled(bool enable); + void updateCursorBlinking(); void updateLayout(); void updateBaselineOffset(); -- cgit v1.2.3 From c71e40b2bdd1dd2f8f4049f3ab2da1446518b9e8 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 20 Apr 2016 13:23:29 +0200 Subject: QML: Access QQuickItemPrivate data (like x/y/etc) directly. This saves ~5% in QQuickAnchorsPrivate::itemGeometryChanged on x86_64. Change-Id: Iccf782521e9c8523c41c6f2e6d87fad401762a9e Reviewed-by: Michael Brasser --- src/quick/items/qquickanchors.cpp | 184 ++++++++++++++++++++++++-------------- 1 file changed, 116 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp index 606d4c45da..187b981abe 100644 --- a/src/quick/items/qquickanchors.cpp +++ b/src/quick/items/qquickanchors.cpp @@ -33,19 +33,48 @@ #include "qquickanchors_p_p.h" -#include "qquickitem.h" #include "qquickitem_p.h" #include QT_BEGIN_NAMESPACE +static Q_ALWAYS_INLINE QQuickItem *readParentItem(QQuickItem *item) +{ + return QQuickItemPrivate::get(item)->parentItem; +} + +static Q_ALWAYS_INLINE qreal readX(QQuickItem *item) +{ + return QQuickItemPrivate::get(item)->x; +} + +static Q_ALWAYS_INLINE qreal readY(QQuickItem *item) +{ + return QQuickItemPrivate::get(item)->y; +} + +static Q_ALWAYS_INLINE qreal readWidth(QQuickItem *item) +{ + return QQuickItemPrivate::get(item)->width; +} + +static Q_ALWAYS_INLINE qreal readHeight(QQuickItem *item) +{ + return QQuickItemPrivate::get(item)->height; +} + +static Q_ALWAYS_INLINE qreal readBaselineOffset(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 *item) { - qreal width = item->width(); + qreal width = readWidth(item); if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) { if (!QQuickAnchorsPrivate::get(anchors)->centerAligned) return width / 2; @@ -59,7 +88,7 @@ static inline qreal hcenter(QQuickItem *item) static inline qreal vcenter(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,25 +107,25 @@ static qreal position(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine) qreal ret = 0.0; switch (anchorLine) { case QQuickAnchorLine::Left: - ret = item->x(); + ret = readX(item); break; case QQuickAnchorLine::Right: - ret = item->x() + item->width(); + ret = readX(item) + readWidth(item); break; case QQuickAnchorLine::Top: - ret = item->y(); + ret = readY(item); break; case QQuickAnchorLine::Bottom: - ret = item->y() + item->height(); + ret = readY(item) + readHeight(item); break; case QQuickAnchorLine::HCenter: - ret = item->x() + hcenter(item); + ret = readX(item) + hcenter(item); break; case QQuickAnchorLine::VCenter: - ret = item->y() + vcenter(item); + ret = readY(item) + vcenter(item); break; case QQuickAnchorLine::Baseline: - ret = item->y() + item->baselineOffset(); + ret = readY(item) + readBaselineOffset(item); break; default: break; @@ -106,7 +135,7 @@ static qreal position(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine) } //position when origin is 0,0 -static qreal adjustedPosition(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine) +static inline qreal adjustedPosition(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine) { qreal ret = 0.0; switch (anchorLine) { @@ -114,13 +143,13 @@ static qreal adjustedPosition(QQuickItem *item, QQuickAnchorLine::AnchorLine anc ret = 0.0; break; case QQuickAnchorLine::Right: - ret = item->width(); + ret = readWidth(item); break; case QQuickAnchorLine::Top: ret = 0.0; break; case QQuickAnchorLine::Bottom: - ret = item->height(); + ret = readHeight(item); break; case QQuickAnchorLine::HCenter: ret = hcenter(item); @@ -129,7 +158,7 @@ static qreal adjustedPosition(QQuickItem *item, QQuickAnchorLine::AnchorLine anc ret = vcenter(item); break; case QQuickAnchorLine::Baseline: - ret = item->baselineOffset(); + ret = readBaselineOffset(item); break; default: break; @@ -169,12 +198,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 { @@ -194,12 +224,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); @@ -258,7 +288,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; @@ -266,7 +296,7 @@ int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) } if (centerIn == controlItem) { - if (controlItem == item->parentItem()) + if (controlItem == readParentItem(item)) dependency |= QQuickItemPrivate::SizeChange; else //sibling dependency |= QQuickItemPrivate::GeometryChange; @@ -276,7 +306,7 @@ int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) if ((usedAnchors & QQuickAnchors::LeftAnchor && left.item == controlItem) || (usedAnchors & QQuickAnchors::RightAnchor && right.item == controlItem) || (usedAnchors & QQuickAnchors::HCenterAnchor && hCenter.item == controlItem)) { - if (controlItem == item->parentItem()) + if (controlItem == readParentItem(item)) dependency |= QQuickItemPrivate::WidthChange; else //sibling dependency |= QFlags(QQuickItemPrivate::XChange | QQuickItemPrivate::WidthChange); @@ -286,7 +316,7 @@ int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) (usedAnchors & QQuickAnchors::BottomAnchor && bottom.item == controlItem) || (usedAnchors & QQuickAnchors::VCenterAnchor && vCenter.item == controlItem) || (usedAnchors & QQuickAnchors::BaselineAnchor && baseline.item == controlItem)) { - if (controlItem == item->parentItem()) + if (controlItem == readParentItem(item)) dependency |= QQuickItemPrivate::HeightChange; else //sibling dependency |= QFlags(QQuickItemPrivate::YChange | QQuickItemPrivate::HeightChange); @@ -442,22 +472,36 @@ 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 & QQuickAnchorLine::Horizontal_Mask) + updateHorizontalAnchors(); + if (usedAnchors & QQuickAnchorLine::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 & 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(); + } } QQuickItem *QQuickAnchors::fill() const @@ -479,7 +523,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; } @@ -515,7 +559,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; } @@ -539,10 +583,10 @@ bool QQuickAnchorsPrivate::calcStretch(const QQuickAnchorLine &edge1, QQuickAnchorLine::AnchorLine 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 = (edge1.item == readParentItem(item)); + bool edge2IsParent = (edge2.item == readParentItem(item)); + bool edge1IsSibling = (readParentItem(edge1.item) == readParentItem(item)); + bool edge2IsSibling = (readParentItem(edge2.item) == readParentItem(item)); bool invalid = false; if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) { @@ -550,10 +594,10 @@ bool QQuickAnchorsPrivate::calcStretch(const QQuickAnchorLine &edge1, - (position(edge1.item, edge1.anchorLine) + offset1); } else if (edge2IsParent && edge1IsSibling) { stretch = (position(edge2.item, edge2.anchorLine) + offset2) - - (position(item->parentItem(), line) + - (position(readParentItem(item), line) + position(edge1.item, edge1.anchorLine) + offset1); } else if (edge2IsSibling && edge1IsParent) { - stretch = (position(item->parentItem(), line) + position(edge2.item, edge2.anchorLine) + offset2) + stretch = (position(readParentItem(item), line) + position(edge2.item, edge2.anchorLine) + offset2) - (position(edge1.item, edge1.anchorLine) + offset1); } else invalid = true; @@ -582,9 +626,9 @@ void QQuickAnchorsPrivate::updateVerticalAnchors() setItemHeight(height); //Handle top - if (top.item == item->parentItem()) { + if (top.item == readParentItem(item)) { setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin); - } else if (top.item->parentItem() == item->parentItem()) { + } else if (readParentItem(top.item) == readParentItem(item)) { setItemY(position(top.item, top.anchorLine) + topMargin); } } else if (usedAnchors & QQuickAnchors::BottomAnchor) { @@ -598,27 +642,29 @@ void QQuickAnchorsPrivate::updateVerticalAnchors() } //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 (bottom.item == readParentItem(item)) { + setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - readHeight(item) - bottomMargin); + } else if (readParentItem(bottom.item) == readParentItem(item)) { + setItemY(position(bottom.item, bottom.anchorLine) - readHeight(item) - bottomMargin); } } else if (usedAnchors & QQuickAnchors::VCenterAnchor) { //(stetching handled above) //Handle vCenter - if (vCenter.item == item->parentItem()) { + if (vCenter.item == readParentItem(item)) { setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset); - } else if (vCenter.item->parentItem() == item->parentItem()) { + } else if (readParentItem(vCenter.item) == readParentItem(item)) { setItemY(position(vCenter.item, vCenter.anchorLine) - 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 (baseline.item == readParentItem(item)) { + setItemY(adjustedPosition(baseline.item, baseline.anchorLine) + - readBaselineOffset(item) + baselineOffset); + } else if (readParentItem(baseline.item) == readParentItem(item)) { + setItemY(position(baseline.item, baseline.anchorLine) + - readBaselineOffset(item) + baselineOffset); } } --updatingVerticalAnchor; @@ -687,9 +733,9 @@ void QQuickAnchorsPrivate::updateHorizontalAnchors() setItemWidth(width); //Handle left - if (effectiveLeft.item == item->parentItem()) { + if (effectiveLeft.item == readParentItem(item)) { setItemX(adjustedPosition(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin); - } else if (effectiveLeft.item->parentItem() == item->parentItem()) { + } else if (readParentItem(effectiveLeft.item) == readParentItem(item)) { setItemX(position(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin); } } else if (usedAnchors & effectiveRightAnchor) { @@ -703,16 +749,18 @@ void QQuickAnchorsPrivate::updateHorizontalAnchors() } //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 (effectiveRight.item == readParentItem(item)) { + setItemX(adjustedPosition(effectiveRight.item, effectiveRight.anchorLine) + - readWidth(item) - effectiveRightMargin); + } else if (readParentItem(effectiveRight.item) == readParentItem(item)) { + setItemX(position(effectiveRight.item, effectiveRight.anchorLine) + - readWidth(item) - effectiveRightMargin); } } else if (usedAnchors & QQuickAnchors::HCenterAnchor) { //Handle hCenter - if (effectiveHorizontalCenter.item == item->parentItem()) { + if (effectiveHorizontalCenter.item == readParentItem(item)) { setItemX(adjustedPosition(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset); - } else if (effectiveHorizontalCenter.item->parentItem() == item->parentItem()) { + } else if (readParentItem(effectiveHorizontalCenter.item) == readParentItem(item)) { setItemX(position(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset); } } @@ -1248,7 +1296,7 @@ bool QQuickAnchorsPrivate::checkHAnchorValid(QQuickAnchorLine anchor) const } else if (anchor.anchorLine & QQuickAnchorLine::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) { @@ -1285,7 +1333,7 @@ bool QQuickAnchorsPrivate::checkVAnchorValid(QQuickAnchorLine anchor) const } else if (anchor.anchorLine & QQuickAnchorLine::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){ -- cgit v1.2.3 From 31ef2e858c2a0835c040b3199c9557f0f6c66808 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 22 Apr 2016 09:49:13 +0200 Subject: QmlDebug: Adapt to renaming of Qt Creators "QML/JS" console Change-Id: Ic9d1a1f90bfda07d2796bca71a1ea61e94ffb6da Reviewed-by: Friedemann Kleint --- src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp index bc259afaa4..28213e7b56 100644 --- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp +++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp @@ -423,7 +423,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\" " -- cgit v1.2.3 From f656fc588bab4104d531cb46836168da6736a518 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 21 Apr 2016 16:38:06 +0200 Subject: Fix compilation with Visual Studio 2015 Update 2 (static build) Fix linker errors: Qt5Qml.lib(qv4value.obj) : error LNK2005: _nextafter already defined in libucrt.lib(nextafter.obj) Qt5Qml.lib(qv4dateobject.obj) : error LNK2005: _nextafter already defined in libucrt.lib(nextafter.obj) Qt5Qml.lib(qv4runtime.obj) : error LNK2005: _nextafter already defined in libucrt.lib(nextafter.obj) Qt5Qml.lib(qv4globalobject.obj) : error LNK2005: _nextafter already defined in libucrt.lib(nextafter.obj) Qt5Qml.lib(qv4jsonobject.obj) : error LNK2005: _nextafter already defined in libucrt.lib(nextafter.obj) All the defined functions where added in Visual Studio 2013: https://blogs.msdn.microsoft.com/vcblog/2013/07/19/c99-library-support-in-visual-studio-2013/ Change-Id: Ied924b6c93c6b2f81f2793237c9370a70bd6a60c Reviewed-by: Erik Verbruggen --- src/3rdparty/masm/wtf/Compiler.h | 3 +++ src/3rdparty/masm/wtf/MathExtras.h | 7 +++++++ 2 files changed, 10 insertions(+) (limited to 'src') diff --git a/src/3rdparty/masm/wtf/Compiler.h b/src/3rdparty/masm/wtf/Compiler.h index b886f37151..fc3b5c5c08 100644 --- a/src/3rdparty/masm/wtf/Compiler.h +++ b/src/3rdparty/masm/wtf/Compiler.h @@ -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 */ diff --git a/src/3rdparty/masm/wtf/MathExtras.h b/src/3rdparty/masm/wtf/MathExtras.h index 9a85291ae2..9ded0ab736 100644 --- a/src/3rdparty/masm/wtf/MathExtras.h +++ b/src/3rdparty/masm/wtf/MathExtras.h @@ -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(intgr); } +#endif // COMPILER(MSVC12_OR_LOWER) #endif // COMPILER(MSVC) inline double deg2rad(double d) { return d * piDouble / 180.0; } -- cgit v1.2.3 From 2e6f7f362e62c3285e7d395aca607502c8e8160e Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 21 Apr 2016 15:30:50 +0200 Subject: V4: 'Cache' enumeration end instead of calling a method. Saves ~2600 instructions on Linux/x86_64 for a normal instantiation of QV4::Heap::QtObject. Change-Id: I20c9311a96fd76911536153ddd1605500c6ac451 Reviewed-by: Lars Knoll --- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index f4e980eefb..b90fd7eb17 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -89,9 +89,9 @@ Heap::QtObject::QtObject(QQmlEngine *qmlEngine) const QMetaObject *qtMetaObject = StaticQtMetaObject::get(); ScopedString str(scope); ScopedValue v(scope); - for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) { + for (int ii = 0, eii = qtMetaObject->enumeratorCount(); ii < eii; ++ii) { QMetaEnum enumerator = qtMetaObject->enumerator(ii); - for (int jj = 0; jj < enumerator.keyCount(); ++jj) { + for (int jj = 0, ejj = enumerator.keyCount(); jj < ejj; ++jj) { o->put((str = scope.engine->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj)))); } } -- cgit v1.2.3 From 124e67adc201781e788aae3092a1bc1846cc4358 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 25 Apr 2016 14:50:29 +0200 Subject: QML: Drop unnecessary include Change-Id: Ife8187cc2f052cf76c528cd35efa509f306129cb Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlvme_p.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h index a59d8e2aec..ac9db5c046 100644 --- a/src/qml/qml/qqmlvme_p.h +++ b/src/qml/qml/qqmlvme_p.h @@ -64,8 +64,6 @@ #include #include -#include - QT_BEGIN_NAMESPACE class QObject; -- cgit v1.2.3 From 9cf3895f4dbb5d0678e2030316c1693581f754c9 Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Tue, 12 Apr 2016 23:14:46 +0300 Subject: QQuickDragAttached: fix updating of "active" property The d->active member variable should be changed regardless of the value of Drag.dragType. Task-number: QTBUG-52540 Change-Id: I7fa39ccf11b1200e9c2f6fe57cba58657b6cff74 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickdrag.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index 7e1ffb6b7e..e1b7ef47d8 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -300,13 +300,14 @@ void QQuickDragAttached::setActive(bool active) else if (active) { if (d->dragType == QQuickDrag::Internal) { d->start(d->supportedActions); - } - else if (d->dragType == QQuickDrag::Automatic) { - // There are different semantics than start() since startDrag() - // may be called after an internal drag is already started. + } else { d->active = true; emit activeChanged(); - d->startDrag(d->supportedActions); + if (d->dragType == QQuickDrag::Automatic) { + // There are different semantics than start() since startDrag() + // may be called after an internal drag is already started. + d->startDrag(d->supportedActions); + } } } else -- cgit v1.2.3 From 84f61dd2d2b0140814b39a2c5238a6e31c49abd7 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Thu, 31 Mar 2016 19:32:59 +0200 Subject: Fix performance issues when handling layout changed in Quick item views. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the layout changes, we mark all rows as changed but do not track where the individual rows get moved. The only reason why one would want to track the moves is to persist the current item selection across a layout change. But even the previous code did not achieve that. I'll create a follow up patch to this one that also implements this behavior as seen in Qt Widget item views. Note that removing this code brings a tremendous performance win on larger models. The repeated calls to _q_itemsMoved triggered O(n^2) behavior in the number of top items in the model. Even with "only" tens of thousands of items in the model, a layout change became very costly and took seconds on a beefy modern desktop machine. Calling _q_itemsMoved in a loop is bad because it: - leads to O(N^2) behavior within QQmlChangeSet when merging the small moves into the item view's current change set - potentially triggers tons of binding/property updates when the cached model indices are updated in _q_itemsMoved Removing this slow path, I did not yet find a behavior change to the previous code. Instead, it just does it all much faster. Change-Id: I67fa99a1c5d8e05d17497d29391da9458bd9bdd0 Task-number: QTBUG-51638 Reviewed-by: Daniel Vrátil Reviewed-by: Robin Burchell --- src/qml/types/qqmldelegatemodel.cpp | 37 +---------------------------------- src/qml/types/qqmldelegatemodel_p.h | 1 - src/qml/types/qqmldelegatemodel_p_p.h | 2 -- src/qml/util/qqmladaptormodel.cpp | 4 ---- 4 files changed, 1 insertion(+), 43 deletions(-) (limited to 'src') diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index cd80cba855..527b8aad55 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -1559,29 +1559,6 @@ bool QQmlDelegateModel::isDescendantOf(const QPersistentModelIndex& desc, const return false; } -void QQmlDelegateModel::_q_layoutAboutToBeChanged(const QList &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 &parents, QAbstractItemModel::LayoutChangeHint hint) { Q_D(QQmlDelegateModel); @@ -1593,19 +1570,7 @@ void QQmlDelegateModel::_q_layoutChanged(const QList &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()); } else if (hint == QAbstractItemModel::HorizontalSortHint) { diff --git a/src/qml/types/qqmldelegatemodel_p.h b/src/qml/types/qqmldelegatemodel_p.h index aea474de67..2986ec7ce5 100644 --- a/src/qml/types/qqmldelegatemodel_p.h +++ b/src/qml/types/qqmldelegatemodel_p.h @@ -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 &); - void _q_layoutAboutToBeChanged(const QList&, QAbstractItemModel::LayoutChangeHint); void _q_layoutChanged(const QList&, QAbstractItemModel::LayoutChangeHint); private: diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h index 8e2d1c1cb3..76e55f718d 100644 --- a/src/qml/types/qqmldelegatemodel_p_p.h +++ b/src/qml/types/qqmldelegatemodel_p_p.h @@ -337,8 +337,6 @@ public: }; QQmlDelegateModelGroup *m_groups[Compositor::MaximumGroupCount]; }; - - QList m_storedPersistentIndexes; }; class QQmlPartsModel : public QQmlInstanceModel, public QQmlDelegateModelGroupEmitter diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp index 15c547b5df..5fc2444b7c 100644 --- a/src/qml/util/qqmladaptormodel.cpp +++ b/src/qml/util/qqmladaptormodel.cpp @@ -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,QAbstractItemModel::LayoutChangeHint)), - vdm, SLOT(_q_layoutAboutToBeChanged(QList,QAbstractItemModel::LayoutChangeHint))); QObject::disconnect(aim, SIGNAL(layoutChanged(QList,QAbstractItemModel::LayoutChangeHint)), vdm, SLOT(_q_layoutChanged(QList,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,QAbstractItemModel::LayoutChangeHint)), - vdm, QQmlDelegateModel, SLOT(_q_layoutAboutToBeChanged(QList,QAbstractItemModel::LayoutChangeHint))); qmlobject_connect(model, QAbstractItemModel, SIGNAL(layoutChanged(QList,QAbstractItemModel::LayoutChangeHint)), vdm, QQmlDelegateModel, SLOT(_q_layoutChanged(QList,QAbstractItemModel::LayoutChangeHint))); } else { -- cgit v1.2.3 From 1be53f4e143d417d60cd1f9a292193dab59b5b20 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Wed, 6 Apr 2016 15:23:58 +0300 Subject: Use QStringRef to optimize memory allocation Replace substring functions that return QString with corresponding functions that return QStringRef where it's possible. Create QString from QStringRef only where necessary. While touching the code, also port loops to C++11 style. Change-Id: I04c99b24ea6afd3715e3edf9ea00bfab838fd53c Reviewed-by: Ulf Hermann Reviewed-by: Simon Hausmann Reviewed-by: Frank Meerkoetter Reviewed-by: Shawn Rutledge Reviewed-by: Robin Burchell --- .../qmldbg_debugger/qqmlenginedebugservice.cpp | 12 +++--- .../qmldbg_debugger/qqmlnativedebugservice.cpp | 2 +- .../qmldbg_native/qqmlnativedebugconnector.cpp | 14 +++---- .../qmltooling/qmldbg_server/qqmldebugserver.cpp | 41 ++++++++++---------- src/qml/compiler/qqmlirbuilder.cpp | 8 ++-- src/qml/compiler/qqmltypecompiler.cpp | 14 +++---- src/qml/compiler/qqmltypecompiler_p.h | 6 ++- src/qml/compiler/qv4compileddata.cpp | 4 +- src/qml/qml/qqmlerror.cpp | 7 ++-- src/qml/qml/qqmlfile.cpp | 2 +- src/qml/qml/qqmlimport.cpp | 15 ++++---- src/qml/qml/qqmlproperty.cpp | 16 ++++---- src/qml/types/qqmldelegatemodel.cpp | 2 +- src/qmltest/quicktest.cpp | 2 +- src/quick/items/context2d/qquickcontext2d.cpp | 28 +++++++------- src/quick/items/qquickpathview.cpp | 2 +- src/quick/items/qquickscalegrid.cpp | 45 +++++++++++----------- src/quick/items/qquickscalegrid_p_p.h | 2 +- src/quick/items/qquicktextinput.cpp | 2 +- .../scenegraph/util/qsgshadersourcebuilder.cpp | 6 +-- src/quick/util/qquickanimation.cpp | 2 +- src/quick/util/qquickglobal.cpp | 22 +++++------ src/quick/util/qquickstategroup.cpp | 18 +++++---- 23 files changed, 141 insertions(+), 131 deletions(-) (limited to 'src') diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp index a9996da7f4..ff4e30835d 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp @@ -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); diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp index 877821e03f..a9b9587aa9 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp @@ -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]; diff --git a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp index cc0118f0c2..3145601612 100644 --- a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp +++ b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp @@ -49,6 +49,7 @@ #include #include #include +#include //#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); diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp index 28213e7b56..a6d93e85ae 100644 --- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp +++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include 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; - - // 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; + 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 (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)); } } diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 065e91109b..eaf0e72296 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -250,8 +250,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); @@ -269,7 +269,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(); @@ -278,7 +278,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(); diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index a71793f2b6..da00496cb2 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -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; @@ -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)); @@ -1163,10 +1163,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 +1197,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. diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h index 240f591f91..273ba01a88 100644 --- a/src/qml/compiler/qqmltypecompiler_p.h +++ b/src/qml/compiler/qqmltypecompiler_p.h @@ -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); diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 4d0361302e..a63f35152a 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -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(); diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp index 47c85c907c..74ceeabeb4 100644 --- a/src/qml/qml/qqmlerror.cpp +++ b/src/qml/qml/qqmlerror.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include @@ -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); diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp index ea4e9a1013..5fe3cba5c3 100644 --- a/src/qml/qml/qqmlfile.cpp +++ b/src/qml/qml/qqmlfile.cpp @@ -583,7 +583,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(); } diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index ec29e600ed..2a1717f190 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -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(); @@ -815,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) @@ -1173,11 +1172,11 @@ bool QQmlImportsPrivate::locateQmldir(const QString &uri, int vmaj, int vmin, QQ QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath); if (!absoluteFilePath.isEmpty()) { QString url; - QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(Slash)+1); + 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(); + url = QUrl::fromLocalFile(absolutePath.toString()).toString(); QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache; cache->versionMajor = vmaj; diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index 22de5e1ae9..df2ff05de1 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -58,6 +58,7 @@ #include #include +#include #include #include #include @@ -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; } } diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 527b8aad55..0e7b0c1b14 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -1042,7 +1042,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(); } diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp index 9ba93a1241..bc26a19033 100644 --- a/src/qmltest/quicktest.cpp +++ b/src/qmltest/quicktest.cpp @@ -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)); diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 734cadf49a..1b0670aabf 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -65,6 +65,7 @@ #include #include +#include #include #include #include @@ -200,7 +201,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); @@ -216,11 +217,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")) { @@ -246,7 +247,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; @@ -259,7 +260,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; @@ -390,16 +391,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; @@ -408,16 +410,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. diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index f0bbb1e732..a56d0fc06e 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -1910,7 +1910,7 @@ void QQuickPathView::refill() if (lcItemViewDelegateLifecycle().isDebugEnabled()) { QQuickText *text = qmlobject_cast(item); if (text) - qCDebug(lcItemViewDelegateLifecycle) << "idx" << idx << "@" << pos << ": QQuickText" << text->objectName() << text->text().left(40); + qCDebug(lcItemViewDelegateLifecycle) << "idx" << idx << "@" << pos << ": QQuickText" << text->objectName() << text->text().leftRef(40); else qCDebug(lcItemViewDelegateLifecycle) << "idx" << idx << "@" << pos << ":" << item; } diff --git a/src/quick/items/qquickscalegrid.cpp b/src/quick/items/qquickscalegrid.cpp index f860c08bad..d7a0f1b681 100644 --- a/src/quick/items/qquickscalegrid.cpp +++ b/src/quick/items/qquickscalegrid.cpp @@ -136,39 +136,38 @@ QQuickGridScaledImage::QQuickGridScaledImage(QIODevice *data) if (colonId <= 0) return; - QStringList list; - list.append(line.left(colonId).trimmed()); - list.append(line.mid(colonId+1).trimmed()); - - if (list[0] == QLatin1String("border.left")) - l = list[1].toInt(); - else if (list[0] == QLatin1String("border.right")) - r = list[1].toInt(); - else if (list[0] == QLatin1String("border.top")) - t = list[1].toInt(); - else if (list[0] == QLatin1String("border.bottom")) - b = list[1].toInt(); - else if (list[0] == QLatin1String("source")) - imgFile = list[1]; - else if (list[0] == QLatin1String("horizontalTileRule") || list[0] == QLatin1String("horizontalTileMode")) - _h = stringToRule(list[1]); - else if (list[0] == QLatin1String("verticalTileRule") || list[0] == QLatin1String("verticalTileMode")) - _v = stringToRule(list[1]); + const QStringRef property = line.leftRef(colonId).trimmed(); + QStringRef value = line.midRef(colonId + 1).trimmed(); + + if (property == QLatin1String("border.left")) { + l = value.toInt(); + } else if (property == QLatin1String("border.right")) { + r = value.toInt(); + } else if (property == QLatin1String("border.top")) { + t = value.toInt(); + } else if (property == QLatin1String("border.bottom")) { + b = value.toInt(); + } else if (property == QLatin1String("source")) { + if (value.startsWith(QLatin1Char('"')) && value.endsWith(QLatin1Char('"'))) + value = value.mid(1, value.size() - 2); // remove leading/trailing quotes. + imgFile = value.toString(); + } else if (property == QLatin1String("horizontalTileRule") || property == QLatin1String("horizontalTileMode")) { + _h = stringToRule(value); + } else if (property == QLatin1String("verticalTileRule") || property == QLatin1String("verticalTileMode")) { + _v = stringToRule(value); + } } if (l < 0 || r < 0 || t < 0 || b < 0 || imgFile.isEmpty()) return; _l = l; _r = r; _t = t; _b = b; - _pix = imgFile; - if (_pix.startsWith(QLatin1Char('"')) && _pix.endsWith(QLatin1Char('"'))) - _pix = _pix.mid(1, _pix.size() - 2); // remove leading/trailing quotes. } -QQuickBorderImage::TileMode QQuickGridScaledImage::stringToRule(const QString &s) +QQuickBorderImage::TileMode QQuickGridScaledImage::stringToRule(const QStringRef &s) { - QString string = s; + QStringRef string = s; if (string.startsWith(QLatin1Char('"')) && string.endsWith(QLatin1Char('"'))) string = string.mid(1, string.size() - 2); // remove leading/trailing quotes. diff --git a/src/quick/items/qquickscalegrid_p_p.h b/src/quick/items/qquickscalegrid_p_p.h index a424002dfb..7f6a31a7bd 100644 --- a/src/quick/items/qquickscalegrid_p_p.h +++ b/src/quick/items/qquickscalegrid_p_p.h @@ -116,7 +116,7 @@ public: QString pixmapUrl() const; private: - static QQuickBorderImage::TileMode stringToRule(const QString &); + static QQuickBorderImage::TileMode stringToRule(const QStringRef &); private: int _l; diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index ab7a0f02dd..504dece0d1 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -1874,7 +1874,7 @@ QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property, QVaria return QVariant(d->m_text.mid(d->m_cursor)); case Qt::ImTextBeforeCursor: if (argument.isValid()) - return QVariant(d->m_text.left(d->m_cursor).right(argument.toInt())); + return QVariant(d->m_text.leftRef(d->m_cursor).right(argument.toInt()).toString()); return QVariant(d->m_text.left(d->m_cursor)); default: return QQuickItem::inputMethodQuery(property); diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp index ec1d316f78..caa296451e 100644 --- a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp +++ b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp @@ -382,9 +382,9 @@ QString QSGShaderSourceBuilder::resolveShaderPath(const QString &path) const int idx = path.lastIndexOf(QLatin1Char('.')); QString resolvedPath; if (idx != -1) - resolvedPath = path.left(idx) - + QStringLiteral("_core") - + path.right(path.length() - idx); + resolvedPath = path.leftRef(idx) + + QLatin1String("_core") + + path.rightRef(path.length() - idx); return resolvedPath; } } diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp index adf8f600a0..741a583803 100644 --- a/src/quick/util/qquickanimation.cpp +++ b/src/quick/util/qquickanimation.cpp @@ -986,7 +986,7 @@ void QQuickScriptActionPrivate::debugAction(QDebug d, int indentLevel) const QByteArray ind(indentLevel, ' '); QString exprStr = expr.expression(); int endOfFirstLine = exprStr.indexOf('\n'); - d << "\n" << ind.constData() << exprStr.left(endOfFirstLine); + d << "\n" << ind.constData() << exprStr.leftRef(endOfFirstLine); if (endOfFirstLine != -1 && endOfFirstLine < exprStr.length()) d << "..."; } diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp index ef54917434..be4c968ab2 100644 --- a/src/quick/util/qquickglobal.cpp +++ b/src/quick/util/qquickglobal.cpp @@ -172,8 +172,8 @@ public: int index = s.indexOf(QLatin1Char(',')); bool xGood, yGood; - float xCoord = s.left(index).toFloat(&xGood); - float yCoord = s.mid(index+1).toFloat(&yGood); + float xCoord = s.leftRef(index).toFloat(&xGood); + float yCoord = s.midRef(index + 1).toFloat(&yGood); if (xGood && yGood) { if (ok) *ok = true; @@ -192,9 +192,9 @@ public: int index2 = s.indexOf(QLatin1Char(','), index+1); bool xGood, yGood, zGood; - float xCoord = s.left(index).toFloat(&xGood); - float yCoord = s.mid(index+1, index2-index-1).toFloat(&yGood); - float zCoord = s.mid(index2+1).toFloat(&zGood); + float xCoord = s.leftRef(index).toFloat(&xGood); + float yCoord = s.midRef(index + 1, index2 - index - 1).toFloat(&yGood); + float zCoord = s.midRef(index2 + 1).toFloat(&zGood); if (xGood && yGood && zGood) { if (ok) *ok = true; @@ -214,10 +214,10 @@ public: int index3 = s.indexOf(QLatin1Char(','), index2+1); bool xGood, yGood, zGood, wGood; - float xCoord = s.left(index).toFloat(&xGood); - float yCoord = s.mid(index+1, index2-index-1).toFloat(&yGood); - float zCoord = s.mid(index2+1, index3-index2-1).toFloat(&zGood); - float wCoord = s.mid(index3+1).toFloat(&wGood); + float xCoord = s.leftRef(index).toFloat(&xGood); + float yCoord = s.midRef(index + 1, index2 - index - 1).toFloat(&yGood); + float zCoord = s.midRef(index2 + 1, index3 - index2 - 1).toFloat(&zGood); + float wCoord = s.midRef(index3 + 1).toFloat(&wGood); if (xGood && yGood && zGood && wGood) { if (ok) *ok = true; @@ -257,10 +257,10 @@ public: if (s.count(QLatin1Char(',')) == 15) { float matValues[16]; bool vOK = true; - QString mutableStr = s; + QStringRef mutableStr(&s); for (int i = 0; vOK && i < 16; ++i) { int cidx = mutableStr.indexOf(QLatin1Char(',')); - matValues[i] = mutableStr.leftRef(cidx).toDouble(&vOK); + matValues[i] = mutableStr.left(cidx).toDouble(&vOK); mutableStr = mutableStr.mid(cidx + 1); } diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp index 791e38e45d..c163b401fb 100644 --- a/src/quick/util/qquickstategroup.cpp +++ b/src/quick/util/qquickstategroup.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -379,28 +380,29 @@ QQuickTransition *QQuickStateGroupPrivate::findTransition(const QString &from, c (t->fromState() == QLatin1String("*") && t->toState() == QLatin1String("*")))) break; - QStringList fromState; - QStringList toState; + const QString fromStateStr = t->fromState(); + const QString toStateStr = t->toState(); - fromState = t->fromState().split(QLatin1Char(',')); + QVector fromState = fromStateStr.splitRef(QLatin1Char(',')); for (int jj = 0; jj < fromState.count(); ++jj) fromState[jj] = fromState.at(jj).trimmed(); - toState = t->toState().split(QLatin1Char(',')); + QVector toState = toStateStr.splitRef(QLatin1Char(',')); for (int jj = 0; jj < toState.count(); ++jj) toState[jj] = toState.at(jj).trimmed(); if (ii == 1) qSwap(fromState, toState); int tScore = 0; - if (fromState.contains(from)) + const QString asterisk = QStringLiteral("*"); + if (fromState.contains(QStringRef(&from))) tScore += 2; - else if (fromState.contains(QLatin1String("*"))) + else if (fromState.contains(QStringRef(&asterisk))) tScore += 1; else continue; - if (toState.contains(to)) + if (toState.contains(QStringRef(&to))) tScore += 2; - else if (toState.contains(QLatin1String("*"))) + else if (toState.contains(QStringRef(&asterisk))) tScore += 1; else continue; -- cgit v1.2.3 From 1ee7efac496d893cea9e5310d249275fe1532f2a Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 25 Apr 2016 15:07:34 +0200 Subject: QmlProfiler: Pass detailType directly, rather than as a bit field There can only be one detail type for compressed set of messages. This is unlikely to change anytime soon. Also, be more careful about not detaching the data when sending the messages. Task-number: QTBUG-52937 Change-Id: I859b12889b0766543dac00b21784e14b76e458b6 Reviewed-by: Simon Hausmann --- .../qmldbg_profiler/qqmlprofileradapter.cpp | 59 ++++++++++------------ src/qml/debugger/qqmlprofiler_p.h | 26 +++++----- 2 files changed, 40 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp index 688ced26ec..0ee69a6e02 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp @@ -65,51 +65,46 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin // 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 &messages) +static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d, QList &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(d.detailType); - //### using QDataStream is relatively expensive - ds << d->time << decodedMessageType << decodedDetailType; - - 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 << (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(); } } qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList &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, messages); + ++next; } next = 0; diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h index 24001159f3..d32b350055 100644 --- a/src/qml/debugger/qqmlprofiler_p.h +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -77,33 +77,33 @@ 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, + QQmlProfilerData(qint64 time, int messageType, RangeType 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, + QQmlProfilerData(qint64 time, int messageType, RangeType 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, + QQmlProfilerData(qint64 time, int messageType, RangeType 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) : + QQmlProfilerData(qint64 time, int messageType, RangeType detailType) : time(time), messageType(messageType), detailType(detailType) {} qint64 time; int messageType; //bit field of QQmlProfilerService::Message - int detailType; + RangeType detailType; // RangeData prefers detailString; RangeLocation prefers detailUrl. QString detailString; //used by RangeData and possibly by RangeLocation @@ -121,7 +121,7 @@ public: void startBinding(const QQmlSourceLocation &location) { m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), - (1 << RangeStart | 1 << RangeLocation), 1 << Binding, + (1 << RangeStart | 1 << RangeLocation), Binding, location.sourceFile, qmlSourceCoordinate(location.line), qmlSourceCoordinate(location.column))); } @@ -131,39 +131,39 @@ public: { m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeStart | 1 << RangeLocation | 1 << RangeData), - 1 << Compiling, url, 1, 1)); + Compiling, url, 1, 1)); } void startHandlingSignal(const QQmlSourceLocation &location) { m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), - (1 << RangeStart | 1 << RangeLocation), 1 << HandlingSignal, + (1 << RangeStart | 1 << RangeLocation), HandlingSignal, location.sourceFile, location.line, location.column)); } 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) { m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeStart | 1 << RangeLocation | 1 << RangeData), - 1 << Creating, typeName, fileName, line, column)); + Creating, typeName, fileName, line, column)); } void updateCreating(const QString &typeName, const QUrl &fileName, int line, int column) { m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeLocation | 1 << RangeData), - 1 << Creating, typeName, fileName, line, column)); + Creating, typeName, fileName, line, column)); } template void endRange() { - m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, 1 << Range)); + m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, Range)); } QQmlProfiler(); -- cgit v1.2.3 From 55e9687368008e66e67db2636f47b87699d083c7 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 26 Apr 2016 08:39:15 +0200 Subject: Revert "Avoid rebuiding batches during a material animation" This reverts commit 26a230ee0ed68d39d4d13bfeaafd9839ee2a2a00. This optimization breaks when we have a single material change in the scene within a batch as the geometry node does not get visited on the next render. Task-number: QTBUG-52983 Change-Id: Ib385407a9fc35ca03ab18727d1e7b550431416f1 Reviewed-by: Michael Brasser Reviewed-by: Jocelyn Turcotte (Woboq GmbH) --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index e829b054fb..525d702a76 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -489,11 +489,6 @@ void Updater::visitGeometryNode(Node *n) if (e->batch) renderer->invalidateBatchAndOverlappingRenderOrders(e->batch); } - if (n->dirtyState & QSGNode::DirtyMaterial) { - Element *e = n->element(); - if (e->batch && e->batch->isMaterialCompatible(e) == BatchBreaksOnCompare) - renderer->invalidateBatchAndOverlappingRenderOrders(e->batch); - } } SHADOWNODE_TRAVERSE(n) visitNode(*child); @@ -1213,7 +1208,10 @@ void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state) if (e->isMaterialBlended != blended) { m_rebuild |= Renderer::FullRebuild; e->isMaterialBlended = blended; - } else if (!e->batch) { + } else if (e->batch) { + if (e->batch->isMaterialCompatible(e) == BatchBreaksOnCompare) + invalidateBatchAndOverlappingRenderOrders(e->batch); + } else { m_rebuild |= Renderer::BuildBatches; } } -- cgit v1.2.3 From 485a381cabc730622dbe1b150260ea417d2bbcfd Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Mon, 25 Apr 2016 17:40:19 +0300 Subject: Qml: use qDeleteAll more qDeleteAll uses iterator-based loop, that produce less code than index-based. Saves ~0.1 KB text size. Config: release build, Ubuntu 14.04 x64, gcc 4.9 Change-Id: Ib6c01f3b6a73367e33aecd34223edde15262d33c Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlxmlhttprequest.cpp | 6 ++---- src/qml/qml/v8/qv8engine.cpp | 3 +-- src/qml/types/qqmllistmodel.cpp | 10 +++------- 3 files changed, 6 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index fe02c6633e..24f49eb6e7 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -117,10 +117,8 @@ class NodeImpl public: NodeImpl() : type(Element), document(0), parent(0) {} virtual ~NodeImpl() { - for (int ii = 0; ii < children.count(); ++ii) - delete children.at(ii); - for (int ii = 0; ii < attributes.count(); ++ii) - delete attributes.at(ii); + qDeleteAll(children); + qDeleteAll(attributes); } // These numbers are copied from the Node IDL definition diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index d322088f61..6949eb43e8 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -155,8 +155,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(); qt_rem_qmlxmlhttprequest(m_v4Engine, m_xmlHttpRequestData); diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index 91eef2d982..44a4ff03e9 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -169,9 +169,7 @@ ListLayout::ListLayout(const ListLayout *other) : currentBlock(0), currentBlockO ListLayout::~ListLayout() { - for (int i=0 ; i < roles.count() ; ++i) { - delete roles[i]; - } + qDeleteAll(roles); } void ListLayout::sync(ListLayout *src, ListLayout *target) @@ -1662,8 +1660,7 @@ QQmlListModel::QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agen QQmlListModel::~QQmlListModel() { - for (int i=0 ; i < m_modelObjects.count() ; ++i) - delete m_modelObjects[i]; + qDeleteAll(m_modelObjects); if (m_primary) { m_listModel->destroy(); @@ -2007,8 +2004,7 @@ void QQmlListModel::clear() emitItemsAboutToBeRemoved(0, cleared); if (m_dynamicRoles) { - for (int i=0 ; i < m_modelObjects.count() ; ++i) - delete m_modelObjects[i]; + qDeleteAll(m_modelObjects); m_modelObjects.clear(); } else { m_listModel->clear(); -- cgit v1.2.3 From 6b810efa7d47d8da19928d1116f71b9fb83215f1 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 18 Apr 2016 18:27:14 +0200 Subject: Make some of the shader manager private There is no need for other classes to directly access the shader cache, and if we ever want a way to invalidate pieces of it, we better prevent such access. Change-Id: I79949b375854445c46b9d8bf6072bb53030b8dac Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index 8cd9e7e3ff..0752beb24e 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -521,7 +521,7 @@ public: float lastOpacity; }; - ShaderManager(QSGRenderContext *ctx) : blitProgram(0), visualizeProgram(0), context(ctx) { } + ShaderManager(QSGRenderContext *ctx) : visualizeProgram(0), blitProgram(0), context(ctx) { } ~ShaderManager() { qDeleteAll(rewrittenShaders); qDeleteAll(stockShaders); @@ -534,11 +534,13 @@ public: Shader *prepareMaterial(QSGMaterial *material); Shader *prepareMaterialNoRewrite(QSGMaterial *material); + QOpenGLShaderProgram *visualizeProgram; + +private: QHash rewrittenShaders; QHash stockShaders; QOpenGLShaderProgram *blitProgram; - QOpenGLShaderProgram *visualizeProgram; QSGRenderContext *context; }; -- cgit v1.2.3 From f36a1b9048bcf7e29eeb92a5b4560d851c527252 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Thu, 28 Apr 2016 11:10:39 +0200 Subject: Doc: Document Window.contentItem QML property Change-Id: I6914919675e8787312824ac958e3ea3fb6dc5264 Task-number: QTBUG-53045 Reviewed-by: J-P Nurmi Reviewed-by: Shawn Rutledge --- src/quick/items/qquickwindow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 24bac168ea..ef534fe35d 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -3971,6 +3971,12 @@ void QQuickWindow::resetOpenGLState() \sa visible, visibility */ +/*! + \qmlproperty Item Window::contentItem + \readonly + \brief The invisible root item of the scene. +*/ + /*! \qmlproperty Qt::ScreenOrientation Window::contentOrientation -- cgit v1.2.3 From 56a82a531771f13adbe74ee08d11b058a87beee2 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 28 Apr 2016 12:16:41 +0200 Subject: Particles: Invalidate all group IDs when groups are reset. Task-number: QTBUG-52325 Change-Id: I38d90b6fb0d7468fb0916bd6dfd1cf07ace4389b Reviewed-by: Gunnar Sletta --- src/particles/qquickparticleemitter_p.h | 5 ++--- src/particles/qquickparticlesystem.cpp | 7 +++++++ 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/particles/qquickparticleemitter_p.h b/src/particles/qquickparticleemitter_p.h index 9b114ad46b..dd55fdc7a6 100644 --- a/src/particles/qquickparticleemitter_p.h +++ b/src/particles/qquickparticleemitter_p.h @@ -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; diff --git a/src/particles/qquickparticlesystem.cpp b/src/particles/qquickparticlesystem.cpp index 17d9e49d63..b60180b2ed 100644 --- a/src/particles/qquickparticlesystem.cpp +++ b/src/particles/qquickparticlesystem.cpp @@ -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); -- cgit v1.2.3 From 1913b0a1233597210091e7a73757fab39ff40fc7 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Thu, 28 Apr 2016 12:24:50 +0200 Subject: Abort application if QJSEngine is constructed before QCoreApplication QJSEngine requires a QCoreApplication instance in order to function correctly, and 57f7fe3e enforces this further. However, currently an application will simply crash because of accessing a non-existent QCoreApplication instance. This patch makes it clear to the user that they need to construct an instance first. Change-Id: Ieaef005ef03da250cc60457b4b1a4baa5db81215 Reviewed-by: Simon Hausmann --- src/qml/jsapi/qjsengine.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index 4241213c09..5bcc4600a2 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -247,6 +247,11 @@ Q_DECLARE_METATYPE(QList) QT_BEGIN_NAMESPACE +static void checkForApplicationInstance() +{ + if (!QCoreApplication::instance()) + qFatal("QJSEngine: Must construct a QCoreApplication before a QJSEngine"); +} /*! Constructs a QJSEngine object. @@ -258,6 +263,8 @@ QJSEngine::QJSEngine() : QObject(*new QJSEnginePrivate, 0) , d(new QV8Engine(this)) { + checkForApplicationInstance(); + QJSEnginePrivate::addToDebugServer(this); } @@ -272,6 +279,8 @@ QJSEngine::QJSEngine(QObject *parent) : QObject(*new QJSEnginePrivate, parent) , d(new QV8Engine(this)) { + checkForApplicationInstance(); + QJSEnginePrivate::addToDebugServer(this); } @@ -282,6 +291,7 @@ QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent) : QObject(dd, parent) , d(new QV8Engine(this)) { + checkForApplicationInstance(); } /*! -- cgit v1.2.3 From fb81ea10520538d59a424678da68e884679f4075 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 28 Apr 2016 13:07:56 +0200 Subject: QML: Replace qIsFinite with qt_is_finite. The latter can be inlined. Change-Id: I57747b84889390839a17faa1df6d359210ef4adf Reviewed-by: Gunnar Sletta --- src/qml/jsruntime/qv4dateobject.cpp | 2 +- src/quick/items/context2d/qquickcontext2d.cpp | 112 +++++++++++----------- src/quick/items/qquickimage.cpp | 4 +- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 8 +- 4 files changed, 63 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 8e4ebb3cb0..5397ad43c5 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -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); } diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 1b0670aabf..ced4d2a6c4 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -1260,7 +1260,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) { @@ -1544,10 +1544,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); @@ -1589,12 +1589,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") } @@ -1636,11 +1636,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"); } @@ -1891,7 +1891,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); } @@ -1920,7 +1920,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); } @@ -1949,7 +1949,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); } @@ -2009,7 +2009,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); } @@ -2037,7 +2037,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); } @@ -2167,7 +2167,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(), @@ -2213,7 +2213,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(), @@ -2276,7 +2276,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); @@ -2372,7 +2372,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); @@ -2396,7 +2396,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); } @@ -2422,7 +2422,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); @@ -2506,7 +2506,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); } @@ -2771,7 +2771,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); @@ -2970,14 +2970,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 @@ -3198,7 +3198,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) @@ -3224,7 +3224,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) @@ -3256,7 +3256,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 imageData(scope, arg0); @@ -3274,7 +3274,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"); @@ -3361,7 +3361,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"); } @@ -3381,7 +3381,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; @@ -3402,7 +3402,7 @@ void QQuickContext2D::rotate(qreal angle) if (!state.invertibleCTM) return; - if (!qIsFinite(angle)) + if (!qt_is_finite(angle)) return; QTransform newTransform =state.matrix; @@ -3423,7 +3423,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; @@ -3444,7 +3444,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; @@ -3465,7 +3465,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); @@ -3482,7 +3482,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; @@ -3539,7 +3539,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)); @@ -3550,7 +3550,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)); @@ -3561,7 +3561,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)); @@ -3572,7 +3572,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); @@ -3718,7 +3718,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); @@ -3736,7 +3736,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) { @@ -3753,7 +3753,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) { @@ -3769,7 +3769,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) { @@ -3795,7 +3795,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) @@ -3934,13 +3934,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(this)->m_path.setFillRule(state.fillRule); diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp index 34b8f0ac49..c04a526bd0 100644 --- a/src/quick/items/qquickimage.cpp +++ b/src/quick/items/qquickimage.cpp @@ -714,9 +714,9 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) sourceRect.height() / nsHeight); if (targetRect.isEmpty() - || !qIsFinite(targetRect.width()) || !qIsFinite(targetRect.height()) + || !qt_is_finite(targetRect.width()) || !qt_is_finite(targetRect.height()) || nsrect.isEmpty() - || !qIsFinite(nsrect.width()) || !qIsFinite(nsrect.height())) { + || !qt_is_finite(nsrect.width()) || !qt_is_finite(nsrect.height())) { delete node; return 0; } diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index e657307efd..0e77befe04 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -598,13 +598,13 @@ void Element::computeBounds() } bounds.map(*node->matrix()); - if (!qIsFinite(bounds.tl.x) || bounds.tl.x == FLT_MAX) + if (!qt_is_finite(bounds.tl.x) || bounds.tl.x == FLT_MAX) bounds.tl.x = -FLT_MAX; - if (!qIsFinite(bounds.tl.y) || bounds.tl.y == FLT_MAX) + if (!qt_is_finite(bounds.tl.y) || bounds.tl.y == FLT_MAX) bounds.tl.y = -FLT_MAX; - if (!qIsFinite(bounds.br.x) || bounds.br.x == -FLT_MAX) + if (!qt_is_finite(bounds.br.x) || bounds.br.x == -FLT_MAX) bounds.br.x = FLT_MAX; - if (!qIsFinite(bounds.br.y) || bounds.br.y == -FLT_MAX) + if (!qt_is_finite(bounds.br.y) || bounds.br.y == -FLT_MAX) bounds.br.y = FLT_MAX; Q_ASSERT(bounds.tl.x <= bounds.br.x); -- cgit v1.2.3 From fb99da23df3b420a0bf475ec56576cf9b199ffcc Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Fri, 29 Apr 2016 15:32:59 +0300 Subject: Add version tag to QQmlExtensionInterface_iid Commit 392c7b99348e2a96ef11adb5712095fbd13fb780 introduced version checking that checks QML extension plugin interface version name. Unfortunately many plugins inside and outside qtdeclarative already defined the string with interface version, leading to plugin not being loaded. Task-number: QTBUG-53090 Change-Id: I792df4ba06753bc21eab4adcd6f2068543d02368 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlextensioninterface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/qml/qqmlextensioninterface.h b/src/qml/qml/qqmlextensioninterface.h index b64fbef1bf..d639ef85d0 100644 --- a/src/qml/qml/qqmlextensioninterface.h +++ b/src/qml/qml/qqmlextensioninterface.h @@ -60,7 +60,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) -- cgit v1.2.3 From 3b0cb49ef0cff2e7ae4ba295d035b87f09fdea4f Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 29 Apr 2016 10:56:03 +0200 Subject: Fix EnterKey::type docs It's an attached property, not an ordinary property. Change-Id: I08123670953288b21daca8bd56129c1e14e36365 Reviewed-by: Mitch Curtis --- src/quick/items/qquickitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index b15dd76f27..c27e9d0d95 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -1624,7 +1624,7 @@ void QQuickItemPrivate::setLayoutMirror(bool mirror) */ /*! - \qmlproperty enumeration QtQuick::EnterKey::type + \qmlattachedproperty enumeration QtQuick::EnterKey::type Holds the type of the Enter key. -- cgit v1.2.3 From 1650377af7dfb01a0641d4e21bf1ba33e6a7320f Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 29 Apr 2016 09:55:49 +0200 Subject: Fix crash when trying to call a property of the scope or context object For calls on properties of the scope or context object the thisObject parameter in the callData is a reference to the QmlContext, not a real object - therefore the toString conversion fails. Task-number: QTBUG-52340 Change-Id: I08d01cc5c05920c2fac46ddd40fa41e630bcade3 Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4runtime.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index a988313f5f..d8ae7d4e92 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -953,10 +953,9 @@ ReturnedValue Runtime::callQmlScopeObjectProperty(ExecutionEngine *engine, int p Scope scope(engine); ScopedFunctionObject o(scope, 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); } @@ -965,7 +964,7 @@ ReturnedValue Runtime::callQmlContextObjectProperty(ExecutionEngine *engine, int Scope scope(engine); ScopedFunctionObject o(scope, 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); } -- cgit v1.2.3 From be031102c226ab9bccc1e73018af25082240bcc3 Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Wed, 27 Apr 2016 08:12:12 +0200 Subject: AnimatedImage: Fix value of sourceSize property Cache the source size of the internal QMovie object during the change of the 'source' property to ensure that always a valid source size is returned without emitting more sourceSizeChanged() signals than necessary. Change-Id: I637b80efb133197b7345b09fcf8a7bb80c5643c9 Reviewed-by: Robin Burchell --- src/quick/items/qquickanimatedimage.cpp | 24 +++++++++++++++--------- src/quick/items/qquickanimatedimage_p_p.h | 3 ++- 2 files changed, 17 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp index 49fef12467..11dad5b001 100644 --- a/src/quick/items/qquickanimatedimage.cpp +++ b/src/quick/items/qquickanimatedimage.cpp @@ -294,8 +294,9 @@ void QQuickAnimatedImage::load() d->status = Null; emit statusChanged(d->status); - if (sourceSize() != d->oldSourceSize) { - d->oldSourceSize = sourceSize(); + d->currentSourceSize = QSize(0, 0); + if (d->currentSourceSize != d->oldSourceSize) { + d->oldSourceSize = d->currentSourceSize; emit sourceSizeChanged(); } if (isPlaying() != d->oldPlaying) @@ -366,8 +367,9 @@ void QQuickAnimatedImage::movieRequestFinished() d->status = Error; emit statusChanged(d->status); - if (sourceSize() != d->oldSourceSize) { - d->oldSourceSize = sourceSize(); + d->currentSourceSize = QSize(0, 0); + if (d->currentSourceSize != d->oldSourceSize) { + d->oldSourceSize = d->currentSourceSize; emit sourceSizeChanged(); } if (isPlaying() != d->oldPlaying) @@ -404,8 +406,14 @@ void QQuickAnimatedImage::movieRequestFinished() if (isPlaying() != d->oldPlaying) emit playingChanged(); - if (sourceSize() != d->oldSourceSize) { - d->oldSourceSize = sourceSize(); + + if (d->_movie) + d->currentSourceSize = d->_movie->currentPixmap().size(); + else + d->currentSourceSize = QSize(0, 0); + + if (d->currentSourceSize != d->oldSourceSize) { + d->oldSourceSize = d->currentSourceSize; emit sourceSizeChanged(); } } @@ -458,9 +466,7 @@ void QQuickAnimatedImage::onCacheChanged() QSize QQuickAnimatedImage::sourceSize() { Q_D(QQuickAnimatedImage); - if (!d->_movie) - return QSize(0, 0); - return QSize(d->_movie->currentPixmap().size()); + return d->currentSourceSize; } void QQuickAnimatedImage::componentComplete() diff --git a/src/quick/items/qquickanimatedimage_p_p.h b/src/quick/items/qquickanimatedimage_p_p.h index bb921fda4a..ed1bf368c8 100644 --- a/src/quick/items/qquickanimatedimage_p_p.h +++ b/src/quick/items/qquickanimatedimage_p_p.h @@ -60,7 +60,7 @@ class QQuickAnimatedImagePrivate : public QQuickImagePrivate public: QQuickAnimatedImagePrivate() - : playing(true), paused(false), preset_currentframe(0), _movie(0), reply(0), redirectCount(0), oldPlaying(false) + : playing(true), paused(false), preset_currentframe(0), _movie(0), reply(0), redirectCount(0), oldPlaying(false), currentSourceSize(0, 0) { } @@ -74,6 +74,7 @@ public: int redirectCount; bool oldPlaying; QMap frameMap; + QSize currentSourceSize; }; QT_END_NAMESPACE -- cgit v1.2.3 From a2e64a20777867726b51a9c9196dc1b8dd68f512 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 21 Apr 2016 16:57:10 +0200 Subject: V4 profiler: Don't duplicate function locations Saving the name/file/line/column over and over for each function call is wasteful. We can instead key them by the pointer to the JS Function object. Also, make sure we don't accidentally detach the data when sending messages. Task-number: QTBUG-52937 Change-Id: I8a03e4003dc3239f88b49c56424df05cd8b9ef8a Reviewed-by: Anton Kudryavtsev Reviewed-by: Simon Hausmann --- .../qmldbg_profiler/qv4profileradapter.cpp | 46 +++++++++++++++------- .../qmldbg_profiler/qv4profileradapter.h | 4 +- src/qml/jsruntime/qv4profiling.cpp | 40 ++++++++++++------- src/qml/jsruntime/qv4profiling_p.h | 14 ++++++- 4 files changed, 73 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp index b50eef5545..68a71a5524 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp @@ -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, + connect(engine->profiler, SIGNAL(dataReady(QV4::Profiling::FunctionLocationHash, + QVector, QVector)), - this, SLOT(receiveData(QVector, + this, SLOT(receiveData(QV4::Profiling::FunctionLocationHash, + QVector, QVector))); } qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList &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 &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 &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 &mes qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList &messages) { QQmlDebugPacket d; + + // Make it const, so that we cannot accidentally detach it. + const QVector &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 &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 &functionCallData, const QVector &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; diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h index f2985af98b..968825c346 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h @@ -74,7 +74,8 @@ signals: void v4ProfilingEnabledWhileWaiting(quint64 v4Features); public slots: - void receiveData(const QVector &, + void receiveData(const QV4::Profiling::FunctionLocationHash &, + const QVector &, const QVector &); private slots: @@ -82,6 +83,7 @@ private slots: void forwardEnabledWhileWaiting(quint64 features); private: + QV4::Profiling::FunctionLocationHash m_functionLocations; QVector m_functionCallData; QVector m_memoryData; int m_functionCallPos; diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp index c0a4129d9d..a59190b846 100644 --- a/src/qml/jsruntime/qv4profiling.cpp +++ b/src/qml/jsruntime/qv4profiling.cpp @@ -46,26 +46,35 @@ QT_BEGIN_NAMESPACE namespace QV4 { namespace Profiling { -FunctionCallProperties FunctionCall::resolve() const +FunctionLocation FunctionCall::resolveLocation() const { - FunctionCallProperties props = { - m_start, - m_end, + FunctionLocation location = { m_function->name()->toQString(), m_function->compilationUnit->fileName(), m_function->compiledFunction->location.line, m_function->compiledFunction->location.column }; - return props; + return location; } +FunctionCallProperties FunctionCall::properties() const +{ + FunctionCallProperties props = { + m_start, + m_end, + reinterpret_cast(m_function) + }; + return props; +} Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(engine) { - static int meta = qRegisterMetaType >(); - static int meta2 = qRegisterMetaType >(); - Q_UNUSED(meta); - Q_UNUSED(meta2); + static const int metatypes[] = { + qRegisterMetaType >(), + qRegisterMetaType >(), + qRegisterMetaType() + }; + Q_UNUSED(metatypes); m_timer.start(); } @@ -85,13 +94,16 @@ bool operator<(const FunctionCall &call1, const FunctionCall &call2) void Profiler::reportData() { std::sort(m_data.begin(), m_data.end()); - QVector resolved; - resolved.reserve(m_data.size()); + QVector properties; + QHash 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()); + locations[properties.constLast().id] = call.resolveLocation(); + } - emit dataReady(resolved, m_memory_data); + emit dataReady(locations, properties, m_memory_data); m_data.clear(); m_memory_data.clear(); } diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h index 25ef8223bf..0b4193204f 100644 --- a/src/qml/jsruntime/qv4profiling_p.h +++ b/src/qml/jsruntime/qv4profiling_p.h @@ -77,12 +77,18 @@ enum MemoryType { struct FunctionCallProperties { qint64 start; qint64 end; + quintptr id; +}; + +struct FunctionLocation { QString name; QString file; int line; int column; }; +typedef QHash FunctionLocationHash; + struct MemoryAllocationProperties { qint64 timestamp; qint64 size; @@ -118,7 +124,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 +180,8 @@ public slots: void setTimer(const QElapsedTimer &timer) { m_timer = timer; } signals: - void dataReady(const QVector &, + void dataReady(const QV4::Profiling::FunctionLocationHash &, + const QVector &, const QVector &); private: @@ -218,8 +226,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) Q_DECLARE_METATYPE(QVector) -- cgit v1.2.3 From 434750f1a6cd78b595933210f41e1bf3ab3bd51b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 25 Apr 2016 14:52:12 +0200 Subject: QmlProfiler: Reduce memory usage for file names and URLs As the various file names are actually not kept as QStrings in the respective objects being profiled, our saving them as QStrings in each and every profiling event is not implicitly shared and causes a huge memory overhead. Avoid that by saving each location only once, indexed by a disguised pointer to the object it refers to. Normally, objects could disappear during the profiling session, and new objects could be allocated in their place, which would mess up our indexing system. We prevent that by referencing the objects when we index them, thus preventing them from getting auto-destructed. Mind that those are not JavaScript objects but rather functions, bindings, components and the like. So, this will only cause a memory leak if you're compiling and dropping QML components over and over. Task-number: QTBUG-52937 Change-Id: Ia4dfb09a71a5c9a2d6ce25c3811bbe2a1036c1c1 Reviewed-by: Simon Hausmann --- .../qmldbg_profiler/qqmlprofileradapter.cpp | 29 ++- .../qmldbg_profiler/qqmlprofileradapter.h | 4 +- src/qml/debugger/qqmlprofiler.cpp | 16 +- src/qml/debugger/qqmlprofiler_p.h | 211 ++++++++++++++------- src/qml/qml/qqmlbinding.cpp | 2 +- src/qml/qml/qqmlobjectcreator.cpp | 15 +- src/qml/qml/qqmltypeloader.cpp | 6 +- 7 files changed, 196 insertions(+), 87 deletions(-) (limited to 'src') diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp index 0ee69a6e02..a193ddea0b 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp @@ -58,14 +58,18 @@ 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)), - this, SLOT(receiveData(QVector))); + connect(engine->profiler, + SIGNAL(dataReady(QVector,QQmlProfiler::LocationHash)), + this, + SLOT(receiveData(QVector,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 &messages) +static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d, + const QQmlProfiler::LocationHash &locations, + QList &messages) { QQmlDebugPacket ds; Q_ASSERT_X((d.messageType & (1 << 31)) == 0, Q_FUNC_INFO, @@ -78,15 +82,18 @@ static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d, QList(d.detailType); + 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); + ds << (l.location.sourceFile.isEmpty() ? l.url.toString() : l.location.sourceFile); break; case QQmlProfilerDefinitions::RangeLocation: - ds << (d.detailUrl.isEmpty() ? d.detailString : d.detailUrl.toString()) << d.x << d.y; + ds << (l.url.isEmpty() ? l.location.sourceFile : l.url.toString()) + << static_cast(l.location.line) << static_cast(l.location.column); break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type."); @@ -103,21 +110,29 @@ qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList &messag const QQmlProfilerData &nextData = data.at(next); if (nextData.time > until || messages.length() > s_numMessagesPerBatch) return nextData.time; - qQmlProfilerDataToByteArrays(nextData, messages); + qQmlProfilerDataToByteArrays(nextData, locations, messages); ++next; } next = 0; data.clear(); + locations.clear(); return -1; } -void QQmlProfilerAdapter::receiveData(const QVector &new_data) +void QQmlProfilerAdapter::receiveData(const QVector &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); } diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h index 2d93efba1b..7e13b6c479 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h @@ -63,10 +63,12 @@ public: qint64 sendMessages(qint64 until, QList &messages) Q_DECL_OVERRIDE; public slots: - void receiveData(const QVector &new_data); + void receiveData(const QVector &new_data, + const QQmlProfiler::LocationHash &locations); private: QVector data; + QQmlProfiler::LocationHash locations; int next; }; diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp index 8d60325a19..629d5cb7b8 100644 --- a/src/qml/debugger/qqmlprofiler.cpp +++ b/src/qml/debugger/qqmlprofiler.cpp @@ -45,7 +45,9 @@ QT_BEGIN_NAMESPACE QQmlProfiler::QQmlProfiler() : featuresEnabled(0) { static int metatype = qRegisterMetaType >(); + static int metatype2 = qRegisterMetaType (); 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 data; + data.swap(m_data); + emit dataReady(data, resolved); } QT_END_NAMESPACE diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h index d32b350055..1380599fb7 100644 --- a/src/qml/debugger/qqmlprofiler_p.h +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -54,6 +54,8 @@ #include #include #include +#include +#include #include "qqmlprofilerdefinitions_p.h" #include "qqmlabstractprofileradapter_p.h" @@ -79,38 +81,16 @@ QT_BEGIN_NAMESPACE // out. struct Q_AUTOTEST_EXPORT QQmlProfilerData : public QQmlProfilerDefinitions { - QQmlProfilerData() {} - - QQmlProfilerData(qint64 time, int messageType, RangeType 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, RangeType 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, RangeType 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, RangeType 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 RangeType 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 }; Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE); @@ -118,27 +98,123 @@ 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::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 ref; + }; + + typedef QHash LocationHash; + + void startBinding(QQmlBinding *binding, QV4::FunctionObject *function) { + quintptr locationId(id(binding)); m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeStart | 1 << RangeLocation), Binding, - location.sourceFile, qmlSourceCoordinate(location.line), qmlSourceCoordinate(location.column))); + 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), - 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), HandlingSignal, - location.sourceFile, location.line, location.column)); + locationId)); + + RefLocation &location = m_locations[locationId]; + if (!location.isValid()) + location = RefLocation(expression); } void startCreating() @@ -146,18 +222,24 @@ public: 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), - 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), - Creating, typeName, fileName, line, column)); + Creating, locationId)); + + RefLocation &location = m_locations[locationId]; + if (!location.isValid()) + location = RefLocation(ref, url, obj, type); } template @@ -170,6 +252,12 @@ public: quint64 featuresEnabled; + template + static quintptr id(const Object *pointer) + { + return reinterpret_cast(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 &); + void dataReady(const QVector &, const QQmlProfiler::LocationHash &); protected: QElapsedTimer m_timer; + QHash m_locations; QVector 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 ranges; + QFiniteStack 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()); } - 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) +Q_DECLARE_METATYPE(QQmlProfiler::LocationHash) #endif // QQMLPROFILER_P_H diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index e8ddfecbe3..1249e1b6c8 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -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); diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 29fff04325..cfe1c86eba 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -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(""), - context->url(), obj->location.line, obj->location.column)); + Q_QML_OC_PROFILE(sharedState->profiler, profiler.update( + compiledData, obj, QStringLiteral(""), 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->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(); } diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index d164dc614f..3f58e4a7e1 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -654,7 +654,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; @@ -1208,7 +1208,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; @@ -1228,7 +1228,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; -- cgit v1.2.3 From 5caa2d03c193f39f9094703d4277122f51a31345 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 26 Apr 2016 14:12:14 +0200 Subject: Quick: expose movementDirection of PathView It is needed by the behavior of TabBar in universal style in QtQC2. [ChangeLog][QtQuick][PathView] Added movementDirection property Change-Id: Iedc214a12e7336e52125ec82b9ded45502905978 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickitemsmodule.cpp | 1 + src/quick/items/qquickpathview.cpp | 55 +++++++++++++++++++++++++++++++---- src/quick/items/qquickpathview_p.h | 7 +++++ src/quick/items/qquickpathview_p_p.h | 4 +-- 4 files changed, 59 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 23245e4a7b..08d95119d7 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -285,6 +285,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType(uri, 2, 7, "GridView"); qmlRegisterType(uri, 2, 7, "TextInput"); qmlRegisterType(uri, 2, 7, "TextEdit"); + qmlRegisterType(uri, 2, 7, "PathView"); qmlRegisterUncreatableType(uri, 2, 7, nullptr, QQuickMouseEvent::tr("MouseEvent is only available within handlers in MouseArea")); } diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index a56d0fc06e..e3d218ff01 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -105,7 +105,8 @@ QQuickPathViewPrivate::QQuickPathViewPrivate() , dragMargin(0), deceleration(100), maximumFlickVelocity(QML_FLICK_DEFAULTMAXVELOCITY) , moveOffset(this, &QQuickPathViewPrivate::setAdjustedOffset), flickDuration(0) , pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0) - , moveReason(Other), moveDirection(Shortest), attType(0), highlightComponent(0), highlightItem(0) + , moveReason(Other), movementDirection(QQuickPathView::Shortest), moveDirection(QQuickPathView::Shortest) + , attType(0), highlightComponent(0), highlightItem(0) , moveHighlight(this, &QQuickPathViewPrivate::setHighlightPosition) , highlightPosition(0) , highlightRangeStart(0), highlightRangeEnd(0) @@ -790,7 +791,7 @@ QQuickItem *QQuickPathView::currentItem() const void QQuickPathView::incrementCurrentIndex() { Q_D(QQuickPathView); - d->moveDirection = QQuickPathViewPrivate::Positive; + d->moveDirection = QQuickPathView::Positive; setCurrentIndex(currentIndex()+1); } @@ -804,7 +805,7 @@ void QQuickPathView::incrementCurrentIndex() void QQuickPathView::decrementCurrentIndex() { Q_D(QQuickPathView); - d->moveDirection = QQuickPathViewPrivate::Negative; + d->moveDirection = QQuickPathView::Negative; setCurrentIndex(currentIndex()-1); } @@ -1372,6 +1373,48 @@ void QQuickPathView::setSnapMode(SnapMode mode) emit snapModeChanged(); } +/*! + \qmlproperty enumeration QtQuick::PathView::movementDirection + \since 5.7 + + This property determines the direction in which items move when setting the current index. + The possible values are: + + \list + \li PathView.Shortest (default) - the items move in the direction that requires the least + movement, which could be either \c Negative or \c Positive. + \li PathView.Negative - the items move backwards towards their destination. + \li PathView.Positive - the items move forwards towards their destination. + \endlist + + For example, suppose that there are 5 items in the model, and \l currentIndex is \c 0. + If currentIndex is set to \c 2, + + \list + \li a \c Positive movement direction will result in the following order: 0, 1, 2 + \li a \c Negative movement direction will result in the following order: 0, 5, 4, 3, 2 + \li a \c Shortest movement direction will result in same order with \c Positive . + \endlist + + \note this property doesn't affect the movement of \l incrementCurrentIndex() and \l decrementCurrentIndex(). +*/ +QQuickPathView::MovementDirection QQuickPathView::movementDirection() const +{ + Q_D(const QQuickPathView); + return d->movementDirection; +} + +void QQuickPathView::setMovementDirection(QQuickPathView::MovementDirection dir) +{ + Q_D(QQuickPathView); + if (dir == d->movementDirection) + return; + d->movementDirection = dir; + if (!d->tl.isActive()) + d->moveDirection = d->movementDirection; + emit movementDirectionChanged(); +} + /*! \qmlmethod QtQuick::PathView::positionViewAtIndex(int index, PositionMode mode) @@ -2231,6 +2274,7 @@ void QQuickPathView::movementEnding() emit movingChanged(); emit movementEnded(); } + d->moveDirection = d->movementDirection; } // find the item closest to the snap position @@ -2340,7 +2384,7 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason) if (!duration) { tl.set(moveOffset, targetOffset); - } else if (moveDirection == Positive || (moveDirection == Shortest && targetOffset - offset > modelCount/2.0)) { + } else if (moveDirection == QQuickPathView::Positive || (moveDirection == QQuickPathView::Shortest && targetOffset - offset > modelCount/2.0)) { qreal distance = modelCount - targetOffset + offset; if (targetOffset > moveOffset) { tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * offset / distance)); @@ -2349,7 +2393,7 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason) } else { tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration); } - } else if (moveDirection == Negative || targetOffset - offset <= -modelCount/2.0) { + } else if (moveDirection == QQuickPathView::Negative || targetOffset - offset <= -modelCount/2.0) { qreal distance = modelCount - offset + targetOffset; if (targetOffset < moveOffset) { tl.move(moveOffset, modelCount, QEasingCurve(targetOffset == 0 ? QEasingCurve::InOutQuad : QEasingCurve::InQuad), int(duration * (modelCount-offset) / distance)); @@ -2361,7 +2405,6 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason) } else { tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration); } - moveDirection = Shortest; } QQuickPathViewAttached *QQuickPathView::qmlAttachedProperties(QObject *obj) diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h index 341af02013..daec965f02 100644 --- a/src/quick/items/qquickpathview_p.h +++ b/src/quick/items/qquickpathview_p.h @@ -92,6 +92,7 @@ class Q_AUTOTEST_EXPORT QQuickPathView : public QQuickItem Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) Q_PROPERTY(int pathItemCount READ pathItemCount WRITE setPathItemCount RESET resetPathItemCount NOTIFY pathItemCountChanged) Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged) + Q_PROPERTY(MovementDirection movementDirection READ movementDirection WRITE setMovementDirection NOTIFY movementDirectionChanged REVISION 7) Q_PROPERTY(int cacheItemCount READ cacheItemCount WRITE setCacheItemCount NOTIFY cacheItemCountChanged) @@ -164,6 +165,11 @@ public: SnapMode snapMode() const; void setSnapMode(SnapMode mode); + enum MovementDirection { Shortest, Negative, Positive }; + Q_ENUM(MovementDirection) + MovementDirection movementDirection() const; + void setMovementDirection(MovementDirection dir); + enum PositionMode { Beginning, Center, End, Contain=4, SnapPosition }; // 3 == Visible in other views Q_ENUM(PositionMode) Q_INVOKABLE void positionViewAtIndex(int index, int mode); @@ -201,6 +207,7 @@ Q_SIGNALS: void highlightMoveDurationChanged(); void movementStarted(); void movementEnded(); + Q_REVISION(7) void movementDirectionChanged(); void flickStarted(); void flickEnded(); void dragStarted(); diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h index 8236d9efd2..d9c4baf572 100644 --- a/src/quick/items/qquickpathview_p_p.h +++ b/src/quick/items/qquickpathview_p_p.h @@ -171,8 +171,8 @@ public: QPointer model; QVariant modelVariant; MovementReason moveReason; - enum MovementDirection { Shortest, Negative, Positive }; - MovementDirection moveDirection; + QQuickPathView::MovementDirection movementDirection; // default + QQuickPathView::MovementDirection moveDirection; // next movement QQmlOpenMetaObjectType *attType; QQmlComponent *highlightComponent; QQuickItem *highlightItem; -- cgit v1.2.3 From b3bc1d6a1c9390ed42a044bad956816836beaad6 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Wed, 20 Apr 2016 15:10:07 +0200 Subject: Add Qt::ImInputItemClipRectangle support to QtQuick items Let QtQuick items respond to ImInputItemClipRectangle inputMethodQuery and notify about potential changes with QInputMethod::update() Change-Id: I3025583d751bcc7f54bab87792bb7a2f38b60591 Reviewed-by: Richard Moe Gustavsen --- src/quick/items/qquickitem.cpp | 17 +++++++++++++++++ src/quick/items/qquicktextedit.cpp | 3 +++ src/quick/items/qquickwindow.cpp | 1 + 3 files changed, 21 insertions(+) (limited to 'src') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 7a5f1a12e8..ee96e346c2 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -4160,6 +4160,23 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const if (d->extra.isAllocated() && d->extra->enterKeyAttached) v = d->extra->enterKeyAttached->type(); break; + case Qt::ImInputItemClipRectangle: + if (!(!window() ||!isVisible() || qFuzzyIsNull(opacity()))) { + QRectF rect = QRectF(0,0, width(), height()); + const QQuickItem *par = this; + while (QQuickItem *parpar = par->parentItem()) { + rect = parpar->mapRectFromItem(par, rect); + if (parpar->clip()) + rect = rect.intersected(parpar->clipRect()); + par = parpar; + } + rect = par->mapRectToScene(rect); + // once we have the rect in scene coordinates, clip to window + rect = rect.intersected(QRectF(QPoint(0,0), window()->size())); + // map it back to local coordinates + v = mapRectFromScene(rect); + } + break; default: break; } diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index d9c0e428a4..5968028c26 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -1842,6 +1842,9 @@ QVariant QQuickTextEdit::inputMethodQuery(Qt::InputMethodQuery property, QVarian case Qt::ImHints: v = (int)d->effectiveInputMethodHints(); break; + case Qt::ImInputItemClipRectangle: + v = QQuickItem::inputMethodQuery(property); + break; default: if (property == Qt::ImCursorPosition && !argument.isNull()) argument = QVariant(argument.toPointF() - QPointF(d->xoff, d->yoff)); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index bb3f5138ad..b94b0b7d59 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -98,6 +98,7 @@ void QQuickWindowPrivate::updateFocusItemTransform() QQuickItemPrivate *focusPrivate = QQuickItemPrivate::get(focus); QGuiApplication::inputMethod()->setInputItemTransform(focusPrivate->itemToWindowTransform()); QGuiApplication::inputMethod()->setInputItemRectangle(QRectF(0, 0, focusPrivate->width, focusPrivate->height)); + focus->updateInputMethod(Qt::ImInputItemClipRectangle); } #endif } -- cgit v1.2.3 From 373c621bf4dc2ab07bb9c4f19c783fd36debb0dc Mon Sep 17 00:00:00 2001 From: Kevin Ottens Date: Tue, 3 May 2016 09:57:24 +0200 Subject: Add QVector support to JS sequences Change-Id: I731355aa1754721236f3711a65af4f96781cebc0 Task-number: QTBUG-51467 Reviewed-by: Simon Hausmann --- src/qml/doc/src/cppintegration/data.qdoc | 6 ++++++ src/qml/jsruntime/qv4sequenceobject.cpp | 12 ++++++++++++ 2 files changed, 18 insertions(+) (limited to 'src') diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc index e153ca3d8b..23f870741b 100644 --- a/src/qml/doc/src/cppintegration/data.qdoc +++ b/src/qml/doc/src/cppintegration/data.qdoc @@ -261,6 +261,9 @@ In particular, QML currently supports: \li \c {QList} \li \c {QList} and \c{QStringList} \li \c {QList} + \li \c {QVector} + \li \c {QVector} + \li \c {QVector} \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 \li boolean value \c {false} \row \li QList and QStringList \li empty QString \row \li QList \li empty QUrl +\row \li QVector \li integer value 0 +\row \li QVector \li real value 0.0 +\row \li QVector \li boolean value \c {false} \endtable If you wish to remove elements from a sequence rather than simply replace diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index b97310c5b9..fa2409a85c 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -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, 0) \ + F(qreal, RealVector, QVector, 0.0) \ + F(bool, BoolVector, QVector, false) \ F(int, Int, QList, 0) \ F(qreal, Real, QList, 0.0) \ F(bool, Bool, QList, false) \ @@ -578,6 +581,15 @@ Heap::QQmlSequence::QQmlSequence(QObject *object, int propertyIndex) namespace QV4 { +typedef QQmlSequence > QQmlIntVectorList; +template<> +DEFINE_OBJECT_VTABLE(QQmlIntVectorList); +typedef QQmlSequence > QQmlRealVectorList; +template<> +DEFINE_OBJECT_VTABLE(QQmlRealVectorList); +typedef QQmlSequence > QQmlBoolVectorList; +template<> +DEFINE_OBJECT_VTABLE(QQmlBoolVectorList); typedef QQmlSequence QQmlQStringList; template<> DEFINE_OBJECT_VTABLE(QQmlQStringList); -- cgit v1.2.3 From 6bead0e730ebf89a6c83de9bf03fad5f9aa56fe3 Mon Sep 17 00:00:00 2001 From: Kai Uwe Broulik Date: Tue, 3 May 2016 10:40:28 +0200 Subject: Docs: Prefer Q_ENUM over Q_ENUMS Change-Id: Ic00e15136b2e4fe977270b081eaf5e765cf5fb7f Reviewed-by: Mitch Curtis --- src/qml/doc/src/cppintegration/data.qdoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc index 23f870741b..0d875bd10f 100644 --- a/src/qml/doc/src/cppintegration/data.qdoc +++ b/src/qml/doc/src/cppintegration/data.qdoc @@ -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 @@ -347,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: @@ -355,7 +355,6 @@ enum: class Message : public QObject { Q_OBJECT - Q_ENUMS(Status) Q_PROPERTY(Status status READ status NOTIFY statusChanged) public: enum Status { @@ -363,6 +362,7 @@ enum: Loading, Error }; + Q_ENUM(Status) Status status() const; signals: void statusChanged(); -- cgit v1.2.3 From 9a7cf067a178c7a08a7ed9f2c6253e1feade5569 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 6 Apr 2016 11:23:11 +0200 Subject: V4: make QQmlEnginePrivate::dereferenceScarceResources inlinable. Done by giving the "expensive" part its own function, that's even unlikely to be called anyway. Change-Id: I35621fb0a764879f9339b9e23f210c66971ff5b7 Reviewed-by: Lars Knoll --- src/qml/qml/qqmlengine.cpp | 32 ++++++++++---------------------- src/qml/qml/qqmlengine_p.h | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 55053c8733..4b718e2c95 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1894,28 +1894,16 @@ void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList 0); - scarceResourcesRefCount -= 1; - - // if the refcount is zero, then evaluation of the "top level" - // expression must have completed. We can safely release the - // scarce resources. - if (Q_UNLIKELY(scarceResourcesRefCount == 0)) { - // iterate through the list and release them all. - // note that the actual SRD is owned by the JS engine, - // so we cannot delete the SRD; but we can free the - // memory used by the variant in the SRD. - QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine()); - while (QV4::ExecutionEngine::ScarceResourceData *sr = engine->scarceResources.first()) { - sr->data = QVariant(); - engine->scarceResources.remove(sr); - } +void QQmlEnginePrivate::cleanupScarceResources() +{ + // iterate through the list and release them all. + // note that the actual SRD is owned by the JS engine, + // so we cannot delete the SRD; but we can free the + // memory used by the variant in the SRD. + QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine()); + while (QV4::ExecutionEngine::ScarceResourceData *sr = engine->scarceResources.first()) { + sr->data = QVariant(); + engine->scarceResources.remove(sr); } } diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index df73118b36..003cfa0112 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -267,6 +267,8 @@ private: struct Deletable { Deletable():next(0) {} virtual ~Deletable() {} Deletable *next; }; QFieldList toDeleteInEngineThread; void doDeleteInEngineThread(); + + void cleanupScarceResources(); }; /* @@ -279,6 +281,26 @@ inline void QQmlEnginePrivate::referenceScarceResources() scarceResourcesRefCount += 1; } +/* + This function should be called after evaluation of the js expression is + complete, and so the scarce resources may be freed safely. + */ +inline void QQmlEnginePrivate::dereferenceScarceResources() +{ + Q_ASSERT(scarceResourcesRefCount > 0); + scarceResourcesRefCount -= 1; + + // if the refcount is zero, then evaluation of the "top level" + // expression must have completed. We can safely release the + // scarce resources. + if (Q_LIKELY(scarceResourcesRefCount == 0)) { + QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine()); + if (Q_UNLIKELY(!engine->scarceResources.isEmpty())) { + cleanupScarceResources(); + } + } +} + /*! Returns true if the calling thread is the QQmlEngine thread. */ -- cgit v1.2.3 From 1372a773e1acc88d454beab850a6e88c4c359d7b Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 3 May 2016 16:22:48 +0200 Subject: QQuickItem: force clear subFocusItem from ancestors Make sure ancestor items don't end up with dangling subFocusItem pointers. Change-Id: I79015abe8215b807b02577c25de58c44bfc70f9e Task-number: QTBUG-51080 Reviewed-by: Liang Qi --- src/quick/items/qquickitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index c27e9d0d95..e963f91961 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2639,7 +2639,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) QQuickItem *scopeItem = 0; - if (hasFocus()) + if (hasFocus() || op->subFocusItem == this) scopeFocusedItem = this; else if (!isFocusScope() && d->subFocusItem) scopeFocusedItem = d->subFocusItem; -- cgit v1.2.3 From 697cbf3474d32ebd4f7e22695223cdb8cdf44f35 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Thu, 28 Apr 2016 13:42:50 +0200 Subject: QQuickWindowPrivate: Only update transform on polish if needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As it stood, whenever QtQuick did a polish we would update IM transform. The result would be that we signaled changes to e.g cursor rectangle and input rectangle each time the cursor was redrawn. This of course caused code elsewhere, e.g in the platform plugins, to recalculate overlays such as cursor handles when nothing with regards to input item transform had actually changed. This patch will add some extra checks that the effective transform of the focus object has really changed before telling IM to update. Change-Id: If7057e4dd8f41e251a27d68fcaebdb10da953ee7 Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickwindow.cpp | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index b94b0b7d59..54e4339f7e 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -257,6 +257,26 @@ void QQuickWindow::focusInEvent(QFocusEvent *ev) d->updateFocusItemTransform(); } +#ifndef QT_NO_IM +static bool transformDirtyOnItemOrAncestor(const QQuickItem *item) +{ + while (item) { + if (QQuickItemPrivate::get(item)->dirtyAttributes & ( + QQuickItemPrivate::TransformOrigin | + QQuickItemPrivate::Transform | + QQuickItemPrivate::BasicTransform | + QQuickItemPrivate::Position | + QQuickItemPrivate::Size | + QQuickItemPrivate::ParentChanged | + QQuickItemPrivate::Clip)) { + return true; + } + item = item->parentItem(); + } + return false; +} +#endif + void QQuickWindowPrivate::polishItems() { // An item can trigger polish on another item, or itself for that matter, @@ -276,7 +296,17 @@ void QQuickWindowPrivate::polishItems() if (recursionSafeguard == 0) qWarning("QQuickWindow: possible QQuickItem::polish() loop"); - updateFocusItemTransform(); +#ifndef QT_NO_IM + if (QQuickItem *focusItem = q_func()->activeFocusItem()) { + // If the current focus item, or any of its anchestors, has changed location + // inside the window, we need inform IM about it. This to ensure that overlays + // such as selection handles will be updated. + const bool isActiveFocusItem = (focusItem == QGuiApplication::focusObject()); + const bool hasImEnabled = focusItem->inputMethodQuery(Qt::ImEnabled).toBool(); + if (isActiveFocusItem && hasImEnabled && transformDirtyOnItemOrAncestor(focusItem)) + updateFocusItemTransform(); + } +#endif } /*! -- cgit v1.2.3 From 4b982c744f538a24e21a2af146c45f93d27dd1cb Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Mon, 11 Apr 2016 23:10:29 +0300 Subject: Add imageSource property to attached Drag property This property holds a URL which is loaded into a QPixmap via QQuickPixmap, and subsequently set on the QDrag object. This is especially important for drag and drop to external applications, where of course a QQuickItem cannot be dragged; however, combined with QQuickItem::grabToImage(), this change allows setting a QQuickItem's contents as the drag pixmap. [ChangeLog][QtQuick][Drag] Added imageSource property to attached Drag object: this allows drag sources to specify the pixmap to be drawn next to the mouse cursor when starting a drag and drop operation. Task-number: QTBUG-37366 Change-Id: Ibcf1d888c525e50976a116ec743ce6fca4c31525 Reviewed-by: Michael Brasser --- src/quick/doc/snippets/qml/externaldrag.qml | 76 +++++++++++++++++++++++++++++ src/quick/items/qquickdrag.cpp | 46 +++++++++++++++-- src/quick/items/qquickdrag_p.h | 6 +++ 3 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 src/quick/doc/snippets/qml/externaldrag.qml (limited to 'src') diff --git a/src/quick/doc/snippets/qml/externaldrag.qml b/src/quick/doc/snippets/qml/externaldrag.qml new file mode 100644 index 0000000000..096a7702b4 --- /dev/null +++ b/src/quick/doc/snippets/qml/externaldrag.qml @@ -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] diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index 4aa54b71df..76e13bc985 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,8 @@ public: bool eventQueued : 1; bool overrideActions : 1; QPointF hotSpot; + QUrl imageSource; + QQuickPixmap pixmapLoader; QStringList keys; QVariantMap externalMimeData; QQuickDrag::DragType dragType; @@ -407,6 +410,43 @@ void QQuickDragAttached::setHotSpot(const QPointF &hotSpot) } } +/*! + \qmlattachedproperty QUrl QtQuick::Drag::imageSource + \since 5.8 + + This property holds the URL of the image which will be used to represent + the data during the drag and drop operation. Changing this property after + the drag operation has started will have no effect. + + The example below uses an item's contents as a drag image: + + \snippet qml/externaldrag.qml 0 + + \sa Item::grabToImage() +*/ + +QUrl QQuickDragAttached::imageSource() const +{ + Q_D(const QQuickDragAttached); + return d->imageSource; +} + +void QQuickDragAttached::setImageSource(const QUrl &url) +{ + Q_D(QQuickDragAttached); + if (d->imageSource != url) { + d->imageSource = url; + + if (url.isEmpty()) { + d->pixmapLoader.clear(); + } else { + d->pixmapLoader.load(qmlEngine(this), url); + } + + Q_EMIT imageSourceChanged(); + } +} + /*! \qmlattachedproperty stringlist QtQuick::Drag::keys @@ -726,9 +766,9 @@ Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedAct mimeData->setData(it.key(), it.value().toString().toUtf8()); drag->setMimeData(mimeData); - - // TODO: how to handle drag image? - // drag->setPixmap(iconPixmap); + if (pixmapLoader.isReady()) { + drag->setPixmap(QPixmap::fromImage(pixmapLoader.image())); + } emit q->dragStarted(); diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h index c1695e49f0..17721251d9 100644 --- a/src/quick/items/qquickdrag_p.h +++ b/src/quick/items/qquickdrag_p.h @@ -58,6 +58,7 @@ #include #include +#include #ifndef QT_NO_DRAGANDDROP @@ -247,6 +248,7 @@ class QQuickDragAttached : public QObject Q_PROPERTY(QObject *source READ source WRITE setSource NOTIFY sourceChanged RESET resetSource) Q_PROPERTY(QObject *target READ target NOTIFY targetChanged) Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot NOTIFY hotSpotChanged) + Q_PROPERTY(QUrl imageSource READ imageSource WRITE setImageSource NOTIFY imageSourceChanged REVISION 8) Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged) Q_PROPERTY(QVariantMap mimeData READ mimeData WRITE setMimeData NOTIFY mimeDataChanged) Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions WRITE setSupportedActions NOTIFY supportedActionsChanged) @@ -268,6 +270,9 @@ public: QPointF hotSpot() const; void setHotSpot(const QPointF &hotSpot); + QUrl imageSource() const; + void setImageSource(const QUrl &url); + QStringList keys() const; void setKeys(const QStringList &keys); @@ -300,6 +305,7 @@ Q_SIGNALS: void sourceChanged(); void targetChanged(); void hotSpotChanged(); + void imageSourceChanged(); void keysChanged(); void mimeDataChanged(); void supportedActionsChanged(); -- cgit v1.2.3 From 6f59c91c51edd7207635c3fa2f0b2b1179e7aa6e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 6 May 2016 16:01:00 +0200 Subject: Revert parts of 392c7b99348e2a96ef11adb5712095fbd13fb780 Revert the plugin loading check for Qt 5.6.x. It turns out that making this check strict broke multiple static plugin builds beyond the qtdeclarative repository. Let's not cause unnecessary breakage in a patch release of Qt to fix a bug that has existed for much longer. I'll revert this change in the dev branch for Qt 5.8, together with an entry in the change log to inform the developers that a behavioral change in their code is necessary (the use of the interface id variable). Change-Id: I3c658433eaa125ac0d272806e3bbbf016cf6d3cb Reviewed-by: J-P Nurmi --- src/qml/qml/qqmlimport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 9fc01c8e35..c4e0c7b778 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -850,7 +850,7 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector &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 (plugin.metaData().value(QStringLiteral("IID")).toString() == QLatin1String(QQmlExtensionInterface_iid)) + if (qobject_cast(plugin.instance())) plugins.append(plugin); } } -- cgit v1.2.3 From f7463a2ae6dd8e9267f99cc88af495281405905a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 9 May 2016 13:29:18 +0200 Subject: De-inline static methods of struct Runtime. They are accessed via function pointer, so, inlining them does not have any effect. Move the implementation into qv4runtime.cpp, fixing MinGW-errors: qtdeclarative/src/qml/jsruntime/qv4runtime_p.h:144:22: error: 'static QV4::ReturnedValue QV4::Runtime::method_uPlus(const QV4::Value&)' redeclared without dllimport attribute after being referenced with dll linkage [-Werror] inline ReturnedValue Runtime::method_uPlus(const Value &value) ^ qtdeclarative/src/qml/jsruntime/qv4runtime_p.h:157:22: error: 'static QV4::ReturnedValue QV4::Runtime::method_uMinus(const QV4::Value&)' redeclared without dllimport attribute after being referenced with dll linkage [-Werror] inline ReturnedValue Runtime::method_uMinus(const Value &value) ^ qtdeclarative/src/qml/jsruntime/qv4runtime_p.h:170:22: error: 'static QV4::ReturnedValue QV4::Runtime::method_complement(const QV4::Value&)' redeclared without dllimport attribute after being referenced with dll linkage [-Werror] inline ReturnedValue Runtime::method_complement(const Value &value) Task-number: QTBUG-53222 Change-Id: I5a9bd162e0b1f52c66cd6a8efbf407fcd46d7fc7 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4runtime.cpp | 345 +++++++++++++++++++++++++++++++++++++++ src/qml/jsruntime/qv4runtime_p.h | 343 -------------------------------------- 2 files changed, 345 insertions(+), 343 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index a974909798..dfac2d9bd9 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1623,6 +1623,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()->isEqualTo(right.cast()); + } + + 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(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(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(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(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 diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index ffae55995f..807fbe2f0e 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -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()->isEqualTo(right.cast()); - } - - 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(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(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(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(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 -- cgit v1.2.3 From 4be62189a17a2b9a3c10a2448f146a6102598312 Mon Sep 17 00:00:00 2001 From: Frank Meerkoetter Date: Fri, 6 May 2016 21:02:43 +0200 Subject: Scrape off some more allocations by using the QStringBuilder Change-Id: I25cbbcad086afb15694f69bdc52bd4ddce4b3a18 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlirbuilder.cpp | 9 +++------ src/qml/jsruntime/qv4errorobject.cpp | 10 +++------- src/qml/jsruntime/qv4jsonobject.cpp | 7 +++---- src/qml/jsruntime/qv4object.cpp | 5 ++--- src/qml/jsruntime/qv4qobjectwrapper.cpp | 12 ++++-------- src/qml/jsruntime/qv4regexpobject.cpp | 3 +-- 6 files changed, 16 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index d4757bed39..6b83bdc7b6 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -900,10 +900,8 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node) property->aliasIdValueIndex = registerString(alias.first()); QString propertyValue = alias.value(1); - if (alias.count() == 3) { - propertyValue += QLatin1Char('.'); - propertyValue += alias.at(2); - } + if (alias.count() == 3) + propertyValue += QLatin1Char('.') + alias.at(2); property->aliasPropertyValueIndex = registerString(propertyValue); } QQmlJS::AST::SourceLocation errorLocation; @@ -1201,8 +1199,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")); diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 9f1e6b613b..2db04bbfda 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -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); } diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index a211d46153..0ae7c33dea 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -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; } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 0727f35edd..ff3208485e 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -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); } } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index fca218d9d0..df58ab5060 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1768,17 +1768,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(')'); diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 71e2bd1a06..05752dc6dc 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -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) -- cgit v1.2.3 From 58bedefe772a83baa8809d7f3f4a683fa35f1ba8 Mon Sep 17 00:00:00 2001 From: Frank Meerkoetter Date: Fri, 6 May 2016 20:32:44 +0200 Subject: Cleanup QStringBuilder usage Modules in QtDeclarative are built with QT_USE_QSTRINGBUILDER. There is no need to include qstringbuilder.h. This also means the + operator can be used instead of the %. Change-Id: I9fc374c25174a66c276f7f67a0abcd8e62a6a485 Reviewed-by: Lars Knoll --- src/qml/qml/qqmlboundsignal.cpp | 1 - src/quick/items/qquickrectangle.cpp | 1 - src/quick/util/qquickstategroup.cpp | 3 +-- 3 files changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index 9879763c72..c1e6543b86 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -56,7 +56,6 @@ #include -#include #include diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp index 74ca0f482a..b8c680433e 100644 --- a/src/quick/items/qquickrectangle.cpp +++ b/src/quick/items/qquickrectangle.cpp @@ -44,7 +44,6 @@ #include #include -#include #include #include diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp index 791e38e45d..da3b6fa561 100644 --- a/src/quick/util/qquickstategroup.cpp +++ b/src/quick/util/qquickstategroup.cpp @@ -44,7 +44,6 @@ #include #include -#include #include #include @@ -305,7 +304,7 @@ void QQuickStateGroup::componentComplete() for (int ii = 0; ii < d->states.count(); ++ii) { QQuickState *state = d->states.at(ii); if (!state->isNamed()) - state->setName(QLatin1String("anonymousState") % QString::number(++d->unnamedCount)); + state->setName(QLatin1String("anonymousState") + QString::number(++d->unnamedCount)); } if (d->updateAutoState()) { -- cgit v1.2.3 From 7234a59e03e0e0088c0be5c4fed1d500d3c4f029 Mon Sep 17 00:00:00 2001 From: Frank Meerkoetter Date: Fri, 6 May 2016 16:08:20 +0200 Subject: Scrape off a few allocations by using the QStringBuilder Change-Id: I7689fabb5398c2c2d2781b2c788dcc60f4e1ea44 Reviewed-by: Lars Knoll --- src/qml/qml/qqmlboundsignal.cpp | 9 ++------- src/qml/qml/qqmlimport.cpp | 5 +---- src/qml/qml/qqmlmetatype.cpp | 3 +-- src/qml/qml/qqmlvaluetypewrapper.cpp | 3 +-- 4 files changed, 5 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index c1e6543b86..b03edc9020 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -80,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; @@ -98,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()) diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index d6c81bcc49..5ce3942be2 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -1647,10 +1647,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()) diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 576478b729..b13009853e 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1961,8 +1961,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(); diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index d313557e98..96bca9070d 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -302,8 +302,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) { -- cgit v1.2.3 From c6c0d730b7a88fa22f40d597183e91b73d9d165d Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 20 Apr 2016 13:39:58 +0200 Subject: QML: Remove internal field padding from QQuickAnchorPrivate. Don't store QQuickAnchorLine, but store both fields separately in QQuickAnchorPrivate. This prevents padding of QQuickAnchorLine, saving 48 bytes on x86_64 (or any platform where structs are 8-byte aligned). On x86_64, this also removes ~180 instructions for each QQuickAnchor creation/removal, and speeds up the constructor by 25%. While in the neighborhood, do a drive-by change and merge QQuickAnchorLine::AnchorLine and QQuickAnchors::Anchor by removing the former. Change-Id: I50ab6252b1903f5f1a075174e6185c3048a8f8ec Reviewed-by: Robin Burchell Reviewed-by: Shawn Rutledge --- src/quick/designer/qquickdesignersupport.cpp | 20 +- src/quick/items/qquickanchors.cpp | 415 +++++++++++++++------------ src/quick/items/qquickanchors_p.h | 1 + src/quick/items/qquickanchors_p_p.h | 137 +++++---- src/quick/items/qquickitem.cpp | 14 +- 5 files changed, 334 insertions(+), 253 deletions(-) (limited to 'src') diff --git a/src/quick/designer/qquickdesignersupport.cpp b/src/quick/designer/qquickdesignersupport.cpp index 5bb36c5192..78ed89a107 100644 --- a/src/quick/designer/qquickdesignersupport.cpp +++ b/src/quick/designer/qquickdesignersupport.cpp @@ -187,17 +187,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(); } } @@ -343,7 +343,7 @@ QPair QQuickDesignerSupport::anchorLineTarget(QQuickItem *ite return QPair(); QQuickAnchorLine anchorLine = metaProperty.read().value(); - if (anchorLine.anchorLine != QQuickAnchorLine::Invalid) { + if (anchorLine.anchorLine != QQuickAnchors::InvalidAnchor) { targetObject = anchorLine.item; targetName = propertyNameForAnchorLine(anchorLine.anchorLine); } diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp index df33a0cc5c..4cbd41106e 100644 --- a/src/quick/items/qquickanchors.cpp +++ b/src/quick/items/qquickanchors.cpp @@ -45,32 +45,32 @@ QT_BEGIN_NAMESPACE -static Q_ALWAYS_INLINE QQuickItem *readParentItem(QQuickItem *item) +static Q_ALWAYS_INLINE QQuickItem *readParentItem(const QQuickItem *item) { return QQuickItemPrivate::get(item)->parentItem; } -static Q_ALWAYS_INLINE qreal readX(QQuickItem *item) +static Q_ALWAYS_INLINE qreal readX(const QQuickItem *item) { return QQuickItemPrivate::get(item)->x; } -static Q_ALWAYS_INLINE qreal readY(QQuickItem *item) +static Q_ALWAYS_INLINE qreal readY(const QQuickItem *item) { return QQuickItemPrivate::get(item)->y; } -static Q_ALWAYS_INLINE qreal readWidth(QQuickItem *item) +static Q_ALWAYS_INLINE qreal readWidth(const QQuickItem *item) { return QQuickItemPrivate::get(item)->width; } -static Q_ALWAYS_INLINE qreal readHeight(QQuickItem *item) +static Q_ALWAYS_INLINE qreal readHeight(const QQuickItem *item) { return QQuickItemPrivate::get(item)->height; } -static Q_ALWAYS_INLINE qreal readBaselineOffset(QQuickItem *item) +static Q_ALWAYS_INLINE qreal readBaselineOffset(const QQuickItem *item) { return QQuickItemPrivate::get(item)->baselineOffset; } @@ -78,7 +78,7 @@ static Q_ALWAYS_INLINE qreal readBaselineOffset(QQuickItem *item) //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 *item) +static inline qreal hcenter(const QQuickItem *item) { qreal width = readWidth(item); if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) { @@ -92,7 +92,7 @@ static inline qreal hcenter(QQuickItem *item) return width / 2; } -static inline qreal vcenter(QQuickItem *item) +static inline qreal vcenter(const QQuickItem *item) { qreal height = readHeight(item); if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) { @@ -106,31 +106,30 @@ static inline qreal vcenter(QQuickItem *item) return height / 2; } -//### const item? //local position -static qreal position(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine) +static inline qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine) { qreal ret = 0.0; switch (anchorLine) { - case QQuickAnchorLine::Left: + case QQuickAnchors::LeftAnchor: ret = readX(item); break; - case QQuickAnchorLine::Right: + case QQuickAnchors::RightAnchor: ret = readX(item) + readWidth(item); break; - case QQuickAnchorLine::Top: + case QQuickAnchors::TopAnchor: ret = readY(item); break; - case QQuickAnchorLine::Bottom: + case QQuickAnchors::BottomAnchor: ret = readY(item) + readHeight(item); break; - case QQuickAnchorLine::HCenter: + case QQuickAnchors::HCenterAnchor: ret = readX(item) + hcenter(item); break; - case QQuickAnchorLine::VCenter: + case QQuickAnchors::VCenterAnchor: ret = readY(item) + vcenter(item); break; - case QQuickAnchorLine::Baseline: + case QQuickAnchors::BaselineAnchor: ret = readY(item) + readBaselineOffset(item); break; default: @@ -141,29 +140,29 @@ static qreal position(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine) } //position when origin is 0,0 -static inline 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: + case QQuickAnchors::RightAnchor: ret = readWidth(item); break; - case QQuickAnchorLine::Top: + case QQuickAnchors::TopAnchor: ret = 0.0; break; - case QQuickAnchorLine::Bottom: + 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: + case QQuickAnchors::BaselineAnchor: ret = readBaselineOffset(item); break; default: @@ -184,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() @@ -256,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; } } @@ -309,19 +308,19 @@ int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) return dependency; //exit early } - if ((usedAnchors & QQuickAnchors::LeftAnchor && left.item == controlItem) || - (usedAnchors & QQuickAnchors::RightAnchor && right.item == controlItem) || - (usedAnchors & QQuickAnchors::HCenterAnchor && hCenter.item == controlItem)) { + 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::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 ((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 @@ -453,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); @@ -486,9 +485,9 @@ void QQuickAnchorsPrivate::update() } else if (centerIn) { centerInChanged(); } else { - if (usedAnchors & QQuickAnchorLine::Horizontal_Mask) + if (usedAnchors & QQuickAnchors::Horizontal_Mask) updateHorizontalAnchors(); - if (usedAnchors & QQuickAnchorLine::Vertical_Mask) + if (usedAnchors & QQuickAnchors::Vertical_Mask) updateVerticalAnchors(); } } @@ -503,9 +502,11 @@ void QQuickAnchorsPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newG, } else if (centerIn) { centerInChanged(); } else { - if ((usedAnchors & QQuickAnchorLine::Horizontal_Mask) && (newG.x() != oldG.x() || newG.width() != oldG.width())) + if ((usedAnchors & QQuickAnchors::Horizontal_Mask) + && (newG.x() != oldG.x() || newG.width() != oldG.width())) updateHorizontalAnchors(); - if ((usedAnchors & QQuickAnchorLine::Vertical_Mask) && (newG.y() != oldG.y() || newG.height() != oldG.height())) + if ((usedAnchors & QQuickAnchors::Vertical_Mask) + && (newG.y() != oldG.y() || newG.height() != oldG.height())) updateVerticalAnchors(); } } @@ -582,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 == readParentItem(item)); - bool edge2IsParent = (edge2.item == readParentItem(item)); - bool edge1IsSibling = (readParentItem(edge1.item) == readParentItem(item)); - bool edge2IsSibling = (readParentItem(edge2.item) == readParentItem(item)); + 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) + stretch = (position(edge2Item, edge2Line) + offset2) - (position(readParentItem(item), line) - + position(edge1.item, edge1.anchorLine) + offset1); + + position(edge1Item, edge1Line) + offset1); } else if (edge2IsSibling && edge1IsParent) { - stretch = (position(readParentItem(item), 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; @@ -623,53 +626,59 @@ 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 == readParentItem(item)) { - setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin); - } else if (readParentItem(top.item) == readParentItem(item)) { - 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 == readParentItem(item)) { - setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - readHeight(item) - bottomMargin); - } else if (readParentItem(bottom.item) == readParentItem(item)) { - setItemY(position(bottom.item, bottom.anchorLine) - readHeight(item) - 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 == readParentItem(item)) { - setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine) + if (vCenterAnchorItem == readParentItem(item)) { + setItemY(adjustedPosition(vCenterAnchorItem, vCenterAnchorLine) - vcenter(item) + vCenterOffset); - } else if (readParentItem(vCenter.item) == readParentItem(item)) { - 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 == readParentItem(item)) { - setItemY(adjustedPosition(baseline.item, baseline.anchorLine) + if (baselineAnchorItem == readParentItem(item)) { + setItemY(adjustedPosition(baselineAnchorItem, baselineAnchorLine) - readBaselineOffset(item) + baselineOffset); - } else if (readParentItem(baseline.item) == readParentItem(item)) { - setItemY(position(baseline.item, baseline.anchorLine) + } else if (readParentItem(baselineAnchorItem) == readParentItem(item)) { + setItemY(position(baselineAnchorItem, baselineAnchorLine) - readBaselineOffset(item) + baselineOffset); } } @@ -680,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; } @@ -700,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; @@ -730,44 +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 == readParentItem(item)) { - setItemX(adjustedPosition(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin); - } else if (readParentItem(effectiveLeft.item) == readParentItem(item)) { - 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 == readParentItem(item)) { - setItemX(adjustedPosition(effectiveRight.item, effectiveRight.anchorLine) + if (effectiveRightItem == readParentItem(item)) { + setItemX(adjustedPosition(effectiveRightItem, effectiveRightLine) - readWidth(item) - effectiveRightMargin); - } else if (readParentItem(effectiveRight.item) == readParentItem(item)) { - setItemX(position(effectiveRight.item, effectiveRight.anchorLine) + } else if (readParentItem(effectiveRightItem) == readParentItem(item)) { + setItemX(position(effectiveRightItem, effectiveRightLine) - readWidth(item) - effectiveRightMargin); } } else if (usedAnchors & QQuickAnchors::HCenterAnchor) { //Handle hCenter - if (effectiveHorizontalCenter.item == readParentItem(item)) { - setItemX(adjustedPosition(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset); - } else if (readParentItem(effectiveHorizontalCenter.item) == readParentItem(item)) { - 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; @@ -780,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; @@ -796,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(); } @@ -808,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(); } @@ -817,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; @@ -833,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(); } @@ -845,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(); } @@ -854,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; @@ -870,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(); } @@ -882,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(); } @@ -891,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; @@ -907,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(); } @@ -919,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(); } @@ -928,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; @@ -944,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(); } @@ -956,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(); } @@ -965,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; @@ -981,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(); } @@ -993,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(); } @@ -1002,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; @@ -1018,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(); } @@ -1030,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(); } @@ -1279,7 +1322,7 @@ void QQuickAnchors::setBaselineOffset(qreal offset) QQuickAnchors::Anchors QQuickAnchors::usedAnchors() const { Q_D(const QQuickAnchors); - return d->usedAnchors; + return static_cast(d->usedAnchors); } bool QQuickAnchorsPrivate::checkHValid() const @@ -1299,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 != readParentItem(item) && readParentItem(anchor.item) != readParentItem(item)){ + } 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) { @@ -1336,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 != readParentItem(item) && readParentItem(anchor.item) != readParentItem(item)){ + } 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){ diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h index 0e02d80ae8..d3c8ed82be 100644 --- a/src/quick/items/qquickanchors_p.h +++ b/src/quick/items/qquickanchors_p.h @@ -90,6 +90,7 @@ public: virtual ~QQuickAnchors(); enum Anchor { + InvalidAnchor = 0x0, LeftAnchor = 0x01, RightAnchor = 0x02, TopAnchor = 0x04, diff --git a/src/quick/items/qquickanchors_p_p.h b/src/quick/items/qquickanchors_p_p.h index 205d9a40da..da659946c0 100644 --- a/src/quick/items/qquickanchors_p_p.h +++ b/src/quick/items/qquickanchors_p_p.h @@ -60,24 +60,15 @@ QT_BEGIN_NAMESPACE class QQuickAnchorLine { public: - enum AnchorLine { - Invalid = 0x0, - Left = 0x01, - Right = 0x02, - Top = 0x04, - Bottom = 0x08, - HCenter = 0x10, - VCenter = 0x20, - Baseline = 0x40, - Horizontal_Mask = Left | Right | HCenter, - Vertical_Mask = Top | Bottom | VCenter | Baseline - }; - - QQuickAnchorLine() : item(0), anchorLine(Invalid) {} - QQuickAnchorLine(QQuickItem *i, AnchorLine l) : item(i), anchorLine(l) {} + QQuickAnchorLine() : item(0), anchorLine(QQuickAnchors::InvalidAnchor) {} + QQuickAnchorLine(QQuickItem *i, QQuickAnchors::Anchor l) : item(i), anchorLine(l) {} + QQuickAnchorLine(QQuickItem *i, uint l) + : item(i) + , anchorLine(static_cast(l)) + { Q_ASSERT(l < ((QQuickAnchors::BaselineAnchor << 1) - 1)); } QQuickItem *item; - AnchorLine anchorLine; + QQuickAnchors::Anchor anchorLine; }; inline bool operator==(const QQuickAnchorLine& a, const QQuickAnchorLine& b) @@ -90,13 +81,44 @@ class QQuickAnchorsPrivate : public QObjectPrivate, public QQuickItemChangeListe Q_DECLARE_PUBLIC(QQuickAnchors) public: QQuickAnchorsPrivate(QQuickItem *i) - : componentComplete(true), updatingMe(false), inDestructor(false), centerAligned(true), - leftMarginExplicit(false), rightMarginExplicit(false), topMarginExplicit(false), - bottomMarginExplicit(false), updatingHorizontalAnchor(0), - updatingVerticalAnchor(0), updatingFill(0), updatingCenterIn(0), item(i), usedAnchors(0), fill(0), - centerIn(0), leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0), - margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0) - + : leftMargin(0) + , rightMargin(0) + , topMargin(0) + , bottomMargin(0) + , margins(0) + , vCenterOffset(0) + , hCenterOffset(0) + , baselineOffset(0) + , item(i) + , fill(Q_NULLPTR) + , centerIn(Q_NULLPTR) + , leftAnchorItem(Q_NULLPTR) + , rightAnchorItem(Q_NULLPTR) + , topAnchorItem(Q_NULLPTR) + , bottomAnchorItem(Q_NULLPTR) + , vCenterAnchorItem(Q_NULLPTR) + , hCenterAnchorItem(Q_NULLPTR) + , baselineAnchorItem(Q_NULLPTR) + , leftAnchorLine(QQuickAnchors::InvalidAnchor) + , leftMarginExplicit(false) + , rightAnchorLine(QQuickAnchors::InvalidAnchor) + , rightMarginExplicit(false) + , topAnchorLine(QQuickAnchors::InvalidAnchor) + , topMarginExplicit(false) + , bottomAnchorLine(QQuickAnchors::InvalidAnchor) + , bottomMarginExplicit(false) + , vCenterAnchorLine(QQuickAnchors::InvalidAnchor) + , updatingMe(false) + , hCenterAnchorLine(QQuickAnchors::InvalidAnchor) + , inDestructor(false) + , baselineAnchorLine(QQuickAnchors::InvalidAnchor) + , centerAligned(true) + , updatingFill(0) + , updatingCenterIn(0) + , updatingHorizontalAnchor(0) + , updatingVerticalAnchor(0) + , componentComplete(true) + , usedAnchors(QQuickAnchors::InvalidAnchor) { } @@ -107,19 +129,6 @@ public: void remDepend(QQuickItem *); bool isItemComplete() const; - bool componentComplete:1; - bool updatingMe:1; - bool inDestructor:1; - bool centerAligned:1; - bool leftMarginExplicit : 1; - bool rightMarginExplicit : 1; - bool topMarginExplicit : 1; - bool bottomMarginExplicit : 1; - uint updatingHorizontalAnchor:2; - uint updatingVerticalAnchor:2; - uint updatingFill:2; - uint updatingCenterIn:2; - void setItemHeight(qreal); void setItemWidth(qreal); void setItemX(qreal); @@ -139,7 +148,9 @@ public: bool checkVValid() const; bool checkHAnchorValid(QQuickAnchorLine anchor) const; bool checkVAnchorValid(QQuickAnchorLine anchor) const; - bool calcStretch(const QQuickAnchorLine &edge1, const QQuickAnchorLine &edge2, qreal offset1, qreal offset2, QQuickAnchorLine::AnchorLine line, qreal &stretch); + bool calcStretch(QQuickItem *edge1Item, QQuickAnchors::Anchor edge1Line, + QQuickItem *edge2Item, QQuickAnchors::Anchor edge2Line, + qreal offset1, qreal offset2, QQuickAnchors::Anchor line, qreal &stretch); bool isMirrored() const; void updateHorizontalAnchors(); @@ -147,20 +158,6 @@ public: void fillChanged(); void centerInChanged(); - QQuickItem *item; - QQuickAnchors::Anchors usedAnchors; - - QQuickItem *fill; - QQuickItem *centerIn; - - QQuickAnchorLine left; - QQuickAnchorLine right; - QQuickAnchorLine top; - QQuickAnchorLine bottom; - QQuickAnchorLine vCenter; - QQuickAnchorLine hCenter; - QQuickAnchorLine baseline; - qreal leftMargin; qreal rightMargin; qreal topMargin; @@ -170,6 +167,44 @@ public: qreal hCenterOffset; qreal baselineOffset; + QQuickItem *item; + + QQuickItem *fill; + QQuickItem *centerIn; + + QQuickItem *leftAnchorItem; + QQuickItem *rightAnchorItem; + QQuickItem *topAnchorItem; + QQuickItem *bottomAnchorItem; + QQuickItem *vCenterAnchorItem; + QQuickItem *hCenterAnchorItem; + QQuickItem *baselineAnchorItem; + + // The bit fields below are carefully laid out in chunks of 1 byte, so the compiler doesn't + // need to generate 2 loads (and combining shifts/ors) to create a single field. + + QQuickAnchors::Anchor leftAnchorLine : 7; + uint leftMarginExplicit : 1; + QQuickAnchors::Anchor rightAnchorLine : 7; + uint rightMarginExplicit : 1; + QQuickAnchors::Anchor topAnchorLine : 7; + uint topMarginExplicit : 1; + QQuickAnchors::Anchor bottomAnchorLine : 7; + uint bottomMarginExplicit : 1; + + QQuickAnchors::Anchor vCenterAnchorLine : 7; + uint updatingMe : 1; + QQuickAnchors::Anchor hCenterAnchorLine : 7; + uint inDestructor : 1; + QQuickAnchors::Anchor baselineAnchorLine : 7; + uint centerAligned : 1; + uint updatingFill : 2; + uint updatingCenterIn : 2; + uint updatingHorizontalAnchor : 2; + uint updatingVerticalAnchor : 2; + + uint componentComplete : 1; + uint usedAnchors : 7; // QQuickAnchors::Anchors static inline QQuickAnchorsPrivate *get(QQuickAnchors *o) { return static_cast(QObjectPrivate::get(o)); diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 0edbcd8780..95b4e09aa5 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -4188,43 +4188,43 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const QQuickAnchorLine QQuickItemPrivate::left() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast(q), QQuickAnchorLine::Left); + return QQuickAnchorLine(const_cast(q), QQuickAnchors::LeftAnchor); } QQuickAnchorLine QQuickItemPrivate::right() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast(q), QQuickAnchorLine::Right); + return QQuickAnchorLine(const_cast(q), QQuickAnchors::RightAnchor); } QQuickAnchorLine QQuickItemPrivate::horizontalCenter() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast(q), QQuickAnchorLine::HCenter); + return QQuickAnchorLine(const_cast(q), QQuickAnchors::HCenterAnchor); } QQuickAnchorLine QQuickItemPrivate::top() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast(q), QQuickAnchorLine::Top); + return QQuickAnchorLine(const_cast(q), QQuickAnchors::TopAnchor); } QQuickAnchorLine QQuickItemPrivate::bottom() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast(q), QQuickAnchorLine::Bottom); + return QQuickAnchorLine(const_cast(q), QQuickAnchors::BottomAnchor); } QQuickAnchorLine QQuickItemPrivate::verticalCenter() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast(q), QQuickAnchorLine::VCenter); + return QQuickAnchorLine(const_cast(q), QQuickAnchors::VCenterAnchor); } QQuickAnchorLine QQuickItemPrivate::baseline() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast(q), QQuickAnchorLine::Baseline); + return QQuickAnchorLine(const_cast(q), QQuickAnchors::BaselineAnchor); } /*! -- cgit v1.2.3 From 531d00c1909527cb1bc28f17197267ccde408b0c Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 11 May 2016 10:41:47 +0200 Subject: QML: Fix anchors on Windows. When using an enum type for a bitfield (i.e. Anchors foo : 7), MSVC will somehow store (or interpret) it as signed, while clang/gcc will do it unsigned. This behavior can be made less exciting by specifying the storage type of the enum. However, as the exception that confirms the rule: gcc 4.8 on OpenSUSE 13 will complain that it can't store all Anchor values in a 7 bit bitfield, but ONLY when a base type for an enum is specified. Change-Id: I7514dd613017d321de55560affb9b355fa75fa2e Reviewed-by: Simon Hausmann --- src/quick/items/qquickanchors_p.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h index d3c8ed82be..2b054e4118 100644 --- a/src/quick/items/qquickanchors_p.h +++ b/src/quick/items/qquickanchors_p.h @@ -89,7 +89,13 @@ public: QQuickAnchors(QQuickItem *item, QObject *parent=0); virtual ~QQuickAnchors(); - enum Anchor { + enum Anchor +#if !(defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (Q_CC_GNU < 500)) + // Not specifying the enum base type will have MSVC 'interpret' it as signed instead of an unsigned bit-field. + // However, specifying the enum base type breaks GCC 4.x on OpenSUSE 13.something, where it complains that it can't store all values in a 7 bit bitfield. + : uint +#endif + { InvalidAnchor = 0x0, LeftAnchor = 0x01, RightAnchor = 0x02, -- cgit v1.2.3 From 39ce4c70e7cfc6b761c2172fe9b048027c220af4 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 26 Apr 2016 10:58:41 +0200 Subject: Teach the QML engine to find static Qt Quick Controls 2 styles The styles are installed to eg. qml/QtQuick/Controls.2/Material. That is, the version is in the parent module. See 3c5e438 for more details. Change-Id: Icdeccb356554ada74dd1116b99be198565c98de6 Task-number: QTBUG-53284 Reviewed-by: Richard Moe Gustavsen --- src/qml/qml/qqmlimport.cpp | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 072ce46273..b51c78b8d4 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -302,7 +302,7 @@ public: int vmaj, int vmin, QV4::CompiledData::Import::ImportType type, QList *errors, bool lowPrecedence = false); #ifndef QT_NO_LIBRARY - bool populatePluginPairVector(QVector &result, const QString &uri, + bool populatePluginPairVector(QVector &result, const QString &uri, const QStringList &versionUris, const QString &qmldirPath, QList *errors); #endif }; @@ -878,14 +878,34 @@ QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QHashedStr return 0; } +/*! + Returns the list of possible versioned URI combinations. For example, if \a uri is + QtQml.Models, \a vmaj is 2, and \a vmin is 0, this method returns the following: + [QtQml.Models.2.0, QtQml.2.0.Models, QtQml.Models.2, QtQml.2.Models, QtQml.Models] + */ +static QStringList versionUriList(const QString &uri, int vmaj, int vmin) +{ + QStringList result; + for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) { + int index = uri.length(); + do { + QString versionUri = uri; + versionUri.insert(index, QQmlImports::versionString(vmaj, vmin, static_cast(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 &result, const QString &uri, +bool QQmlImportsPrivate::populatePluginPairVector(QVector &result, const QString &uri, const QStringList &versionUris, const QString &qmldirPath, QList *errors) { static QVector plugins; @@ -914,7 +934,7 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector &res } // A plugin can be set up to handle multiple URIs, so go through the list: foreach (const QJsonValue &metaTagUri, metaTagsUriList) { - if (metaTagUri.toString().startsWith(uri)) { + if (versionUris.contains(metaTagUri.toString())) { result.append(qMakePair(plugin, metaTagsUriList)); break; } @@ -1007,14 +1027,13 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, // versioned to unversioned, we need to compare with differnt version strings. If a module // has several plugins, they must all have the same version. Start by populating pluginPairs // with relevant plugins to cut the list short early on: + const QStringList versionUris = versionUriList(uri, vmaj, vmin); QVector 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(version)); - + for (const QString &versionUri : versionUris) { foreach (const StaticPluginPair &pair, pluginPairs) { foreach (const QJsonValue &metaTagUri, pair.second) { if (versionUri == metaTagUri.toString()) { @@ -1035,6 +1054,8 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, } } } + if (staticPluginsFound > 0) + break; } } -- cgit v1.2.3 From 28128f2dc6c5eb63d52658ede840e02b06f9ac2c Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 28 Apr 2016 11:09:41 +0200 Subject: QML: Fill QtObject lazily. Only iterate over the enumerations/enumerators in the staticQtMetaObject when a get() is done, and the key/value is not yet in stored in the underlying Object. The whole cost of the iteration is now moved to get() and advanceIterator(). The latter will add all items in one swoop, but iteration over QtObject isn't used much (if at all). The get() will add all key/value pairs up until it finds the requested key. Checking a number of applications shows that none of them use all (or the "last") key, so it will actually save entries (which equals memory) too. This change reduces the instruction count for QtObject from 2.7M instructions down to 95k. As this initialization is done from the QQmlEngine constructor, it also speeds up that initialization. Task-number: QTBUG-43770 Change-Id: I71331ff76bdacdd4790f7ff0430c4cbc214fe0ab Reviewed-by: Simon Hausmann --- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 82 ++++++++++++++++++++++++++++----- src/qml/qml/v8/qqmlbuiltinfunctions_p.h | 14 ++++++ 2 files changed, 85 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index ed478fa17f..ecfc817d3b 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -87,22 +87,18 @@ struct StaticQtMetaObject : public QObject }; Heap::QtObject::QtObject(QQmlEngine *qmlEngine) + : enumeratorIterator(0) + , keyIterator(0) { Scope scope(internalClass->engine); ScopedObject o(scope, this); - // Set all the enums from the "Qt" namespace - const QMetaObject *qtMetaObject = StaticQtMetaObject::get(); - ScopedString str(scope); - ScopedValue v(scope); - for (int ii = 0, eii = qtMetaObject->enumeratorCount(); ii < eii; ++ii) { - QMetaEnum enumerator = qtMetaObject->enumerator(ii); - for (int jj = 0, ejj = enumerator.keyCount(); jj < ejj; ++jj) { - o->put((str = scope.engine->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj)))); - } + { + ScopedString str(scope); + ScopedValue v(scope); + o->put((str = scope.engine->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0))); + o->put((str = scope.engine->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1))); } - o->put((str = scope.engine->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0))); - o->put((str = scope.engine->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1))); o->defineDefaultProperty(QStringLiteral("include"), QV4Include::method_include); o->defineDefaultProperty(QStringLiteral("isQtObject"), QV4::QtObject::method_isQtObject); @@ -151,6 +147,70 @@ Heap::QtObject::QtObject(QQmlEngine *qmlEngine) o->defineAccessorProperty(QStringLiteral("styleHints"), QV4::QtObject::method_get_styleHints, 0); } +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(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(m); + if (!that->d()->isComplete()) { + that->addAll(); + } + + QV4::Object::advanceIterator(m, it, name, index, p, attributes); +} /*! \qmlmethod bool Qt::isQtObject(object) diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h index 53468f062b..dc806c6031 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h +++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h @@ -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); @@ -124,6 +134,10 @@ struct QtObject : Object static ReturnedValue method_get_inputMethod(CallContext *ctx); #endif static ReturnedValue method_get_styleHints(CallContext *ctx); + +private: + void addAll(); + ReturnedValue findAndAdd(const QString *name, bool &foundProperty) const; }; struct ConsoleObject : Object -- cgit v1.2.3 From 50b12610a701e14c315839cd091e0f654c52f019 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 11 May 2016 14:39:05 +0200 Subject: Eradicate Q_FOREACH loops from headers They may prevent use of QT_NO_FOREACH in other Qt modules. Change-Id: Iafc04a73579a90492f3ff303978b78b71eec4e55 Reviewed-by: Lars Knoll --- src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h | 2 +- src/qml/compiler/qv4ssa_p.h | 2 +- src/qml/jit/qv4targetplatform_p.h | 3 ++- src/qml/parser/qqmljsparser_p.h | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h b/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h index 668ce2558d..85ff9b182f 100644 --- a/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h +++ b/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h @@ -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(); } diff --git a/src/qml/compiler/qv4ssa_p.h b/src/qml/compiler/qv4ssa_p.h index 86f812bc41..e608c08591 100644 --- a/src/qml/compiler/qv4ssa_p.h +++ b/src/qml/compiler/qv4ssa_p.h @@ -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); diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h index 80a18a7f5b..54b17c4f07 100644 --- a/src/qml/jit/qv4targetplatform_p.h +++ b/src/qml/jit/qv4targetplatform_p.h @@ -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::ebx) { ebxIdx = calleeSaves; break; diff --git a/src/qml/parser/qqmljsparser_p.h b/src/qml/parser/qqmljsparser_p.h index 02dbe7d323..00ffb6aca3 100644 --- a/src/qml/parser/qqmljsparser_p.h +++ b/src/qml/parser/qqmljsparser_p.h @@ -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; } -- cgit v1.2.3 From 32897258b4b9309cae9562a61fea280acd954aa5 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 21 Apr 2016 12:10:44 +0200 Subject: V4: Replace QList with std::vector in InternalClass::destroy() This nearly halves the number of instructions in the benchmark librarymetrics_performance instantiation #060: it goes from 23M to 17M for 23 iterations. Change-Id: Icc3cebc19998b67b95e6642b1daa1b2371cdecd2 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4internalclass.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index a5405dad0d..9660a5e76d 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -429,11 +429,13 @@ InternalClass *InternalClass::propertiesFrozen() const void InternalClass::destroy() { - QList destroyStack; - destroyStack.append(this); + std::vector 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(); next->propertyData.~SharedInternalClassData(); 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(); -- cgit v1.2.3 From ed7d33ebcddc617a7e0197aa559e2fb15ce7a172 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 12 May 2016 10:47:30 +0200 Subject: Fix anchor enum again, now for more broken versions of GCC. Apparently only very recent versions of gcc can correctly deduce that the Anchor enum can be stored in a 7-bit bitfield. So to be sure we don't run into compiler errors, do not specify the base type for any GCC version. Task-number: QTBUG-53317 Change-Id: I825946862dea1eabfb68a3fbe8cbd31bc71bdd10 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickanchors_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h index 2b054e4118..f00b8b5ba7 100644 --- a/src/quick/items/qquickanchors_p.h +++ b/src/quick/items/qquickanchors_p.h @@ -90,9 +90,9 @@ public: virtual ~QQuickAnchors(); enum Anchor -#if !(defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (Q_CC_GNU < 500)) +#if defined(Q_CC_CLANG) || !defined(Q_CC_GNU) // meaning: clang and msvc, but NOT gcc proper (because, you know, Q_CC_CLANG implies Q_CC_GNU) // Not specifying the enum base type will have MSVC 'interpret' it as signed instead of an unsigned bit-field. - // However, specifying the enum base type breaks GCC 4.x on OpenSUSE 13.something, where it complains that it can't store all values in a 7 bit bitfield. + // However, specifying the enum base type breaks many GCCs, which complain that it can't store all values in a 7 bit bitfield. : uint #endif { -- cgit v1.2.3 From a7b383ab989e74ef552c2ef9c38377e065f1ab0e Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 21 Apr 2016 14:08:06 +0200 Subject: V4: calculate the hash only once when inserting a string. Reduces the number of instructions of IdentifierTable::identifier by ~15%. Change-Id: I5a234fa96a6ee3e7202150ded512d1be0b36560d Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4identifier.cpp | 2 +- src/qml/jsruntime/qv4identifiertable.cpp | 10 ++- src/qml/jsruntime/qv4string.cpp | 114 ++++++++++--------------------- src/qml/jsruntime/qv4string_p.h | 4 +- src/qml/qml/ftw/qhashedstring.cpp | 4 +- 5 files changed, 49 insertions(+), 85 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp index c8d66b1254..626648067f 100644 --- a/src/qml/jsruntime/qv4identifier.cpp +++ b/src/qml/jsruntime/qv4identifier.cpp @@ -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) diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp index 5adb17b4ea..3def6defbf 100644 --- a/src/qml/jsruntime/qv4identifiertable.cpp +++ b/src/qml/jsruntime/qv4identifiertable.cpp @@ -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; } diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index abef885249..1455a06c4a 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -49,9 +49,15 @@ 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 +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,7 +66,7 @@ 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; @@ -75,30 +81,26 @@ static uint toArrayIndex(const QChar *ch, const QChar *end) #ifndef V4_BOOTSTRAP -static uint toArrayIndex(const char *ch, const char *end) +template +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 +200,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(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 worklist; @@ -243,45 +220,26 @@ void Heap::String::append(const String *data, QChar *ch) } } +void Heap::String::createHashValue() const +{ + if (largestSubLength) + simplifyString(); + Q_ASSERT(!largestSubLength); + const QChar *ch = reinterpret_cast(text->data()); + const QChar *end = ch + text->size; + stringHash = calculateHashValue(ch, end, &subtype); +} - - -uint String::createHashValue(const QChar *ch, int length) +uint String::createHashValue(const QChar *ch, int length, uint *subtype) { 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; + return calculateHashValue(ch, end, subtype); } -uint String::createHashValue(const char *ch, int length) +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) diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index 3196f49896..60e2655536 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -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(); diff --git a/src/qml/qml/ftw/qhashedstring.cpp b/src/qml/qml/ftw/qhashedstring.cpp index 37c1003748..5c5d2a31ac 100644 --- a/src/qml/qml/ftw/qhashedstring.cpp +++ b/src/qml/qml/ftw/qhashedstring.cpp @@ -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 -- cgit v1.2.3 From 174996a45633c5440b9707856fb8bea95b8330c2 Mon Sep 17 00:00:00 2001 From: Frank Meerkoetter Date: Wed, 11 May 2016 22:03:26 +0200 Subject: Avoid QHash::values() Doing so will spare us from creating a temporary container just to iterate over it. Change-Id: Iab6aec0d83bfc168f12d2348909b053dfddf67a1 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlimport.cpp | 2 +- src/qml/qml/qqmlmetatype.cpp | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 69adce3da2..8a7fa369e6 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -191,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())); diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index b13009853e..13ec492c54 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1914,14 +1914,11 @@ QList QQmlMetaType::qmlSingletonTypes() QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - QList alltypes = data->nameToType.values(); QList 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; } -- cgit v1.2.3 From 5241bcecea1b357dfe614346ae58e78ffd9578f8 Mon Sep 17 00:00:00 2001 From: Frank Meerkoetter Date: Wed, 11 May 2016 22:06:28 +0200 Subject: Make this loop more readable with a range-for Change-Id: I867652aa168bd4a3eae191bf09946f98207a5ba6 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlmetatype.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 13ec492c54..1c5a7ad8c1 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1926,9 +1926,9 @@ const QQmlPrivate::CachedQmlUnit *QQmlMetaType::findCachedCompilationUnit(const { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - for (QVector::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; -- cgit v1.2.3 From ec78cd1d22f943aa638749a8d3670e0138122c4a Mon Sep 17 00:00:00 2001 From: Frank Meerkoetter Date: Fri, 13 May 2016 10:17:42 +0200 Subject: Avoid memory allocations Avoids at least three memory allocations (values() twice and a local QList for the result of a concatenation. Change-Id: I83776652ddd30642e25144f5b173dd6b1074ac79 Reviewed-by: Simon Hausmann --- src/quick/util/qquickpixmapcache.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index 2b6e8f68c3..597613c9fd 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -455,13 +455,19 @@ QQuickPixmapReader::~QQuickPixmapReader() } jobs.clear(); #ifndef QT_NO_NETWORK - QList activeJobs = networkJobs.values() + asyncResponses.values(); - foreach (QQuickPixmapReply *reply, activeJobs ) { + + const auto cancelJob = [this](QQuickPixmapReply *reply) { if (reply->loading) { cancelled.append(reply); reply->data = 0; } - } + }; + + for (auto *reply : qAsConst(networkJobs)) + cancelJob(reply); + + for (auto *reply : qAsConst(asyncResponses)) + cancelJob(reply); #endif if (threadObject) threadObject->processJobs(); mutex.unlock(); -- cgit v1.2.3 From b9e4a4df577959579b2322fb6077bde82d9ffce3 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 25 Feb 2016 13:48:08 +0100 Subject: Flickable: add AutoFlickIfNeeded as an option for flickableDirection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If you want to disable all movement when the user tries to flick or drag, you previously had to set interactive: false. Maybe you need to bind that to some calculation to determine whether the content fits completely inside the Flickable or not. This way is easier. BTW the AutoFlickIfNeeded can be ORed with HorizontalFlick or VerticalFlick, but we don't document it because AutoFlickDirection=0, so it's not useful to OR that with anything. Task-number: QTBUG-31121 Change-Id: Ib03b0f223cb40f0338510c318aa37e70ce71514d Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickflickable.cpp | 8 ++++++++ src/quick/items/qquickflickable_p.h | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index b0245f402b..ae138d7ceb 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -881,6 +881,10 @@ QQuickFlickableVisibleArea *QQuickFlickable::visibleArea() \e contentHeight is not equal to the \e height of the Flickable. Allows flicking horizontally if the \e contentWidth is not equal to the \e width of the Flickable. + \li Flickable.AutoFlickIfNeeded - allows flicking vertically if the + \e contentHeight is greater than the \e height of the Flickable. + Allows flicking horizontally if the \e contentWidth is greater than + to the \e width of the Flickable. \li Flickable.HorizontalFlick - allows flicking horizontally. \li Flickable.VerticalFlick - allows flicking vertically. \li Flickable.HorizontalAndVerticalFlick - allows flicking in both directions. @@ -2167,6 +2171,8 @@ qreal QQuickFlickable::vHeight() const bool QQuickFlickable::xflick() const { Q_D(const QQuickFlickable); + if ((d->flickableDirection & QQuickFlickable::AutoFlickIfNeeded) && (vWidth() > width())) + return true; if (d->flickableDirection == QQuickFlickable::AutoFlickDirection) return std::floor(qAbs(vWidth() - width())); return d->flickableDirection & QQuickFlickable::HorizontalFlick; @@ -2175,6 +2181,8 @@ bool QQuickFlickable::xflick() const bool QQuickFlickable::yflick() const { Q_D(const QQuickFlickable); + if ((d->flickableDirection & QQuickFlickable::AutoFlickIfNeeded) && (vHeight() > height())) + return true; if (d->flickableDirection == QQuickFlickable::AutoFlickDirection) return std::floor(qAbs(vHeight() - height())); return d->flickableDirection & QQuickFlickable::VerticalFlick; diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h index 6cf78dcf63..318b8ce473 100644 --- a/src/quick/items/qquickflickable_p.h +++ b/src/quick/items/qquickflickable_p.h @@ -192,7 +192,8 @@ public: QQuickItem *contentItem(); - enum FlickableDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 }; + enum FlickableDirection { AutoFlickDirection=0x0, HorizontalFlick=0x1, VerticalFlick=0x2, HorizontalAndVerticalFlick=0x3, + AutoFlickIfNeeded=0xc }; Q_ENUM(FlickableDirection) FlickableDirection flickableDirection() const; void setFlickableDirection(FlickableDirection); -- cgit v1.2.3 From 35d8d4bc2bf84a2ea9744382a5a2eb7a51aaea3a Mon Sep 17 00:00:00 2001 From: Frank Meerkoetter Date: Fri, 13 May 2016 21:46:47 +0200 Subject: Do not initialize twice Change-Id: If801f84b90fa1335a019751dc097568202aa4750 Reviewed-by: Simon Hausmann --- src/quick/util/qquicksmoothedanimation.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/quick/util/qquicksmoothedanimation.cpp b/src/quick/util/qquicksmoothedanimation.cpp index b7eadf5e30..d4956983fb 100644 --- a/src/quick/util/qquicksmoothedanimation.cpp +++ b/src/quick/util/qquicksmoothedanimation.cpp @@ -377,9 +377,8 @@ QQuickSmoothedAnimation::~QQuickSmoothedAnimation() } QQuickSmoothedAnimationPrivate::QQuickSmoothedAnimationPrivate() - : anim(0) + : anim(new QSmoothedAnimation) { - anim = new QSmoothedAnimation; } QQuickSmoothedAnimationPrivate::~QQuickSmoothedAnimationPrivate() -- cgit v1.2.3 From 1c51ae2911636e61a698967fd9c6aabd28f5ceb9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 12 May 2016 10:19:14 +0200 Subject: Fix visibility of properties in value types It should be possible to enumerate the properties of value types (gadgets), in order for things like JSON.stringify(Qt.point(10, 20)) to return something sensible. Task-number: QTBUG-43382 Task-number: QTBUG-34878 Change-Id: I3a2c09151ebe97fd97760dfbbf5a4f58e022bc94 Reviewed-by: Mitch Curtis Reviewed-by: Robin Burchell --- src/qml/qml/qqmlvaluetypewrapper.cpp | 29 +++++++++++++++++++++++++++++ src/qml/qml/qqmlvaluetypewrapper_p.h | 1 + 2 files changed, 30 insertions(+) (limited to 'src') diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 96bca9070d..fdac41a420 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -50,6 +50,7 @@ #include #include #include +#include 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(m); + + if (QQmlValueTypeReference *ref = that->as()) { + 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(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()) diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h index c2861f5bfa..94eeba366a 100644 --- a/src/qml/qml/qqmlvaluetypewrapper_p.h +++ b/src/qml/qml/qqmlvaluetypewrapper_p.h @@ -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); -- cgit v1.2.3 From 27567f7c4cb9c74c2ad3829f716caf8c5095b16b Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 21 Apr 2016 14:41:02 +0200 Subject: V4: Use built-in overflow checking add/mul for index calculation. This signals the compiler the actual intent (i.e. it doesn't rely on unsigned int overflow behavior) and even allows for slightly better code generation. Change-Id: I915ebbeab2e60decb6adf816e9cf010ab41d172a Reviewed-by: Robin Burchell Reviewed-by: Frank Meerkoetter --- src/qml/jsruntime/qv4string.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 1455a06c4a..7c965ce441 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -46,6 +46,7 @@ #include "qv4stringobject_p.h" #endif #include +#include using namespace QV4; @@ -69,11 +70,8 @@ static inline uint toArrayIndex(const T *ch, const T *end) 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; -- cgit v1.2.3 From 709f6370884b110def2e4665df8fa7bbf5fae734 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 13 May 2016 14:24:59 +0200 Subject: Re-apply the cast part of commit 392c7b99348e2a96ef11adb5712095fbd13fb780 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We reverted this in 6f59c91c51edd7207635c3fa2f0b2b1179e7aa6e to avoid further breakage in a patch release. Now let's do the right thing in the next minor release and replace the qobject_cast on the instance with the IID check that won't require instantiating the plugin in the qml loader thread. [ChangeLog][QtQml][Important Behavior Changes] When the engine looks for QML modules / extension plugins in statically linked applications, the plugins are not instantiated in the qml loader thread anymore. For this to work however it is necessary for plugins to use Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) in their class declaration instead of hardcoding the interface id as a string literal. Task-number: QTBUG-52012 Change-Id: I45fe8b9fec23b3d0408b7ee79ce297c7d47ce36d Reviewed-by: Sebastian Lösch Reviewed-by: J-P Nurmi --- src/qml/qml/qqmlimport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 8a7fa369e6..5ed2ad6bf1 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -893,7 +893,7 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector &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(plugin.instance())) + if (plugin.metaData().value(QStringLiteral("IID")).toString() == QLatin1String(QQmlExtensionInterface_iid)) plugins.append(plugin); } } -- cgit v1.2.3 From c78a4dcb610de48d6d339ca61b38bd1394e11995 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 17 May 2016 16:58:01 +0200 Subject: V4 profiling: Don't needlessly resolve locations Resolving locations is fairly expensive and we only need to do it once per location. Change-Id: I8716858f45da9c085e50527ada0611531641dafe Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4profiling.cpp | 17 ++++++++--------- src/qml/jsruntime/qv4profiling_p.h | 12 +++++++++++- 2 files changed, 19 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp index a59190b846..72475c5416 100644 --- a/src/qml/jsruntime/qv4profiling.cpp +++ b/src/qml/jsruntime/qv4profiling.cpp @@ -48,13 +48,10 @@ namespace Profiling { FunctionLocation FunctionCall::resolveLocation() const { - FunctionLocation location = { - m_function->name()->toQString(), - m_function->compilationUnit->fileName(), - m_function->compiledFunction->location.line, - m_function->compiledFunction->location.column - }; - return location; + return FunctionLocation(m_function->name()->toQString(), + m_function->compilationUnit->fileName(), + m_function->compiledFunction->location.line, + m_function->compiledFunction->location.column); } FunctionCallProperties FunctionCall::properties() const @@ -95,12 +92,14 @@ void Profiler::reportData() { std::sort(m_data.begin(), m_data.end()); QVector properties; - QHash locations; + FunctionLocationHash locations; properties.reserve(m_data.size()); foreach (const FunctionCall &call, m_data) { properties.append(call.properties()); - locations[properties.constLast().id] = call.resolveLocation(); + FunctionLocation &location = locations[properties.constLast().id]; + if (!location.isValid()) + location = call.resolveLocation(); } emit dataReady(locations, properties, m_memory_data); diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h index 0b4193204f..bb128b7cf3 100644 --- a/src/qml/jsruntime/qv4profiling_p.h +++ b/src/qml/jsruntime/qv4profiling_p.h @@ -81,13 +81,23 @@ struct FunctionCallProperties { }; 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 FunctionLocationHash; +typedef QHash FunctionLocationHash; struct MemoryAllocationProperties { qint64 timestamp; -- cgit v1.2.3 From 7d5ce4284badb1fd54a67938039d0a1908f34370 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 17 May 2016 10:35:56 +0200 Subject: Cleanup Remove two dummy forwarding functions Change-Id: I053f9aecc761772c932550a0ddbea390621049c1 Reviewed-by: Lars Knoll --- src/qml/qml/qqmlcompiler_p.h | 2 -- src/qml/qml/qqmlcomponent.cpp | 2 +- src/qml/qml/qqmlincubator.cpp | 4 ++-- src/qml/qml/qqmlobjectcreator.cpp | 8 ++++---- 4 files changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index 1c43a85de3..cbe70a7077 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -89,8 +89,6 @@ public: QQmlEngine *engine; - QString fileName() const { return compilationUnit->fileName(); } - QUrl url() const { return compilationUnit->url(); } QQmlTypeNameCache *importCache; int metaTypeId; diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 61a4b701c0..6aa3710731 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -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; } diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp index 235aa1bf44..eba93bfb1a 100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@ -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 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; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index cfe1c86eba..2ffb1596f5 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -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 >()) { 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 value; value.append(u); argv[0] = reinterpret_cast(&value); @@ -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); @@ -1072,7 +1072,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo } else { Q_ASSERT(typeRef->component); Q_QML_OC_PROFILE(sharedState->profiler, profiler.update( - compiledData, obj, typeRef->component->fileName(), + compiledData, obj, typeRef->component->compilationUnit->fileName(), context->url())); if (typeRef->component->compilationUnit->data->isSingleton()) { -- cgit v1.2.3 From a5626dbe6769af2ccf7089d2ae7ef58f76f75ea5 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 18 May 2016 16:21:11 +0200 Subject: Minor VME meta object context handling cleanup There is no need to go through the public QQmlContext in order to retrieve the QQmlContextData the QQmlVMEMetaObject is associated with. Change-Id: I648454c217fa594d4017c3af67848eacab55edfc Reviewed-by: Lars Knoll --- src/qml/qml/qqmlvmemetaobject.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index ef00a582ef..3ded302681 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -1143,10 +1143,7 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, 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(); + *target = ctxt->idValues[d->contextIdx].data(); if (!*target) return false; -- cgit v1.2.3 From ef6469a95948b8c95ed6fb0cbbe7daaa1960c956 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 18 May 2016 15:48:18 +0200 Subject: VME Method object data cleanup Get rid of the redundant MethodData meta-data that is stored per-type. Change-Id: I9faa284bdd0c9f0c9ebb3c66905ab5e34a9ee3a4 Reviewed-by: Lars Knoll --- .../qmldbg_debugger/qqmlenginedebugservice.cpp | 7 ++++++- src/qml/compiler/qqmltypecompiler.cpp | 21 ++------------------ src/qml/qml/qqmlvmemetaobject.cpp | 23 +++------------------- src/qml/qml/qqmlvmemetaobject_p.h | 11 ----------- 4 files changed, 11 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp index ff4e30835d..e08436b7a3 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp @@ -766,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; diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index da00496cb2..fcb94a9645 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -660,7 +660,6 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob QByteArray &dynamicData = vmeMetaObjects[objectIndex] = QByteArray(sizeof(QQmlVMEMetaData) + obj->propertyCount() * sizeof(VMD::PropertyData) - + obj->functionCount() * sizeof(VMD::MethodData) + aliasCount * sizeof(VMD::AliasData), 0); int effectivePropertyIndex = cache->propertyIndexCacheStart; @@ -879,24 +878,8 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob ((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; - } + VMD *vmd = (QQmlVMEMetaData *)dynamicData.data(); + vmd->methodCount = obj->functionCount(); return true; } diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 3ded302681..3173e1d09c 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -877,12 +877,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); @@ -1039,22 +1038,6 @@ 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()) { diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index fcdac3cc53..20b8b99522 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -121,12 +121,6 @@ struct QQmlVMEMetaData int propertyType; }; - struct MethodData { - int runtimeFunctionIndex; - int parameterCount; - quint16 lineNumber; - }; - PropertyData *propertyData() const { return (PropertyData *)(((char *)const_cast(this)) + sizeof(QQmlVMEMetaData)); } @@ -134,10 +128,6 @@ struct QQmlVMEMetaData AliasData *aliasData() const { return (AliasData *)(propertyData() + propertyCount); } - - MethodData *methodData() const { - return (MethodData *)(aliasData() + aliasCount); - } }; class QQmlVMEMetaObject; @@ -204,7 +194,6 @@ public: 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); -- cgit v1.2.3 From 219873c65fed284310bfb6d32d8b7ddf8fc15da1 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 13 May 2016 13:41:42 +0200 Subject: Fix regression with assignments to default properties With commit ad8d760decd5f1c6242a42688417b3c86122121c the precision of the location (row/column) fields was reduced. The same fields are used to preserve the insertion orer of bindings as they appear in the .qml file, which meant that for large qml files without any line feeds we may end up with an overrun in the column range (2048). This happened in the Tests_TabView::test_mousePressOnTabBar test in qtquickcontrols. The reduced precision is fine because those column/row fields should only be used for error reporting. In this case where we need the precision we can just as well use the file offset in the temporary QML-IR Binding data structure. Task-number: QTBUG-53115 Change-Id: Ifb6f76b4f83a06fa228211134d12cc67c071bbec Reviewed-by: Robin Burchell --- src/qml/compiler/qqmlirbuilder.cpp | 5 ++++- src/qml/compiler/qqmlirbuilder_p.h | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index df0b1f67b1..bd4261493c 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -190,7 +190,7 @@ Binding *Object::findBinding(quint32 nameIndex) const void Object::insertSorted(Binding *b) { - Binding *insertionPoint = bindings->findSortedInsertionPoint(b); + Binding *insertionPoint = bindings->findSortedInsertionPoint(b); bindings->insertAfter(insertionPoint, b); } @@ -1082,6 +1082,7 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo { Binding *binding = New(); binding->propertyNameIndex = propertyNameIndex; + binding->offset = nameLocation.offset; binding->location.line = nameLocation.startLine; binding->location.column = nameLocation.startColumn; binding->flags = 0; @@ -1101,6 +1102,7 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo Binding *binding = New(); binding->propertyNameIndex = propertyNameIndex; + binding->offset = nameLocation.offset; binding->location.line = nameLocation.startLine; binding->location.column = nameLocation.startColumn; @@ -1225,6 +1227,7 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O if (!binding) { binding = New(); 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; diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index 057ed1be9f..18daab9ce4 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -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,6 +227,10 @@ 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; }; -- cgit v1.2.3 From 5e841b26ee90fa91fb8aea0ab17b738a0a49ce74 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 19 May 2016 15:03:33 +0200 Subject: Minor optimization for VME meta objects Instead of storing the methods of a qml object in an array of persistents, let's just store them in the same member data array we also use for properties. That reduces the amount of persistents and saves one pointer per instance. Change-Id: I1ad1d9ec76b78fce01bc6ded7eaf536cb99dd245 Reviewed-by: Frank Meerkoetter Reviewed-by: Lars Knoll --- src/qml/qml/qqmlvmemetaobject.cpp | 127 ++++++++++++++++---------------------- src/qml/qml/qqmlvmemetaobject_p.h | 6 +- 2 files changed, 56 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 3173e1d09c..8211a834ec 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -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 sp(scope, m_target->properties.value()); + QV4::Scoped sp(scope, m_target->propertyAndMethodStorage.value()); if (sp) *(sp->data() + m_index) = QV4::Primitive::nullValue(); } @@ -307,132 +307,122 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, const QQmlVMEMetaData *meta) : QQmlInterceptorMetaObject(obj, cache), ctxt(QQmlData::get(obj, true)->outerContext), metaData(meta), - aliasEndpoints(0), - methods(0) + aliasEndpoints(0) { cache->addref(); QQmlData::get(obj)->hasVMEMetaObject = true; - int qobject_type = qMetaTypeId(); - int variant_type = qMetaTypeId(); - // 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); - - // ### 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 (metaData->propertyCount || metaData->methodCount) { + Q_ASSERT(cache && cache->engine); + QV4::ExecutionEngine *v4 = cache->engine; + QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, metaData->propertyCount + metaData->methodCount); + propertyAndMethodStorage.set(v4, data); + std::fill(data->data, data->data + data->size, QV4::Encode::undefined()); - if (needsJSWrapper) + + // Need JS wrapper to ensure properties/methods are marked. 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(properties.asManaged()); + return static_cast(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 +437,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 +450,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 +463,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 +476,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 +489,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 +503,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 +517,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 +531,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 +545,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 +559,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 +573,7 @@ QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id) QList *QQmlVMEMetaObject::readPropertyAsList(int id) { - QV4::MemberData *md = propertiesAsMemberData(); + QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (!md) return 0; @@ -599,7 +589,7 @@ QList *QQmlVMEMetaObject::readPropertyAsList(int id) QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id) { - QV4::MemberData *md = propertiesAsMemberData(); + QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (!md) return QRectF(); @@ -695,7 +685,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * p->dummy1 = this; p->dummy2 = reinterpret_cast(quintptr(methodOffset() + id)); } else { - QV4::MemberData *md = propertiesAsMemberData(); + QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) { QV4::VariantObject *v = (md->data() + id)->as(); if (v) @@ -757,7 +747,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * writeProperty(id, *reinterpret_cast(a[0])); break; default: { - QV4::MemberData *md = propertiesAsMemberData(); + QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) { QV4::VariantObject *v = (md->data() + id)->as(); if (!v) { @@ -915,17 +905,18 @@ QV4::ReturnedValue QQmlVMEMetaObject::method(int index) return QV4::Encode::undefined(); } - if (!methods) + QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); + if (!md) return QV4::Encode::undefined(); - return methods[index].value(); + return (md->data() + index + metaData->propertyCount)->asReturnedValue(); } QV4::ReturnedValue QQmlVMEMetaObject::readVarProperty(int id) { Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType); - QV4::MemberData *md = propertiesAsMemberData(); + QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) return (md->data() + id)->asReturnedValue(); return QV4::Primitive::undefinedValue().asReturnedValue(); @@ -933,7 +924,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(); if (wrapper) @@ -950,7 +941,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value) { Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType); - QV4::MemberData *md = propertiesAsMemberData(); + QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (!md) return; @@ -989,7 +980,7 @@ 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(); + QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (!md) return; @@ -1019,7 +1010,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(); needActivate = (!v || @@ -1059,11 +1050,11 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &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]; - int methodIndex = index - methodOffset() - plainSignals; - methods[methodIndex].set(function.as()->engine(), function); + QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); + if (!md) + return; + *(md->data() + methodIndex + metaData->propertyCount) = function; } QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index) @@ -1098,22 +1089,12 @@ 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); diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 20b8b99522..cbb79f2d0c 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -219,9 +219,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); @@ -254,7 +253,6 @@ public: void connectAlias(int aliasId); - QV4::PersistentValue *methods; QV4::ReturnedValue method(int); QV4::ReturnedValue readVarProperty(int); -- cgit v1.2.3 From 02c384e48d672bac1ee8ba554ba335ce0442057e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 19 May 2016 15:51:03 +0200 Subject: Save a little bit of memory per declared property We only need one bit for the flags, to save four bytes. Change-Id: I73cbf8c2ef8b532dfe494b1b31ab242cccc38686 Reviewed-by: Lars Knoll --- src/qml/compiler/qv4compileddata_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 8990db075d..ac27124d70 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -358,13 +358,13 @@ struct Property }; quint32 nameIndex; - quint32 type; + quint32 type : 31; + quint32 flags : 1; // readonly union { quint32 customTypeNameIndex; // If type >= Custom quint32 aliasIdValueIndex; // If type == Alias }; quint32 aliasPropertyValueIndex; - quint32 flags; // readonly Location location; Location aliasLocation; // If type == Alias }; -- cgit v1.2.3 From b0377f4581a7f62cccd375a1f9400ca57225e4ac Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 19 May 2016 16:14:22 +0200 Subject: Optimize property/alias data structures We used to store property declarations and alias declarations in the same properties array in CompiledData::Object. However at run-time the QQmlVMEMetaObject implements them separately, using separate data structures (in the meta-data) and (most importantly) using separate property id segments: First the properties, then the aliases. By reflecting the same separation in CompiledData::Object with property arrays and alias arrays, we can pave the way for getting rid of the meta-data in QQmlVMEMetaObject. Change-Id: Ia84813fe3da6f3fdbd4d2b16136a8bf11fa175a6 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlirbuilder.cpp | 292 +++++++++++++++++++++------------- src/qml/compiler/qqmlirbuilder_p.h | 14 +- src/qml/compiler/qqmltypecompiler.cpp | 130 ++++++++------- src/qml/compiler/qv4compileddata_p.h | 32 +++- src/qml/qml/qqmlobjectcreator.cpp | 2 +- 5 files changed, 282 insertions(+), 188 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index bd4261493c..ac59c04e87 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -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 >(); + aliases = pool->New >(); qmlSignals = pool->New >(); bindings = pool->New >(); functions = pool->New >(); @@ -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; @@ -806,128 +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(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(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->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")); + if (!typeFound) { + recordError(node->typeToken, QCoreApplication::translate("QQmlParser","Expected property type")); + return false; + } - QQmlJS::AST::SourceLocation rhsLoc; - if (node->binding) - rhsLoc = node->binding->firstSourceLocation(); - else if (node->statement) - rhsLoc = node->statement->firstSourceLocation(); + Property *property = New(); + 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 - rhsLoc = node->semicolonToken; - property->aliasLocation.line = rhsLoc.startLine; - property->aliasLocation.column = rhsLoc.startColumn; - - QStringList alias; - - if (QQmlJS::AST::ExpressionStatement *stmt = QQmlJS::AST::cast(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 , . or ..")); - } else { - COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias location")); - } - } - } else { - COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as , . or ..")); - } + property->customTypeNameIndex = emptyStringIndex; - if (alias.count() < 1 || alias.count() > 3) - COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as , . or ..")); + const QString propName = name.toString(); + property->nameIndex = registerString(propName); - property->aliasIdValueIndex = registerString(alias.first()); + QQmlJS::AST::SourceLocation loc = node->firstSourceLocation(); + property->location.line = loc.startLine; + property->location.column = loc.startColumn; - QString propertyValue = alias.value(1); - if (alias.count() == 3) - propertyValue += QLatin1Char('.') + alias.at(2); - property->aliasPropertyValueIndex = registerString(propertyValue); - } - QQmlJS::AST::SourceLocation errorLocation; - QString error; + 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 (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; + if (!error.isEmpty()) { + if (errorLocation.startLine == 0) + errorLocation = node->identifierToken; - recordError(errorLocation, error); - return false; - } + 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); + 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); } - qSwap(_propertyDeclaration, property); } return false; @@ -1132,6 +1119,79 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo } } +bool IRBuilder::appendAlias(QQmlJS::AST::UiPublicMember *node) +{ + Alias *alias = New(); + 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->propertyIndex = 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(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 , . or ..")); + } else { + COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias location")); + } + } + } else { + COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as , . or ..")); + } + + if (aliasReference.count() < 1 || aliasReference.count() > 3) + COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as , . or ..")); + + alias->idIndex = registerString(aliasReference.first()); + + QString propertyValue = aliasReference.value(1); + if (aliasReference.count() == 3) + propertyValue += QLatin1Char('.') + aliasReference.at(2); + alias->propertyIndex = 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) @@ -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(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(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; } diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index 18daab9ce4..060c888cd8 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -235,6 +235,11 @@ struct Binding : public QV4::CompiledData::Binding Binding *next; }; +struct Alias : public QV4::CompiledData::Alias +{ + Alias *next; +}; + struct Function { QQmlJS::AST::FunctionDeclaration *functionDeclaration; @@ -270,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; } + const 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; } @@ -294,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); @@ -309,6 +318,7 @@ private: friend struct IRLoader; PoolList *properties; + PoolList *aliases; PoolList *qmlSignals; PoolList *bindings; PoolList *functions; @@ -414,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); diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index fcb94a9645..fed0ec1f37 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -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 { @@ -638,29 +638,40 @@ 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) - + aliasCount * sizeof(VMD::AliasData), 0); + + obj->aliasCount() * sizeof(VMD::AliasData), 0); + + VMD *vmd = (QQmlVMEMetaData *)dynamicData.data(); + // Dynamic slot data - comes after the property data + vmd->methodCount = obj->functionCount(); + // Alias property count. Actual data is setup in resolveAliases() + vmd->aliasCount = obj->aliasCount(); + vmd->signalCount = obj->signalCount(); + vmd->propertyCount = obj->propertyCount(); int effectivePropertyIndex = cache->propertyIndexCacheStart; int effectiveMethodIndex = cache->methodIndexCacheStart; @@ -688,25 +699,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 @@ -751,8 +762,6 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob } } - ((QQmlVMEMetaData *)dynamicData.data())->signalCount++; - quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction | QQmlPropertyData::IsVMESignal; if (paramCount) @@ -794,14 +803,10 @@ 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; @@ -863,24 +868,17 @@ 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++; + (vmd->propertyData() + propertyIdx)->propertyType = vmePropertyType; } - // Alias property count. Actual data is setup in buildDynamicMetaAliases - ((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount; - - // Dynamic slot data - comes after the property data - VMD *vmd = (QQmlVMEMetaData *)dynamicData.data(); - vmd->methodCount = obj->functionCount(); - return true; } @@ -1301,7 +1299,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()) @@ -1333,7 +1331,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) @@ -1373,7 +1371,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) @@ -1480,7 +1478,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.")); @@ -1551,12 +1549,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 @@ -1587,21 +1581,18 @@ 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 (const 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); - const QString aliasPropertyValue = stringAt(p->aliasPropertyValueIndex); + const QString aliasPropertyValue = stringAt(alias->propertyIndex); QStringRef property; QStringRef subProperty; @@ -1642,7 +1633,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; } @@ -1656,7 +1647,7 @@ 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; } @@ -1665,7 +1656,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases() 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); @@ -1702,7 +1693,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; @@ -1712,8 +1703,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++); @@ -1825,7 +1819,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(); @@ -2545,7 +2539,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; diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index ac27124d70..27debc0ce8 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -351,7 +351,7 @@ 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 @@ -360,13 +360,20 @@ struct Property quint32 nameIndex; quint32 type : 31; quint32 flags : 1; // readonly - union { - quint32 customTypeNameIndex; // If type >= Custom - quint32 aliasIdValueIndex; // If type == Alias + quint32 customTypeNameIndex; // If type >= Custom + Location location; +}; + +struct Alias { + enum Flags { + IsReadOnly = 0x1 }; - quint32 aliasPropertyValueIndex; + quint32 nameIndex; + quint32 idIndex; + quint32 propertyIndex : 31; + quint32 flags : 1; Location location; - Location aliasLocation; // If type == Alias + Location referenceLocation; }; struct Object @@ -376,11 +383,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 +402,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 +424,11 @@ struct Object return reinterpret_cast(reinterpret_cast(this) + offsetToProperties); } + const Alias *aliasTable() const + { + return reinterpret_cast(reinterpret_cast(this) + offsetToAliases); + } + const Binding *bindingTable() const { return reinterpret_cast(reinterpret_cast(this) + offsetToBindings); diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 2ffb1596f5..b8c12f70d1 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -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) { -- cgit v1.2.3 From 7f7e2b0c9cc8e6d4f4eb18be8e5cc4053a0d4b11 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 20 May 2016 15:22:31 +0200 Subject: Simplify VME meta object meta-data For each type of VME meta object we store an array of integers holding the meta-type ids of the QML declared properties. We can replace that array with access to the QV4::CompiledData::Property entry for each property, where the type is also accessible. This is a fairly straight-forward change, except for the bit in QV4::CompilationUnit where we delay the release of the CompiledData::Unit and friends until the destructor instead of releasing it at unlink time. That should be a safe change and is necessary as there are a few tests around where the VME meta object still needs access to this meta-data at a very late stage in the life-cycle right before the deferred deletion is run. Change-Id: I431de15d12766df837c0e0251192df16a5a76868 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 11 -- src/qml/compiler/qv4compileddata.cpp | 6 +- src/qml/qml/qqmlobjectcreator.cpp | 2 +- src/qml/qml/qqmlvmemetaobject.cpp | 168 +++++++++++++++++--------- src/qml/qml/qqmlvmemetaobject_p.h | 21 ++-- src/quick/designer/qqmldesignermetaobject.cpp | 2 +- 6 files changed, 121 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index fed0ec1f37..594a0d9152 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -662,7 +662,6 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob typedef QQmlVMEMetaData VMD; QByteArray &dynamicData = vmeMetaObjects[objectIndex] = QByteArray(sizeof(QQmlVMEMetaData) - + obj->propertyCount() * sizeof(VMD::PropertyData) + obj->aliasCount() * sizeof(VMD::AliasData), 0); VMD *vmd = (QQmlVMEMetaData *)dynamicData.data(); @@ -808,16 +807,13 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob int propertyIdx = 0; for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next, ++propertyIdx) { 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; @@ -840,20 +836,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 >(); } tdata->release(); } else { if (p->type == QV4::CompiledData::Property::Custom) { propertyType = qmltype->typeId(); - vmePropertyType = QMetaType::QObjectStar; } else { propertyType = qmltype->qListTypeId(); - vmePropertyType = qMetaTypeId >(); } } @@ -874,9 +866,6 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob propertyType, effectiveSignalIndex); effectiveSignalIndex++; - - VMD *vmd = (QQmlVMEMetaData *)dynamicData.data(); - (vmd->propertyData() + propertyIdx)->propertyType = vmePropertyType; } return true; diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index a63f35152a..ded2c1a9f8 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -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; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index b8c12f70d1..8d3c5962bd 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1289,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(data.constData())); + vmeMetaObject = new QQmlVMEMetaObject(_qobject, cache, reinterpret_cast(data.constData()), compiledData->compilationUnit, _compiledObjectIndex); if (_ddata->propertyCache) _ddata->propertyCache->release(); _ddata->propertyCache = cache; diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 8211a834ec..14d2e39ccb 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -304,23 +304,25 @@ 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) + aliasEndpoints(0), compilationUnit(qmlCompilationUnit), compiledObject(0) { cache->addref(); QQmlData::get(obj)->hasVMEMetaObject = true; if (metaData->propertyCount || metaData->methodCount) { + Q_ASSERT(compilationUnit); + Q_ASSERT(qmlObjectId >= 0); + compiledObject = compilationUnit->data->objectAt(qmlObjectId); Q_ASSERT(cache && cache->engine); QV4::ExecutionEngine *v4 = cache->engine; QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, metaData->propertyCount + metaData->methodCount); 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(); } @@ -615,11 +617,11 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * if (id >= propOffset()) { id -= propOffset(); - if (id < metaData->propertyCount) { - int t = (metaData->propertyData() + id)->propertyType; + if (id < metaData->propertyCount && compiledObject) { + const QV4::CompiledData::Property::Type t = static_cast(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(); @@ -635,131 +637,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(a[0]) = readPropertyAsInt(id); break; - case QVariant::Bool: + case QV4::CompiledData::Property::Bool: *reinterpret_cast(a[0]) = readPropertyAsBool(id); break; - case QVariant::Double: + case QV4::CompiledData::Property::Real: *reinterpret_cast(a[0]) = readPropertyAsDouble(id); break; - case QVariant::String: + case QV4::CompiledData::Property::String: *reinterpret_cast(a[0]) = readPropertyAsString(id); break; - case QVariant::Url: + case QV4::CompiledData::Property::Url: *reinterpret_cast(a[0]) = readPropertyAsUrl(id); break; - case QVariant::Date: + case QV4::CompiledData::Property::Date: *reinterpret_cast(a[0]) = readPropertyAsDate(id); break; - case QVariant::DateTime: + case QV4::CompiledData::Property::DateTime: *reinterpret_cast(a[0]) = readPropertyAsDateTime(id); break; - case QVariant::RectF: + case QV4::CompiledData::Property::Rect: *reinterpret_cast(a[0]) = readPropertyAsRectF(id); break; - case QVariant::SizeF: + case QV4::CompiledData::Property::Size: *reinterpret_cast(a[0]) = readPropertyAsSizeF(id); break; - case QVariant::PointF: + case QV4::CompiledData::Property::Point: *reinterpret_cast(a[0]) = readPropertyAsPointF(id); break; - case QMetaType::QObjectStar: + case QV4::CompiledData::Property::Custom: *reinterpret_cast(a[0]) = readPropertyAsQObject(id); break; - case QMetaType::QVariant: + case QV4::CompiledData::Property::Variant: *reinterpret_cast(a[0]) = readPropertyAsVariant(id); break; - default: - { - if (t == qMetaTypeId >()) { - QList *list = readPropertyAsList(id); - QQmlListProperty *p = static_cast *>(a[0]); - *p = QQmlListProperty(object, list, - list_append, list_count, list_at, - list_clear); - p->dummy1 = this; - p->dummy2 = reinterpret_cast(quintptr(methodOffset() + id)); - } else { - QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); - if (md) { - QV4::VariantObject *v = (md->data() + id)->as(); - if (v) - QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], t); - } - } + case QV4::CompiledData::Property::CustomList: { + QList *list = readPropertyAsList(id); + QQmlListProperty *p = static_cast *>(a[0]); + *p = QQmlListProperty(object, list, + list_append, list_count, list_at, + list_clear); + p->dummy1 = this; + p->dummy2 = reinterpret_cast(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(); + 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(a[0]) != readPropertyAsInt(id); writeProperty(id, *reinterpret_cast(a[0])); break; - case QVariant::Bool: + case QV4::CompiledData::Property::Bool: needActivate = *reinterpret_cast(a[0]) != readPropertyAsBool(id); writeProperty(id, *reinterpret_cast(a[0])); break; - case QVariant::Double: + case QV4::CompiledData::Property::Real: needActivate = *reinterpret_cast(a[0]) != readPropertyAsDouble(id); writeProperty(id, *reinterpret_cast(a[0])); break; - case QVariant::String: + case QV4::CompiledData::Property::String: needActivate = *reinterpret_cast(a[0]) != readPropertyAsString(id); writeProperty(id, *reinterpret_cast(a[0])); break; - case QVariant::Url: + case QV4::CompiledData::Property::Url: needActivate = *reinterpret_cast(a[0]) != readPropertyAsUrl(id); writeProperty(id, *reinterpret_cast(a[0])); break; - case QVariant::Date: + case QV4::CompiledData::Property::Date: needActivate = *reinterpret_cast(a[0]) != readPropertyAsDate(id); writeProperty(id, *reinterpret_cast(a[0])); break; - case QVariant::DateTime: + case QV4::CompiledData::Property::DateTime: needActivate = *reinterpret_cast(a[0]) != readPropertyAsDateTime(id); writeProperty(id, *reinterpret_cast(a[0])); break; - case QVariant::RectF: + case QV4::CompiledData::Property::Rect: needActivate = *reinterpret_cast(a[0]) != readPropertyAsRectF(id); writeProperty(id, *reinterpret_cast(a[0])); break; - case QVariant::SizeF: + case QV4::CompiledData::Property::Size: needActivate = *reinterpret_cast(a[0]) != readPropertyAsSizeF(id); writeProperty(id, *reinterpret_cast(a[0])); break; - case QVariant::PointF: + case QV4::CompiledData::Property::Point: needActivate = *reinterpret_cast(a[0]) != readPropertyAsPointF(id); writeProperty(id, *reinterpret_cast(a[0])); break; - case QMetaType::QObjectStar: + case QV4::CompiledData::Property::Custom: needActivate = *reinterpret_cast(a[0]) != readPropertyAsQObject(id); writeProperty(id, *reinterpret_cast(a[0])); break; - case QMetaType::QVariant: + case QV4::CompiledData::Property::Variant: writeProperty(id, *reinterpret_cast(a[0])); break; - default: { - QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); - 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(); if (!v) { *(md->data() + id) = cache->engine->newVariantObject(QVariant()); v = (md->data() + id)->as(); - 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(); } } @@ -914,7 +964,7 @@ QV4::ReturnedValue QQmlVMEMetaObject::method(int index) 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 = propertyAndMethodStorageAsMemberData(); if (md) @@ -939,7 +989,7 @@ 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 = propertyAndMethodStorageAsMemberData(); if (!md) @@ -979,7 +1029,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value) void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) { - if ((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType) { + if (compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (!md) return; diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index cbb79f2d0c..2b1956ecfd 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -113,20 +113,8 @@ struct QQmlVMEMetaData } }; - enum { - VarPropertyType = -1 - }; - - struct PropertyData { - int propertyType; - }; - - PropertyData *propertyData() const { - return (PropertyData *)(((char *)const_cast(this)) + sizeof(QQmlVMEMetaData)); - } - AliasData *aliasData() const { - return (AliasData *)(propertyData() + propertyCount); + return (AliasData *)(((char *)const_cast(this)) + sizeof(QQmlVMEMetaData)); } }; @@ -189,7 +177,7 @@ 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; @@ -267,6 +255,11 @@ public: QList 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 compilationUnit; + const QV4::CompiledData::Object *compiledObject; }; QQmlVMEMetaObject *QQmlVMEMetaObject::get(QObject *obj) diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp index 0bfa72e9d4..05794e262b 100644 --- a/src/quick/designer/qqmldesignermetaobject.cpp +++ b/src/quick/designer/qqmldesignermetaobject.cpp @@ -157,7 +157,7 @@ void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine) } 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) -- cgit v1.2.3 From 16067fd85c720ad531f88e08a68eddd6222770f7 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 20 May 2016 15:55:34 +0200 Subject: Remove dependency of QQmlDesignerMetaObject to QQmlVMEMetaData The constructor will use "fake" VME meta data if the provided QObject has a VME meta object - that is the behavior of the vMEMetaDataForObject(object) call. The QQmlVMEMetaObject constructor will set hasVMEMetaObject to true unconditionally. By detecting the use of the fake meta data we can restore the hasVMEMetaObject flag to what it was before. As I would like to remove the VME meta-data, this patch removes the dependency to the meta data as a way of detecting the situation where we have to restore the hasVMEMetaObject flag. Instead this is done explicitly in the factor method that calls the constructor. Change-Id: I9c5cbfbd8fb41ca65c597669ee04c1c5694dee2a Reviewed-by: Lars Knoll --- src/quick/designer/qqmldesignermetaobject.cpp | 23 +++++++++-------------- src/quick/designer/qqmldesignermetaobject_p.h | 2 +- 2 files changed, 10 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp index 05794e262b..f4e31f73d1 100644 --- a/src/quick/designer/qqmldesignermetaobject.cpp +++ b/src/quick/designer/qqmldesignermetaobject.cpp @@ -79,14 +79,6 @@ struct MetaPropertyData { QVector > 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; @@ -125,7 +117,15 @@ QQmlDesignerMetaObject* QQmlDesignerMetaObject::getNodeInstanceMetaObject(QObjec return static_cast(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) @@ -148,10 +148,6 @@ void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine) cache = m_cache; } - //If our parent is not a VMEMetaObject we just se the flag to false again - if (constructedMetaData(metaData)) - QQmlData::get(object)->hasVMEMetaObject = false; - nodeInstanceMetaObjectList.insert(this, true); hasAssignedMetaObjectData = true; } @@ -165,7 +161,6 @@ 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); diff --git a/src/quick/designer/qqmldesignermetaobject_p.h b/src/quick/designer/qqmldesignermetaobject_p.h index c45f83dc1e..a5402ccbc4 100644 --- a/src/quick/designer/qqmldesignermetaobject_p.h +++ b/src/quick/designer/qqmldesignermetaobject_p.h @@ -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 m_context; -- cgit v1.2.3 From 1337e0d0827e86591e67a6dbaaeb3bd3f9ed733b Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 20 May 2016 16:21:52 +0200 Subject: Shrink QQmlVMEMetaData The count of properties, aliases, signals and methods is also accessible through CompiledData::Object. Change-Id: I4693ea672b643cdaabf752c3f0d71abdcc032395 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 11 +--- src/qml/qml/qqmlvmemetaobject.cpp | 72 ++++++++++++++++----------- src/qml/qml/qqmlvmemetaobject_p.h | 6 +-- src/quick/designer/qqmldesignermetaobject.cpp | 8 +-- 4 files changed, 46 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 594a0d9152..c18ffbd5fb 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -661,16 +661,7 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob typedef QQmlVMEMetaData VMD; - QByteArray &dynamicData = vmeMetaObjects[objectIndex] = QByteArray(sizeof(QQmlVMEMetaData) - + obj->aliasCount() * sizeof(VMD::AliasData), 0); - - VMD *vmd = (QQmlVMEMetaData *)dynamicData.data(); - // Dynamic slot data - comes after the property data - vmd->methodCount = obj->functionCount(); - // Alias property count. Actual data is setup in resolveAliases() - vmd->aliasCount = obj->aliasCount(); - vmd->signalCount = obj->signalCount(); - vmd->propertyCount = obj->propertyCount(); + vmeMetaObjects[objectIndex] = QByteArray(sizeof(QQmlVMEMetaData) + obj->aliasCount() * sizeof(VMD::AliasData), 0); int effectivePropertyIndex = cache->propertyIndexCacheStart; int effectiveMethodIndex = cache->methodIndexCacheStart; diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 14d2e39ccb..c82da696c8 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -140,11 +140,12 @@ 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 { QQmlVMEMetaData::AliasData *d = metaObject->metaData->aliasData() + aliasId; @@ -313,18 +314,19 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, QQmlData::get(obj)->hasVMEMetaObject = true; - if (metaData->propertyCount || metaData->methodCount) { - Q_ASSERT(compilationUnit); - Q_ASSERT(qmlObjectId >= 0); + if (compilationUnit && qmlObjectId >= 0) { compiledObject = compilationUnit->data->objectAt(qmlObjectId); - Q_ASSERT(cache && cache->engine); - QV4::ExecutionEngine *v4 = cache->engine; - QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, metaData->propertyCount + metaData->methodCount); - 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 (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(); + } } } @@ -613,11 +615,16 @@ 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 && compiledObject) { + if (id < propertyCount) { const QV4::CompiledData::Property::Type t = static_cast(compiledObject->propertyTable()[id].type); bool needActivate = false; @@ -822,9 +829,9 @@ 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) { QQmlVMEMetaData::AliasData *d = metaData->aliasData() + id; @@ -884,8 +891,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; @@ -893,7 +899,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 @@ -950,7 +956,7 @@ 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(); } @@ -959,7 +965,7 @@ QV4::ReturnedValue QQmlVMEMetaObject::method(int index) if (!md) return QV4::Encode::undefined(); - return (md->data() + index + metaData->propertyCount)->asReturnedValue(); + return (md->data() + index + compiledObject->nProperties)->asReturnedValue(); } QV4::ReturnedValue QQmlVMEMetaObject::readVarProperty(int id) @@ -1085,8 +1091,10 @@ QV4::ReturnedValue QQmlVMEMetaObject::vmeMethod(int index) 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); } @@ -1097,14 +1105,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 (!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; QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (!md) return; - *(md->data() + methodIndex + metaData->propertyCount) = function; + *(md->data() + methodIndex + compiledObject->nProperties) = function; } QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index) @@ -1147,7 +1157,7 @@ void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e) 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; @@ -1156,7 +1166,7 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, if (!ctxt) return false; - QQmlVMEMetaData::AliasData *d = metaData->aliasData() + (index - propOffset() - metaData->propertyCount); + QQmlVMEMetaData::AliasData *d = metaData->aliasData() + (index - propOffset() - compiledObject->nProperties); *target = ctxt->idValues[d->contextIdx].data(); if (!*target) return false; @@ -1174,8 +1184,9 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, 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; @@ -1193,8 +1204,9 @@ void QQmlVMEMetaObject::connectAlias(int aliasId) 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); diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 2b1956ecfd..77b4e4de98 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -78,11 +78,8 @@ QT_BEGIN_NAMESPACE 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; @@ -256,6 +253,7 @@ public: 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 compilationUnit; diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp index f4e31f73d1..63b4102b10 100644 --- a/src/quick/designer/qqmldesignermetaobject.cpp +++ b/src/quick/designer/qqmldesignermetaobject.cpp @@ -81,13 +81,7 @@ struct MetaPropertyData { 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) -- cgit v1.2.3 From 81dfb0bdebb5432828f77eb4c0b1eb3a8366d8de Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 23 May 2016 10:38:33 +0200 Subject: Remove QQmlVMEMetaData::AliasData::contextIdx We can store the id (in QQmlContextData::idValues) for the alias target in the QV4::CompiledData::Alias. Change-Id: I3f32648aef28d96ddedff6b3d2cde75969a46fa1 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlirbuilder_p.h | 2 +- src/qml/compiler/qqmltypecompiler.cpp | 10 ++++++---- src/qml/compiler/qv4compileddata_p.h | 14 +++++++++----- src/qml/qml/qqmlvmemetaobject.cpp | 16 ++++++++++------ src/qml/qml/qqmlvmemetaobject_p.h | 1 - 5 files changed, 26 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index 060c888cd8..c53004a331 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -283,7 +283,7 @@ public: const Property *firstProperty() const { return properties->first; } int propertyCount() const { return properties->count; } - const Alias *firstAlias() const { return aliases->first; } + 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; } diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index c18ffbd5fb..c2420063b9 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1562,15 +1562,17 @@ bool QQmlComponentAndAliasResolver::resolveAliases() int effectiveAliasIndex = 0; int aliasIndex = 0; - for (const QmlIR::Alias *alias = obj->firstAlias(); alias; alias = alias->next, ++aliasIndex) { + 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(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(alias->propertyIndex); @@ -1663,7 +1665,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases() } } - QQmlVMEMetaData::AliasData aliasData = { targetId, propIdx, propType, flags, notifySignal }; + QQmlVMEMetaData::AliasData aliasData = { propIdx, propType, flags, notifySignal }; typedef QQmlVMEMetaData VMD; QByteArray &dynamicData = (*vmeMetaObjectData)[objectIndex]; diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 27debc0ce8..6239c96312 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -366,12 +366,16 @@ struct Property struct Alias { enum Flags { - IsReadOnly = 0x1 + IsReadOnly = 0x1, + Resolved = 0x2 }; - quint32 nameIndex; - quint32 idIndex; - quint32 propertyIndex : 31; - quint32 flags : 1; + quint32 nameIndex : 30; + quint32 flags : 2; + union { + quint32 idIndex; // string index + quint32 targetObjectId; // object id index (in QQmlContextData::idValues) + }; + quint32 propertyIndex; Location location; Location referenceLocation; }; diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index c82da696c8..54a9566162 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -148,10 +148,11 @@ void QQmlVMEMetaObjectEndpoint::tryConnect() 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()) { QQmlContextData *ctxt = metaObject->ctxt; - QObject *target = ctxt->idValues[d->contextIdx].data(); + QObject *target = ctxt->idValues[aliasData->targetObjectId].data(); if (!target) return; @@ -834,6 +835,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * if (id < aliasCount) { QQmlVMEMetaData::AliasData *d = metaData->aliasData() + id; + const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[id]; if (d->flags & QML_ALIAS_FLAG_PTR && c == QMetaObject::ReadProperty) *reinterpret_cast(a[0]) = 0; @@ -843,7 +845,7 @@ 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; @@ -1166,8 +1168,10 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, if (!ctxt) return false; - QQmlVMEMetaData::AliasData *d = metaData->aliasData() + (index - propOffset() - compiledObject->nProperties); - *target = ctxt->idValues[d->contextIdx].data(); + const int aliasId = index - propOffset() - compiledObject->nProperties; + const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[aliasId]; + QQmlVMEMetaData::AliasData *d = metaData->aliasData() + aliasId; + *target = ctxt->idValues[aliasData->targetObjectId].data(); if (!*target) return false; @@ -1188,7 +1192,7 @@ void QQmlVMEMetaObject::connectAlias(int aliasId) if (!aliasEndpoints) 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()) { @@ -1198,7 +1202,7 @@ void QQmlVMEMetaObject::connectAlias(int aliasId) } endpoint->metaObject = this; - endpoint->connect(&ctxt->idValues[d->contextIdx].bindings); + endpoint->connect(&ctxt->idValues[aliasData->targetObjectId].bindings); endpoint->tryConnect(); } diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 77b4e4de98..ddd1243b54 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -82,7 +82,6 @@ struct QQmlVMEMetaData int dummy; struct AliasData { - int contextIdx; int propertyIdx; int propType; int flags; -- cgit v1.2.3 From 46c6db6f58fadb2bc4d3e9be5a7f93824e43db64 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 23 May 2016 14:15:47 +0200 Subject: Shrink QQmlVMEMetaData::AliasData We can retrieve the alias property index from the QV4::CompiledData::Alias and the property type from the property cache (only needed for aliases to value types). Change-Id: Ibf0cb909a4cd1ce1c2d67b57e1be1de491d4d598 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlirbuilder.cpp | 4 ++-- src/qml/compiler/qqmltypecompiler.cpp | 8 +++---- src/qml/compiler/qv4compileddata_p.h | 10 ++++++++- src/qml/qml/qqmlvmemetaobject.cpp | 41 +++++++++++++++++++---------------- src/qml/qml/qqmlvmemetaobject_p.h | 23 -------------------- 5 files changed, 36 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index ac59c04e87..a1713dd809 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1133,7 +1133,7 @@ bool IRBuilder::appendAlias(QQmlJS::AST::UiPublicMember *node) alias->location.line = loc.startLine; alias->location.column = loc.startColumn; - alias->propertyIndex = emptyStringIndex; + alias->propertyNameIndex = emptyStringIndex; if (!node->statement && !node->binding) COMPILE_EXCEPTION(loc, tr("No property alias location")); @@ -1171,7 +1171,7 @@ bool IRBuilder::appendAlias(QQmlJS::AST::UiPublicMember *node) QString propertyValue = aliasReference.value(1); if (aliasReference.count() == 3) propertyValue += QLatin1Char('.') + aliasReference.at(2); - alias->propertyIndex = registerString(propertyValue); + alias->propertyNameIndex = registerString(propertyValue); QQmlJS::AST::SourceLocation errorLocation; QString error; diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index c2420063b9..cc8043ea4e 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1574,7 +1574,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases() Q_ASSERT(_objectIndexToIdInScope->contains(targetObjectIndex)); alias->targetObjectId = _objectIndexToIdInScope->value(targetObjectIndex); - const QString aliasPropertyValue = stringAt(alias->propertyIndex); + const QString aliasPropertyValue = stringAt(alias->propertyNameIndex); QStringRef property; QStringRef subProperty; @@ -1587,7 +1587,6 @@ bool QQmlComponentAndAliasResolver::resolveAliases() property = QStringRef(&aliasPropertyValue, 0, aliasPropertyValue.length()); int propIdx = -1; - int propType = 0; int notifySignal = -1; int flags = 0; int type = 0; @@ -1633,8 +1632,6 @@ bool QQmlComponentAndAliasResolver::resolveAliases() return false; } - propType = type; - int valueTypeIndex = valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData()); if (valueTypeIndex == -1) { @@ -1665,7 +1662,8 @@ bool QQmlComponentAndAliasResolver::resolveAliases() } } - QQmlVMEMetaData::AliasData aliasData = { propIdx, propType, flags, notifySignal }; + alias->encodedMetaPropertyIndex = propIdx; + QQmlVMEMetaData::AliasData aliasData = { flags, notifySignal }; typedef QQmlVMEMetaData VMD; QByteArray &dynamicData = (*vmeMetaObjectData)[objectIndex]; diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 6239c96312..c3a20e9366 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -375,9 +375,17 @@ struct Alias { quint32 idIndex; // string index quint32 targetObjectId; // object id index (in QQmlContextData::idValues) }; - quint32 propertyIndex; + union { + quint32 propertyNameIndex; // string index + qint32 encodedMetaPropertyIndex; + }; Location location; Location referenceLocation; + + bool isObjectAlias() const { + Q_ASSERT(flags & Resolved); + return encodedMetaPropertyIndex == -1; + } }; struct Object diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 54a9566162..bb02c2c218 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -150,7 +150,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect() } 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[aliasData->targetObjectId].data(); if (!target) @@ -851,36 +851,46 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * connectAlias(id); - if (d->isObjectAlias()) { + if (aliasData->isObjectAlias()) { *reinterpret_cast(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(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); } } @@ -1170,19 +1180,12 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, const int aliasId = index - propOffset() - compiledObject->nProperties; const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[aliasId]; - QQmlVMEMetaData::AliasData *d = metaData->aliasData() + 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; } diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index ddd1243b54..d70ee88b20 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -82,31 +82,8 @@ struct QQmlVMEMetaData int dummy; struct AliasData { - 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; - } }; AliasData *aliasData() const { -- cgit v1.2.3 From ec2b2a5f5d804095b6b2b8575b1cd1b75a8335ff Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 23 May 2016 14:29:43 +0200 Subject: Fold QQmlVMEMetaData::Alias::flags into QV4::CompiledData::Alias::flags We only need one bit, so this is easy to merge. Change-Id: I98bf882b8c1bf10f2172a9e22331d621985d3ed4 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 7 +++---- src/qml/compiler/qv4compileddata_p.h | 7 ++++--- src/qml/qml/qqmlvmemetaobject.cpp | 4 +--- src/qml/qml/qqmlvmemetaobject_p.h | 3 --- 4 files changed, 8 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index cc8043ea4e..097d072734 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1588,7 +1588,6 @@ bool QQmlComponentAndAliasResolver::resolveAliases() int propIdx = -1; int notifySignal = -1; - int flags = 0; int type = 0; bool writable = false; bool resettable = false; @@ -1605,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); @@ -1657,13 +1656,13 @@ bool QQmlComponentAndAliasResolver::resolveAliases() propertyFlags |= QQmlPropertyData::IsQVariant; if (targetProperty->isQObject()) - flags |= QML_ALIAS_FLAG_PTR; + alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject; } } } alias->encodedMetaPropertyIndex = propIdx; - QQmlVMEMetaData::AliasData aliasData = { flags, notifySignal }; + QQmlVMEMetaData::AliasData aliasData = { notifySignal }; typedef QQmlVMEMetaData VMD; QByteArray &dynamicData = (*vmeMetaObjectData)[objectIndex]; diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index c3a20e9366..3c2d895bff 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -367,10 +367,11 @@ struct Property struct Alias { enum Flags { IsReadOnly = 0x1, - Resolved = 0x2 + Resolved = 0x2, + AliasPointsToPointerObject = 0x4 }; - quint32 nameIndex : 30; - quint32 flags : 2; + quint32 nameIndex : 29; + quint32 flags : 3; union { quint32 idIndex; // string index quint32 targetObjectId; // object id index (in QQmlContextData::idValues) diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index bb02c2c218..b0b7995ae2 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -833,11 +833,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * id -= propertyCount; if (id < aliasCount) { - - QQmlVMEMetaData::AliasData *d = metaData->aliasData() + id; const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[id]; - if (d->flags & QML_ALIAS_FLAG_PTR && c == QMetaObject::ReadProperty) + if ((aliasData->flags & QV4::CompiledData::Alias::AliasPointsToPointerObject) && c == QMetaObject::ReadProperty) *reinterpret_cast(a[0]) = 0; if (!ctxt) return -1; diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index d70ee88b20..f9f9ec47af 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -74,15 +74,12 @@ QT_BEGIN_NAMESPACE -#define QML_ALIAS_FLAG_PTR 0x00000001 - struct QQmlVMEMetaData { // Make sure this structure is always aligned to int int dummy; struct AliasData { - int flags; int notifySignal; }; -- cgit v1.2.3