mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-14 16:39:57 +00:00
Implemented compare mode for RideMapWindow (#786)
* Multiple activities can be viewed on one map at the same time * Implemented for OSM ang Google
This commit is contained in:
committed by
Damien Grauser
parent
69c2b447aa
commit
59a8ca2314
@@ -168,6 +168,9 @@ RideMapWindow::RideMapWindow(Context *context, int mapType) : GcChartWindow(cont
|
||||
connect(context, SIGNAL(intervalSelected()), webBridge, SLOT(intervalsChanged()));
|
||||
connect(context, SIGNAL(intervalZoom(IntervalItem*)), this, SLOT(zoomInterval(IntervalItem*)));
|
||||
connect(context, SIGNAL(configChanged(qint32)), this, SLOT(configChanged(qint32)));
|
||||
connect(context, SIGNAL(compareIntervalsStateChanged(bool)), this, SLOT(compareIntervalsStateChanged(bool)));
|
||||
connect(context, SIGNAL(compareIntervalsChanged()), this, SLOT(compareIntervalsChanged()));
|
||||
connect(context, SIGNAL(compareIntervalsChanged()), webBridge, SLOT(compareIntervalsChanged()));
|
||||
|
||||
// just the hr and power as a plot
|
||||
smallPlot = new SmallPlot(this);
|
||||
@@ -263,12 +266,18 @@ void
|
||||
RideMapWindow::showMarkersChanged(int value)
|
||||
{
|
||||
Q_UNUSED(value);
|
||||
if (context->isCompareIntervals) {
|
||||
return;
|
||||
}
|
||||
forceReplot();
|
||||
}
|
||||
|
||||
void
|
||||
RideMapWindow::showIntervalsChanged(int value)
|
||||
{
|
||||
if (context->isCompareIntervals) {
|
||||
return;
|
||||
}
|
||||
// show or hide the helper
|
||||
overlayWidget->setVisible(value);
|
||||
}
|
||||
@@ -276,6 +285,9 @@ RideMapWindow::showIntervalsChanged(int value)
|
||||
void
|
||||
RideMapWindow::showFullPlotChanged(int value)
|
||||
{
|
||||
if (context->isCompareIntervals) {
|
||||
return;
|
||||
}
|
||||
smallPlot->setVisible(value != 0);
|
||||
}
|
||||
|
||||
@@ -283,6 +295,9 @@ void
|
||||
RideMapWindow::hideShadedZonesChanged(int value)
|
||||
{
|
||||
Q_UNUSED(value);
|
||||
if (context->isCompareIntervals) {
|
||||
return;
|
||||
}
|
||||
forceReplot();
|
||||
}
|
||||
|
||||
@@ -290,6 +305,9 @@ void
|
||||
RideMapWindow::hideYellowLineChanged(int value)
|
||||
{
|
||||
Q_UNUSED(value);
|
||||
if (context->isCompareIntervals) {
|
||||
return;
|
||||
}
|
||||
forceReplot();
|
||||
}
|
||||
|
||||
@@ -297,6 +315,9 @@ void
|
||||
RideMapWindow::hideRouteLineOpacityChanged(int value)
|
||||
{
|
||||
Q_UNUSED(value);
|
||||
if (context->isCompareIntervals) {
|
||||
return;
|
||||
}
|
||||
forceReplot();
|
||||
}
|
||||
|
||||
@@ -338,13 +359,22 @@ RideMapWindow::configChanged(qint32 value)
|
||||
void
|
||||
RideMapWindow::forceReplot()
|
||||
{
|
||||
stale=true;
|
||||
rideSelected();
|
||||
if (context->isCompareIntervals) {
|
||||
createHtml();
|
||||
view->page()->setHtml(currentPage);
|
||||
} else {
|
||||
stale=true;
|
||||
rideSelected();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RideMapWindow::rideSelected()
|
||||
{
|
||||
if (context->isCompareIntervals) {
|
||||
return;
|
||||
}
|
||||
|
||||
RideItem * ride = myRideItem;
|
||||
|
||||
// set/unset blank then decide what to do next
|
||||
@@ -399,24 +429,22 @@ void RideMapWindow::createHtml()
|
||||
{
|
||||
RideItem * ride = myRideItem;
|
||||
currentPage = "";
|
||||
double minLat, minLon, maxLat, maxLon;
|
||||
minLat = minLon = 1000;
|
||||
maxLat = maxLon = -1000; // larger than 360
|
||||
|
||||
// get bounding co-ordinates for ride
|
||||
foreach(RideFilePoint *rfp, myRideItem->ride()->dataPoints()) {
|
||||
if (rfp->lat || rfp->lon) {
|
||||
minLat = std::min(minLat,rfp->lat);
|
||||
maxLat = std::max(maxLat,rfp->lat);
|
||||
minLon = std::min(minLon,rfp->lon);
|
||||
maxLon = std::max(maxLon,rfp->lon);
|
||||
}
|
||||
double minLat = 1000;
|
||||
double minLon = 1000;
|
||||
double maxLat = -1000;
|
||||
double maxLon = -1000;
|
||||
bool hasComparePositions = false;
|
||||
|
||||
if (context->isCompareIntervals) {
|
||||
hasComparePositions = getCompareBoundingBox(minLat, maxLat, minLon, maxLon);
|
||||
}
|
||||
|
||||
// No GPS data, so sorry no map
|
||||
QColor bgColor = GColor(CPLOTBACKGROUND);
|
||||
QColor fgColor = GCColor::invertColor(bgColor);
|
||||
if(!ride || !ride->ride() || ride->ride()->areDataPresent()->lat == false || ride->ride()->areDataPresent()->lon == false) {
|
||||
if( (context->isCompareIntervals && ! hasComparePositions)
|
||||
|| !ride || !ride->ride() || ride->ride()->areDataPresent()->lat == false || ride->ride()->areDataPresent()->lon == false) {
|
||||
currentPage = QString("<STYLE>BODY { background-color: %1; color: %2 }</STYLE><center>%3</center>").arg(bgColor.name()).arg(fgColor.name()).arg(tr("No GPS Data Present"));
|
||||
setIsBlank(true);
|
||||
return;
|
||||
@@ -424,6 +452,18 @@ void RideMapWindow::createHtml()
|
||||
setIsBlank(false);
|
||||
}
|
||||
|
||||
// get bounding co-ordinates for ride
|
||||
if (! context->isCompareIntervals) {
|
||||
foreach(RideFilePoint *rfp, myRideItem->ride()->dataPoints()) {
|
||||
if (rfp->lat || rfp->lon) {
|
||||
minLat = std::min(minLat,rfp->lat);
|
||||
maxLat = std::max(maxLat,rfp->lat);
|
||||
minLon = std::min(minLon,rfp->lon);
|
||||
maxLon = std::max(maxLon,rfp->lon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// html page
|
||||
currentPage = QString("<!DOCTYPE html> \n"
|
||||
"<html>\n"
|
||||
@@ -470,140 +510,246 @@ void RideMapWindow::createHtml()
|
||||
|
||||
// local functions
|
||||
currentPage += QString("<script type=\"text/javascript\">\n"
|
||||
"var map;\n" // the map object
|
||||
"var intervalList;\n" // array of intervals
|
||||
"var markerList;\n" // array of markers
|
||||
"var polyList;\n" // array of polylines
|
||||
"var tmpIntervalHighlighter;\n" // temp interval
|
||||
|
||||
// Draw the entire route, we use a local webbridge
|
||||
// to supply the data to a) reduce bandwidth and
|
||||
// b) allow local manipulation. This makes the UI
|
||||
// considerably more 'snappy'
|
||||
"function drawRoute() {\n"
|
||||
// load the GPS co-ordinates
|
||||
" webBridge.getLatLons(0, drawRouteForLatLons);\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
|
||||
if (mapCombo->currentIndex() == OSM) {
|
||||
|
||||
currentPage += QString("function drawRouteForLatLons(latlons) {\n"
|
||||
|
||||
|
||||
// route will be drawn with these options
|
||||
" var routeOptionsYellow = {\n"
|
||||
" stroke : true,\n"
|
||||
" color: '#FFFF00',\n"
|
||||
" opacity: %1,\n"
|
||||
" weight: 10,\n"
|
||||
" zIndex: -2\n"
|
||||
" };\n"
|
||||
|
||||
// lastly, populate the route path
|
||||
" var path = [];\n"
|
||||
" var j=0;\n"
|
||||
" while (j < latlons.length) { \n"
|
||||
" path.push(new L.LatLng(latlons[j], latlons[j+1]));\n"
|
||||
" j += 2;\n"
|
||||
" };\n"
|
||||
|
||||
" var routeYellow = new L.Polyline(path, routeOptionsYellow).addTo(map);\n"
|
||||
|
||||
// Listen mouse events
|
||||
"routeYellow.on('mousedown', function(event) { map.dragging.disable();L.DomEvent.stopPropagation(event);webBridge.clickPath(event.latlng.lat, event.latlng.lng); });\n" // map.setOptions({draggable: false, zoomControl: false, scrollwheel: false, disableDoubleClickZoom: true});
|
||||
"routeYellow.on('mouseup', function(event) { map.dragging.enable();L.DomEvent.stopPropagation(event);webBridge.mouseup(); });\n" // setOptions ?
|
||||
"routeYellow.on('mouseover', function(event) { webBridge.hoverPath(event.latlng.lat, event.latlng.lng); });\n"
|
||||
"routeYellow.on('mousemove', function(event) { webBridge.hoverPath(event.latlng.lat, event.latlng.lng); });\n"
|
||||
|
||||
"}\n").arg(hideYellowLine() ? 0.0 : 0.4f);
|
||||
}
|
||||
else if (mapCombo->currentIndex() == GOOGLE) {
|
||||
|
||||
currentPage += QString("function drawRouteForLatLons(latlons) {\n"
|
||||
|
||||
// route will be drawn with these options
|
||||
" var routeOptionsYellow = {\n"
|
||||
" strokeColor: '#FFFF00',\n"
|
||||
" strokeOpacity: %1,\n"
|
||||
" strokeWeight: 10,\n"
|
||||
" zIndex: -2\n"
|
||||
" };\n"
|
||||
|
||||
// create the route Polyline
|
||||
" var routeYellow = new google.maps.Polyline(routeOptionsYellow);\n"
|
||||
" routeYellow.setMap(map);\n"
|
||||
|
||||
// lastly, populate the route path
|
||||
" var path = routeYellow.getPath();\n"
|
||||
" var j=0;\n"
|
||||
" while (j < latlons.length) { \n"
|
||||
" path.push(new google.maps.LatLng(latlons[j], latlons[j+1]));\n"
|
||||
" j += 2;\n"
|
||||
" }\n"
|
||||
|
||||
// Listen mouse events
|
||||
" google.maps.event.addListener(routeYellow, 'mousedown', function(event) { map.setOptions({draggable: false, zoomControl: false, scrollwheel: false, disableDoubleClickZoom: true}); webBridge.clickPath(event.latLng.lat(), event.latLng.lng()); });\n"
|
||||
" google.maps.event.addListener(routeYellow, 'mouseup', function(event) { map.setOptions({draggable: true, zoomControl: true, scrollwheel: true, disableDoubleClickZoom: false}); webBridge.mouseup(); });\n"
|
||||
" google.maps.event.addListener(routeYellow, 'mouseover', function(event) { webBridge.hoverPath(event.latLng.lat(), event.latLng.lng()); });\n"
|
||||
|
||||
"}\n").arg(hideYellowLine() ? 0.0 : 0.4f);
|
||||
"var map;\n"); // the map object
|
||||
if (context->isCompareIntervals) {
|
||||
currentPage += QString("var compareIntervalGroup;\n"); // compare Intervals
|
||||
} else {
|
||||
currentPage += QString("var intervalList;\n" // array of intervals
|
||||
"var markerList;\n" // array of markers
|
||||
"var polyList;\n" // array of polylines
|
||||
"var tmpIntervalHighlighter;\n"); // temp interval
|
||||
}
|
||||
|
||||
currentPage += QString("function drawIntervals() { \n"
|
||||
// how many to draw?
|
||||
" webBridge.intervalCount(drawIntervalsCount);\n"
|
||||
"}\n"
|
||||
|
||||
"function drawIntervalsCount(intervals) { \n"
|
||||
// remove previous intervals highlighted
|
||||
" j= intervalList.length;\n"
|
||||
" while (j) {\n"
|
||||
" var highlighted = intervalList.pop();\n");
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// drawRoute
|
||||
|
||||
// remove highlighted
|
||||
if (mapCombo->currentIndex() == OSM) {
|
||||
if (! context->isCompareIntervals) {
|
||||
currentPage += QString(""
|
||||
" map.removeLayer(highlighted);\n");
|
||||
} else if (mapCombo->currentIndex() == GOOGLE) {
|
||||
currentPage += QString(""
|
||||
" highlighted.setMap(null);\n");
|
||||
// Draw the entire route, we use a local webbridge
|
||||
// to supply the data to a) reduce bandwidth and
|
||||
// b) allow local manipulation. This makes the UI
|
||||
// considerably more 'snappy'
|
||||
"function drawRoute() {\n"
|
||||
// load the GPS co-ordinates
|
||||
" webBridge.getLatLons(0, drawRouteForLatLons);\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
|
||||
if (mapCombo->currentIndex() == OSM) {
|
||||
currentPage += QString("function drawRouteForLatLons(latlons) {\n"
|
||||
|
||||
// route will be drawn with these options
|
||||
" var routeOptionsYellow = {\n"
|
||||
" stroke : true,\n"
|
||||
" color: '#FFFF00',\n"
|
||||
" opacity: %1,\n"
|
||||
" weight: 10,\n"
|
||||
" zIndex: -2\n"
|
||||
" };\n"
|
||||
|
||||
// lastly, populate the route path
|
||||
" var path = [];\n"
|
||||
" var j=0;\n"
|
||||
" while (j < latlons.length) { \n"
|
||||
" path.push(new L.LatLng(latlons[j], latlons[j+1]));\n"
|
||||
" j += 2;\n"
|
||||
" };\n"
|
||||
|
||||
" var routeYellow = new L.Polyline(path, routeOptionsYellow).addTo(map);\n"
|
||||
|
||||
// Listen mouse events
|
||||
" routeYellow.on('mousedown', function(event) { map.dragging.disable();L.DomEvent.stopPropagation(event);webBridge.clickPath(event.latlng.lat, event.latlng.lng); });\n" // map.setOptions({draggable: false, zoomControl: false, scrollwheel: false, disableDoubleClickZoom: true});
|
||||
" routeYellow.on('mouseup', function(event) { map.dragging.enable();L.DomEvent.stopPropagation(event);webBridge.mouseup(); });\n" // setOptions ?
|
||||
" routeYellow.on('mouseover', function(event) { webBridge.hoverPath(event.latlng.lat, event.latlng.lng); });\n"
|
||||
" routeYellow.on('mousemove', function(event) { webBridge.hoverPath(event.latlng.lat, event.latlng.lng); });\n"
|
||||
|
||||
"}\n").arg(hideYellowLine() ? 0.0 : 0.4f);
|
||||
}
|
||||
else if (mapCombo->currentIndex() == GOOGLE) {
|
||||
|
||||
currentPage += QString("function drawRouteForLatLons(latlons) {\n"
|
||||
|
||||
// route will be drawn with these options
|
||||
" var routeOptionsYellow = {\n"
|
||||
" strokeColor: '#FFFF00',\n"
|
||||
" strokeOpacity: %1,\n"
|
||||
" strokeWeight: 10,\n"
|
||||
" zIndex: -2\n"
|
||||
" };\n"
|
||||
|
||||
// create the route Polyline
|
||||
" var routeYellow = new google.maps.Polyline(routeOptionsYellow);\n"
|
||||
" routeYellow.setMap(map);\n"
|
||||
|
||||
// lastly, populate the route path
|
||||
" var path = routeYellow.getPath();\n"
|
||||
" var j=0;\n"
|
||||
" while (j < latlons.length) { \n"
|
||||
" path.push(new google.maps.LatLng(latlons[j], latlons[j+1]));\n"
|
||||
" j += 2;\n"
|
||||
" }\n"
|
||||
|
||||
// Listen mouse events
|
||||
" google.maps.event.addListener(routeYellow, 'mousedown', function(event) { map.setOptions({draggable: false, zoomControl: false, scrollwheel: false, disableDoubleClickZoom: true}); webBridge.clickPath(event.latLng.lat(), event.latLng.lng()); });\n"
|
||||
" google.maps.event.addListener(routeYellow, 'mouseup', function(event) { map.setOptions({draggable: true, zoomControl: true, scrollwheel: true, disableDoubleClickZoom: false}); webBridge.mouseup(); });\n"
|
||||
" google.maps.event.addListener(routeYellow, 'mouseover', function(event) { webBridge.hoverPath(event.latLng.lat(), event.latLng.lng()); });\n"
|
||||
|
||||
"}\n").arg(hideYellowLine() ? 0.0 : 0.4f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// drawCompareIntervals
|
||||
|
||||
if (context->isCompareIntervals) {
|
||||
currentPage += QString("function drawCompareIntervals() { \n"
|
||||
" webBridge.setCompareIntervals(doDrawCompareIntervals);\n"
|
||||
"} \n");
|
||||
|
||||
if (mapCombo->currentIndex() == OSM) {
|
||||
currentPage += QString("function doDrawCompareIntervals(intervalInfos) { \n"
|
||||
" compareIntervalGroup.clearLayers();\n"
|
||||
" for (i in intervalInfos) {\n"
|
||||
" var interval = intervalInfos[i];\n"
|
||||
" var polyOptions = {\n"
|
||||
" stroke : true,\n"
|
||||
" color: interval['color'],\n"
|
||||
" opacity: 0.8,\n"
|
||||
" weight: 5,\n"
|
||||
" zIndex: -1\n"
|
||||
" }\n"
|
||||
" var path = [];\n"
|
||||
" for (j in interval['lats']) {\n"
|
||||
" path.push([interval['lats'][j], interval['lons'][j]]);\n"
|
||||
" }\n"
|
||||
" compareIntervalGroup.addLayer(L.polyline(path, polyOptions));\n"
|
||||
" }\n"
|
||||
" map.fitBounds(compareIntervalGroup.getBounds());\n"
|
||||
"} \n");
|
||||
} else if (mapCombo->currentIndex() == GOOGLE) {
|
||||
currentPage += QString("function doDrawCompareIntervals(intervalInfos) { \n"
|
||||
" var minLat = 1000;\n"
|
||||
" var minLon = 1000;\n"
|
||||
" var maxLat = -1000;\n"
|
||||
" var maxLon = -1000;\n"
|
||||
" for (r in compareIntervalGroup) {\n"
|
||||
" compareIntervalGroup[r].setMap(null);\n"
|
||||
" }\n"
|
||||
" compareIntervalGroup = [];\n"
|
||||
" for (i in intervalInfos) {\n"
|
||||
" var interval = intervalInfos[i];\n"
|
||||
" var routeOptions = {\n"
|
||||
" strokeColor: interval['color'],\n"
|
||||
" strokeOpacity: 0.8,\n"
|
||||
" strokeWeight: 5,\n"
|
||||
" zIndex: -1\n"
|
||||
" };\n"
|
||||
" var route = new google.maps.Polyline(routeOptions);\n"
|
||||
" route.setMap(map);\n"
|
||||
" var path = route.getPath();\n"
|
||||
" for (j in interval['lats']) {\n"
|
||||
" path.push(new google.maps.LatLng(interval['lats'][j], interval['lons'][j]));\n"
|
||||
" minLat = Math.min(minLat, interval['lats'][j]);\n"
|
||||
" maxLat = Math.max(maxLat, interval['lats'][j]);\n"
|
||||
" minLon = Math.min(minLon, interval['lons'][j]);\n"
|
||||
" maxLon = Math.max(maxLon, interval['lons'][j]);\n"
|
||||
" }\n"
|
||||
" compareIntervalGroup.push(route);\n"
|
||||
" }\n"
|
||||
" var southwest = new google.maps.LatLng(minLat, minLon);\n"
|
||||
" var northeast = new google.maps.LatLng(maxLat, maxLon);\n"
|
||||
" map.fitBounds(new google.maps.LatLngBounds(southwest, northeast));\n"
|
||||
"} \n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// drawIntervals
|
||||
|
||||
if (! context->isCompareIntervals) {
|
||||
currentPage += QString("function drawIntervals() { \n"
|
||||
// how many to draw?
|
||||
" webBridge.intervalCount(drawIntervalsCount);\n"
|
||||
"}\n"
|
||||
|
||||
"function drawIntervalsCount(intervals) { \n"
|
||||
// remove previous intervals highlighted
|
||||
" j= intervalList.length;\n"
|
||||
" while (j) {\n"
|
||||
" var highlighted = intervalList.pop();\n");
|
||||
|
||||
// remove highlighted
|
||||
if (mapCombo->currentIndex() == OSM) {
|
||||
currentPage += QString(""
|
||||
" map.removeLayer(highlighted);\n");
|
||||
} else if (mapCombo->currentIndex() == GOOGLE) {
|
||||
currentPage += QString(""
|
||||
" highlighted.setMap(null);\n");
|
||||
}
|
||||
|
||||
currentPage += QString(""
|
||||
" j--;\n"
|
||||
" }\n"
|
||||
|
||||
" while (intervals > 0) {\n"
|
||||
" webBridge.getLatLons(intervals, drawInterval);\n"
|
||||
" intervals--;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
|
||||
if (mapCombo->currentIndex() == OSM) {
|
||||
currentPage += QString("function drawInterval(latlons) { \n"
|
||||
// intervals will be drawn with these options
|
||||
" var polyOptions = {\n"
|
||||
" stroke : true,\n"
|
||||
" color: '#0000FF',\n"
|
||||
" opacity: 0.6,\n"
|
||||
" weight: 10,\n"
|
||||
" zIndex: -1\n" // put at the bottom
|
||||
" }\n"
|
||||
" var path = [];\n"
|
||||
" var j=0;\n"
|
||||
" while (j<latlons.length) {\n"
|
||||
" path.push([latlons[j], latlons[j+1]]);\n"
|
||||
" j += 2;\n"
|
||||
" }\n"
|
||||
|
||||
" var intervalHighlighter = L.polyline(path, polyOptions).addTo(map);\n"
|
||||
" intervalList.push(intervalHighlighter);\n"
|
||||
"}\n");
|
||||
} else if (mapCombo->currentIndex() == OSM) {
|
||||
currentPage += QString("function drawInterval(latlons) { \n"
|
||||
// intervals will be drawn with these options
|
||||
" var polyOptions = {\n"
|
||||
" strokeColor: '#0000FF',\n"
|
||||
" strokeOpacity: 0.6,\n"
|
||||
" strokeWeight: 10,\n"
|
||||
" zIndex: -1\n" // put at the bottom
|
||||
" }\n"
|
||||
" var intervalHighlighter = new google.maps.Polyline(polyOptions);\n"
|
||||
" intervalHighlighter.setMap(map);\n"
|
||||
" intervalList.push(intervalHighlighter);\n"
|
||||
" var path = intervalHighlighter.getPath();\n"
|
||||
" var j=0;\n"
|
||||
" while (j<latlons.length) {\n"
|
||||
" path.push(new google.maps.LatLng(latlons[j], latlons[j+1]));\n"
|
||||
" j += 2;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Initialize
|
||||
|
||||
currentPage += QString(""
|
||||
" j--;\n"
|
||||
" }\n"
|
||||
|
||||
" while (intervals > 0) {\n"
|
||||
" webBridge.getLatLons(intervals, drawInterval);\n"
|
||||
" intervals--;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
|
||||
// initialise function called when map loaded
|
||||
"function initialize() {\n");
|
||||
if (mapCombo->currentIndex() == OSM) {
|
||||
currentPage += QString("function drawInterval(latlons) { \n"
|
||||
// intervals will be drawn with these options
|
||||
" var polyOptions = {\n"
|
||||
" stroke : true,\n"
|
||||
" color: '#0000FF',\n"
|
||||
" opacity: 0.6,\n"
|
||||
" weight: 10,\n"
|
||||
" zIndex: -1\n" // put at the bottom
|
||||
" }\n"
|
||||
" var path = [];\n"
|
||||
" var j=0;\n"
|
||||
" while (j<latlons.length) {\n"
|
||||
" path.push([latlons[j], latlons[j+1]]);\n"
|
||||
" j += 2;\n"
|
||||
" }\n"
|
||||
|
||||
" var intervalHighlighter = L.polyline(path, polyOptions).addTo(map);\n"
|
||||
" intervalList.push(intervalHighlighter);\n"
|
||||
"}\n"
|
||||
|
||||
// initialise function called when map loaded
|
||||
"function initialize() {\n");
|
||||
|
||||
currentPage += QString(""
|
||||
// TERRAIN style map please and make it draggable
|
||||
// note that because QT webkit offers touch/gesture
|
||||
@@ -639,58 +785,45 @@ void RideMapWindow::createHtml()
|
||||
" maxZoom: 18"
|
||||
" }).addTo(map);\n").arg(tsUrl);
|
||||
|
||||
if (context->isCompareIntervals) {
|
||||
currentPage += QString(""
|
||||
// initialise local variables
|
||||
" compareIntervalGroup = L.featureGroup().addTo(map);\n"
|
||||
|
||||
" drawCompareIntervals();\n"
|
||||
// catch signals to redraw intervals
|
||||
" webBridge.drawCompareIntervals.connect(drawCompareIntervals);\n");
|
||||
} else {
|
||||
currentPage += QString(""
|
||||
// initialise local variables
|
||||
" markerList = new Array();\n"
|
||||
" intervalList = new Array();\n"
|
||||
" polyList = new Array();\n"
|
||||
|
||||
// draw the main route data, getting the geo
|
||||
// data from the webbridge - reduces data sent/received
|
||||
// to the map server and makes the UI pretty snappy
|
||||
" drawRoute();\n"
|
||||
" drawIntervals();\n"
|
||||
// catch signals to redraw intervals
|
||||
" webBridge.drawIntervals.connect(drawIntervals);\n"
|
||||
|
||||
// we're done now let the C++ side draw its overlays
|
||||
" webBridge.drawOverlays();\n"
|
||||
|
||||
// Liste mouse events
|
||||
" map.on('mouseup', function(event) { map.dragging.enable();L.DomEvent.stopPropagation(event); webBridge.mouseup(); });\n");
|
||||
}
|
||||
currentPage += QString(""
|
||||
// initialise local variables
|
||||
" markerList = new Array();\n"
|
||||
" intervalList = new Array();\n"
|
||||
" polyList = new Array();\n"
|
||||
|
||||
// draw the main route data, getting the geo
|
||||
// data from the webbridge - reduces data sent/received
|
||||
// to the map server and makes the UI pretty snappy
|
||||
" drawRoute();\n"
|
||||
" drawIntervals();\n"
|
||||
// catch signals to redraw intervals
|
||||
" webBridge.drawIntervals.connect(drawIntervals);\n"
|
||||
|
||||
// we're done now let the C++ side draw its overlays
|
||||
" webBridge.drawOverlays();\n"
|
||||
|
||||
// Liste mouse events
|
||||
" map.on('mouseup', function(event) { map.dragging.enable();L.DomEvent.stopPropagation(event); webBridge.mouseup(); });\n"
|
||||
|
||||
|
||||
"}\n"
|
||||
"</script>\n");
|
||||
} else if (mapCombo->currentIndex() == GOOGLE) {
|
||||
currentPage += QString("function drawInterval(latlons) { \n"
|
||||
// intervals will be drawn with these options
|
||||
" var polyOptions = {\n"
|
||||
" strokeColor: '#0000FF',\n"
|
||||
" strokeOpacity: 0.6,\n"
|
||||
" strokeWeight: 10,\n"
|
||||
" zIndex: -1\n" // put at the bottom
|
||||
" }\n"
|
||||
" var intervalHighlighter = new google.maps.Polyline(polyOptions);\n"
|
||||
" intervalHighlighter.setMap(map);\n"
|
||||
" intervalList.push(intervalHighlighter);\n"
|
||||
" var path = intervalHighlighter.getPath();\n"
|
||||
" var j=0;\n"
|
||||
" while (j<latlons.length) {\n"
|
||||
" path.push(new google.maps.LatLng(latlons[j], latlons[j+1]));\n"
|
||||
" j += 2;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
|
||||
// initialise function called when map loaded
|
||||
"function initialize() {\n");
|
||||
|
||||
// TERRAIN style map please and make it draggable
|
||||
// note that because QT webkit offers touch/gesture
|
||||
// support the Google API only supports dragging
|
||||
// via gestures - this is alrady registered as a bug
|
||||
// with the google map team
|
||||
currentPage += QString(""
|
||||
// TERRAIN style map please and make it draggable
|
||||
// note that because QT webkit offers touch/gesture
|
||||
// support the Google API only supports dragging
|
||||
// via gestures - this is alrady registered as a bug
|
||||
// with the google map team
|
||||
currentPage += QString(""
|
||||
" var controlOptions = {\n"
|
||||
" style: google.maps.MapTypeControlStyle.DEFAULT\n"
|
||||
" };\n");
|
||||
@@ -706,8 +839,6 @@ void RideMapWindow::createHtml()
|
||||
" };\n").arg("google.maps.MapTypeId.TERRAIN")
|
||||
.arg("false");
|
||||
|
||||
|
||||
|
||||
currentPage += QString(""
|
||||
// setup the map, and fit to contain the limits of the route
|
||||
" map = new google.maps.Map(document.getElementById('map-canvas'), myOptions);\n"
|
||||
@@ -719,45 +850,77 @@ void RideMapWindow::createHtml()
|
||||
arg(maxLat,0,'g',GPS_COORD_TO_STRING).
|
||||
arg(maxLon,0,'g',GPS_COORD_TO_STRING);
|
||||
|
||||
|
||||
currentPage += QString(""
|
||||
// add the bike layer, useful in some areas, but coverage
|
||||
// is limited, US gets best coverage at this point (Summer 2011)
|
||||
" var bikeLayer = new google.maps.BicyclingLayer();\n"
|
||||
" bikeLayer.setMap(map);\n");
|
||||
|
||||
if (context->isCompareIntervals) {
|
||||
currentPage += QString(""
|
||||
// initialise local variables
|
||||
" compareIntervalGroup = new Array();\n"
|
||||
|
||||
" drawCompareIntervals();\n"
|
||||
// catch signals to redraw intervals
|
||||
" webBridge.drawCompareIntervals.connect(drawCompareIntervals);\n");
|
||||
} else {
|
||||
currentPage += QString(""
|
||||
// initialise local variables
|
||||
" markerList = new Array();\n"
|
||||
" intervalList = new Array();\n"
|
||||
" polyList = new Array();\n"
|
||||
|
||||
// draw the main route data, getting the geo
|
||||
// data from the webbridge - reduces data sent/received
|
||||
// to the map server and makes the UI pretty snappy
|
||||
" drawRoute();\n"
|
||||
" drawIntervals();\n"
|
||||
// catch signals to redraw intervals
|
||||
" webBridge.drawIntervals.connect(drawIntervals);\n"
|
||||
|
||||
// we're done now let the C++ side draw its overlays
|
||||
" webBridge.drawOverlays();\n"
|
||||
|
||||
// Liste mouse events
|
||||
" google.maps.event.addListener(map, 'mouseup', function(event) { map.setOptions({draggable: true, zoomControl: true, scrollwheel: true, disableDoubleClickZoom: false}); webBridge.mouseup(); });\n");
|
||||
}
|
||||
currentPage += QString(""
|
||||
// initialise local variables
|
||||
" markerList = new Array();\n"
|
||||
" intervalList = new Array();\n"
|
||||
" polyList = new Array();\n"
|
||||
|
||||
// draw the main route data, getting the geo
|
||||
// data from the webbridge - reduces data sent/received
|
||||
// to the map server and makes the UI pretty snappy
|
||||
" drawRoute();\n"
|
||||
" drawIntervals();\n"
|
||||
// catch signals to redraw intervals
|
||||
" webBridge.drawIntervals.connect(drawIntervals);\n"
|
||||
|
||||
// we're done now let the C++ side draw its overlays
|
||||
" webBridge.drawOverlays();\n"
|
||||
|
||||
// Liste mouse events
|
||||
" google.maps.event.addListener(map, 'mouseup', function(event) { map.setOptions({draggable: true, zoomControl: true, scrollwheel: true, disableDoubleClickZoom: false}); webBridge.mouseup(); });\n"
|
||||
|
||||
|
||||
"}\n"
|
||||
"</script>\n");
|
||||
|
||||
|
||||
"}\n"
|
||||
"</script>\n");
|
||||
}
|
||||
|
||||
// the main page is rather trivial
|
||||
currentPage += QString("</body>\n"
|
||||
"</html>\n");
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
RideMapWindow::getCompareBoundingBox
|
||||
(double &minLat, double &maxLat, double &minLon, double &maxLon) const
|
||||
{
|
||||
// values outside -360..360
|
||||
minLat = minLon = 1000;
|
||||
maxLat = maxLon = -1000;
|
||||
if (! context->isCompareIntervals) {
|
||||
return false;
|
||||
}
|
||||
bool hasPositions = false;
|
||||
for (const CompareInterval &ci : context->compareIntervals) {
|
||||
if (ci.isChecked()) {
|
||||
for (RideFilePoint const * const &rfp : ci.data->dataPoints()) {
|
||||
if (rfp->lat || rfp->lon) {
|
||||
minLat = std::min(minLat, rfp->lat);
|
||||
maxLat = std::max(maxLat, rfp->lat);
|
||||
minLon = std::min(minLon, rfp->lon);
|
||||
maxLon = std::max(maxLon, rfp->lon);
|
||||
hasPositions = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hasPositions;
|
||||
}
|
||||
|
||||
|
||||
@@ -771,6 +934,9 @@ QColor RideMapWindow::GetColor(int watts)
|
||||
void
|
||||
RideMapWindow::drawShadedRoute()
|
||||
{
|
||||
if (context->isCompareIntervals) {
|
||||
return;
|
||||
}
|
||||
int intervalTime = 60; // 60 seconds
|
||||
double rtime=0; // running total for accumulated data
|
||||
int count=0; // how many samples ?
|
||||
@@ -865,6 +1031,9 @@ RideMapWindow::drawShadedRoute()
|
||||
|
||||
void
|
||||
RideMapWindow::clearTempInterval() {
|
||||
if (context->isCompareIntervals) {
|
||||
return;
|
||||
}
|
||||
QString code;
|
||||
if (mapCombo->currentIndex() == OSM) {
|
||||
code = QString( "{ \n"
|
||||
@@ -880,8 +1049,50 @@ RideMapWindow::clearTempInterval() {
|
||||
view->page()->runJavaScript(code);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RideMapWindow::compareIntervalsStateChanged
|
||||
(bool state)
|
||||
{
|
||||
countCompareIntervals = context->compareIntervals.size();
|
||||
smallPlot->setVisible(! state && showFullPlotCk->checkState() != Qt::Unchecked);
|
||||
overlayWidget->setVisible(! state && showInt->checkState() != Qt::Unchecked);
|
||||
|
||||
forceReplot();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RideMapWindow::compareIntervalsChanged
|
||||
()
|
||||
{
|
||||
if (! context->isCompareIntervals) {
|
||||
return;
|
||||
}
|
||||
int oldCountCompareIntervals = countCompareIntervals;
|
||||
countCompareIntervals = 0;
|
||||
for (const CompareInterval &ci : context->compareIntervals) {
|
||||
if (ci.isChecked()) {
|
||||
for (RideFilePoint const * const &rfp : ci.data->dataPoints()) {
|
||||
if (rfp->lat || rfp->lon) {
|
||||
++countCompareIntervals;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (oldCountCompareIntervals == 0 || countCompareIntervals == 0) {
|
||||
createHtml();
|
||||
view->page()->setHtml(currentPage);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RideMapWindow::drawTempInterval(IntervalItem *current) {
|
||||
if (context->isCompareIntervals) {
|
||||
return;
|
||||
}
|
||||
QString code;
|
||||
|
||||
if (mapCombo->currentIndex() == OSM) {
|
||||
@@ -978,7 +1189,7 @@ static double distanceBetween(double fromLat, double fromLon, double toLat, doub
|
||||
void
|
||||
RideMapWindow::createMarkers()
|
||||
{
|
||||
if (!showMarkersCk->checkState())
|
||||
if (!showMarkersCk->checkState() || context->isCompareIntervals)
|
||||
return;
|
||||
QString code;
|
||||
|
||||
@@ -1251,6 +1462,10 @@ MapWebBridge::getLatLons(int i)
|
||||
void
|
||||
MapWebBridge::drawOverlays()
|
||||
{
|
||||
if (context->isCompareIntervals) {
|
||||
return;
|
||||
}
|
||||
|
||||
// overlay the markers
|
||||
mw->createMarkers();
|
||||
|
||||
@@ -1445,6 +1660,32 @@ MapWebBridge::mouseup()
|
||||
}
|
||||
|
||||
|
||||
QVariantList
|
||||
MapWebBridge::setCompareIntervals
|
||||
()
|
||||
{
|
||||
QVariantList intervals;
|
||||
for (const CompareInterval &ci : context->compareIntervals) {
|
||||
if (ci.isChecked()) {
|
||||
QVariantMap interval;
|
||||
interval["color"] = ci.color.name();
|
||||
QVariantList lats;
|
||||
QVariantList lons;
|
||||
for (RideFilePoint const * const &rfp : ci.data->dataPoints()) {
|
||||
if (rfp->lat || rfp->lon) {
|
||||
lats << rfp->lat;
|
||||
lons << rfp->lon;
|
||||
}
|
||||
}
|
||||
interval["lons"] = lons;
|
||||
interval["lats"] = lats;
|
||||
intervals << interval;
|
||||
}
|
||||
}
|
||||
return intervals;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
RideMapWindow::event(QEvent *event)
|
||||
{
|
||||
|
||||
@@ -92,10 +92,15 @@ class MapWebBridge : public QObject
|
||||
Q_INVOKABLE void clickPath(double lat, double lng);
|
||||
Q_INVOKABLE void mouseup();
|
||||
|
||||
// Comparemode
|
||||
Q_INVOKABLE QVariantList setCompareIntervals();
|
||||
|
||||
void intervalsChanged() { emit drawIntervals(); }
|
||||
void compareIntervalsChanged() { emit drawCompareIntervals(); }
|
||||
|
||||
signals:
|
||||
void drawIntervals();
|
||||
void drawCompareIntervals();
|
||||
};
|
||||
|
||||
class RideMapWindow : public GcChartWindow
|
||||
@@ -180,6 +185,9 @@ class RideMapWindow : public GcChartWindow
|
||||
void drawTempInterval(IntervalItem *current);
|
||||
void clearTempInterval();
|
||||
|
||||
void compareIntervalsStateChanged(bool state);
|
||||
void compareIntervalsChanged();
|
||||
|
||||
private:
|
||||
|
||||
bool first;
|
||||
@@ -212,6 +220,10 @@ class RideMapWindow : public GcChartWindow
|
||||
QColor GetColor(int watts);
|
||||
void createHtml();
|
||||
|
||||
bool getCompareBoundingBox(double &minLat, double &maxLat, double &minLon, double &maxLon) const;
|
||||
|
||||
int countCompareIntervals = 0;
|
||||
|
||||
private slots:
|
||||
void loadRide();
|
||||
void updateFrame();
|
||||
|
||||
Reference in New Issue
Block a user