Changes to Qt QML | Qt Qml | Qt 6.11.0
Description: Migrate Qt QML to Qt 6.

- Qt 6.11
- Qt Qml
- Changes to Qt QML
- Qt 6.11.0 Reference Documentation

Memory Management in the JavaScript Engine

# Changes to Qt QML

Qt 6 is a result of the conscious effort to make the framework more efficient and easy to use.

We try to maintain binary and source compatibility for all the public APIs in each release. But some changes were inevitable in an effort to make Qt a better framework.

In this topic we summarize those changes in Qt QML, and provide guidance to handle them.

## QML language

### URL resolution

In Qt 5, relative urls were often, albeit inconsistently, directly resolved, especially when assigned to an url property. In Qt 6 this is no longer the case.

If you had a QML file stored under "/home/qml/example.qml", and "example.qml" contained

     property url imageFolder: "./images"

then the url property would store the URL "/home/qml/images". This made it impossible to use relative URLs in QML in this way, so in Qt 6, the URL stays relative, and only gets resolved when this is required (e.g. when it is used as the source of an Image component). If you depend on the old behavior, you can use `Qt.resolvedUrl`

For example, if you have code like

     property url imageFolder: "./images"

you can rewrite it as

     property url imageFolder: Qt.resolvedUrl("./images")

Qt.resolvedUrl can be used in both Qt 5 and 6.

As a porting aid, the `QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT` environment variable can be set to 1 to obtain the Qt 5 behavior. This is possible since Qt 6.2.2. However, it is recommended to only use this to unblock a port, and to use `Qt.resolvedUrl` as explained above.

### Variant Properties

`variant` properties, which have been marked as obsolete since Qt 5, are now treated in exactly the same way as `var` properties. Code that relied on implicit string conversion triggered on assignment to variant properties should be updated to explicitly create an object of the correct type.

For example, if you have code like

     property variant myColor: "red"

you can rewrite it as

     property variant myColor: Qt.color("red")

Implicit conversions were done for strings that could be parsed as

- color (use Qt.color instead),
- date (use the Date object instead),
- rect (use Qt.rect instead) and
- size (use Qt.size instead)

`variant` still remains a deprecated keyword in Qt 6, though new code is strongly encouraged to use `var` properties instead.

Note: If the type of the property is known not to change, use a property of the concrete type, instead of a `var` property.

Note: These conversions were also applied to `QVariant` properties of classes registered with the engine. As with `variant` properties, code that relied on implicit string conversions need to use the corresponding functions of the Qt object.

## Source Incompatible API Changes

### Changed API

`QQmlListProperty`'s `CountFunction` and `AtFunction` have been changed to use `qsizetype` instead of `int` to align with the corresponding changes in Qt's containers.

For example, if you have code like

     int myCountFunction(QQmlListProperty<MyType> *);
     MyType *myAtFunction(QQmlListProperty<MyType> *, int);

     QQmlListProperty<MyType> myReadOnlyList(containingObject, container, &myCountFunction,
                                             &myAtFunction);

you can rewrite it as

     qsizetype myCountFunction(QQmlListProperty<MyType> *);
     MyType *myAtFunction(QQmlListProperty<MyType> *, qsizetype);

     QQmlListProperty<MyType> myReadOnlyList(containingObject, container, &myCountFunction,
                                             &myAtFunction);

Code which needs to supports both Qt 5 and Qt 6 can either use a typedef which is `int` in Qt 5 and `qsizetype` in Qt 6, or use `QList::size_type`, which already is such a type alias.

### Removed API

Various deprecated functions have been removed.

- The QQmlListProperty constructor taking a reference has been removed.

  For example, if you have code like

       QQmlListProperty<QObject>(owner, owner->objectList);

  you can rewrite it as

       QQmlListProperty<QObject>(owner, &owner->objectList);

- The functions `qmlDebug`, `qmlInfo`, `qmlWarning`, `qmlContext` and `qmlEngine` used to exist both in the global namespace (or Qt namespace in namespaced builds), and in the `QtQml` namespace. These functions now exist only in the global namespace.

  For example, if you have code like

       QQmlEngine *engine = QtQml::qmlEngine(qmlObject);

  you can rewrite it as

       QQmlEngine *engine = qmlEngine(qmlObject);

- The `qmlRegisterType` overload taking no arguments has been removed. Use `qmlRegisterAnonymousType` instead, or switch to declarative type registration with `QML_ANONYMOUS`.

  For example, if you have code like

       class AnonymousType : public QObject {
         // ...
       };

       qmlRegisterType<AnonymousType>();

  you can rewrite it as

       class AnonymousType : public QObject {
         // ...
       };

       qmlRegisterAnonymousType<AnonymousType>("MyModule", 1);

  Or alternatively

       class AnonymousType : public QObject {
           QML_ANONYMOUS
           // ...
       };

- The overloads of `qmlRegisterExtendedType` and `qmlRegisterInterface` which take no version argument have been removed. Use the overloads providing a version, or switch to declarative type registration with QML_EXTENDED and QML_INTERFACE.

  For example, if you have code like

       struct GreetInterface
       {
          virtual ~GreetInterface();
          virtual void greet();
       };
       Q_DECLARE_INTERFACE(GreetInterface, "org.hi.GreetInterface")

       qmlRegisterInterface<GreetInterface>("Greeter");

  you can rewrite it as

       struct GreetInterface
       {
          virtual ~GreetInterface();
          virtual void greet();
       };
       Q_DECLARE_INTERFACE(GreetInterface, "org.hi.GreetInterface")

       qmlRegisterInterface<GreetInterface>("Greeter", 1);

  Alternatively

       struct GreetInterface
       {
          QML_INTERFACE(Greeter)
          virtual ~GreetInterface();
          virtual void greet();
       };
       Q_DECLARE_INTERFACE(GreetInterface, "org.hi.GreetInterface")

  Note: In new code, declarative type registration should be preferred.

- The function `QJSValue::engine` has been removed. If access to the engine is required, a reference to it must be stored instead.
- `qmlAttachedPropertiesObjectById` and `qmlAttachedPropertiesObject(int *, const QObject *, const QMetaObject *, bool)` have been removed. Use the `qmlAttachedPropertiesObject(QObject *, QQmlAttachedPropertiesFunc, bool)` overload of `qmlAttachedPropertiesObject` instead.
- `QJSEngine::installTranslatorFunctions` has been removed. `QJSEngine::installExtensions` is available as a replacement.

  For example, if you have code like

       QJSEngine engine;
       engine.installTranslatorFunctions();

  you can rewrite it as

       QJSEngine engine;
       engine.installExtensions(QJSEngine::TranslationExtension);

See also Modernizing QML Modules and Port QML modules to CMake.

Memory Management in the JavaScript Engine