How can I access to member of QPointer in QML?

90 views Asked by At

My project uses Qt and QML.

I want to bind a property that can be multiple types of a class.

For example:

class base : public QObject
{
Q_OBJECT
public:
    Q_PROPERTY(QVariant myVar read myVar NOTIFY myVarChanged)
    QVariant myVar() {return var;}
    
signals:
    void myVarChanged();
private:
    QVariant var
}

class A : public QObject
{
Q_OBJECT
/* 
similar with upper class
*/
    QString myStr;
}

somewhere
{
    QPointer<A> mine = new A;
    base.myVar = QVariant::fromValue(mine)
}

Now I can have Base in QML.

When I call:

console.log(base.myVar)

console prints:

QVariant(QPoitner<A>(/*address*/)

But I can't get further. I want to get myStr by using base.myVar.myStr, but it is undefined. How do I solve this?

I can't use Q_GADGET because myStr changes.

I have to put class B or C in myVar sometimes, not only class A, so I have to use QVariant.

1

There are 1 answers

0
Stephen Quan On BEST ANSWER

There's QVariant::fromValue and qvariant_cast.

If you want to cast to QObject* as an intermediate step, you can dynamic_cast before converting it to a QVariant on the way out, and, on the way back, you use qvariant_cast then qobject_cast.

    YourObject* m_ptr;

    Q_INVOKABLE QVariant getValue()
    {
        return toQVariant(m_ptr);
    }

    Q_INVOKABLE bool compare(const QVariant& other)
    {
        return comparePointers(m_ptr, fromQVariant(other));
    }

protected:
    static QVariant toQVariant(const YourObject* ptr)
    {
        // Direct Method: convert C++ YourObject* pointer to QVariant for QML
        return QVariant::fromValue<YourObject*>(ptr);

        // QObject Method: convert C++ YourObject* to a QObject* then to QVariant
        // return QVariant::fromValue<QObject*>(dynamic_cast<QObject*>(ptr));
    }

    QStatic YourObject* fromQVariant(const QVariant& variantValue)
    {
        // Direct Method: convert QVariant from QML to a C++ YourObject* ptr;
        return _other = qvariant_cast<YourObject*>(other);

        // QObject Method: convert QVariant to QObject to YourQObject.
        // QObject* qobj = qvariant_cast<QObject*>(other);
        // return qobject_cast<YourObject*>(qobj);
    }

    static bool comparePointers(YourObject* a, YourObject* b)
    {
        // ...
    }

Another solution you may want to consider is using QJSValue. QJSValue QJSEngine::newQObject(QObject* object) basically creates a JavaScript object that wraps the given QObject with JavaScriptOwnership. i.e. the QML Engine's garbage collector will take care of cleanup of the object when it goes out of scope. You usually use this approach if you are newing to your QObject, but, you want QML Engine to take care of the remainder of the object life-cycle. If you were to receive a QJSValue from QML, you will have to call QString QJSValue::toObject() to recover the QObject and then you will have to do a qobject_cast.

References: