QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
OfflineMapEditor.qml
Go to the documentation of this file.
1import QtQuick
2import QtQuick.Controls
3import QtQuick.Layouts
4import QtQuick.Dialogs
5import QtQuick.Controls
6import QtLocation
7import QtPositioning
8
9import QGroundControl
10import QGroundControl.Controls
11import QGroundControl.FlightMap
12import QGroundControl.FactControls
13
14FlightMap {
15 id: _map
16 allowGCSLocationCenter: true
17 allowVehicleLocationCenter: false
18 mapName: "OfflineMap"
19
20 property var tileSet: null
21
22 property string mapKey: "lastMapType"
23
24 property var _settingsManager: QGroundControl.settingsManager
25 property var _settings: _settingsManager ? _settingsManager.offlineMapsSettings : null
26 property var _fmSettings: _settingsManager ? _settingsManager.flightMapSettings : null
27 property var _appSettings: _settingsManager.appSettings
28 property Fact _tiandituFact: _settingsManager ? _settingsManager.appSettings.tiandituToken : null
29 property Fact _mapboxFact: _settingsManager ? _settingsManager.appSettings.mapboxToken : null
30 property Fact _mapboxAccountFact: _settingsManager ? _settingsManager.appSettings.mapboxAccount : null
31 property Fact _mapboxStyleFact: _settingsManager ? _settingsManager.appSettings.mapboxStyle : null
32 property Fact _esriFact: _settingsManager ? _settingsManager.appSettings.esriToken : null
33 property Fact _customURLFact: _settingsManager ? _settingsManager.appSettings.customURL : null
34 property Fact _vworldFact: _settingsManager ? _settingsManager.appSettings.vworldToken : null
35
36 property string mapType: _fmSettings ? (_fmSettings.mapProvider.value + " " + _fmSettings.mapType.value) : ""
37 property bool isMapInteractive: false
38 property var savedCenter: undefined
39 property real savedZoom: 3
40 property string savedMapType: ""
41 property bool _showPreview: true
42 property bool _defaultSet: tileSet && tileSet.defaultSet
43 property real _margins: ScreenTools.defaultFontPixelWidth * 0.5
44 property real _buttonSize: ScreenTools.defaultFontPixelWidth * 12
45 property real _bigButtonSize: ScreenTools.defaultFontPixelWidth * 16
46
47 property bool _saveRealEstate: ScreenTools.isTinyScreen || ScreenTools.isShortScreen
48 property real _adjustableFontPointSize: _saveRealEstate ? ScreenTools.smallFontPointSize : ScreenTools.defaultFontPointSize
49
50 property var _mapAdjustedColor: _map.isSatelliteMap ? "white" : "black"
51 property bool _tooManyTiles: QGroundControl.mapEngineManager.tileCount > _maxTilesForDownload
52 property var _addNewSetViewObject: null
53
54 readonly property real minZoomLevel: 1
55 readonly property real maxZoomLevel: 20
56 readonly property real sliderTouchArea: ScreenTools.defaultFontPixelWidth * (ScreenTools.isTinyScreen ? 5 : (ScreenTools.isMobile ? 6 : 3))
57
58 readonly property int _maxTilesForDownload: _settings ? _settings.maxTilesForDownload.rawValue : 0
59
60 QGCPalette { id: qgcPal }
61
62 Component.onCompleted: {
63 QGroundControl.mapEngineManager.loadTileSets()
64 resetMapToDefaults()
65 updateMap()
66 savedCenter = _map.toCoordinate(Qt.point(_map.width / 2, _map.height / 2), false /* clipToViewPort */)
67 settingsPage.enabled = false // Prevent mouse events from bleeding through to the settings page which is below this in hierarchy
68 }
69
70 Component.onDestruction: settingsPage.enabled = true
71
72 Connections {
73 target: QGroundControl.mapEngineManager
74 onErrorMessageChanged: errorDialogFactory.open()
75 }
76
77 function handleChanges() {
78 if (isMapInteractive) {
79 var xl = 0
80 var yl = 0
81 var xr = _map.width.toFixed(0) - 1 // Must be within boundaries of visible map
82 var yr = _map.height.toFixed(0) - 1 // Must be within boundaries of visible map
83 var c0 = _map.toCoordinate(Qt.point(xl, yl), false /* clipToViewPort */)
84 var c1 = _map.toCoordinate(Qt.point(xr, yr), false /* clipToViewPort */)
85 QGroundControl.mapEngineManager.updateForCurrentView(c0.longitude, c0.latitude, c1.longitude, c1.latitude, _addNewSetViewObject.sliderMinZoom.value, _addNewSetViewObject.sliderMaxZoom.value, mapType)
86 }
87 }
88
89 function updateMap() {
90 for (var i = 0; i < _map.supportedMapTypes.length; i++) {
91 if (mapType === _map.supportedMapTypes[i].name) {
92 _map.activeMapType = _map.supportedMapTypes[i]
93 handleChanges()
94 return
95 }
96 }
97 }
98
99 function addNewSet() {
100 _addNewSetViewObject = addNewSetViewComponent.createObject(_map)
101 isMapInteractive = true
102 mapType = _fmSettings.mapProvider.value + " " + _fmSettings.mapType.value
103 resetMapToDefaults()
104 handleChanges()
105 }
106
107 function showInfo() {
108 isMapInteractive = false
109 savedCenter = _map.toCoordinate(Qt.point(_map.width / 2, _map.height / 2), false /* clipToViewPort */)
110 savedZoom = _map.zoomLevel
111 savedMapType = mapType
112 if (!tileSet.defaultSet) {
113 mapType = tileSet.mapTypeStr
114 _map.center = midPoint(tileSet.topleftLat, tileSet.bottomRightLat, tileSet.topleftLon, tileSet.bottomRightLon)
115 //-- Delineate Set Region
116 var x0 = tileSet.topleftLon
117 var x1 = tileSet.bottomRightLon
118 var y0 = tileSet.topleftLat
119 var y1 = tileSet.bottomRightLat
120 mapBoundary.topLeft = QtPositioning.coordinate(y0, x0)
121 mapBoundary.bottomRight = QtPositioning.coordinate(y1, x1)
122 mapBoundary.visible = true
123 // Some times, for whatever reason, the bounding box is correct (around ETH for instance), but the rectangle is drawn across the planet.
124 // When that happens, the "_map.fitViewportToMapItems()" below makes the map to zoom to the entire earth.
125 //console.log("Map boundary: " + mapBoundary.topLeft + " " + mapBoundary.bottomRight)
126 _map.fitViewportToVisibleMapItems()
127 }
128 infoViewComponent.createObject(_map)
129 }
130
131 function toRadian(deg) {
132 return deg * Math.PI / 180
133 }
134
135 function toDegree(rad) {
136 return rad * 180 / Math.PI
137 }
138
139 function midPoint(lat1, lat2, lon1, lon2) {
140 var dLon = toRadian(lon2 - lon1);
141 lat1 = toRadian(lat1);
142 lat2 = toRadian(lat2);
143 lon1 = toRadian(lon1);
144 var Bx = Math.cos(lat2) * Math.cos(dLon);
145 var By = Math.cos(lat2) * Math.sin(dLon);
146 var lat3 = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + Bx) * (Math.cos(lat1) + Bx) + By * By));
147 var lon3 = lon1 + Math.atan2(By, Math.cos(lat1) + Bx);
148 return QtPositioning.coordinate(toDegree(lat3), toDegree(lon3))
149 }
150
151 function resetMapToDefaults() {
152 _map.center = QGroundControl.flightMapPosition
153 _map.zoomLevel = QGroundControl.flightMapZoom
154 }
155
156 onMapTypeChanged: {
157 updateMap()
158 if(isMapInteractive) {
159 QGroundControl.mapEngineManager.saveSetting(mapKey, mapType)
160 }
161 }
162
163 property bool isSatelliteMap: activeMapType.name.indexOf("Satellite") > -1 || activeMapType.name.indexOf("Hybrid") > -1
164
165 MapRectangle {
166 id: mapBoundary
167 border.width: 2
168 border.color: "red"
169 color: Qt.rgba(1,0,0,0.05)
170 smooth: true
171 antialiasing: true
172 }
173
174 onCenterChanged: handleChanges()
175 onZoomLevelChanged: handleChanges()
176 onWidthChanged: handleChanges()
177 onHeightChanged: handleChanges()
178
179 MapScale {
180 anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 2
181 anchors.bottomMargin: anchors.leftMargin
182 anchors.left: parent.left
183 anchors.bottom: parent.bottom
184 mapControl: _map
185 }
186
187 //-----------------------------------------------------------------
188 //-- Show Set Info
189 Component {
190 id: infoViewComponent
191
192 Rectangle {
193 id: infoView
194 anchors.margins: ScreenTools.defaultFontPixelHeight
195 anchors.right: parent.right
196 anchors.verticalCenter: parent.verticalCenter
197 width: tileInfoColumn.width + (ScreenTools.defaultFontPixelWidth * 2)
198 height: tileInfoColumn.height + (ScreenTools.defaultFontPixelHeight * 2)
199 color: Qt.rgba(qgcPal.window.r, qgcPal.window.g, qgcPal.window.b, 0.85)
200 radius: ScreenTools.defaultFontPixelWidth * 0.5
201
202 property bool _extraButton: {
203 if(!tileSet)
204 return false;
205 var curSel = tileSet;
206 return !_defaultSet && ((!curSel.complete && !curSel.downloading) || (!curSel.complete && curSel.downloading));
207 }
208
209 property real _labelWidth: ScreenTools.defaultFontPixelWidth * 10
210 property real _valueWidth: ScreenTools.defaultFontPixelWidth * 14
211 Column {
212 id: tileInfoColumn
213 anchors.margins: ScreenTools.defaultFontPixelHeight * 0.5
214 spacing: ScreenTools.defaultFontPixelHeight * 0.5
215 anchors.centerIn: parent
216 QGCLabel {
217 anchors.left: parent.left
218 anchors.right: parent.right
219 wrapMode: Text.WordWrap
220 text: tileSet ? tileSet.name : ""
221 font.pointSize: _saveRealEstate ? ScreenTools.defaultFontPointSize : ScreenTools.mediumFontPointSize
222 horizontalAlignment: Text.AlignHCenter
223 visible: _defaultSet
224 }
225 QGCTextField {
226 id: editSetName
227 anchors.left: parent.left
228 anchors.right: parent.right
229 visible: !_defaultSet
230 text: tileSet ? tileSet.name : ""
231 }
232 QGCLabel {
233 anchors.left: parent.left
234 anchors.right: parent.right
235 wrapMode: Text.WordWrap
236 text: {
237 if(tileSet) {
238 if(tileSet.defaultSet)
239 return qsTr("System Wide Tile Cache");
240 else
241 return "(" + tileSet.mapTypeStr + ")"
242 } else
243 return "";
244 }
245 horizontalAlignment: Text.AlignHCenter
246 }
247 //-- Tile Sets
248 Row {
249 spacing: ScreenTools.defaultFontPixelWidth
250 anchors.horizontalCenter: parent.horizontalCenter
251 visible: !_defaultSet && mapType !== QGroundControl.elevationProviderName
252 QGCLabel { text: qsTr("Zoom Levels:"); width: infoView._labelWidth; }
253 QGCLabel { text: tileSet ? (tileSet.minZoom + " - " + tileSet.maxZoom) : ""; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; }
254 }
255 Row {
256 spacing: ScreenTools.defaultFontPixelWidth
257 anchors.horizontalCenter: parent.horizontalCenter
258 visible: !_defaultSet
259 QGCLabel { text: qsTr("Total:"); width: infoView._labelWidth; }
260 QGCLabel { text: (tileSet ? tileSet.totalTileCountStr : "") + " (" + (tileSet ? tileSet.totalTilesSizeStr : "") + ")"; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; }
261 }
262 Row {
263 spacing: ScreenTools.defaultFontPixelWidth
264 anchors.horizontalCenter: parent.horizontalCenter
265 visible: tileSet && !_defaultSet && tileSet.uniqueTileCount > 0
266 QGCLabel { text: qsTr("Unique:"); width: infoView._labelWidth; }
267 QGCLabel { text: (tileSet ? tileSet.uniqueTileCountStr : "") + " (" + (tileSet ? tileSet.uniqueTileSizeStr : "") + ")"; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; }
268 }
269
270 Row {
271 spacing: ScreenTools.defaultFontPixelWidth
272 anchors.horizontalCenter: parent.horizontalCenter
273 visible: tileSet && !_defaultSet && !tileSet.complete
274 QGCLabel { text: qsTr("Downloaded:"); width: infoView._labelWidth; }
275 QGCLabel { text: (tileSet ? tileSet.savedTileCountStr : "") + " (" + (tileSet ? tileSet.savedTileSizeStr : "") + ")"; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; }
276 }
277 Row {
278 spacing: ScreenTools.defaultFontPixelWidth
279 anchors.horizontalCenter: parent.horizontalCenter
280 visible: tileSet && !_defaultSet && !tileSet.complete && tileSet.errorCount > 0
281 QGCLabel { text: qsTr("Error Count:"); width: infoView._labelWidth; }
282 QGCLabel { text: tileSet ? tileSet.errorCountStr : ""; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; }
283 }
284 //-- Default Tile Set
285 Row {
286 spacing: ScreenTools.defaultFontPixelWidth
287 anchors.horizontalCenter: parent.horizontalCenter
288 visible: _defaultSet
289 QGCLabel { text: qsTr("Size:"); width: infoView._labelWidth; }
290 QGCLabel { text: tileSet ? tileSet.savedTileSizeStr : ""; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; }
291 }
292 Row {
293 spacing: ScreenTools.defaultFontPixelWidth
294 anchors.horizontalCenter: parent.horizontalCenter
295 visible: _defaultSet
296 QGCLabel { text: qsTr("Tile Count:"); width: infoView._labelWidth; }
297 QGCLabel { text: tileSet ? tileSet.savedTileCountStr : ""; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; }
298 }
299 Row {
300 spacing: ScreenTools.defaultFontPixelWidth
301 anchors.horizontalCenter: parent.horizontalCenter
302 QGCButton {
303 text: qsTr("Resume Download")
304 visible: tileSet && tileSet && !_defaultSet && (!tileSet.complete && !tileSet.downloading)
305 width: ScreenTools.defaultFontPixelWidth * 16
306 onClicked: {
307 if(tileSet)
308 tileSet.resumeDownloadTask()
309 }
310 }
311 QGCButton {
312 text: qsTr("Cancel Download")
313 visible: tileSet && tileSet && !_defaultSet && (!tileSet.complete && tileSet.downloading)
314 width: ScreenTools.defaultFontPixelWidth * 16
315 onClicked: {
316 if(tileSet)
317 tileSet.cancelDownloadTask()
318 }
319 }
320 QGCButton {
321 text: qsTr("Delete")
322 width: ScreenTools.defaultFontPixelWidth * (infoView._extraButton ? 6 : 10)
323 onClicked: deleteConfirmationDialogFactory.open()
324 enabled: tileSet ? (tileSet.savedTileSize > 0) : false
325 }
326 QGCButton {
327 text: qsTr("Ok")
328 width: ScreenTools.defaultFontPixelWidth * (infoView._extraButton ? 6 : 10)
329 visible: !_defaultSet
330 enabled: editSetName.text !== ""
331 onClicked: {
332 if (editSetName.text !== tileSet.name) {
333 QGroundControl.mapEngineManager.renameTileSet(tileSet, editSetName.text)
334 }
335 _map.destroy()
336 }
337 }
338 QGCButton {
339 text: _defaultSet ? qsTr("Close") : qsTr("Cancel")
340 width: ScreenTools.defaultFontPixelWidth * (infoView._extraButton ? 6 : 10)
341 onClicked: _map.destroy()
342 }
343 }
344 }
345 }
346 }
347
348 Component {
349 id: addNewSetViewComponent
350
351 Item {
352 id: addNewSetView
353 anchors.fill: parent
354
355 property var sliderMinZoom: sliderMinZoom
356 property var sliderMaxZoom: sliderMaxZoom
357
358 Column {
359 anchors.verticalCenter: parent.verticalCenter
360 anchors.leftMargin: _margins
361 anchors.left: parent.left
362 spacing: _margins
363
364 QGCButton {
365 text: qsTr("Show zoom previews")
366 visible: !_showPreview
367 onClicked: _showPreview = !_showPreview
368 }
369
370 Map {
371 id: minZoomPreview
372 width: addNewSetView.width / 4
373 height: addNewSetView.height / 4
374 center: _map.center
375 activeMapType: _map.activeMapType
376 zoomLevel: sliderMinZoom.value
377 visible: _showPreview
378
379 property bool isSatelliteMap: activeMapType.name.indexOf("Satellite") > -1 || activeMapType.name.indexOf("Hybrid") > -1
380
381 plugin: Plugin { name: "QGroundControl" }
382
383 MapScale {
384 anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 2
385 anchors.bottomMargin: anchors.leftMargin
386 anchors.left: parent.left
387 anchors.bottom: parent.bottom
388 mapControl: parent
389 }
390
391 Rectangle {
392 anchors.fill: parent
393 border.color: _mapAdjustedColor
394 color: "transparent"
395
396 QGCMapLabel {
397 anchors.centerIn: parent
398 map: minZoomPreview
399 text: qsTr("Min Zoom: %1").arg(sliderMinZoom.value)
400 }
401 MouseArea {
402 anchors.fill: parent
403 onClicked: _showPreview = false
404 }
405 }
406 } // Map
407
408 Map {
409 id: maxZoomPreview
410 width: minZoomPreview.width
411 height: minZoomPreview.height
412 center: _map.center
413 activeMapType: _map.activeMapType
414 zoomLevel: sliderMaxZoom.value
415 visible: _showPreview
416
417 property bool isSatelliteMap: activeMapType.name.indexOf("Satellite") > -1 || activeMapType.name.indexOf("Hybrid") > -1
418
419 plugin: Plugin { name: "QGroundControl" }
420
421 MapScale {
422 anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 2
423 anchors.bottomMargin: anchors.leftMargin
424 anchors.left: parent.left
425 anchors.bottom: parent.bottom
426 mapControl: parent
427 }
428
429 Rectangle {
430 anchors.fill: parent
431 border.color: _mapAdjustedColor
432 color: "transparent"
433
434 QGCMapLabel {
435 anchors.centerIn: parent
436 map: maxZoomPreview
437 text: qsTr("Max Zoom: %1").arg(sliderMaxZoom.value)
438 }
439 MouseArea {
440 anchors.fill: parent
441 onClicked: _showPreview = false
442 }
443 }
444 } // Map
445 }
446
447 Rectangle {
448 anchors.margins: ScreenTools.defaultFontPixelWidth
449 anchors.verticalCenter: parent.verticalCenter
450 anchors.right: parent.right
451 width: ScreenTools.defaultFontPixelWidth * (ScreenTools.isTinyScreen ? 24 : 28)
452 height: Math.min(parent.height - (anchors.margins * 2), addNewSetFlickable.y + addNewSetColumn.height + addNewSetLabel.anchors.margins)
453 color: Qt.rgba(qgcPal.window.r, qgcPal.window.g, qgcPal.window.b, 0.85)
454 radius: ScreenTools.defaultFontPixelWidth * 0.5
455
456 //-- Eat mouse events
457 DeadMouseArea {
458 anchors.fill: parent
459 }
460
461 QGCLabel {
462 id: addNewSetLabel
463 anchors.margins: ScreenTools.defaultFontPixelHeight / 2
464 anchors.top: parent.top
465 anchors.left: parent.left
466 anchors.right: parent.right
467 wrapMode: Text.WordWrap
468 text: qsTr("Add New Set")
469 font.pointSize: _saveRealEstate ? ScreenTools.defaultFontPointSize : ScreenTools.mediumFontPointSize
470 horizontalAlignment: Text.AlignHCenter
471 }
472
473 QGCFlickable {
474 id: addNewSetFlickable
475 anchors.leftMargin: ScreenTools.defaultFontPixelWidth
476 anchors.rightMargin: anchors.leftMargin
477 anchors.topMargin: ScreenTools.defaultFontPixelWidth / 3
478 anchors.bottomMargin: anchors.topMargin
479 anchors.top: addNewSetLabel.bottom
480 anchors.left: parent.left
481 anchors.right: parent.right
482 anchors.bottom: parent.bottom
483 clip: true
484 contentHeight: addNewSetColumn.height
485
486 Column {
487 id: addNewSetColumn
488 anchors.left: parent.left
489 anchors.right: parent.right
490 spacing: ScreenTools.defaultFontPixelHeight * (ScreenTools.isTinyScreen ? 0.25 : 0.5)
491
492 Column {
493 spacing: ScreenTools.isTinyScreen ? 0 : ScreenTools.defaultFontPixelHeight * 0.25
494 anchors.left: parent.left
495 anchors.right: parent.right
496 QGCLabel { text: qsTr("Name:") }
497 QGCTextField {
498 id: setName
499 anchors.left: parent.left
500 anchors.right: parent.right
501 Component.onCompleted: text = QGroundControl.mapEngineManager.getUniqueName()
502 Connections {
503 target: QGroundControl.mapEngineManager
504 onTileSetsChanged: setName.text = QGroundControl.mapEngineManager.getUniqueName()
505 }
506 }
507 }
508
509 Column {
510 spacing: ScreenTools.isTinyScreen ? 0 : ScreenTools.defaultFontPixelHeight * 0.25
511 anchors.left: parent.left
512 anchors.right: parent.right
513 QGCLabel {
514 text: qsTr("Map type:")
515 visible: !_saveRealEstate
516 }
517 QGCComboBox {
518 id: mapCombo
519 anchors.left: parent.left
520 anchors.right: parent.right
521 model: QGroundControl.mapEngineManager.mapList
522 onActivated: (index) => {
523 mapType = textAt(index)
524 }
525 Component.onCompleted: {
526 var index = mapCombo.find(mapType)
527 if (index === -1) {
528 console.warn("Active map name not in combo", mapType)
529 } else {
530 mapCombo.currentIndex = index
531 }
532 }
533 }
534 QGCCheckBox {
535 anchors.left: parent.left
536 anchors.right: parent.right
537 text: qsTr("Fetch elevation data")
538 checked: QGroundControl.mapEngineManager.fetchElevation
539 onClicked: {
540 QGroundControl.mapEngineManager.fetchElevation = checked
541 handleChanges()
542 }
543 }
544 }
545
546 Rectangle {
547 anchors.left: parent.left
548 anchors.right: parent.right
549 height: zoomColumn.height + ScreenTools.defaultFontPixelHeight * 0.5
550 color: qgcPal.window
551 border.color: qgcPal.text
552 radius: ScreenTools.defaultFontPixelWidth * 0.5
553
554 Column {
555 id: zoomColumn
556 spacing: ScreenTools.isTinyScreen ? 0 : ScreenTools.defaultFontPixelHeight * 0.5
557 anchors.margins: ScreenTools.defaultFontPixelHeight * 0.25
558 anchors.top: parent.top
559 anchors.left: parent.left
560 anchors.right: parent.right
561
562 QGCLabel {
563 text: qsTr("Min/Max Zoom Levels")
564 font.pointSize: _adjustableFontPointSize
565 anchors.horizontalCenter: parent.horizontalCenter
566 }
567
568 Slider {
569 id: sliderMinZoom
570 anchors.left: parent.left
571 anchors.right: parent.right
572 height: sliderTouchArea * 1.25
573 from: minZoomLevel
574 to: maxZoomLevel
575 stepSize: 1
576 live: true
577 property bool _updateSetting: false
578 Component.onCompleted: {
579 sliderMinZoom.value = _settings.minZoomLevelDownload.rawValue
580 _updateSetting = true
581 }
582 onValueChanged: {
583 if(sliderMinZoom.value > sliderMaxZoom.value) {
584 sliderMaxZoom.value = sliderMinZoom.value
585 }
586 if (_updateSetting) {
587 // Don't update setting until after Component.onCompleted since bad values come through before that
588 _settings.minZoomLevelDownload.rawValue = value
589 }
590 handleChanges()
591 }
592 handle: Rectangle {
593 x: sliderMinZoom.leftPadding + sliderMinZoom.visualPosition * (sliderMinZoom.availableWidth - width)
594 y: sliderMinZoom.topPadding + sliderMinZoom.availableHeight * 0.5 - height * 0.5
595 implicitWidth: sliderTouchArea
596 implicitHeight: sliderTouchArea
597 radius: sliderTouchArea * 0.5
598 color: qgcPal.button
599 border.width: 1
600 border.color: qgcPal.buttonText
601 Label {
602 text: sliderMinZoom.value
603 anchors.centerIn: parent
604 font.family: ScreenTools.normalFontFamily
605 font.pointSize: ScreenTools.smallFontPointSize
606 color: qgcPal.buttonText
607 }
608 }
609 } // Slider - min zoom
610
611 Slider {
612 id: sliderMaxZoom
613 anchors.left: parent.left
614 anchors.right: parent.right
615 height: sliderTouchArea * 1.25
616 from: minZoomLevel
617 to: maxZoomLevel
618 stepSize: 1
619 live: true
620 property bool _updateSetting: false
621 Component.onCompleted: {
622 sliderMaxZoom.value = _settings.maxZoomLevelDownload.rawValue
623 _updateSetting = true
624 }
625 onValueChanged: {
626 if(sliderMaxZoom.value < sliderMinZoom.value) {
627 sliderMinZoom.value = sliderMaxZoom.value
628 }
629 if (_updateSetting) {
630 // Don't update setting until after Component.onCompleted since bad values come through before that
631 _settings.maxZoomLevelDownload.rawValue = value
632 }
633 handleChanges()
634 }
635 handle: Rectangle {
636 x: sliderMaxZoom.leftPadding + sliderMaxZoom.visualPosition * (sliderMaxZoom.availableWidth - width)
637 y: sliderMaxZoom.topPadding + sliderMaxZoom.availableHeight * 0.5 - height * 0.5
638 implicitWidth: sliderTouchArea
639 implicitHeight: sliderTouchArea
640 radius: sliderTouchArea * 0.5
641 color: qgcPal.button
642 border.width: 1
643 border.color: qgcPal.buttonText
644 Label {
645 text: sliderMaxZoom.value
646 anchors.centerIn: parent
647 font.family: ScreenTools.normalFontFamily
648 font.pointSize: ScreenTools.smallFontPointSize
649 color: qgcPal.buttonText
650 }
651 }
652 } // Slider - max zoom
653
654 GridLayout {
655 columns: 2
656 rowSpacing: ScreenTools.isTinyScreen ? 0 : ScreenTools.defaultFontPixelHeight * 0.5
657 QGCLabel {
658 text: qsTr("Tile Count:")
659 font.pointSize: _adjustableFontPointSize
660 }
661 QGCLabel {
662 text: QGroundControl.mapEngineManager.tileCountStr
663 font.pointSize: _adjustableFontPointSize
664 }
665
666 QGCLabel {
667 text: qsTr("Est Size:")
668 font.pointSize: _adjustableFontPointSize
669 }
670 QGCLabel {
671 text: QGroundControl.mapEngineManager.tileSizeStr
672 font.pointSize: _adjustableFontPointSize
673 }
674 }
675 } // Column - Zoom info
676 } // Rectangle - Zoom info
677
678 QGCLabel {
679 text: qsTr("Too many tiles")
680 visible: _tooManyTiles
681 color: qgcPal.warningText
682 anchors.horizontalCenter: parent.horizontalCenter
683 }
684
685 Row {
686 id: addButtonRow
687 spacing: ScreenTools.defaultFontPixelWidth
688 anchors.horizontalCenter: parent.horizontalCenter
689 QGCButton {
690 text: qsTr("Download")
691 width: (addNewSetColumn.width * 0.5) - (addButtonRow.spacing * 0.5)
692 enabled: !_tooManyTiles && setName.text.length > 0
693 onClicked: {
694 if (QGroundControl.mapEngineManager.findName(setName.text)) {
695 duplicateName.visible = true
696 } else {
697 QGroundControl.mapEngineManager.startDownload(setName.text, mapType);
698 _map.destroy()
699 }
700 }
701 }
702 QGCButton {
703 text: qsTr("Cancel")
704 width: (addNewSetColumn.width * 0.5) - (addButtonRow.spacing * 0.5)
705 onClicked: _map.destroy()
706 }
707 }
708 }
709 }
710 }
711 }
712 }
713
714 CenterMapDropButton {
715 id: centerMapButton
716 topMargin: 0
717 anchors.margins: _margins
718 anchors.left: map.left
719 anchors.top: map.top
720 map: _map
721 showMission: false
722 showAllItems: false
723 visible: _addNewSetViewObject
724 }
725
726 QGCPopupDialogFactory {
727 id: errorDialogFactory
728
729 dialogComponent: errorDialogComponent
730 }
731
732 Component {
733 id: errorDialogComponent
734
735 QGCSimpleMessageDialog {
736 title: qsTr("Error Message")
737 text: _mapEngineManager.errorMessage
738 buttons: Dialog.Close
739 }
740 }
741
742 QGCPopupDialogFactory {
743 id: deleteConfirmationDialogFactory
744
745 dialogComponent: deleteConfirmationDialogComponent
746 }
747
748 Component {
749 id: deleteConfirmationDialogComponent
750
751 QGCSimpleMessageDialog {
752 title: qsTr("Confirm Delete")
753 text: tileSet.defaultSet ?
754 qsTr("This will delete all tiles INCLUDING the tile sets you have created yourself.\n\nIs this really what you want?") :
755 qsTr("Delete %1 and all its tiles.\n\nIs this really what you want?").arg(tileSet.name)
756 buttons: Dialog.Yes | Dialog.No
757
758 onAccepted: {
759 QGroundControl.mapEngineManager.deleteTileSet(tileSet)
760 _map.destroy()
761 }
762 }
763 }
764}