views:

1812

answers:

4

I've successfully added an C++ object to a QWebFrame with addToJavaScriptWindowObject, and can call a slot on that object from javascript.

But what I really want to do is have one of those slots return a new object. For example, I have a slot like this, which returns a QObject derived class instance:

   MyObject* MyApp::helloWorld()
   {
          //MyObject is dervied from QObject
          return new MyObject();
   }

I can call this slot from javascript successfully like this

   var foo=myapp.helloWorld();

But foo appears to be empty, I can't call any slots or access any properties on it from Javascript.

Any ideas on how I can achieve this?

A: 

Assuming this is C++, you will have to do

MyObject *foo = myapp.hellowWorld();

And your method will need to return a pointer of temporary local object. That is one way you can do it.

Fox
I'm not sure you understood the question - you've just rewritten my JS fragment as C++!
Paul Dixon
+1  A: 

One rather ugly hack I've considered is to use addToJavaScriptWindowObject to drop the object I want to return into the window object with a random name, then have my slot return the name of the object instance instead:

QString MyApp::helloWorld()
{
     //general a unique name for the js variable
     QString name=getRandomVariableName();

     //here's the object we want to expose to js
     MyObject* pReturn=new MyObject();

     //we make attach our object to the js window object    
     getWebFrame()->addToJavaScriptWindowObject(name, pReturn,
         QScriptEngine::ScriptOwnership);  

     //tell js the name we used
     return name;
}

The JS can be written to check if the return value is a string, and if it is, grab the object from the window.:

var foo=myapp.helloWorld();
if (typeof foo == "string")
{
    foo=window[foo];
}

A little ugly, but will get me by until a better method comes along. Future Qt versions are going unify the scripting support so that it's all based on the JavaScriptCore in WebKit, so hopefully this will improve then!

Paul Dixon
+1  A: 

QtScript has the notion of prototypes - which allows you to create a C++ prototype for a script value. We are investigating wether we can bridge QtScript with JavaScriptCore - which should result in the possibility of using prototypes from WebKit's JavaScript environment as well; http://doc.trolltech.com/4.5/qtscript.html#making-use-of-prototype-based-inheritance

Henrik Hartz
Yes, I saw that some unification is on the roadmap, which would will be nice. I've mananged to hide the "ugliness" of my workaround anyway, so the the js I write will remain largely usable when a better solutions comes along.
Paul Dixon
A: 

Try returning your new object as a QObject* rather than a MyObject*. If you're just working with QtScript, then you can call qScriptRegisterMetaType to define some code for handling conversion of MyObject*s into QScriptValues (or QVariants), but there doesn't seem to be an equivalent for the JavaScript engine used in QtWebKit.

Annoyingly, this means that exposing your internal object model to WebKit will involve either having a separate set of proxy functions that convert your object pointers to QObject*s, or using adapter classes of some kind to do the same thing.

Rob Knight
Indeed, what I've wound up with is adapter classes in both C++ and JS to bridge the gap and let the "real" JS feel like everything is happening as it should.
Paul Dixon