qqmlintegration.h Proxy Page

Macros

Macro Documentation

QML_ADDED_IN_VERSION(MAJOR, MINOR)

Declares that the enclosing type or namespace was added in the specified MAJOR.MINOR version. The version is assumed to be in line with any revisions given by Q_REVISION() macros on methods, slots, or signals, and any REVISION() attributes on properties declared with Q_PROPERTY().

QML_ADDED_IN_VERSION() only takes effect if the type or namespace is available in QML, by having a QML_ELEMENT, QML_NAMED_ELEMENT(), QML_ANONYMOUS, or QML_INTERFACE macro.

If the QML module the type belongs to is imported with a lower version than the one determined this way, the QML type is invisible.

See also QML_ELEMENT and QML_NAMED_ELEMENT.

QML_ANONYMOUS

Declares the enclosing type to be available, but anonymous in QML. The type cannot be created or used to declare properties in QML, but when passed from C++, it is recognized. In QML, you can use properties of this type if they are declared in C++.

See also QML_ELEMENT, QML_NAMED_ELEMENT(), QML_UNCREATABLE(), and QML_INTERFACE.

QML_ATTACHED(ATTACHED_TYPE)

Declares that the enclosing type attaches ATTACHED_TYPE as an attached property to other types. This takes effect if the type is exposed to QML using a QML_ELEMENT or QML_NAMED_ELEMENT() macro.

Note: The class name needs to be fully qualified, even if you're already inside the namespace.

See also QML_ELEMENT, QML_NAMED_ELEMENT(), qmlAttachedPropertiesObject(), and Providing Attached Properties.

[since 6.5] QML_CONSTRUCTIBLE_VALUE

Marks the surrounding value type as constructible. That is, any Q_INVOKABLE constructors of the type that take exactly one argument can be used when assigning a JavaScript value to a property of this type.

You can declare a constructible value type as follows:

class MyValueType
{
    Q_GADGET
    QML_VALUE_TYPE(myValueType)
    QML_CONSTRUCTIBLE_VALUE
public:
    Q_INVOKABLE MyValueType(double d);

    // ...
};

With the above type, the following QML code will produce a MyValueType value using the given constructor and assign it to the property.

QtObject {
    property myValueType v: 5.4
}

You can also construct lists of values this way:

QtObject {
    property list<myValueType> v: [5.4, 4.5, 3.3]
}

If you make value types addressable, you can use such a type in a type assertion to explicitly construct it:

pragma ValueTypeBehavior: Addressable

QtObject {
    function process(d: real) {
        let v = d as myValueType;
        // v is a myValueType now, not a number
    }
}

This macro was introduced in Qt 6.5.

See also QML_VALUE_TYPE.

QML_ELEMENT

Declares the enclosing type or namespace to be available in QML, using its class or namespace name as the QML element name.

For example, this makes the C++ class Slider available as a QML type named Slider. All its properties, invokable methods and enums are exposed.

class Slider : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged FINAL)
    // ...
public:
    enum Slippiness {
        Dry, Wet, Icy
    };
    Q_ENUM(Slippiness)

    Q_INVOKABLE void slide(Slippiness slippiness);

    // ...
}

You can use the build system to register the type in the type namespace com.mycompany.qmlcomponents with major version 1. For qmake, specify the following in your project file:

CONFIG += qmltypes
QML_IMPORT_NAME = com.mycompany.qmlcomponents
QML_IMPORT_MAJOR_VERSION = 1

With CMake, you pass the URI and version to qt_add_qml_module

qt6_add_qml_module(myapp
  URI com.mycompany.qmlcomponents
  VERSION 1.0
)

Once registered, the type can be used in QML by importing the same type namespace and version number:

import com.mycompany.qmlcomponents 1.0

Slider {
    value: 12
    Component.onCompleted: slide(Slider.Icy)

    // ...
}

You can also make namespaces tagged with Q_NAMESPACE available this way, in order to expose any enums tagged with Q_ENUM_NS they contain:

namespace MyNamespace {
  Q_NAMESPACE
  QML_ELEMENT

  enum MyEnum {
      Key1,
      Key2,
  };
  Q_ENUM_NS(MyEnum)
}

In QML, you can then use the enums:

Component.onCompleted: console.log(MyNamespace.Key2)

NOTE: When classes have the same name but are located in different namespaces using QML_ELEMENT on both of them will cause a conflict. Make sure to use QML_NAMED_ELEMENT() for one of them instead.

Note: The class name needs to be fully qualified, even if you're already inside the namespace.

See also Choosing the Correct Integration Method Between C++ and QML, QML_NAMED_ELEMENT(), Q_REVISION(), and QML_ADDED_IN_VERSION().

QML_EXTENDED(EXTENDED_TYPE)

Declares that the enclosing type uses EXTENDED_TYPE as an extension to provide further properties, methods, and enumerations in QML. This takes effect if the type is exposed to QML using a QML_ELEMENT or QML_NAMED_ELEMENT() macro.

Warning: Members of EXTENDED_TYPE are implicitly treated as FINAL.

Note: The class name needs to be fully qualified, even if you're already inside the namespace.

See also QML_ELEMENT, QML_NAMED_ELEMENT(), QML_EXTENDED_NAMESPACE(), and Registering Extension Objects.

QML_EXTENDED_NAMESPACE(EXTENDED_NAMESPACE)

Declares that the enclosing type uses EXTENDED_NAMESPACE as an extension to provide further enumerations in QML. This takes effect if the type is exposed to QML using a QML_ELEMENT or QML_NAMED_ELEMENT() macro. The enumerations need to be exposed to the metaobject system for this to work.

For example, give the following C++ code

namespace MyNamespace {
    Q_NAMESPACE
    enum MyEnum { MyEnumerator = 10 };
    Q_ENUM_NS(MyEnum)
}

class QmlType : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    QML_EXTENDED_NAMESPACE(MyNamespace)
}

we can access the enum in QML:

QmlType {
    property int i: QmlType.MyEnumerator // i will be 10
}

Note: EXTENDED_NAMESPACE can also be a QObject or QGadget; in that case - and in contrast to QML_EXTENDED, which also exposes methods and properties - only its enumerations are exposed.

Note: EXTENDED_NAMESPACE must have a metaobject; i.e. it must either be a namespace which contains the Q_NAMESPACE macro or a QObject/QGadget.

Note: The class name needs to be fully qualified, even if you're already inside the namespace.

See also QML_ELEMENT, QML_NAMED_ELEMENT(), QML_EXTENDED(), Registering Extension Objects, Q_ENUM, and Q_ENUM_NS.

QML_EXTRA_VERSION(MAJOR, MINOR)

Declare that the type should also be available in version MAJOR.MINOR. This can be helpful if a type should be available in multiple major versions.

Types are automatically registered for:

  • The major version they were introduced in, see QML_ADDED_IN_VERSION.
  • Any major versions any their members were introduced in.
  • The current major version of their module, unless they were QML_REMOVED_IN_VERSION before that.

Notably, they are not automatically registered in any PAST_MAJOR_VERSIONS between the above. You can use QML_EXTRA_VERSION to manually register your types in further major versions.

Note: Keeping multiple PAST_MAJOR_VERSIONS around is computationally expensive.

See also QML_ELEMENT and QML_ADDED_IN_VERSION.

QML_FOREIGN(FOREIGN_TYPE)

Declares that any QML_ELEMENT, QML_NAMED_ELEMENT(), QML_ANONYMOUS, QML_INTERFACE, QML_UNCREATABLE(), QML_SINGLETON, QML_ADDED_IN_VERSION(), QML_REMOVED_IN_VERSION(), QML_ADDED_IN_MINOR_VERSION(), QML_REMOVED_IN_MINOR_VERSION(), QML_EXTENDED(), or QML_EXTENDED_NAMESPACE() macros in the enclosing C++ type do not apply to the enclosing type but instead to FOREIGN_TYPE. The enclosing type still needs to be registered with the meta object system using a Q_GADGET or Q_OBJECT macro.

This is useful for registering types that cannot be amended to add the macros, for example because they belong to 3rdparty libraries. To register a namespace, see QML_FOREIGN_NAMESPACE().

Note: You may want to use QML_NAMED_ELEMENT() instead of QML_ELEMENT. With QML_ELEMENT, the element is named after the struct it is contained in, not the foreign type. The Foreign objects integration chapter in Writing advanced QML Extensions with C++ demonstrates this.

Note: QML_ATTACHED() can currently not be redirected like this. It has to be specificed in the same type that implements qmlAttachedProperties().

Note: The class name needs to be fully qualified, even if you're already inside the namespace.

See also QML_ELEMENT, QML_NAMED_ELEMENT(), and QML_FOREIGN_NAMESPACE().

QML_FOREIGN_NAMESPACE(FOREIGN_NAMESPACE)

Declares that any QML_ELEMENT, QML_NAMED_ELEMENT(), QML_ANONYMOUS, QML_INTERFACE, QML_UNCREATABLE(), QML_SINGLETON, QML_ADDED_IN_VERSION(), QML_REMOVED_IN_VERSION(), QML_ADDED_IN_MINOR_VERSION(), or QML_REMOVED_IN_MINOR_VERSION() macros in the enclosing C++ namespace do not apply to the enclosing type but instead to FOREIGN_NAMESPACE. The enclosing namespace still needs to be registered with the meta object system using a Q_NAMESPACE macro.

This is useful for registering namespaces that cannot be amended to add the macros, for example because they belong to 3rdparty libraries.

See also QML_ELEMENT, QML_NAMED_ELEMENT(), and QML_FOREIGN().

QML_IMPLEMENTS_INTERFACES(interfaces)

This macro tells Qt which QML interfaces the class implements. This macro should only be used for interfacing with classes using QML_INTERFACE, use Q_INTERFACES otherwise. It's required in order for declarative registration via QML_ELEMENT to function properly.

See also QML_INTERFACE and Q_INTERFACES.

QML_INTERFACE

This macro registers the enclosing C++ type in the QML system as an interface.

Types registered as an interface in QML should also declare themselves as an interface with the meta object system. For example:

struct FooInterface
{
    QML_INTERFACE
public:
    virtual ~FooInterface();
    virtual void doSomething() = 0;
};

Q_DECLARE_INTERFACE(FooInterface, "org.foo.FooInterface")

When registered with QML in this way, they can be used as property types:

Q_PROPERTY(FooInterface *foo READ foo WRITE setFoo)

When you assign a QObject sub-class to this property, the QML engine does the interface cast to FooInterface* automatically.

Interface types are implicitly anonymous and uncreatable in QML.

NOTE: When inheriting from types using QML_INTERFACE, use QML_IMPLEMENTS_INTERFACES instead of Q_INTERFACES.

See also QML_IMPLEMENTS_INTERFACES(), QML_ELEMENT, QML_NAMED_ELEMENT(), QML_UNCREATABLE(), and QML_ANONYMOUS.

QML_NAMED_ELEMENT(name)

Declares the enclosing type or namespace to be available in QML, using name as the element name. Otherwise behaves the same as QML_ELEMENT.

class SqlEventDatabase : public QObject
{
    Q_OBJECT
    QML_NAMED_ELEMENT(EventDatabase)

    // ...
};

See also Choosing the Correct Integration Method Between C++ and QML and QML_ELEMENT.

QML_REMOVED_IN_VERSION(MAJOR, MINOR)

Declares that the enclosing type or namespace was removed in the specified MAJOR.MINOR version. This is primarily useful when replacing the implementation of a QML type. If a corresponding QML_ADDED_IN_VERSION() is present on a different type or namespace of the same QML name, then the removed type is used when importing versions of the module lower than MAJOR.MINOR, and the added type is used when importing versions of the module greater or equal MAJOR.MINOR.

QML_REMOVED_IN_VERSION() only takes effect if type or namespace is available in QML, by having a QML_ELEMENT, QML_NAMED_ELEMENT(), QML_ANONYMOUS, or QML_INTERFACE macro.

See also QML_ELEMENT and QML_NAMED_ELEMENT.

QML_SEQUENTIAL_CONTAINER(VALUE_TYPE)

This macro declares the enclosing or referenced type as a sequential container managing a sequence of VALUE_TYPE elements. VALUE_TYPE can be an actual value type or a pointer to an object type. You will rarely be able to add this macro to the actual container declaration since containers are usually templates. You should use QML_FOREIGN to attach the type registration to a template instantiation. Using this technique you can, for example, declare sequential containers like this:

class IntDequeRegistration
{
  Q_GADGET
  QML_FOREIGN(std::deque<int>)
  QML_ANONYMOUS
  QML_SEQUENTIAL_CONTAINER(int)
};

After this, you can use the container like a JavaScript array in QML.

class Maze
{
  Q_OBJECT
  Q_ELEMENT
  // 0: North, 1: East, 2: South, 3: West
  Q_PROPERTY(std::deque<int> solution READ solution CONSTANT FINAL)
  [...]
}
Item {
  Maze {
    id: maze
  }

  function showSolution() {
      maze.solution.forEach([...])
  }
}

Note: For QML Value Types QList is automatically registered as sequential container. For QML Object Types QQmlListProperty is. You don't have to add these registrations.

Note: You cannot currently give the container a custom name. Any argument passed to QML_NAMED_ELEMENT is ignored. The automatically registered sequential containers are available under the familiar list<...> names, for example list<QtObject> or list<font>.

Note: The class name needs to be fully qualified, even if you're already inside the namespace.

See also QML_ANONYMOUS and QML_FOREIGN().

QML_SINGLETON

Declares the enclosing type to be a singleton in QML. This only takes effect if the type is a Q_OBJECT and is available in QML (by having a QML_ELEMENT or QML_NAMED_ELEMENT() macro). By default, each QQmlEngine will try to create a singleton instance using either the type's default constructor or a static factory function of the signature T *create(QQmlEngine *, QJSEngine *) when the type is first accessed. If both do exist and are accessible, the default constructor is preferred. If there is no default constructor and no factory function the singleton is inaccessible. The QML engine generally assumes ownership of the singleton and will delete it when the engine itself is destroyed. You can prevent this by calling QJSEngine::setObjectOwnership() on the singleton.

In order to declare a default-constructible class as singleton, all you have to do is add QML_SINGLETON:

class MySingleton : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    QML_SINGLETON
    // Q_PROPERTY( ... )
public:
    // members, Q_INVOKABLE functions, etc.
};

If the singleton class is not default-constructible, but you can modify it, you can add a factory function to it, in order to make it accessible:

class MySingleton : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    QML_SINGLETON
    // Q_PROPERTY( ... )

public:
    static MySingleton *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
    {
        MySingleton *result = nullptr;
        // Create the object using some custom constructor or factory.
        // The QML engine will assume ownership and delete it, eventually.
        return result;
    }

    // members, Q_INVOKABLE functions, etc
};

If you cannot modify the class and it does not have a default constructor or a suitable factory function, you can provide a QML_FOREIGN wrapper to define the factory function:

struct SingletonForeign
{
    Q_GADGET
    QML_FOREIGN(MySingleton)
    QML_SINGLETON
    QML_NAMED_ELEMENT(MySingleton)
public:

    static MySingleton *create(QQmlEngine *, QJSEngine *engine)
    {
        MySingleton *result = nullptr;
        // Create the instance using some custom constructor or factory.
        // The QML engine will assume ownership and delete it, eventually.
        return result;
    }
};

Finally, if you want to provide one specific singleton object, the creation of which you cannot control, you can return that from a factory function. This is a replacement for the qmlRegisterSingletonInstance function. If you were calling

qmlRegisterSingletonInstance("MyModule", 1, 0, "MySingleton", myObject);

with myObject being of type MySingleton *, you can do the following instead:

struct SingletonForeign
{
    Q_GADGET
    QML_FOREIGN(MySingleton)
    QML_SINGLETON
    QML_NAMED_ELEMENT(MySingleton)
public:

    // Initialize this using myObject where you would previously
    // call qmlRegisterSingletonInstance().
    inline static MySingleton *s_singletonInstance = nullptr;

    static MySingleton *create(QQmlEngine *, QJSEngine *engine)
    {
        // The instance has to exist before it is used. We cannot replace it.
        Q_ASSERT(s_singletonInstance);

        // The engine has to have the same thread affinity as the singleton.
        Q_ASSERT(engine->thread() == s_singletonInstance->thread());

        // There can only be one engine accessing the singleton.
        if (s_engine)
            Q_ASSERT(engine == s_engine);
        else
            s_engine = engine;

        // Explicitly specify C++ ownership so that the engine doesn't delete
        // the instance.
        QJSEngine::setObjectOwnership(s_singletonInstance,
                                      QJSEngine::CppOwnership);
        return s_singletonInstance;
    }

private:
    inline static QJSEngine *s_engine = nullptr;
};

This way, the pre-existing class MySingleton is declared to be a QML singleton, called MySingleton. You can specify an instance for it any time before it is used by setting the s_singletonInstance member. None of this requires modification of MySingleton itself.

Note: This pattern doesn't work if either the singleton is accessed by multiple QML engines, or if the QML engine accessing it has a different thread affinity than the singleton object itself. As shown above, you can check the parameters to the create() method for identity and thread affinity of the engine in order to assert on that.

See also QML_ELEMENT, QML_NAMED_ELEMENT(), qmlRegisterSingletonInstance(), QQmlEngine::singletonInstance(), and Singletons in QML.

[since 6.5] QML_STRUCTURED_VALUE

Marks the surrounding value type as structured. Structured value types can and will preferably be constructed property-by-property from a JavaScript object. A structured value type, however is always QML_CONSTRUCTIBLE_VALUE, too. This means, you can still provide Q_INVOKABLE constructors in order to handle construction from primitive types.

You can declare a structured value type as follows:

class MyValueType
{
    Q_GADGET
    QML_VALUE_TYPE(myValueType)
    QML_STRUCTURED_VALUE
    Q_PROPERTY(double d READ d WRITE setD)
    Q_PROPERTY(string e READ e WRITE setE)

    // ...
};

Then you can populate a property of this type as follows:

QtObject {
    property myValueType v: ({d: 4.4, e: "a string"})
}

The extra parentheses are necessary to disambiguate the JavaScript object from what might be interpreted as a JavaScript code block.

You can also construct lists of values this way:

QtObject {
    property list<myValueType> v: [
        {d: 4.4, e: "a string"},
        {d: 7.1, e: "another string"}
    ]
}

If you make value types addressable, you can use such a type in a type assertion to explicitly construct it:

pragma ValueTypeBehavior: Addressable

QtObject {
    function process(d: real) {
        let v = {d: d, e: objectName} as myValueType;
        // v is a myValueType now
    }
}

This macro was introduced in Qt 6.5.

See also QML_VALUE_TYPE and QML_CONSTRUCTIBLE_VALUE.

QML_UNAVAILABLE

This macro declares the enclosing type to be unavailable in QML. It registers an internal dummy type called QQmlTypeNotAvailable as QML_FOREIGN() type, using any further QML macros you specify.

Normally, the types exported by a module should be fixed. However, if a C++ type is not available, you should at least "reserve" the QML type name, and give the user of the unavailable type a meaningful error message.

Example:

#ifdef NO_GAMES_ALLOWED
struct MinehuntGame
{
    Q_GADGET
    QML_NAMED_ELEMENT(Game)
    QML_UNAVAILABLE
    QML_UNCREATABLE("Get back to work, slacker!");
};
#else
class MinehuntGame : public QObject
{
    Q_OBJECT
    QML_NAMED_ELEMENT(Game)
    // ...
};
#endif

This will cause any QML which attempts to use the "Game" type to produce an error message:

fun.qml: Get back to work, slacker!
   Game {
   ^

Using this technique, you only need a Q_GADGET struct to customize the error message, not a full-blown QObject. Without QML_UNCREATABLE(), QML_UNAVAILABLE still results in a more specific error message than the usual "is not a type" for completely unknown types.

Note: The class name needs to be fully qualified, even if you're already inside the namespace.

See also QML_ELEMENT, QML_NAMED_ELEMENT(), QML_UNCREATABLE(), and QML_FOREIGN().

QML_UNCREATABLE(reason)

Declares that the enclosing type shall not be creatable from QML. This takes effect if the type is available in QML, by having a QML_ELEMENT or QML_NAMED_ELEMENT() macro. The reason will be emitted as error message if an attempt to create the type from QML is detected.

Some QML types are implicitly uncreatable, in particular types exposed with QML_ANONYMOUS or namespaces exposed with QML_ELEMENT or QML_NAMED_ELEMENT().

Since Qt 6.0 you can use "" instead of a reason to use a standard message instead.

See also QML_ELEMENT, QML_NAMED_ELEMENT(), and QML_ANONYMOUS.

QML_VALUE_TYPE(name)

Declares the enclosing type or namespace to be available in QML, using name as the name. The type has to be a value type and the name has to be lower case.

class MyValueType
{
    Q_GADGET
    QML_VALUE_TYPE(myValueType)

    // ...
};

See also Choosing the Correct Integration Method Between C++ and QML and QML_NAMED_ELEMENT.

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.