Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-106480

Unify construction of value types in QML

    XMLWordPrintable

Details

    • 3195b44e1c (qt/qtdeclarative/dev) 3195b44e1c (qt/tqtc-qtdeclarative/dev)

    Description

      We currently have the following ways of constructing value types in QML:

      1. The engine can invoke constructors that take QJSValue. If you assign just any JS value to a value type, and such a constructor is present, it will be used.
      2. The engine can invoke a static create() method that takes a QJSValue. This method can also be defined on the local part of a QML_FOREIGN construction.
      3. The engine can invoke a QMetaType converter function taking QVariantMap
      4. The engine can invoke a QMetaType converter function taking QJSValue
      5. There are special types that can be populated from formatted strings using QQmlStringConverter

      None of this works universally in all places. For example the QVariantMap conversion only takes place when constructing the elements of a sequence type. The QJSValue conversion, however, takes place when populating a single valued property.

      The factory functions and constructors taking QJSValue are undocumented. They have the additional drawback that in order to call them, whatever source data has to be converted to a QJSValue first. QJSValue is a rather costly storage, due to its interaction with the JS heap.

      Needless to say, this fragmented state of affairs is not very appealing to users. You can technically get any value type constructed from QML somehow, but it requires a lot of magic.

      Furthermore, eventually we would like to optimize value type construction by compiling to C++ with qmlsc and qmlcachegen. Of the above methods, only the QJSValue constructor and the string converter can be detected at compile time. However, we due to performance reasons we don't want to use the QJSValue constructor in compiled code. Also, in general, we don't want to use the string converters due to their ugliness.

      This leaves us with exactly nothing we can do right now to implement value type construction in generated C++.

      In order to improve on this, we need to consider what kinds of value types we might have:

      1. There are value types defined by their properties. Such as rect, font, etc. If you set all their properties, you have exhaustively initialized the value type.
      2. There are value types defined by some hidden data that mostly provide functions to be called. This is the case for locale or date.

      What we might try is:

      1. Query the meta-object for constructors of any kind that take one argument. It doesn't have to be QJSValue. We can do our function call resolution to find the right one. Then we can invoke such a constructor to create a value type if a fitting value is assigned in a binding.
      2. Do property-by-property initialization from a JavaScript object.

      Both options need to be opt-in on a per-type level since they need to override the existing construction methods in order to be useful for the compilation to C++. In order to facilitate this, we might add QML_VALUE_CONSTRUCTIBLE and QML_PROPERTY_BY_PROPERTY_CONSTRUCTIBLE macros.

      Attachments

        For Gerrit Dashboard: QTBUG-106480
        # Subject Branch Project Status CR V

        Activity

          People

            ulherman Ulf Hermann
            ulherman Ulf Hermann
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes