diff --git a/src/Resources/xml/video-layout.xml b/src/Resources/xml/video-layout.xml
index 257882b6b..0fa5730e2 100644
--- a/src/Resources/xml/video-layout.xml
+++ b/src/Resources/xml/video-layout.xml
@@ -189,6 +189,7 @@
16
+ http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png
diff --git a/src/Train/MeterWidget.cpp b/src/Train/MeterWidget.cpp
index 0ad41d463..33448c877 100644
--- a/src/Train/MeterWidget.cpp
+++ b/src/Train/MeterWidget.cpp
@@ -22,8 +22,9 @@
#include "ErgFile.h"
#include "Context.h"
#include "Units.h"
-
-#include
+#include "LocationInterpolation.h"
+#include
+#include
MeterWidget::MeterWidget(QString Name, QWidget *parent, QString Source) : QWidget(parent), m_Name(Name), m_container(parent), m_Source(Source)
{
@@ -52,7 +53,6 @@ MeterWidget::MeterWidget(QString Name, QWidget *parent, QString Source) : QWidge
m_RangeMax = 100;
m_Angle = 180.0;
m_SubRange = 10;
- m_Zoom = 16;
boundingRectVisibility = false;
backgroundVisibility = false;
forceSquareRatio = true;
@@ -115,6 +115,17 @@ QSize MeterWidget::minimumSize() const
return QSize(m_Width, m_Height);
}
+void MeterWidget::startPlayback(Context* context)
+{
+
+}
+
+void MeterWidget::stopPlayback()
+{
+
+}
+
+
void MeterWidget::paintEvent(QPaintEvent* paintevent)
{
Q_UNUSED(paintevent);
@@ -421,12 +432,12 @@ void ElevationMeterWidget::lazySetup(void)
void ElevationMeterWidget::paintEvent(QPaintEvent* paintevent)
{
+ MeterWidget::paintEvent(paintevent);
+
// TODO : show Power when not in slope simulation mode
if (!context || !context->currentErgFile() || context->currentErgFile()->Points.size()<=1)
return;
- MeterWidget::paintEvent(paintevent);
-
m_MainBrush = QBrush(m_MainColor);
m_BackgroundBrush = QBrush(m_BackgroundColor);
m_OutlinePen = QPen(m_OutlineColor);
@@ -498,86 +509,231 @@ void ElevationMeterWidget::paintEvent(QPaintEvent* paintevent)
painter.drawText(distanceDrawX, distanceDrawY, distanceString);
}
-
-LiveMapWidget::LiveMapWidget(QString Name, QWidget *parent, QString Source) : MeterWidget(Name, parent, Source)
+LiveMapWidget::LiveMapWidget(QString Name, QWidget* parent, QString Source, Context* context) : MeterWidget(Name, parent, Source), context(context)
{
+ m_Zoom = 16;
+ m_osmURL = "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
forceSquareRatio = false;
liveMapView = new QWebEngineView(this);
- liveMapInitialized = false;
+ webPage = new QWebEnginePage(liveMapView);
+ liveMapView->setPage(webPage);
+ routeInitialized = false;
+ mapInitialized = false;
+ // Connect JS to C++
+ webobj = new WebClass();
+ channel = new QWebChannel(this);
+ channel->registerObject("webobj", webobj);
+ liveMapView->page()->setWebChannel(channel);
+ loadingLiveMap();
}
-void LiveMapWidget::resizeEvent(QResizeEvent *)
+void LiveMapWidget::startPlayback(Context* context)
+{
+ MeterWidget::startPlayback(context);
+ if (context->currentErgFile())
+ {
+ buildRouteArrayLatLngs(context);
+ if (!mapInitialized) {
+ initLiveMap(context);
+ mapInitialized = true;
+ }
+ }
+ else
+ {
+ qDebug() << "Error: LiveMap cannot find Ergfile";
+ }
+}
+
+LiveMapWidget::~LiveMapWidget()
+{
+ delete webobj;
+ delete channel;
+ delete webPage;
+ delete liveMapView;
+}
+
+void LiveMapWidget::stopPlayback()
+{
+ MeterWidget::stopPlayback();
+ loadingLiveMap();
+ mapInitialized = false;
+}
+
+void LiveMapWidget::resizeEvent(QResizeEvent*)
{
liveMapView->resize(m_Width, m_Height);
}
+void LiveMapWidget::loadingLiveMap()
+{
+ //Set initial page to display loading map.
+ currentPage = QString("\n"
+ "Loading map...
\n"
+ "\n");
+ liveMapView->page()->setHtml(currentPage);
+}
+
+// Initialize map, build route and show it
+void LiveMapWidget::initLiveMap(Context* context)
+{
+ QString startingLat = QVariant(context->currentErgFile()->Points[0].lat).toString();
+ QString startingLon = QVariant(context->currentErgFile()->Points[0].lon).toString();
+
+ if (startingLat == "0" && startingLon == "0")
+ {
+ currentPage = QString("\n"
+ "Ride contains invalid data
\n"
+ "\n");
+ liveMapView->page()->setHtml(currentPage);
+ }
+ else
+ {
+ QString js = ("\n");
+ routeLatLngs = "[";
+ QString code = "";
+
+ for (int pt = 0; pt < context->currentErgFile()->Points.size() - 1; pt++) {
+
+ geolocation geoloc(context->currentErgFile()->Points[pt].lat, context->currentErgFile()->Points[pt].lon, context->currentErgFile()->Points[pt].y);
+ if (geoloc.IsReasonableGeoLocation()) {
+ if (pt == 0) { routeLatLngs += "["; }
+ else { routeLatLngs += ",["; }
+ routeLatLngs += QVariant(context->currentErgFile()->Points[pt].lat).toString();
+ routeLatLngs += ",";
+ routeLatLngs += QVariant(context->currentErgFile()->Points[pt].lon).toString();
+ routeLatLngs += "]";
+ }
+
+ }
+ routeLatLngs += "]";
+ // We can either setHTML page or runJavaScript but not both.
+ // So we create divs with the 2 methods we need to run when the document loads
+ code = QString("showRoute (" + routeLatLngs + ");");
+ js += ("\n");
+ createHtml(m_osmURL, js);
+ liveMapView->page()->setHtml(currentPage);
+ routeInitialized = true;
+ }
+}
+
+// Show route or move the marker at the next location
void LiveMapWidget::plotNewLatLng(double dLat, double dLon)
{
- if ( ! liveMapInitialized ) initLiveMap(dLat, dLon);
-
+ QString code = "";
QString sLat = QString::number(dLat);
QString sLon = QString::number(dLon);
- QString code = QString("moveMarker(" + sLat + " , " + sLon + ")");
+ QString sMapZoom = QString::number(m_Zoom);
- liveMapView->page()->runJavaScript(code);
+ if (!routeInitialized)
+ {
+ code = QString("showRoute(" + routeLatLngs + ");");
+ liveMapView->page()->runJavaScript(code);
+ routeInitialized = true;
+ }
+ else {
+ code += QString("moveMarker(" + sLat + " , " + sLon + ");");
+ liveMapView->page()->runJavaScript(code);
+ }
}
-void LiveMapWidget::initLiveMap(double dLat, double dLon)
+// Build LatLon array for selected workout
+void LiveMapWidget::buildRouteArrayLatLngs(Context* context)
{
- createHtml(dLat, dLon, m_Zoom);
- liveMapView->page()->setHtml(currentPage);
- liveMapView->show();
- liveMapInitialized = true;
+ routeLatLngs = "[";
+ for (int pt = 0; pt < context->currentErgFile()->Points.size() - 1; pt++) {
+ if (pt == 0) { routeLatLngs += "["; }
+ else { routeLatLngs += ",["; }
+ routeLatLngs += QVariant(context->currentErgFile()->Points[pt].lat).toString();
+ routeLatLngs += ",";
+ routeLatLngs += QVariant(context->currentErgFile()->Points[pt].lon).toString();
+ routeLatLngs += "]";
+ }
+ routeLatLngs += "]";
}
-void LiveMapWidget::createHtml(double dLat, double dLon, int iMapZoom)
+
+// Build HTML code with all the javascript functions to be called later
+// to update the postion on the map
+void LiveMapWidget::createHtml(QString sBaseUrl, QString autoRunJS)
{
- QString sLat = QString::number(dLat);
- QString sLon = QString::number(dLon);
- QString sWidth = QString::number(m_Width);
- QString sHeight = QString::number(m_Height);
- QString sMapZoom = QString::number(iMapZoom);
currentPage = "";
currentPage = QString("\n"
- " \n"
- "\n"
- "GoldenCheetah LiveMap - TrainView\n");
- //Leaflet CSS and JS
- currentPage += QString("\n"
- "\n"
- "\n");
-
- // local functions
- currentPage += QString("\n"
- "\n"
+ "\n"
+ "\n"
+ "\n"
- "\n");
+ " doubleClickZoom : false }\n"
+ " mymap = L.map('mapid', mapOptions);\n"
+ " myscale = L.control.scale().addTo(mymap);\n"
+ " mylayer = new L.tileLayer('" + sBaseUrl + "');\n"
+ " mymap.addLayer(mylayer);\n"
+ "}\n"
+ "function showMyMarker(myLat, myLon) {\n"
+ " mymarker = new L.marker([myLat, myLon], {\n"
+ " draggable: false,\n"
+ " title : \"GoldenCheetah - Workout LiveMap\",\n"
+ " alt : \"GoldenCheetah - Workout LiveMap\",\n"
+ " riseOnHover : true\n"
+ " }).addTo(mymap);\n"
+ "}\n"
+ "function centerMap(myLat, myLon, myZoom) {\n"
+ " latlng = L.latLng(myLat, myLon);\n"
+ " mymap.setView(latlng, myZoom)\n"
+ "}\n"
+ "function showRoute(myRouteLatlngs) {\n"
+ " routepolyline = L.polyline(myRouteLatlngs, { color: 'red' }).addTo(mymap);\n"
+ //" mymap.fitBounds(routepolyline.getBounds());\n"
+ "}\n"
+ "\n"
+ + autoRunJS +
+ "