Script prototype for value



  • Hi,

    I'm trying to pass my custom class, not based on QObject, to a script. I created a prototype that inherits from QScriptable, implemented all the properties and functions (as slots) I wanted, called Q_DECLARE_METATYPE and registered it to my QScriptEngine:

    @PlanetPrototype planetPrototype = new PlanetPrototype;
    QScriptValue planetProto = scriptEngine->newQObject(planetPrototype);
    scriptEngine->setDefaultPrototype(qMetaTypeId<Planet
    >(), planetProto);@

    So how do I now convert a Planet* to QScriptValue? If I do either of:
    @engine->toScriptValue<Planet*>(myplanet);
    engine->toObject(engine->toScriptValue<Planet*>(myplanet)@
    the result is undefined in JavaScript.

    Regards,
    Marcin Jakubowski



  • How does your code compare with the following?

    @
    #include <QtCore>
    #include <QtScript/QtScript>

    class Data
    {
    public:
    Data() : _id("no-data"), _num(0) {}
    Data(const QString &id, int num):
    _id(id), _num(num)
    {}

    QString id() const { return _id; }
    void setId(const QString& id) { _id = id; }
    
    int num() const { return _num; }
    void setNum(int num) { _num = num; }
    

    private:
    QString _id;
    int _num;
    };

    Q_DECLARE_METATYPE(Data*)

    class DataPrototype : public QObject, public QScriptable
    {
    Q_OBJECT
    Q_PROPERTY(QString id READ id)
    Q_PROPERTY(int num READ num)
    public:
    DataPrototype(QObject *parent = 0) : QObject(parent) {}

    QString id() const
    {
        Data *item = qscriptvalue_cast<Data*>(thisObject());
        if (item)
            return item->id();
        return "none";
    }
    
    int num() const
    {
        Data *item = qscriptvalue_cast<Data*>(thisObject());
        if (item)
            return item->num();
        return 1;
    }
    

    };

    int main(int argc, char *argv[])
    {
    QCoreApplication app(argc, argv);

    QScriptEngine engine;
    
    DataPrototype dataPrototype;
    QScriptValue dataProto = engine.newQObject(&dataPrototype);
    engine.setDefaultPrototype(qMetaTypeId<Data*>(), dataProto);
    
    Data d("test", 7);
    engine.globalObject().setProperty("d", engine.toScriptValue(&d));
    
    QScriptValue result = engine.evaluate("d.id + ': ' + d.num");
    qDebug() << result.toString();        // displays "test: 7"
    
    QTimer::singleShot(1000, &app, SLOT(quit()));
    return app.exec();
    

    }

    #include "main.moc"
    @



  • Seems correct to me, pretty much the same as yours:

    @

    Q_DECLARE_METATYPE(Planet*)

    class PlanetPrototype : public QObject, public QScriptable
    {
    Q_OBJECT

    Q_PROPERTY(QString id READ id)
    Q_PROPERTY(QString name READ name)
    Q_PROPERTY(int iCoords READ iCoords)
    Q_PROPERTY(QString coords READ coords)
    

    public:
    PlanetPrototype(QObject *parent = 0);

    QString id() const;
    QString name() const;
    
    int iCoords() const;
    QString coords() const;
    

    public slots:
    int info(int id);

    private:
    Planet* thisPlanet() const;
    };

    // somewhere else

    PlanetPrototype planetPrototype = new PlanetPrototype;
    QScriptValue planetProto = scriptEngine->newQObject(planetPrototype);
    qDebug() << qMetaTypeId<Planet
    >(); // is ok, returns 277

    Planet *p = new Planet("test planet", "1000", PlanetCoords(1, 2, 3, 4, 5));
    scriptEngine->globalObject().setProperty("myplanet", scriptEngine->toScriptValue(p));

    scriptEngine->globalObject().setProperty("myplanet", scriptEngine->toScriptValue(p));
    QScriptValue result = scriptEngine->evaluate("'givf object plx:' + myplanet");
    qDebug() << result.toString(); // gives undefined

    @



  • Oh the stupidity.

    @
    QScriptValue result = scriptEngine->evaluate("'givf object plx:' + myplanet + ' - ' + myplanet.name");
    qDebug() << result.toString(); // givf object plx:undefined - test planet
    @

    Although it seems strange that it says undefined even though it is not... I'm not an ECMAScript expert but I thought it should give me an Object.



  • It says undefined because the toString() function is undefined for the prototype set for Planet*. If the setDefaultPrototype() on Planet* is not used, it would probably result in "givf object plx:QVariant(Planet*) - undefined". Define a toString() slot for the PlanetPrototype class and see how the result changes.



  • Indeed, changes accordingly. Makes sense, thank you very much!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.