1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2026-06-01 21:54:55 -04:00

Add better Map API key support

This commit is contained in:
Jon Beniston
2021-11-23 16:44:07 +00:00
parent a41d0319dc
commit c0fdb670ab
17 changed files with 558 additions and 69 deletions
+246 -13
View File
@@ -669,6 +669,9 @@ void MapGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
(void) rollDown;
m_settings.m_rollupState = saveState();
applySettings();
}
MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent) :
@@ -684,6 +687,12 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur
{
ui->setupUi(this);
quint16 port = 0; // Pick a free port
// Free keys, so no point in stealing them :)
QString tfKey = m_settings.m_thunderforestAPIKey.isEmpty() ? "3e1f614f78a345459931ba3c898e975e" : m_settings.m_thunderforestAPIKey;
QString mtKey = m_settings.m_maptilerAPIKey.isEmpty() ? "q2RVNAe3eFKCH4XsrE3r" : m_settings.m_maptilerAPIKey;
m_templateServer = new OSMTemplateServer(tfKey, mtKey, m_osmPort);
ui->map->rootContext()->setContextProperty("mapModel", &m_mapModel);
// 5.12 doesn't display map items when fully zoomed out
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
@@ -745,6 +754,11 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur
MapGUI::~MapGUI()
{
if (m_templateServer)
{
m_templateServer->close();
delete m_templateServer;
}
delete ui;
}
@@ -804,42 +818,252 @@ void MapGUI::addRadioTimeTransmitters()
}
}
static QString arrayToString(QJsonArray array)
{
QString s;
for (int i = 0; i < array.size(); i++)
{
s = s.append(array[i].toString());
s = s.append(" ");
}
return s;
}
// Coming soon
void MapGUI::addDAB()
{
QFile file("stationlist_SI.json");
if (file.open(QIODevice::ReadOnly))
{
QByteArray bytes = file.readAll();
QJsonParseError error;
QJsonDocument json = QJsonDocument::fromJson(bytes, &error);
if (!json.isNull())
{
if (json.isObject())
{
QJsonObject obj = json.object();
QJsonValue stations = obj.value("stations");
QJsonArray stationsArray = stations.toArray();
for (int i = 0; i < stationsArray.size(); i++)
{
QJsonObject station = stationsArray[i].toObject();
// "txs" contains array of transmitters
QString stationName = station.value("stationName").toString();
QJsonArray txs = station.value("txs").toArray();
QString languages = arrayToString(station.value("language").toArray());
QString format = arrayToString(station.value("format").toArray());
for (int j = 0; j < txs.size(); j++)
{
QJsonObject tx = txs[j].toObject();
QString band = tx.value("band").toString();
double lat = tx.value("latitude").toString().toDouble();
double lon = tx.value("longitude").toString().toDouble();
double alt = tx.value("haat").toString().toDouble(); // This is height above terrain - not actual height - Check "haatUnits" is m
double frequency = tx.value("frequency").toString().toDouble(); // Can be MHz or kHz for AM
double erp = tx.value("erp").toString().toDouble();
SWGSDRangel::SWGMapItem mapItem;
mapItem.setLatitude(lat);
mapItem.setLongitude(lon);
mapItem.setAltitude(alt);
mapItem.setImageRotation(0);
mapItem.setImageMinZoom(8);
if (band == "DAB")
{
// Name should be unique - can we use TII code for this? can it repeat across countries?
QString name = QString("%1").arg(tx.value("tsId").toString());
mapItem.setName(new QString(name));
mapItem.setImage(new QString("antennadab.png"));
// Need tiicode?
QString text = QString("%1 Transmitter\nStation: %2\nFrequency: %3 %4\nPower: %5 %6\nLanguage(s): %7\nType: %8\nService: %9\nEnsemble: %10")
.arg(band)
.arg(stationName)
.arg(frequency)
.arg(tx.value("frequencyUnits").toString())
.arg(erp)
.arg(tx.value("erpUnits").toString())
.arg(languages)
.arg(format)
.arg(tx.value("serviceLabel").toString())
.arg(tx.value("ensembleLabel").toString())
;
mapItem.setText(new QString(text));
m_mapModel.update(m_map, &mapItem, MapSettings::SOURCE_DAB);
}
else if (band == "FM")
{
// Name should be unique
QString name = QString("%1").arg(tx.value("tsId").toString());
mapItem.setName(new QString(name));
mapItem.setImage(new QString("antennafm.png"));
QString text = QString("%1 Transmitter\nStation: %2\nFrequency: %3 %4\nPower: %5 %6\nLanguage(s): %7\nType: %8")
.arg(band)
.arg(stationName)
.arg(frequency)
.arg(tx.value("frequencyUnits").toString())
.arg(erp)
.arg(tx.value("erpUnits").toString())
.arg(languages)
.arg(format)
;
mapItem.setText(new QString(text));
m_mapModel.update(m_map, &mapItem, MapSettings::SOURCE_FM);
}
else if (band == "AM")
{
// Name should be unique
QString name = QString("%1").arg(tx.value("tsId").toString());
mapItem.setName(new QString(name));
mapItem.setImage(new QString("antennaam.png"));
QString text = QString("%1 Transmitter\nStation: %2\nFrequency: %3 %4\nPower: %5 %6\nLanguage(s): %7\nType: %8")
.arg(band)
.arg(stationName)
.arg(frequency)
.arg(tx.value("frequencyUnits").toString())
.arg(erp)
.arg(tx.value("erpUnits").toString())
.arg(languages)
.arg(format)
;
mapItem.setText(new QString(text));
m_mapModel.update(m_map, &mapItem, MapSettings::SOURCE_AM);
}
}
}
}
else
{
qDebug() << "MapGUI::addDAB: Expecting an object in DAB json:";
}
}
else
{
qDebug() << "MapGUI::addDAB: Failed to parse DAB json: " << error.errorString();
}
}
else
{
qDebug() << "MapGUI::addDAB: Failed to open DAB json";
}
}
void MapGUI::blockApplySettings(bool block)
{
m_doApplySettings = !block;
}
QString MapGUI::osmCachePath()
{
return QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + "/QtLocation/5.8/tiles/osm/sdrangel_map";
}
void MapGUI::clearOSMCache()
{
// Delete all cached custom tiles when user changes the URL. Is there a better way to do this?
QDir dir(osmCachePath());
if (dir.exists())
{
QStringList filenames = dir.entryList({"osm_100-l-8-*.png"});
for (const auto& filename : filenames)
{
QFile file(dir.filePath(filename));
if (!file.remove()) {
qDebug() << "MapGUI::clearOSMCache: Failed to remove " << file;
}
}
}
}
void MapGUI::applyMapSettings()
{
float stationLatitude = MainCore::instance()->getSettings().getLatitude();
float stationLongitude = MainCore::instance()->getSettings().getLongitude();
float stationAltitude = MainCore::instance()->getSettings().getAltitude();
QQuickItem *item = ui->map->rootObject();
// Save existing position of map
QObject *object = item->findChild<QObject*>("map");
QGeoCoordinate coords;
double zoom;
if (object != nullptr)
{
// Save existing position of map
coords = object->property("center").value<QGeoCoordinate>();
zoom = object->property("zoomLevel").value<double>();
}
else
{
// Center on my location when map is first opened
coords.setLatitude(stationLatitude);
coords.setLongitude(stationLongitude);
coords.setAltitude(stationAltitude);
zoom = 10.0;
}
// Create the map using the specified provider
QQmlProperty::write(item, "mapProvider", m_settings.m_mapProvider);
QVariantMap parameters;
if (!m_settings.m_mapBoxApiKey.isEmpty() && m_settings.m_mapProvider == "mapbox")
if (!m_settings.m_mapBoxAPIKey.isEmpty() && m_settings.m_mapProvider == "mapbox")
{
parameters["mapbox.map_id"] = "mapbox.satellite"; // The only one that works
parameters["mapbox.access_token"] = m_settings.m_mapBoxApiKey;
parameters["mapbox.access_token"] = m_settings.m_mapBoxAPIKey;
}
if (!m_settings.m_mapBoxApiKey.isEmpty() && m_settings.m_mapProvider == "mapboxgl")
if (!m_settings.m_mapBoxAPIKey.isEmpty() && m_settings.m_mapProvider == "mapboxgl")
{
parameters["mapboxgl.access_token"] = m_settings.m_mapBoxApiKey;
parameters["mapboxgl.access_token"] = m_settings.m_mapBoxAPIKey;
if (!m_settings.m_mapBoxStyles.isEmpty())
parameters["mapboxgl.mapping.additional_style_urls"] = m_settings.m_mapBoxStyles;
}
//QQmlProperty::write(item, "mapParameters", parameters);
QMetaObject::invokeMethod(item, "createMap", Q_ARG(QVariant, QVariant::fromValue(parameters)));
if (m_settings.m_mapProvider == "osm")
{
// Allow user to specify URL
if (!m_settings.m_osmURL.isEmpty()) {
parameters["osm.mapping.custom.host"] = m_settings.m_osmURL; // E.g: "http://a.tile.openstreetmap.fr/hot/"
}
// Use our repo, so we can append API key
parameters["osm.mapping.providersrepository.address"] = QString("http://127.0.0.1:%1/").arg(m_osmPort);
// Use application specific cache, as other apps may not use API key so will have different images
QString cachePath = osmCachePath();
parameters["osm.mapping.cache.directory"] = cachePath;
// On Linux, we need to create the directory
QDir dir(cachePath);
if (!dir.exists()) {
dir.mkpath(cachePath);
}
}
QVariant retVal;
if (!QMetaObject::invokeMethod(item, "createMap", Qt::DirectConnection,
Q_RETURN_ARG(QVariant, retVal),
Q_ARG(QVariant, QVariant::fromValue(parameters)),
//Q_ARG(QVariant, mapType),
Q_ARG(QVariant, QVariant::fromValue(this))))
{
qCritical() << "MapGUI::applyMapSettings - Failed to invoke createMap";
}
QObject *newMap = retVal.value<QObject *>();
// Restore position of map
object = item->findChild<QObject*>("map");
if ((object != nullptr) && coords.isValid())
object->setProperty("center", QVariant::fromValue(coords));
if (newMap != nullptr)
{
if (coords.isValid())
{
newMap->setProperty("zoomLevel", QVariant::fromValue(zoom));
newMap->setProperty("center", QVariant::fromValue(coords));
}
}
else
{
qCritical() << "MapGUI::applyMapSettings - createMap returned a nullptr";
}
supportedMapsChanged();
}
void MapGUI::supportedMapsChanged()
{
QQuickItem *item = ui->map->rootObject();
QObject *object = item->findChild<QObject*>("map");
// Get list of map types
ui->mapTypes->clear();
@@ -847,14 +1071,17 @@ void MapGUI::applyMapSettings()
{
// Mapbox plugin only works for Satellite imagary, despite what is indicated
if (m_settings.m_mapProvider == "mapbox")
{
ui->mapTypes->addItem("Satellite");
}
else
{
QVariant mapTypesVariant;
QMetaObject::invokeMethod(item, "getMapTypes", Q_RETURN_ARG(QVariant, mapTypesVariant));
QStringList mapTypes = mapTypesVariant.value<QStringList>();
for (int i = 0; i < mapTypes.size(); i++)
for (int i = 0; i < mapTypes.size(); i++) {
ui->mapTypes->addItem(mapTypes[i]);
}
}
}
}
@@ -880,6 +1107,7 @@ void MapGUI::displaySettings()
m_mapModel.setGroundTrackColor(m_settings.m_groundTrackColor);
m_mapModel.setPredictedGroundTrackColor(m_settings.m_predictedGroundTrackColor);
applyMapSettings();
restoreState(m_settings.m_rollupState);
blockApplySettings(false);
}
@@ -1052,11 +1280,16 @@ void MapGUI::on_displaySettings_clicked()
MapSettingsDialog dialog(&m_settings);
if (dialog.exec() == QDialog::Accepted)
{
if (dialog.m_mapSettingsChanged)
if (dialog.m_osmURLChanged) {
clearOSMCache();
}
if (dialog.m_mapSettingsChanged) {
applyMapSettings();
}
applySettings();
if (dialog.m_sourcesChanged)
if (dialog.m_sourcesChanged) {
m_mapModel.setSources(m_settings.m_sources);
}
m_mapModel.setGroundTrackColor(m_settings.m_groundTrackColor);
m_mapModel.setPredictedGroundTrackColor(m_settings.m_predictedGroundTrackColor);
}