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

Q_GADGET types not handled properly when passed as QML function arguments

    XMLWordPrintable

Details

    Description

      It is not possible to access idx.row if idx is a QVariant containing a QModelIndex.

      There does not appear to be an alternative way to make the index known to the javascript engine for a function call, except by using QJSEngine::toScriptValue which wraps in that way.

      
      #include <QGuiApplication>
      #include <QQuickView>
      #include <QQmlEngine>
      #include <QQmlContext>
      #include <QStandardItemModel>
      #include <QDebug>
      
      class Something : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(QJSValue theFunction READ function WRITE setFunction NOTIFY functionChanged)
          Q_PROPERTY(QJSValue theRectFunction READ rectFunction WRITE setRectFunction NOTIFY rectFunctionChanged)
      public:
          Something(QObject* = 0)
          {
          }
      
          void setFunction(const QJSValue& function)
          {
            if (!mFunction.equals(function))
            {
              mFunction = function;
              Q_ASSERT(mFunction.isCallable());
              Q_EMIT functionChanged();
            }
          }
      
          QJSValue function() const
          {
            return mFunction;
          }
      
          void setRectFunction(const QJSValue& function)
          {
            if (!mRectFunction.equals(function))
            {
              mRectFunction = function;
              Q_ASSERT(mRectFunction.isCallable());
              Q_EMIT rectFunctionChanged();
            }
          }
      
          QJSValue rectFunction() const
          {
            return mRectFunction;
          }
      
          Q_INVOKABLE void callFunction(const QModelIndex& idx)
          {
              qDebug() << "Something::callFunction" << idx;
              QJSValueList args = QJSValueList() << qjsEngine(this)->toScriptValue(idx);
              mFunction.call(args).toVariant();
          }
      
          Q_INVOKABLE void callRectFunction(const QRect& rect)
          {
              qDebug() << "Something::callRectFunction" << rect;
              QJSValueList args = QJSValueList() << qjsEngine(this)->toScriptValue(rect);
              mRectFunction.call(args).toVariant();
          }
      
      
      Q_SIGNALS:
        void functionChanged();
        void rectFunctionChanged();
      
      private:
          mutable QJSValue mFunction;
          mutable QJSValue mRectFunction;
      };
      
      int main(int argc, char** argv)
      {
          QGuiApplication app(argc, argv);
      
          QStandardItemModel model;
          model.appendRow(new QStandardItem("First"));
          model.appendRow(new QStandardItem("Second"));
      
          qmlRegisterType<Something>("Things", 1, 0, "Something");
      
          QQuickView view;
          view.engine()->rootContext()->setContextProperty("_model", &model);
          view.setSource(QUrl("main.qml"));
          view.show();
      
          return app.exec();
      }
      
      #include "main.moc"
      
      import QtQuick 2.3
      
      import Things 1.0
      
      Rectangle {
          id: root
          width: 560
          height: 360
      
          Something {
              id: st
              theFunction: function(idx) {
                  console.log("theFunction idx", idx);
                  console.log("theFunction row", idx.row);
                  return 42;
              }
      
              theRectFunction: function(rect) {
                  console.log("theFunction rect", rect);
                  console.log("theFunction rectWidth", rect.width);
              }
          }
      
          Text {
              id: textElement
              text: "Click"
              width: 200
              height: 30
              MouseArea {
                  anchors.fill: parent
                  onClicked: {
                      var idx = _model.index(0, 0);
                      console.log("onClicked: idx", idx);
                      console.log("onClicked: row", idx.row);
                      st.callFunction(idx);
      
                      var rect = Qt.rect(50, 50, 100, 100);
                      console.log("onClicked: rect", rect)
                      console.log("onClicked: rectWidth", rect.width)
                      st.callRectFunction(rect)
                  }
              }
          }
      }
      

      Output after clicking:

      $ ./QTBUG-48073.app/Contents/MacOS/QTBUG-48073 
      qml: onClicked: idx QModelIndex(0,0,0x7ff18a5733e0,QStandardItemModel(0x7fff5aed4880))
      qml: onClicked: row 0
      Something::callFunction QModelIndex(0,0,0x7ff18a5733e0,QStandardItemModel(0x7fff5aed4880))
      qml: theFunction idx QVariant(QModelIndex)
      qml: theFunction row undefined
      qml: onClicked: rect QRectF(50, 50, 100, 100)
      qml: onClicked: rectWidth 100
      Something::callRectFunction QRect(50,50 100x100)
      qml: theFunction rect QVariant(QRect)
      qml: theFunction rectWidth undefined
      

      Attachments

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

        Activity

          People

            ulherman Ulf Hermann
            ske Steve
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes