svalaskevicius / qtjs-generator

Qt API bindings generator for Node.js
38 stars 9 forks source link

test and implement compatibility with QML Js types #3

Closed svalaskevicius closed 10 years ago

svalaskevicius commented 11 years ago

generate bindings for QML code and prepare usage example js

svalaskevicius commented 11 years ago

Hey @Statixcinder,

I am currently working on integrating QML support.

The basic feature set is mostly working, however, its at a very early stage.

Could you maybe review the initial (and ugly :) ) example of usage here: qml.js and qml/main.qml.

In the qml.js file, the cpgf based Js code for business logic registers a few dynamic classes to interact with the frontend written in QML. QML then can use the class same way as its described in the C++ based examples.

I'm still going to amend the examples - clean them up and implement a few minor features:

What do you think about this kind of integration in general? can it be improved? Also, are there any more QML features to cover that would improve the usage of it?

Thanks.

Kind regards, Sarunas

Statixcinder commented 11 years ago

I've been out of the loop for awhile on this so let me reiterate the entirety of what I do so we can decipher any missing gaps :) The cpgf example seems like a completely new instantiation method unless im looking at it wrong.

Step 1: I define OmniORB IDL for my objects (POD-Types which (after talking to Lars Knoll) are not currently supported in Qt V8 or upcoming V4 due to lack of time which i think is the primary issue).

module MintIDL {
  struct VlanData {
    MintIDL::AssetId switchAssetId;
    string vlanId;
    string name;
  }
}

I run this through my IDL parser to generate toScriptValue and fromScriptValue conversions for the POD types (which can't be reinterpreted as QObject because of copy-semantics)

static QScriptValue script_VlanData_Ctor(QScriptContext* /*context*/, QScriptEngine* engine)
{
    VlanData obj;
    return engine->toScriptValue(obj);
}
static QScriptValue script_VlanData_toScriptValue(QScriptEngine* engine, VlanData const &in)
{
    QScriptValue a = engine->newObject();
    a.setProperty("switchAssetId", qScriptValueFromValue(engine, in.switchAssetId));
    a.setProperty("vlanId", qScriptValueFromValue(engine, in.vlanId));
    a.setProperty("name", qScriptValueFromValue(engine, QString(in.name)));
    return a;
}
static void script_VlanData_fromScriptValue(const QScriptValue &object, VlanData &out)
{
    out.switchAssetId=mint_qscriptvalue_cast< ::MintIDL::AssetId >(object.property("switchAssetId"));
    out.vlanId=(long)object.property("vlanId").toInt32();
    out.name = qPrintable(object.property("name").toString());
}

Now in the old QDeclarativeEngine (Qt4.8.4) i would hi-jack the QScriptEngine embedded inside of it and then i would do the normal qRegisterMetaType and notify the engine of all of these conversions methods.

Once i did that i would re-lock the global object and it worked just like a normal QDeclartiveEngine (In V8 the global object seems to be frozen from what sifting around i could do, the only way to undo it is to duplicate the object i believe).

Anyway. Once i notified the conversion methods for the QScriptEngine in QDeclartiveEngine everything was just like native QtScript (within the JS contexts). For example i could expose all of the QtScriptGenerator imports, all of my conversion methods, etc. Then in the QML code I could easily do the following.

Item{ 
 id: mytem
 onCompleted:
 {
   var file = new QFile("myfile.txt");
   file.open(QIODevice.ReadOnly);

   var vlanData = new MintIDL.VlanData(); //I registered these as properties of a MintIDL Object
   vlanData.name = file.readAll();

   /*Having the POD types available here also let me set IDL Sequence objects as Models for things such as ListView
     which made everything awesome when returning data from CORBA services and not having to do a bunch of conversions. Essentially my GUI layer had full access to all known datatypes and core services until Qt 5.0 :(
   */
 }
}

If i'm not mistaken the approach in the KeyGenerator basically makes that a QObject (due to the slots?) which isn't possible for my setup. All of this goes away if we had POD types i think. there are already a few open bugs about it for v8.

svalaskevicius commented 11 years ago

Ah, I think I understand now :)

While I think this could be achieved with qtjs-generator, it would be an overkill to use it if you only want to bind some POD types to QML.

The main goal of qtjs-generator is to provide an ability to write pure Js applications with Qt.

The way I see this could be implemented is:

Also, api registered in cpgf is not available in QML, even though they're using the same v8 (this is almost intended as I see some benefits to have a clear code separation for business logic vs UI).

P.S. while I see there are _field and _property binding methods in cpgf api, I dont think I've tried them yet.

svalaskevicius commented 11 years ago

btw, have you managed to use QtScriptGenerator with V8? i.e. to bind the qt class wrappers? as I think this would be a bigger problem to solve - one could generate a custom wrapper for POD types once that is done :)

svalaskevicius commented 10 years ago

closing this issue as from Qt 5.2 qml is not using V8 anymore and the functionality is now implemented as: