Skip to content

Commit 5d5bffd

Browse files
author
William Goodspeed
committed
Support customizing the tile server for online map
In some countries with Internet censorship, the default OpenStreetMap tile server may not be accessible. This commit adds an option to choose the preferred tile server from a predefined list or customize them as needed. By default, the online map retains the old behaviour which defaults to the user's system language and it also provides an option to choose the langugage for OSM. Signed-off-by: William Goodspeed <goodspeed@anche.no>
1 parent d744cb8 commit 5d5bffd

File tree

6 files changed

+258
-6
lines changed

6 files changed

+258
-6
lines changed

res/map/onlinemap.html

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@
6767
<div id="map"></div>
6868

6969
<script>
70-
7170
var grids_worked = []; //field of Grids used for rendering Worked Grids
7271
var grids_confirmed = []; //field of Grids used for rendering Confirmed Grids
7372
var mylocations = []; //field of My Locations
@@ -126,7 +125,6 @@
126125
popupAnchor: [1, -14]
127126
});
128127

129-
130128
var language = navigator.language || navigator.userLanguage;
131129
var mapUrl;
132130

@@ -139,9 +137,16 @@
139137
mapUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
140138
}
141139

142-
L.tileLayer(mapUrl, {
143-
attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a>'
144-
}).addTo(map);
140+
if (!window.tileConfig) {
141+
window.tileConfig = {
142+
url: mapUrl,
143+
options: {
144+
attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a>',
145+
},
146+
};
147+
}
148+
149+
L.tileLayer(window.tileConfig.url, window.tileConfig.options).addTo(map);
145150

146151
var maidenheadConfWorked = L.maidenheadConfWorked({color : 'rgba(255, 0, 0, 0.5)'}).addTo(map);
147152
var grayline = L.terminator({fillOpacity: 0.2})

ui/OnlineMapWidget.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
#include <QVector3D>
77
#include <QtMath>
88
#include <QFile>
9+
#include <QJsonDocument>
10+
#include <QWebEngineScript>
11+
#include <QWebEngineScriptCollection>
912
#include "OnlineMapWidget.h"
1013
#include "core/debug.h"
1114
#include "data/Gridsquare.h"
@@ -37,7 +40,7 @@ OnlineMapWidget::OnlineMapWidget(QWidget *parent):
3740
FCT_IDENTIFICATION;
3841

3942
main_page->setWebChannel(&channel);
40-
43+
injectTileConfig();
4144
setPage(main_page);
4245
main_page->load(QUrl(QLatin1String("qrc:/res/map/onlinemap.html")));
4346
connect(this, &OnlineMapWidget::loadFinished, this, &OnlineMapWidget::finishLoading);
@@ -56,6 +59,36 @@ OnlineMapWidget::OnlineMapWidget(QWidget *parent):
5659
connect(&webChannelHandler, &MapWebChannelHandler::IBPPressed, this, &OnlineMapWidget::IBPCallsignTrigger);
5760
}
5861

62+
void OnlineMapWidget::injectTileConfig()
63+
{
64+
if (!main_page)
65+
return;
66+
67+
QSettings settings;
68+
QString optionsStr = settings.value("tileServer/config", "{}").toString();
69+
70+
QJsonDocument doc = QJsonDocument::fromJson(optionsStr.toUtf8());
71+
72+
if (doc.isObject()) {
73+
QJsonObject obj = doc.object();
74+
if (!obj.contains("url") || !obj["url"].isString() ||
75+
!obj.contains("options") || !obj["options"].isObject()) {
76+
optionsStr = "undefined";
77+
}
78+
}
79+
80+
QString jsCode = QString("window.tileConfig = %1;").arg(optionsStr);
81+
82+
QWebEngineScript script;
83+
script.setName("InjectTileConfig");
84+
script.setSourceCode(jsCode);
85+
script.setInjectionPoint(QWebEngineScript::DocumentCreation);
86+
script.setWorldId(QWebEngineScript::MainWorld);
87+
script.setRunsOnSubFrames(false);
88+
89+
main_page->scripts().insert(script);
90+
}
91+
5992
void OnlineMapWidget::setTarget(double lat, double lon)
6093
{
6194
FCT_IDENTIFICATION;

ui/OnlineMapWidget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ protected slots:
6363
double lastSeenAzimuth, lastSeenElevation;
6464
bool isRotConnected;
6565

66+
void injectTileConfig(void);
6667
void runJavaScript(const QString &);
6768
};
6869

ui/SettingsDialog.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,40 @@ SettingsDialog::SettingsDialog(MainWindow *parent) :
293293
ui->cwKeyModeSelect->addItem(tr("Ultimate"), CWKey::ULTIMATE);
294294
ui->cwKeyModeSelect->setCurrentIndex(ui->cwKeyModeSelect->findData(CWKey::IAMBIC_B));
295295

296+
tileServers.append({"OpenStreetMap (Default, System Language)", QJsonObject{}});
297+
tileServers.append({"OpenStreetMap (English)", QJsonObject{
298+
{"url", "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"},
299+
{"options", QJsonObject{{"attribution", "&copy; OpenStreetMap"}}},
300+
}});
301+
tileServers.append({"OpenStreetMap (French)", QJsonObject{
302+
{"url", "https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png"},
303+
{"options", QJsonObject{{"attribution", "&copy; OpenStreetMap"}}},
304+
}});
305+
tileServers.append({"OpenStreetMap (German)", QJsonObject{
306+
{"url", "https://tile.openstreetmap.de/{z}/{x}/{y}.png"},
307+
{"options", QJsonObject{{"attribution", "&copy; OpenStreetMap"}}},
308+
}});
309+
tileServers.append({"AutoNavi (Satellite, Chinese)", QJsonObject{
310+
{"url", "https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}"},
311+
{"options", QJsonObject{{"attribution", "&copy; AutoNavi"}}},
312+
}});
313+
tileServers.append({"AutoNavi (Roadmap, Chinese)", QJsonObject{
314+
{"url", "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}"},
315+
{"options", QJsonObject{{"attribution", "&copy; AutoNavi"}}},
316+
}});
317+
318+
ui->tileServerComboBox->setEditable(true);
319+
for (const auto &pair : tileServers) {
320+
QString name = pair.first;
321+
QJsonObject info = pair.second;
322+
ui->tileServerComboBox->addItem(name);
323+
}
324+
ui->tileServerComboBox->addItem("Custom");
325+
326+
connect(ui->tileServerComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
327+
this, &SettingsDialog::onTileServerComboBoxChanged);
328+
onTileServerComboBoxChanged(ui->tileServerComboBox->currentIndex());
329+
296330
/* disable WSJTX Multicast by default */
297331
joinMulticastChanged(false);
298332

@@ -301,6 +335,47 @@ SettingsDialog::SettingsDialog(MainWindow *parent) :
301335
readSettings();
302336
}
303337

338+
void SettingsDialog::onTileServerComboBoxChanged(int index)
339+
{
340+
bool isCustom = index == (ui->tileServerComboBox->count() - 1);
341+
QString configStr = settings.value("tileServer/config", "{}").toString();
342+
343+
if (isCustom) {
344+
ui->tileOptionsTextEdit->setReadOnly(false);
345+
ui->tileMapUrlLineEdit->setReadOnly(false);
346+
347+
QJsonDocument info = QJsonDocument::fromJson(configStr.toUtf8());
348+
if (info.object().isEmpty() || settings.value("tileServer/index", 0).toInt()) {
349+
ui->tileMapUrlLineEdit->setText("");
350+
ui->tileOptionsTextEdit->setPlainText("");
351+
return;
352+
};
353+
354+
QJsonObject obj = info.object();
355+
ui->tileMapUrlLineEdit->setText(obj.contains("options") ? obj["url"].toString() : "");
356+
ui->tileOptionsTextEdit->setPlainText(obj.contains("options")
357+
? QJsonDocument(obj["options"].toObject()).toJson(QJsonDocument::Compact)
358+
: "");
359+
return;
360+
} else {
361+
ui->tileOptionsTextEdit->setReadOnly(true);
362+
ui->tileMapUrlLineEdit->setReadOnly(true);
363+
}
364+
365+
QJsonObject info = tileServers[index].second;
366+
if (info.isEmpty()) {
367+
ui->tileMapUrlLineEdit->setText("");
368+
ui->tileOptionsTextEdit->setPlainText("");
369+
return;
370+
};
371+
372+
ui->tileMapUrlLineEdit->setText(info.contains("options") ? info["url"].toString() : "");
373+
ui->tileOptionsTextEdit->setPlainText(info.contains("options")
374+
? QJsonDocument(info["options"].toObject()).toJson(QJsonDocument::Compact)
375+
: "");
376+
}
377+
378+
304379
void SettingsDialog::save() {
305380
FCT_IDENTIFICATION;
306381

@@ -2401,6 +2476,21 @@ void SettingsDialog::readSettings()
24012476
ui->dateFormatCustomRadioButton->setChecked(!dateSystemFormat);
24022477
ui->dateFormatStringEdit->setText(locale.getSettingDateFormat());
24032478

2479+
/**************/
2480+
/* Online Map */
2481+
/**************/
2482+
2483+
int index = settings.value("tileServer/index", 0).toInt();
2484+
QString configStr = settings.value("tileServer/config", "{}").toString();
2485+
2486+
if (index >= ui->tileServerComboBox->count()) index = 0;
2487+
if (index == 0 && !QJsonDocument::fromJson(configStr.toUtf8()).object().isEmpty()) {
2488+
/* For convenience, `default' and `custom' use the same index, but options was stored only for `custom'. */
2489+
ui->tileServerComboBox->setCurrentIndex(ui->tileServerComboBox->count() - 1);
2490+
} else {
2491+
ui->tileServerComboBox->setCurrentIndex(index);
2492+
}
2493+
24042494
/******************/
24052495
/* END OF Reading */
24062496
/******************/
@@ -2525,6 +2615,26 @@ void SettingsDialog::writeSettings()
25252615
locale.setSettingUseSystemDateFormat(systemDateChecked);
25262616
if ( !systemDateChecked )
25272617
locale.setSettingDateFormat(ui->dateFormatStringEdit->text());
2618+
2619+
/**************/
2620+
/* Online Map */
2621+
/**************/
2622+
int index = ui->tileServerComboBox->currentIndex();
2623+
bool isCustom = index == (ui->tileServerComboBox->count() - 1);
2624+
2625+
if (isCustom) {
2626+
settings.setValue("tileServer/index", 0);
2627+
QJsonObject info = QJsonObject{
2628+
{"url", ui->tileMapUrlLineEdit->text()},
2629+
{"options", QJsonDocument::fromJson(ui->tileOptionsTextEdit->toPlainText().toUtf8()).object()}
2630+
};
2631+
settings.setValue("tileServer/config", QJsonDocument(info).toJson(QJsonDocument::Compact));
2632+
return;
2633+
}
2634+
2635+
settings.setValue("tileServer/index", index);
2636+
QJsonObject info = tileServers[index].second;
2637+
settings.setValue("tileServer/config", QJsonDocument(info).toJson(QJsonDocument::Compact));
25282638
}
25292639

25302640
/* this function is called when user modify rig progile

ui/SettingsDialog.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ public slots:
133133
void generateMembershipCheckboxes();
134134
void generateQRZAPICallsignTable();
135135
void saveQRZAPICallsignTable();
136+
void onTileServerComboBoxChanged(int index);
136137

137138
QSqlTableModel* modeTableModel;
138139
QSqlTableModel* bandTableModel;
@@ -151,6 +152,8 @@ public slots:
151152
QList<QCheckBox*> memberListCheckBoxes;
152153
Ui::SettingsDialog *ui;
153154
LogLocale locale;
155+
QVector<QPair<QString, QJsonObject>> tileServers;
156+
QSettings settings;
154157
bool sotaFallback;
155158
bool potaFallback;
156159
bool wwffFallback;

ui/SettingsDialog.ui

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4564,6 +4564,106 @@
45644564
</item>
45654565
</layout>
45664566
</widget>
4567+
<widget class="QWidget" name="onlineMapTab">
4568+
<attribute name="title">
4569+
<string>Online Map</string>
4570+
</attribute>
4571+
<layout class="QVBoxLayout" name="verticalLayout_20">
4572+
<item>
4573+
<layout class="QGridLayout" name="gridLayout">
4574+
<item row="1" column="1">
4575+
<widget class="QLineEdit" name="tileMapUrlLineEdit">
4576+
<property name="font">
4577+
<font>
4578+
<family>Monospace</family>
4579+
</font>
4580+
</property>
4581+
</widget>
4582+
</item>
4583+
<item row="2" column="1">
4584+
<widget class="QPlainTextEdit" name="tileOptionsTextEdit">
4585+
<property name="sizePolicy">
4586+
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
4587+
<horstretch>0</horstretch>
4588+
<verstretch>0</verstretch>
4589+
</sizepolicy>
4590+
</property>
4591+
<property name="font">
4592+
<font>
4593+
<family>Monospace</family>
4594+
</font>
4595+
</property>
4596+
<property name="readOnly">
4597+
<bool>true</bool>
4598+
</property>
4599+
</widget>
4600+
</item>
4601+
<item row="2" column="0">
4602+
<widget class="QLabel" name="label_6">
4603+
<property name="sizePolicy">
4604+
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
4605+
<horstretch>0</horstretch>
4606+
<verstretch>0</verstretch>
4607+
</sizepolicy>
4608+
</property>
4609+
<property name="text">
4610+
<string>Options (JSON): </string>
4611+
</property>
4612+
</widget>
4613+
</item>
4614+
<item row="0" column="1">
4615+
<widget class="QComboBox" name="tileServerComboBox">
4616+
<property name="sizePolicy">
4617+
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
4618+
<horstretch>0</horstretch>
4619+
<verstretch>0</verstretch>
4620+
</sizepolicy>
4621+
</property>
4622+
</widget>
4623+
</item>
4624+
<item row="0" column="0">
4625+
<widget class="QLabel" name="label_4">
4626+
<property name="sizePolicy">
4627+
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
4628+
<horstretch>0</horstretch>
4629+
<verstretch>0</verstretch>
4630+
</sizepolicy>
4631+
</property>
4632+
<property name="text">
4633+
<string>Tile Server: </string>
4634+
</property>
4635+
</widget>
4636+
</item>
4637+
<item row="1" column="0">
4638+
<widget class="QLabel" name="label_9">
4639+
<property name="sizePolicy">
4640+
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
4641+
<horstretch>0</horstretch>
4642+
<verstretch>0</verstretch>
4643+
</sizepolicy>
4644+
</property>
4645+
<property name="text">
4646+
<string>Map Url:</string>
4647+
</property>
4648+
</widget>
4649+
</item>
4650+
</layout>
4651+
</item>
4652+
<item>
4653+
<spacer name="verticalSpacer_25">
4654+
<property name="orientation">
4655+
<enum>Qt::Orientation::Vertical</enum>
4656+
</property>
4657+
<property name="sizeHint" stdset="0">
4658+
<size>
4659+
<width>20</width>
4660+
<height>40</height>
4661+
</size>
4662+
</property>
4663+
</spacer>
4664+
</item>
4665+
</layout>
4666+
</widget>
45674667
</widget>
45684668
</item>
45694669
</layout>

0 commit comments

Comments
 (0)