3

I want to display a map via HTML/CSS/JS in a QWebEngineView using Qt5 C++.

It already works with leaflet (https://leafletjs.com/): enter image description here
As you can see the window shows a map with a marker at a given position.

However trying the same with wrld (https://github.com/wrld3d/wrld.js), a 3D map based on leaflet, I only get a black window: enter image description here
Additionally the following errors/warnings are displayed on the command line:

js: Refused to set unsafe header "Content-length"
js: Refused to set unsafe header "Connection"
js: Failed to load qrc://webgl-cdn1.eegeo.com/art_edits/continuous/incremental/us/sf/251/Ground/0/1/1/3/1/2/3/2/1/2/3/1/1/3/Ground.hcff?appinfo=Undefined%1Fb37aeaf9b6cd7eb5bc303d144af98ad0%1F1879%1Fd2cae54f44447344cfb3802d9365c03c3aa35e47%1FUndefined%1FUndefined%1FJavascript%1FUndefined%1FUndefined%1FJavascript: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
js: Uncaught abort() at Error
    at Sa (https://cdn-webgl.wrld3d.com/eegeojs/public/v1879/eeGeoWebGL.jgz:63:124)
    at Ra (https://cdn-webgl.wrld3d.com/eegeojs/public/v1879/eeGeoWebGL.jgz:63:22)
    at Object.q [as abort] (https://cdn-webgl.wrld3d.com/eegeojs/public/v1879/eeGeoWebGL.jgz:410:102)
    at _abort (https://cdn-webgl.wrld3d.com/eegeojs/public/v1879/eeGeoWebGL.jgz:257:368)
    at Rh (https://cdn-webgl.wrld3d.com/eegeojs/public/v1879/eeGeoWebGL.jgz:275:40424)
    at or (https://cdn-webgl.wrld3d.com/eegeojs/public/v1879/eeGeoWebGL.jgz:275:389787)
    at pgc (https://cdn-webgl.wrld3d.com/eegeojs/public/v1879/eeGeoWebGL.jgz:283:389489)
    at ogc (https://cdn-webgl.wrld3d.com/eegeojs/public/v1879/eeGeoWebGL.jgz:283:389037)
    at ldc (https://cdn-webgl.wrld3d.com/eegeojs/public/v1879/eeGeoWebGL.jgz:283:298507)
    at kdc (https://cdn-webgl.wrld3d.com/eegeojs/public/v1879/eeGeoWebGL.jgz:283:296713)
If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.

As far as I already figured out it has something to do with missing tags in the response header (Access-Control-Allow-Headers), but I can't get it working. I already tried to inject these headers via a QWebEngineUrlRequestInterceptor, but with no success.

Here is a minimal "working" example:

main.cpp:

#include <QApplication>
#include <QWebEngineView>

int main(int argc, char** argv) {
  qputenv("QT_STYLE_OVERRIDE", "Fusion");
  QApplication app(argc, argv);

  QWebEngineView* mapview = new QWebEngineView();
  mapview->load(QUrl("qrc:/map.html"));
  mapview->show();

  app.exec();

  return 0;
}

map.html: (you need an api key from https://www.wrld3d.com/ to use the wrld version)

<!doctype html>
<html lang="de">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css"
    integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
    crossorigin=""/>

    <!-- comment in for the leaflet version -->
    <!-- <script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"
        integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og=="
        crossorigin=""></script> -->

    <!-- wrld version -> not working -->
    <script src="https://cdn-webgl.wrld3d.com/wrldjs/dist/latest/wrld.js"></script>

</head>
<body>

<div id="mapid" style="width: 95vw; height: 95vh;"></div>
<script type="application/javascript">
    // comment in for the leaflet version
    // var map = L.map('mapid').setView([51.505, -0.09], 13);
    // L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    //   maxZoom: 18,
    //   attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
    //   '<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
    //   'Imagery © <a href="http://www.openstreetmap.org/#map=6/51.">OpenStreetMap</a>',
    //   id: 'mapbox.streets'
    // }).addTo(map);

    var map = L.Wrld.map("mapid", "PUT_YOUR_API_KEY_HERE");
</script>
</body>
</html>

resources.qrc:

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
    <file>map.html</file>
</qresource>
</RCC>

CMakeLists.txt:

project (PROJ LANGUAGES CXX)

cmake_minimum_required (VERSION 3.9)

# set compiler flags for better warnings
add_compile_options(-Wall -Wextra -pedantic)


# set the required c++ standard to c++20
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)

# find Qt5
find_package(Qt5 REQUIRED Network WebEngine Widgets WebEngineWidgets)
qt5_add_resources(RCC_SOURCES resources.qrc)


# create executable with main file
add_executable(prog ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp ${RCC_SOURCES})
target_link_libraries(prog Qt5::Widgets Qt5::WebEngine Qt5::Network Qt5::WebEngineWidgets)

To run the example put all four files in one directory und use cmake/make to compile everything.

The desired output should look like: enter image description here

Is it possible to achieve that with Qt's QWebEngineView? Leaflet works fine. That is I see no real reason why it shouldn't work with wrld too.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
breyerml
  • 267
  • 2
  • 14

1 Answers1

3

This is not a Qt error but a wrld.js bug as noted in this discussion. From that conversion it is concluded that the library only supports http or https, and not another scheme.

So the solution is to launch the html through an HTTP server, there are several options but assuming that you only want to use Qt then we can take advantage of the following module: Qt HTTP server. To install it you must execute the following steps:

git clone --recursive https://codereview.qt-project.org/qt-labs/qthttpserver
cd qthttpserver
qmake
make
sudo make install

After that you must modify the main.cpp to:

#include <QApplication>
#include <QWebEngineView>
#include <QHttpServer>

int main(int argc, char** argv) {
    qputenv("QT_STYLE_OVERRIDE", "Fusion");
    QApplication app(argc, argv);

    QHttpServer httpServer;
    httpServer.route("/", []() {
        return QHttpServerResponse::fromFile(QStringLiteral(":/map.html"));
    });

    const auto port = httpServer.listen(QHostAddress::Any);
    if (port == -1) {
        qDebug() << QStringLiteral("Could not run on http://127.0.0.1:%1/").arg(port);
        return 0;
    }

    QWebEngineView view;
    view.load(QUrl(QStringLiteral("http://127.0.0.1:%1/").arg(port)));
    view.show();

    return app.exec();
}

And also the CMakeLists.txt:

project (PROJ LANGUAGES CXX)

cmake_minimum_required (VERSION 3.9)

# set compiler flags for better warnings
add_compile_options(-Wall -Wextra -pedantic)


# set the required c++ standard to c++20
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)

# find Qt5
find_package(Qt5 REQUIRED Network WebEngine Widgets WebEngineWidgets HttpServer)
qt5_add_resources(RCC_SOURCES resources.qrc)


# create executable with main file
add_executable(prog ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp ${RCC_SOURCES})
target_link_libraries(prog Qt5::Widgets Qt5::WebEngine Qt5::Network Qt5::WebEngineWidgets Qt5::HttpServer)

Resulting in:

enter image description here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thank you for your fast reply. Unfortunately i can't get qthttpserver working. I cloned that git repo, but then i can't run make (because there is no make file). So i tried qmake -project -> qmake -> make But make fails with the output: "src/httpserver/qabstracthttpserver.cpp:30:46: fatal error: QtHttpServer/qabstracthttpserver.h: No such file or directory compilation terminated.". – breyerml Jul 02 '19 at 07:35
  • 1
    @Arkantos493 Do not put all the commands to compile Qt Http server, now I have corrected it, try it back – eyllanesc Jul 02 '19 at 07:38
  • No it works thank you. The main problem was that qmake used the wrong Qt version. – breyerml Jul 02 '19 at 09:42
  • Sorry for another stupid question, but how can i get your code working if map.html is located in a subdirectory? For example in a resources folder? Simply changing ":/map.html" to ":/resources/map.html" doesn't work at all. – breyerml Jul 02 '19 at 19:26