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

Using QML_EXTENDED to add a property to a Qt QML object

    XMLWordPrintable

Details

    • All

    Description

      I want to add a new property to the QtMultimedia VideoOutput QML object. It appears I should use QML_EXTENDED to do that.
      https://doc.qt.io/qt-6/qtqml-cppintegration-definetypes.html#registering-extension-objects

      It's not clear from the documentation how to do this. I see two approaches, include the private header so I can use QQuickVideoOutput - the undocumented private implementation of the VideoOutput QML object:

      #include <QtMultimediaQuick/private/qquickvideooutput_p.h>
      struct VideoOutputForeign
      {
          Q_GADGET
          QML_FOREIGN(QQuickVideoOutput)
          QML_NAMED_ELEMENT(VideoOutput)
          QML_EXTENDED(VideoOutputExtension)
      };
      

      Or add my property to the public base class of QQuickVideoOutput - QQuickItem:

      #include <QQuickItem>
      struct VideoOutputForeign
      {
          Q_GADGET
          QML_FOREIGN(QQuickItem)
          QML_NAMED_ELEMENT(Item)
          QML_EXTENDED(VideoOutputExtension)
      };
      

      and then deal with users attempting to use my property on classes I don't support (i.e. anything other than VideoOutput)

      I implemented both approaches in the attached project and both seem to work.
      cmake -DPRIVATE=1 to use the QQuickVideoOutput approach, and don't define PRIVATE to use the QQuickItem approach.

      One oddity is I log the object I'm extending in my extension constructor:

      VideoOutputExtension::VideoOutputExtension(QObject *object)
          : QObject(object)
          , m_videoOutput(object)
      {
          QVideoSink* videoSink = nullptr;
          auto* mo = m_videoOutput->metaObject();
          mo->invokeMethod(m_videoOutput, "videoSink", Q_RETURN_ARG(QVideoSink*, videoSink));
          qDebug() << m_videoOutput << "class" << mo->className() << "videoSink" << videoSink;
      }
      

      In both cases it logs itself as VideoOutputExtension instead of QQuickItem or QQuickVideoOutput - but when it is attached to a VideoOutput, it has a videoSink property so it must be the correct object.

      QQuickItem implementation logs:

      QMetaObject::invokeMethod: No such method VideoOutputExtension::videoSink()
      VideoOutputExtension(0x600001a4c0e0) class VideoOutputExtension videoSink QObject(0x0)
      setFoobar 42
      VideoOutputExtension(0x154a18a80) class VideoOutputExtension videoSink QVideoSink(0x600002305540)
      setFoobar 23
      qml: loaded video-item.qml
      

      QQuickVideoOutput implementation logs:

      VideoOutputExtension(0x142106ad0) class VideoOutputExtension videoSink QVideoSink(0x600000948a00)
      setFoobar 23
      qml: loaded video.qml
      

      Could the QML_EXTENDED documentation be enhanced to recommend the preferred way to extend QML objects that have private Qt implementations?

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            qtmultimediateam Qt Multimedia Team
            rectalogic Andrew Wason
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes