0

As I'm new into javascript/HTML and recently I started a project using Qt QWebEngineView. I've been stuck for some time on finding the best way to share data from the C++ program to Javascript. So far the only way I was able to send data to the Javascript program is by using the QWebEnginePage::runJavaScript function. I also have seen that there is the possibility of using QWebChannels described here but I prefer the QWebEnginePage::runJavaScript for its simplicity.

The only issue I've had so far with the runJavaScript method has been that in order to write a variable, this needs to be defined in the HTML file, I'm actually not 100% sure if this is the only way to do it but it has been the only way it worked for me. My current scenario looks something like this:

In the HTML file:

...
        <div id="latitude" ></div>
        <div id="longitude"></div>
        <div id="heading" "></div>
...

In the C++ file:

...
     double Latitude = 44.244; Longitude = 10.3; Heading = 90;
     QString jsQuery = QObject::tr(
                "document.getElementById('latitude').innerHTML  =%1; "
                "document.getElementById('longitude').innerHTML =%2; "
                "document.getElementById('heading').innerHTML   =%3;"
                ).arg(Latitude).arg(Longitude).arg(Heading));
     mapWebView->page()->runJavaScript(jsQuery);
...

With this setup, I'm able to write the variables in the Javascript/HTML side from the C++ code. Because with this solution I need to create as many individual variables on the HTML file for each value I want to send, I wanted to ask if it is possible to instead of using individual variables use a class object or a JavaScript Object. I create a class with some methods to write the class members like the one below: In the js file:

...
export default class PositionState{
    setPosition(latitude = 0.0, longitude = 0.0, heading = 0.0){
        this.Latitude   = latitude;
        this.Longitude  = longitude;
        this.Heading    = heading;
    }
    getLatitude(){
        return this.Latitude;
    }
    getLongitude(){
        return this.Longitude;
    }
    getHeading(){
        return this.Heading;
    }
}

var obj = new PositionState();
...

With this solution, if I create an object of the PositionState class and call the function obj.setPosition(44,10.45) from the javascript file the object's class members are set correctly, But if I try it from the C++ I get some errors.

 double Latitude = 44.244; Longitude = 10.3; Heading = 90;
 Qstring jsQuery = QObject::tr(
                    "obj.setPosition(%1, %2, %3);"
                    ).arg(Latitude).arg(Longitude).arg(Heading));
mapWebView->page()->runJavaScript(jsQuery);

If only define the obj in the Javascript file I get the error js: Uncaught ReferenceError: obj is not defined. And if I define a variable in the HTML file with the Id="obj" and run the same script I get the error js: Uncaught TypeError: obj.setPosition is not a function, the error occurs even if instead of just obj.setPosition i use document.getElementById('obj').setPosition.

So for what I get with my little to none HTML/Javascript knowledge is that the HTML file is not aware of my class definition, thus not recognizing the setPosition method. So my question is if there's a way to from the C++ code write the class object.

I also tried using a JavaScript Object like var Position = {Latitude: 0, Longitude: 0, Heading: 0} and from the C++ code run the a script with the QString Position = {Latitude: 40, Longitude: 9, Heading: 20}; but was also no able to change the Position object properties.

Any help will be really appreciated, thanks.

Andersen
  • 93
  • 10

1 Answers1

0

Honestly, you seem to be overcomplicating things...

Your "simplier" approach is nowhere as simple as using the QWebChannel to share objects between the JS and the C++ world. Additionally, you are losing a lot of functionality by going another way: connecting to Qt signals in JS, overloading methods, reading and setting properties directly from JS...

Just use the QWebChannel to register QObjects into the QWebEnginePage, load QWebChannel into your HTML page, setup the connection, and that's it!

This article has an excelent and simple explanation (with code snippets) on how to do this.

There is no need for you to reinvent the wheel.

Hineios
  • 1
  • 1