I have yet to conclude on how to submit a pull request. And still no success in being able to build for Android (yes - when I go out I bring phones and tablets. The PC stays at home). But if you like, here’s how I’ve implemented Mapbox styled maps in QGC:
BASICS
To use Mapbox you already need to enter the mapboxToken (available in Mapbox - Account). This is created once you create an account. There is no charge for mapbox accounts as long as you do not use maps on a large scale. In other words, do not share the mapbox token with others that may use your maps big time
I decided to introduce two attributes into QGC: mapboxAccount and mapboxStyle. Source for these attributes are Mapbox Studio. When you click “menu” for the desired style, the style URL appears at the bottom of the popup. The url is in form:
mapbox://styles/mapboxAccount/mapboxStyle
In QGC
End result looks like this when you click settings, then offline maps and finally options:
FIRST: I defined the new attributes and included two new fields to capture their values:
\src\Settings\AppSettings.cc
Declared the following:
DECLARE_SETTINGSFACT(AppSettings, mapboxAccount)
DECLARE_SETTINGSFACT(AppSettings, mapboxStyle)
\Settings\AppSettings.h
Defined the following;
DEFINE_SETTINGFACT(mapboxAccount)
DEFINE_SETTINGFACT(mapboxStyle)
\Settings\App.SettingsGroup.json
Defined these attributes:
{
“name”: “mapboxAccount”,
“shortDescription”: “User account for Mapbox maps”,
“longDescription”: “Your personal user account for Mapbox maps”,
“type”: “string”,
“defaultValue”: “”
},
{
“name”: “mapboxStyle”,
“shortDescription”: “Mapbox style identificator”,
“longDescription”: “Mapbox design style for Mapbox maps”,
“type”: “string”,
“defaultValue”: “”
},
\src\QtLocationPlugin\QMLControl\OfflineMap.qml
Defined in the property facts section:
property Fact _mapboxAccountFact: QGroundControl.settingsManager.appSettings.mapboxAccount
property Fact _mapboxStyleFact: QGroundControl.settingsManager.appSettings.mapboxStyle
Then in the same file in the UI section, I place entry of the two fields between the mapbox token and ersi access token. I added:
Item { width: 1; height: 1; visible: _mapboxAccountFact ? _mapboxAccountFact.visible : false }
QGCLabel { text: qsTr("Mapbox User Name"); visible: _mapboxAccountFact ? _mapboxAccountFact.visible : false }
FactTextField {
fact: _mapboxAccountFact
visible: _mapboxAccountFact ? _mapboxAccountFact.visible : false
maximumLength: 256
width: ScreenTools.defaultFontPixelWidth * 30
}
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
text: qsTr("To enable styled Mapbox maps, enter your mapbox account name.")
visible: _mapboxAccountFact ? _mapboxAccountFact.visible : false
font.pointSize: _adjustableFontPointSize
}
Item { width: 1; height: 1; visible: _mapboxStyleFact ? _mapboxStyleFact.visible : false }
QGCLabel { text: qsTr("Mapbox Style ID"); visible: _mapboxStyleFact ? _mapboxStyleFact.visible : false }
FactTextField {
fact: _mapboxStyleFact
visible: _mapboxStyleFact ? _mapboxStyleFact.visible : false
maximumLength: 256
width: ScreenTools.defaultFontPixelWidth * 30
}
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
text: qsTr("To enable styled Mapbox maps, enter your mapbox style ID.")
visible: _mapboxStyleFact ? _mapboxStyleFact.visible : false
font.pointSize: _adjustableFontPointSize
}
SECOND: Since I now have the attributes defined and captured, I can now use them to build the URL for styled maptiles download. These are minor changes. I collect the values of account and style, then IF the style has a value I override whatever maptype is selected for mapbox and retrieve styled maps with API V1instead. However, if there is no value for the style (“else”), the remaining code is not changed. QGC will then build the URL with its existing V4 API. We do want to break the existing functionality.
\src\QtLocationPlugin\QGCMapUrlEngine.cpp
In the section to build the URL for mapbox I added:
_* Retrieval of the values for mapboxAccount and mapboxStyle _
Right below the existing retrieval of mapboxToken
* Then below the condition to check if mapboxToken has a value:
Added build of URL if mapboxStyle has value with V1 API, else use the existing V4 API
{
QString mapBoxToken = qgcApp()->toolbox()->settingsManager()->appSettings()->mapboxToken()->rawValue().toString();
QString mapBoxAccount = qgcApp()->toolbox()->settingsManager()->appSettings()->mapboxAccount()->rawValue().toString();
QString mapBoxStyle = qgcApp()->toolbox()->settingsManager()->appSettings()->mapboxStyle()->rawValue().toString();
if(!mapBoxToken.isEmpty()) {
if(!mapBoxStyle.isEmpty()) {
QString server = "https://api.mapbox.com/styles/v1";
server += QString("/%1/%2/tiles/256").arg(mapBoxAccount).arg(mapBoxStyle);
server += QString("/%1/%2/%3?access_token=%4").arg(zoom).arg(x).arg(y).arg(mapBoxToken);
return server;
}
else {
QString server = "https://api.mapbox.com/v4/";
THE END RESULT
Being an angler, I look forward to instruct my boat to drive out and drop bait and hooks on each side of the small plateau I’ve found and one on the top. I guess the fish will swim on each side of it. And maybe they also feed on the top. An educated guess, and user friendly to have this directly in QGC. The map is a shaded version with 50 % transparency set in Mapbox Studio.