diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc
index 38d3168..ceaef77 100644
--- a/qgroundcontrol.qrc
+++ b/qgroundcontrol.qrc
@@ -99,6 +99,7 @@
src/ui/flightdisplay/components/QGCMapBackground.qml
src/ui/flightdisplay/components/QGCPitchWidget.qml
src/ui/flightdisplay/components/QGCSpeedWidget.qml
+ src/ui/flightdisplay/components/QGCSlider.qml
src/ui/flightdisplay/components/compass.svg
src/ui/flightdisplay/components/compassNeedle.svg
src/ui/flightdisplay/components/crossHair.svg
@@ -106,6 +107,8 @@
src/ui/flightdisplay/components/rollDialWhite.svg
src/ui/flightdisplay/components/rollPointer.svg
src/ui/flightdisplay/components/rollPointerWhite.svg
+ src/ui/flightdisplay/components/scale.png
+ src/ui/flightdisplay/components/scale_end.png
diff --git a/src/QtLocationPlugin/qgeomapreplyqgc.cpp b/src/QtLocationPlugin/qgeomapreplyqgc.cpp
index 7fad5e7..fda5efe 100644
--- a/src/QtLocationPlugin/qgeomapreplyqgc.cpp
+++ b/src/QtLocationPlugin/qgeomapreplyqgc.cpp
@@ -86,10 +86,16 @@ void QGeoMapReplyQGC::replyDestroyed()
void QGeoMapReplyQGC::networkReplyFinished()
{
if (!m_reply)
+ {
+ qWarning() << "NULL Map request reply";
return;
+ }
if (m_reply->error() != QNetworkReply::NoError)
+ {
+ qWarning() << "Map request reply error:" << m_reply->error();
return;
+ }
QByteArray a = m_reply->readAll();
setMapImageData(a);
@@ -131,10 +137,16 @@ void QGeoMapReplyQGC::networkReplyFinished()
void QGeoMapReplyQGC::networkReplyError(QNetworkReply::NetworkError error)
{
if (!m_reply)
+ {
+ qWarning() << "NULL Map request error";
return;
+ }
if (error != QNetworkReply::OperationCanceledError)
+ {
setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString());
+ qWarning() << "Map request reply error:" << m_reply->errorString();
+ }
setFinished(true);
m_reply->deleteLater();
diff --git a/src/QtLocationPlugin/qgeotiledmappingmanagerengineqgc.cpp b/src/QtLocationPlugin/qgeotiledmappingmanagerengineqgc.cpp
index ae5cd85..bce55cc 100644
--- a/src/QtLocationPlugin/qgeotiledmappingmanagerengineqgc.cpp
+++ b/src/QtLocationPlugin/qgeotiledmappingmanagerengineqgc.cpp
@@ -58,8 +58,9 @@ QGeoTiledMappingManagerEngineQGC::QGeoTiledMappingManagerEngineQGC(const QVarian
: QGeoTiledMappingManagerEngine()
{
QGeoCameraCapabilities cameraCaps;
- cameraCaps.setMinimumZoomLevel(0.0);
- cameraCaps.setMaximumZoomLevel(22.0);
+ cameraCaps.setMinimumZoomLevel(2.0);
+ cameraCaps.setMaximumZoomLevel(20.0);
+ cameraCaps.setSupportsBearing(true);
setCameraCapabilities(cameraCaps);
setTileSize(QSize(256, 256));
diff --git a/src/ui/flightdisplay/FlightDisplay.qml b/src/ui/flightdisplay/FlightDisplay.qml
index 3793782..b1dc013 100644
--- a/src/ui/flightdisplay/FlightDisplay.qml
+++ b/src/ui/flightdisplay/FlightDisplay.qml
@@ -200,6 +200,7 @@ Rectangle {
}
}
+ /*
MenuItem {
text: "Map Always Points North"
checkable: true
@@ -210,6 +211,7 @@ Rectangle {
flightDisplay.saveSetting("mapAlwaysPointsNorth", setBool(mapBackground.alwaysNorth));
}
}
+ */
Menu {
id: mapTypeMenu
diff --git a/src/ui/flightdisplay/components/QGCMapBackground.qml b/src/ui/flightdisplay/components/QGCMapBackground.qml
index 1323174..20132ad 100644
--- a/src/ui/flightdisplay/components/QGCMapBackground.qml
+++ b/src/ui/flightdisplay/components/QGCMapBackground.qml
@@ -31,11 +31,13 @@ import QtQuick 2.4
import QtPositioning 5.3
import QtLocation 5.3
+import QGroundControl.HUDControls 1.0
+
Rectangle {
id: root
property real latitude: 37.803784
property real longitude : -122.462276
- property real zoomLevel: 12
+ property real zoomLevel: (map.maximumZoomLevel - map.minimumZoomLevel) / 2
property real heading: 0
property bool alwaysNorth: true
property alias mapItem: map
@@ -46,7 +48,7 @@ Rectangle {
function adjustSize() {
if(root.visible) {
- if(alwaysNorth) {
+ if(true /*alwaysNorth*/) {
map.width = root.width;
map.height = root.height;
} else {
@@ -60,6 +62,25 @@ Rectangle {
}
}
+ function formatDistance(meters)
+ {
+ var dist = Math.round(meters)
+ if (dist > 1000 ){
+ if (dist > 100000){
+ dist = Math.round(dist / 1000)
+ }
+ else{
+ dist = Math.round(dist / 100)
+ dist = dist / 10
+ }
+ dist = dist + " km"
+ }
+ else{
+ dist = dist + " m"
+ }
+ return dist
+ }
+
Plugin {
id: mapPlugin
name: "QGroundControl"
@@ -67,26 +88,153 @@ Rectangle {
Map {
id: map
- property real lon: (longitude > -180.1 && longitude < 180.1) ? longitude : 0
- property real lat: (latitude > -180.1 && latitude < 180.1) ? latitude : 0
+ property real lon: (longitude >= -180 && longitude <= 180) ? longitude : 0
+ property real lat: (latitude >= -90 && latitude <= 90) ? latitude : 0
+ property variant scaleLengths: [5, 10, 25, 50, 100, 150, 250, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000, 2000000]
plugin: mapPlugin
width: 1
height: 1
- zoomLevel: zoomLevel
+ zoomLevel: root.zoomLevel
anchors.centerIn: parent
center: map.visible ? QtPositioning.coordinate(lat, lon) : QtPositioning.coordinate(0,0)
+ /*
transform: Rotation {
origin.x: map.width / 2
origin.y: map.height / 2
angle: map.visible ? (alwaysNorth ? 0 : -heading) : 0
}
+ */
gesture.flickDeceleration: 3000
gesture.enabled: true
+
+ onWidthChanged: {
+ scaleTimer.restart()
+ }
+
+ onHeightChanged: {
+ scaleTimer.restart()
+ }
+
+ onZoomLevelChanged:{
+ scaleTimer.restart()
+ }
+
+ function calculateScale() {
+ var coord1, coord2, dist, text, f
+ f = 0
+ coord1 = map.toCoordinate(Qt.point(0,scale.y))
+ coord2 = map.toCoordinate(Qt.point(0+scaleImage.sourceSize.width,scale.y))
+ dist = Math.round(coord1.distanceTo(coord2))
+ if (dist === 0) {
+ // not visible
+ } else {
+ for (var i = 0; i < scaleLengths.length-1; i++) {
+ if (dist < (scaleLengths[i] + scaleLengths[i+1]) / 2 ) {
+ f = scaleLengths[i] / dist
+ dist = scaleLengths[i]
+ break;
+ }
+ }
+ if (f === 0) {
+ f = dist / scaleLengths[i]
+ dist = scaleLengths[i]
+ }
+ }
+ text = formatDistance(dist)
+ scaleImage.width = (scaleImage.sourceSize.width * f) - 2 * scaleImageLeft.sourceSize.width
+ scaleText.text = text
+ }
}
- onVisibleChanged: adjustSize();
- onWidthChanged: adjustSize();
- onHeightChanged: adjustSize();
- onAlwaysNorthChanged: adjustSize();
+ QGCSlider {
+ id: zoomSlider;
+ minimum: map.minimumZoomLevel;
+ maximum: map.maximumZoomLevel;
+ opacity: 1
+ visible: parent.visible
+ z: map.z + 3
+ anchors {
+ bottom: parent.bottom;
+ bottomMargin: 15; rightMargin: 20; leftMargin: 20
+ left: parent.left
+ }
+ width: parent.width - anchors.rightMargin - anchors.leftMargin
+ value: map.zoomLevel
+ Binding {
+ target: zoomSlider; property: "value"; value: map.zoomLevel
+ }
+ onValueChanged: {
+ map.zoomLevel = value
+ }
+ }
+
+ Item {
+ id: scale
+ parent: zoomSlider.parent
+ visible: scaleText.text != "0 m"
+ z: map.z + 2
+ opacity: 1
+ anchors {
+ bottom: zoomSlider.top;
+ bottomMargin: 8;
+ left: zoomSlider.left
+ }
+ Image {
+ id: scaleImageLeft
+ source: "/qml/scale_end.png"
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ }
+ Image {
+ id: scaleImage
+ source: "/qml/scale.png"
+ anchors.bottom: parent.bottom
+ anchors.left: scaleImageLeft.right
+ }
+ Image {
+ id: scaleImageRight
+ source: "/qml/scale_end.png"
+ anchors.bottom: parent.bottom
+ anchors.left: scaleImage.right
+ }
+ Text {
+ id: scaleText
+ color: "white"
+ font.weight: Font.DemiBold
+ horizontalAlignment: Text.AlignHCenter
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.bottomMargin: 8
+ text: "0 m"
+ }
+ Component.onCompleted: {
+ map.calculateScale();
+ }
+ }
+ Timer {
+ id: scaleTimer
+ interval: 100
+ running: false
+ repeat: false
+ onTriggered: {
+ map.calculateScale()
+ }
+ }
+
+ onVisibleChanged: {
+ adjustSize();
+ }
+
+ onAlwaysNorthChanged: {
+ adjustSize();
+ }
+
+ onWidthChanged: {
+ adjustSize();
+ }
+
+ onHeightChanged: {
+ adjustSize();
+ }
}
diff --git a/src/ui/flightdisplay/components/QGCSlider.qml b/src/ui/flightdisplay/components/QGCSlider.qml
new file mode 100644
index 0000000..93fc898
--- /dev/null
+++ b/src/ui/flightdisplay/components/QGCSlider.qml
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+ id: slider;
+ height: 10
+ property real value // value is read/write.
+ property real minimum: 0
+ property real maximum: 1
+ property int length: width - handle.width
+
+ Rectangle {
+ anchors.fill: parent
+ border.width: 1;
+ border.color: "lightgrey"
+ radius: 8
+ color: "white"
+ opacity: 1
+ }
+
+ Rectangle {
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.top: parent.top
+ anchors.topMargin: (parent.height - height)/2
+ height: 3
+ width: handle.x - x
+ color: "#1c94fc"
+ }
+
+
+ Rectangle {
+ id: labelRect
+ width: label.width
+ height: label.height + 4
+ radius: 4
+ smooth: true
+ color: "white"
+ border.color: "lightgrey"
+ anchors.bottom: handle.top
+ anchors.bottomMargin: 4
+ x: Math.max(Math.min(handle.x + (handle.width - width )/2, slider.width - width),0)
+ visible: mouseRegion.pressed
+ Text{
+ id: label
+ color: "darkgrey"
+ text: slider.value.toFixed(2)
+ width: font.pointSize * 3.5
+ anchors.horizontalCenter: labelRect.horizontalCenter
+ horizontalAlignment: Text.AlignHCenter
+ anchors.baseline: parent.bottom
+ anchors.baselineOffset: -6
+ font.pixelSize: 14
+ }
+ }
+
+ Rectangle {
+ id: handle;
+ smooth: true
+ width: 26;
+ y: (slider.height - height)/2;
+ x: (slider.value - slider.minimum) * slider.length / (slider.maximum - slider.minimum)
+
+ height: width; radius: width/2
+ gradient: normalGradient
+ border.width: 2
+ border.color: "white"
+
+ Gradient {
+ id: normalGradient
+ GradientStop { position: 0.0; color: "#b0b0b0" }
+ GradientStop { position: 0.66; color: "#909090" }
+ GradientStop { position: 1.0; color: "#545454" }
+ }
+
+ MouseArea {
+ id: mouseRegion
+ hoverEnabled: false
+ anchors.fill: parent; drag.target: parent
+ drag.axis: Drag.XAxis; drag.minimumX: 0; drag.maximumX: slider.length
+ preventStealing: true
+ onPositionChanged: { slider.value = (slider.maximum - slider.minimum) * handle.x / slider.length + slider.minimum; }
+ }
+ }
+}
diff --git a/src/ui/flightdisplay/components/qmldir b/src/ui/flightdisplay/components/qmldir
index cda9932..647204b 100644
--- a/src/ui/flightdisplay/components/qmldir
+++ b/src/ui/flightdisplay/components/qmldir
@@ -8,3 +8,4 @@ QGCCurrentSpeed 1.0 QGCCurrentSpeed.qml
QGCMapBackground 1.0 QGCMapBackground.qml
QGCPitchWidget 1.0 QGCPitchWidget.qml
QGCSpeedWidget 1.0 QGCSpeedWidget.qml
+QGCSlider 1.0 QGCSlider.qml
\ No newline at end of file
diff --git a/src/ui/flightdisplay/components/scale.png b/src/ui/flightdisplay/components/scale.png
new file mode 100644
index 0000000..703d3a2
Binary files /dev/null and b/src/ui/flightdisplay/components/scale.png differ
diff --git a/src/ui/flightdisplay/components/scale_end.png b/src/ui/flightdisplay/components/scale_end.png
new file mode 100644
index 0000000..1a7ed9a
Binary files /dev/null and b/src/ui/flightdisplay/components/scale_end.png differ