PDA

View Full Version : QtScript: Properties of the object inherited from QObjectList are not visible from JS



platon
18th September 2012, 13:34
I'm trying to expose to JS the audioTracks object which should be accessible from JS as array (audioTracks[index]) and at the same time should have method audioTracks.getTrackById("id").
Here is my object:


class AudioTrackList : public QObject, public QObjectList
{
Q_OBJECT

public:
AudioTrackList(ScriptableIfaceMedia*);

Q_PROPERTY(int length READ size SCRIPTABLE true)

Q_INVOKABLE QObject* getTrackById(QString id);

private:
ScriptableIfaceMedia* m_impl;
QScriptEngine m_engine;

};

The problem is that when I expose the object in the following way:


Q_PROPERTY(QObjectList audioTracks READ audioTracks SCRIPTABLE true)
QObjectList audioTracks();



QObjectList MediaTracks::audioTracks()
{
int i;

QScriptValue rv = m_engine.newArray(m_audio_tracks->size());
for (i = 0; i < m_audio_tracks->size(); i++) {
rv.setProperty(i, m_engine.newQObject(m_audio_tracks->at(i), QScriptEngine::QtOwnership));
}

return static_cast<QObjectList>(*m_audio_tracks);
}

I have audioTracks[index] working but audioTracks.getTrackById("id") not.
Instead when I expose the object another way:


Q_PROPERTY(QObject* audioTracks READ audioTracks SCRIPTABLE true)
QObject* audioTracks();



QObject* MediaTracks::audioTracks()
{
m_engine.newQObject(m_audio_tracks, QScriptEngine::QtOwnership);
return m_audio_tracks;
}

I have audioTracks.getTrackById("id") working but audioTracks[index] not.
Is there any way to export my object to make it possible to access it from JS both like array and like object?

pkj
19th September 2012, 14:07
After having introduced the qobject into script, get hold of the array QScriptValue. The idea is to introduce a native function to the the qobject.

QScriptValue arrayVal = objectScriptVal.property(QString("propertyName"));
...
QScriptValue someFunctionName(QScriptContext *ctx, QScriptEngine *eng)
{
QObject* obj = ctx->thisObject()->toQObject();
if (obj){
MyClass* myClassObj = qobject_cast<MyClass*>(obj);
QObject* result = myClassObj->function(ctx->argument(0).toString());
return result; // or return eng->newQObject(result); //both should work
}
...
arrayVal.setProperty("functionName", engine->newFunction(someFunctionName));

In jist: here what has been done.
1. Introduced object with an array property.
2. Got hold of QScriptValue of array property.
3. Introduce a native function to the array property.

platon
20th September 2012, 10:25
Still can't make it to work :(
pkj, did you manage to do such trick?
It seems that when my AudioTrackList is exposed to JS like array (by newArray()) then only standard JS array methods and properties are accessible.
When I try to call getTrackById() method I get such error:
http://192.168.23.2/play.html:94: TypeError: 'undefined' is not a function (evaluating 'p.audioTracks.getTrackById("id1")')

platon
20th September 2012, 13:12
I just found out that when I expose my object by QScriptEngine::newArray() I can't add to my object even a simple property like:


Q_PROPERTY(int myprop READ myprop SCRIPTABLE true)
int myprop() const;

In JavaScript it becomes a usual array.

platon
2nd October 2012, 18:39
I have found a solution for my problem.
Since in JavaScript .0 and ['0'] are the same things I made the following workaround in my code:


value = m_engine.newQObject(m_audio_tracks, QScriptEngine::QtOwnership);
for (i = 0; i < m_audio_tracks->tracks().size(); i++) {
m_audio_tracks->setProperty(QString("%1").arg(i).toLocal8Bit().data(), qVariantFromValue(m_audio_tracks->tracks().at(i)));
value.setProperty(QString("%1").arg(i), m_engine.newQObject(m_audio_tracks->tracks().at(i), QScriptEngine::QtOwnership));
}

to make it possible to access my object like array from JavaScript.