For a recent side-project I’ve been working on (a cycle computer for UBPorts phones) I found that when using the QtLocation Map QML element, nearly all the map types provided by the OSM plugin (besides the basic streetmap type) require an API key from Thunderforest. Unfortunately, there doesn’t appear to be a documented way of supplying an API key to the plugin, and the handful of forum posts and Stack Overflow questions on the topic are either unanswered or answered by people believing that it’s not possible. It’s not obvious, but after a bit of digging into the way the OSM plugin works I’ve discovered a mechanism by which an API key can be supplied to tile servers that require one.
When the OSM plugin is initialised it communicates with the Qt providers repository which tells it what URLs to use for each map type. The location of the providers repository can be customised through the osm.mapping.providersrepository.address OSM plugin property, so all we need to do to use our API key is to set up our own providers repository with URLs that include our API key as a parameter. The repository itself is just a collection of JSON files, with specific names (cycle, cycle-hires, hiking, hiking-hires, night-transit, night-transit-hires, satellite, street, street-hires, terrain, terrain-hires, transit, transit-hires) each corresponding to a map type. The *-hires files provide URLs for tiles at twice the normal resolution, for high DPI displays.
For example, this is the cycle file served by the default Qt providers repository:
{ "UrlTemplate" : "http://a.tile.thunderforest.com/cycle/%z/%x/%y.png", "ImageFormat" : "png", "QImageFormat" : "Indexed8", "ID" : "thf-cycle", "MaximumZoomLevel" : 20, "MapCopyRight" : "<a href='http://www.thunderforest.com/'>Thunderforest</a>", "DataCopyRight" : "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors" }
To provide an API key with our tile requests we can simply modify the UrlTemplate:
"UrlTemplate" : "http://a.tile.thunderforest.com/cycle/%z/%x/%y.png?apikey=YOUR_API_KEY",
Automatic repository setup
I’ve created a simple tool for setting up a complete repository using a custom API key here: https://github.com/Elleo/qt-osm-map-providers
- First obtain an API key from https://www.thunderforest.com/docs/apikeys/
- Next clone my repository:
git clone https://github.com/Elleo/qt-osm-map-providers.git
- Run:
./set_api_keys.sh your_api_key
(replacing your_api_key with the key you obtained in step 1) - Copy the files from this repository to your webserver (e.g. http://www.mywebsite.com/osm_repository)
- Set the osm.mapping.providersrepository.address property to point to the location setup in step 4 (see the QML example below)
QML Example
Here’s a quick example QML app that will make use of the custom repository we’ve set up:
import QtQuick 2.7 import QtQuick.Controls 2.5 import QtLocation 5.10 ApplicationWindow { title: qsTr("Map Example") width: 1280 height: 720 Map { anchors.fill: parent zoomLevel: 14 plugin: Plugin { name: "osm" PluginParameter { name: "osm.mapping.providersrepository.address"; value: "http://www.mywebsite.com/osm_repository" } PluginParameter { name: "osm.mapping.highdpi_tiles"; value: true } } activeMapType: supportedMapTypes[1] // Cycle map provided by Thunderforest } }
Would it be possible to do this without an own webserver? having the JSON as a local file resource?
Best regards,
Andreas
Comment by Andreas Axelsson — August 10, 2021 @ 3:25 pm
Would it be possible to do this without an own webserver?
Comment by khadim — August 7, 2024 @ 11:54 am
Hi Khadim!
I posted this article as an answer on Stack Overflow, and a few people have had success with various approaches (depending on your Qt version), either hosting a small webserver within your application itself, using local file:/// urls (only seems to work on certain Qt versions) or with recent versions of Qt it’s possible to set a custom host parameter without the need for a full repository. See the Stack Overflow comments for full details.
Cheers,
Mike
Comment by Mike — August 8, 2024 @ 1:48 pm