Warning, /education/marble/src/apps/marble-maps/MainScreen.qml is written in an unsupported language. File is not indexed.
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2015 Gábor Péterffy <peterffy95@gmail.com> 0004 // SPDX-FileCopyrightText: 2015 Dennis Nienhüser <nienhueser@kde.org> 0005 // SPDX-FileCopyrightText: 2015 Mikhail Ivchenko <ematirov@gmail.com> 0006 // 0007 0008 import QtQuick 2.7 0009 import QtQuick.Controls 2.2 0010 import QtQuick.Window 2.2 0011 import QtQuick.Controls.Material 2.0 0012 0013 0014 import org.kde.marble 0.20 0015 import org.kde.kirigami 2.0 as Kirigami 0016 0017 Kirigami.AbstractApplicationWindow { 0018 id: app 0019 title: qsTr("Marble Maps") 0020 visible: true 0021 0022 width: 600 0023 height: 400 0024 0025 Material.theme: Material.Light 0026 Material.accent: Material.Blue 0027 0028 color: "#f9f9f9" // Keep the background white while no dialog is loaded 0029 0030 property alias state: stateTracker.state 0031 0032 property var selectedPlacemark 0033 property bool showOsmTags: false 0034 property int currentWaypointIndex: 0 0035 0036 property real animatedMargin: app.state === "none" ? 0 : -dialogLoader.height 0037 property bool dialogExpanded: animatedMargin === -dialogLoader.height 0038 property real mapOffset: !dialogExpanded ? animatedMargin / 2 : 0 0039 0040 Behavior on animatedMargin { 0041 NumberAnimation { 0042 id: dialogAnimation 0043 duration: 200 0044 easing.type: Easing.OutQuart 0045 } 0046 } 0047 0048 onSelectedPlacemarkChanged: { 0049 if (!selectedPlacemark) { 0050 app.state = "none" 0051 } 0052 else { 0053 bookmarkButton.bookmark = bookmarks.isBookmark(selectedPlacemark.longitude, selectedPlacemark.latitude) 0054 } 0055 } 0056 0057 SystemPalette{ 0058 id: palette 0059 colorGroup: SystemPalette.Active 0060 } 0061 0062 Settings { 0063 id: settings 0064 } 0065 0066 0067 property bool aboutToQuit: false 0068 0069 onClosing: { 0070 if (app.aboutToQuit || Qt.platform.os !== "android") { 0071 close.accepted = true // we will quit 0072 return 0073 } else if (sidePanel.drawerOpen) { 0074 sidePanel.close() 0075 } else if (pageStack.depth > 1) { 0076 pageStack.pop() 0077 } else if (navigationManager.visible) { 0078 navigationManager.visible = false 0079 } else if (app.state !== "none") { 0080 app.state = "none" 0081 } else if(search.searchResultsVisible.visible){ 0082 search.searchResultsVisible = false 0083 } 0084 else { 0085 if(search.searchResultsVisible){ 0086 search.searchResultsVisible = false 0087 } 0088 app.aboutToQuit = true 0089 quitHelper.visible = true 0090 } 0091 close.accepted = false 0092 } 0093 0094 globalDrawer: Kirigami.GlobalDrawer { 0095 id: sidePanel 0096 title: qsTr("Settings") 0097 0098 handleVisible: false 0099 property alias showAccessibility: accessibilityAction.checked 0100 0101 Settings { 0102 id: sidePanelSettings 0103 property bool showUpdateInfo: Number(value("MarbleMaps", "updateInfoVersion", "0")) < 1 0104 Component.onDestruction: { 0105 sidePanelSettings.setValue("MarbleMaps", "showAccessibility", accessibilityAction.checked ? "true" : "false") 0106 } 0107 } 0108 0109 actions: [ 0110 Kirigami.Action { 0111 id: publicTransportAction 0112 text: qsTr("Public Transport") 0113 checkable: true 0114 checked: marbleMaps.showPublicTransport 0115 iconName: "qrc:///material/directions-bus.svg" 0116 visible: true 0117 onTriggered: { 0118 sidePanel.close() 0119 marbleMaps.showPublicTransport = checked 0120 publicTransportDialog.open() 0121 } 0122 }, 0123 Kirigami.Action { 0124 id: outdoorActivitiesAction 0125 checkable: true 0126 checked: marbleMaps.showOutdoorActivities 0127 text: qsTr("Outdoor Activities") 0128 visible: true 0129 iconName: "qrc:///material/directions-run.svg" 0130 onTriggered: { 0131 sidePanel.close() 0132 marbleMaps.showOutdoorActivities = checked 0133 } 0134 }, 0135 Kirigami.Action { 0136 id: accessibilityAction 0137 checkable: true 0138 checked: settings.value("MarbleMaps", "showAccessibility", "false") === "true" 0139 text: qsTr("Accessibility") 0140 visible: true 0141 iconName: "qrc:///material/wheelchair.svg" 0142 onTriggered: { 0143 sidePanelSettings.value("MarbleMaps", "showAccessibility", "false") === "true" 0144 } 0145 }, 0146 Kirigami.Action{ enabled: false}, 0147 Kirigami.Action { 0148 text: qsTr("About") 0149 iconName: "qrc:///marble.svg" 0150 visible: true 0151 onTriggered: { 0152 app.state = "about" 0153 sidePanel.close() 0154 source = "" 0155 app.pageStack.push("qrc:///AboutDialog.qml") 0156 } 0157 }, 0158 Kirigami.Action { 0159 text: qsTr("Bookmarks") 0160 iconName: "qrc:///material/star.svg" 0161 onTriggered: { 0162 app.state = "bookmarks" 0163 sidePanel.close() 0164 app.pageStack.push("qrc:///Bookmarks.qml") 0165 } 0166 }, 0167 Kirigami.Action { 0168 text: qsTr("Layer Options") 0169 iconName: "qrc:///settings.png" 0170 onTriggered: { 0171 app.state = "options" 0172 sidePanel.close() 0173 app.pageStack.push("qrc:///Options.qml") 0174 } 0175 }, 0176 Kirigami.Action { 0177 text: qsTr("Routing") 0178 iconName: "qrc:///material/directions.svg" 0179 onTriggered: { 0180 app.state = "route" 0181 } 0182 } 0183 ] 0184 0185 Binding { 0186 target: pageStack.currentItem 0187 property: "marbleQuickItem" 0188 value: marbleMaps 0189 when: app.state === "bookmarks" 0190 } 0191 } 0192 0193 pageStack: StackView { 0194 anchors.fill: parent 0195 initialItem: page 0196 } 0197 0198 Kirigami.Page { 0199 id: page 0200 padding: 0 0201 topPadding: 0 0202 leftPadding: 0 0203 rightPadding: 0 0204 bottomPadding: 0 0205 title: qsTr("Marble Maps") 0206 0207 Item { 0208 id: mapItem 0209 0210 width: parent.width 0211 height: parent.height - dialogLoader.height - bottomMenu.height 0212 0213 PinchArea { 0214 anchors.fill: parent 0215 enabled: true 0216 0217 onPinchStarted: marbleMaps.handlePinchStarted(pinch.center) 0218 onPinchFinished: marbleMaps.handlePinchFinished(pinch.center) 0219 onPinchUpdated: marbleMaps.handlePinchUpdated(pinch.center, pinch.scale); 0220 0221 MarbleMaps { 0222 id: marbleMaps 0223 0224 property string currentPositionProvider: "QtPositioning" 0225 property bool wlanOnly: false 0226 property bool smallZoom : radius < 2 * Math.max(app.width, app.height) 0227 0228 anchors.fill: parent 0229 visible: true 0230 0231 // Theme settings. 0232 projection: smallZoom ? MarbleItem.Spherical : MarbleItem.Mercator 0233 mapThemeId: settings.value("MarbleMaps", "mapThemeId", "earth/vectorosm/vectorosm.dgml") 0234 0235 // Visibility of layers/plugins. 0236 showFrameRate: false 0237 showAtmosphere: smallZoom 0238 showCompass: false 0239 showClouds: false 0240 showCrosshairs: false 0241 showGrid: smallZoom 0242 showOverviewMap: false 0243 showOtherPlaces: false 0244 showScaleBar: false 0245 showBackground: smallZoom 0246 showPublicTransport: settings.value("MarbleMaps", "showPublicTransport", "false") === "true" 0247 positionProvider: suspended ? "" : currentPositionProvider 0248 keepScreenOn: !suspended && navigationManager.guidanceModeEnabled 0249 showPositionMarker: false 0250 animationViewContext: dialogAnimation.running 0251 0252 placemarkDelegate: Image { 0253 id: balloon 0254 property int xPos: 0 0255 property int yPos: 0 0256 property real animationOffset: 0 0257 property var placemark: null 0258 x: xPos - 0.5 * width 0259 y: yPos - height - 30 * Screen.pixelDensity * animationOffset 0260 opacity: 1.0 - animationOffset 0261 0262 Connections { 0263 target: app 0264 onSelectedPlacemarkChanged: balloonAnimation.restart() 0265 } 0266 0267 NumberAnimation { 0268 id: balloonAnimation 0269 target: balloon 0270 property: "animationOffset" 0271 from: 1 0272 to: 0 0273 duration: 1000 0274 easing.type: Easing.OutBounce 0275 } 0276 0277 0278 width: Screen.pixelDensity*6 0279 height: width 0280 source: "qrc:///ic_place.png" 0281 onPlacemarkChanged: { 0282 app.selectedPlacemark = placemark 0283 if (placemark) { 0284 app.state = "place" 0285 } else { 0286 app.state = "none" 0287 } 0288 } 0289 } 0290 0291 onPositionAvailableChanged: { 0292 updateIndicator(); 0293 } 0294 onPositionVisibleChanged: { 0295 updateIndicator(); 0296 } 0297 onVisibleLatLonAltBoxChanged: { 0298 !panningDetectionTimer.restart(); 0299 updateIndicator(); 0300 } 0301 onCurrentPositionChanged: { 0302 updateIndicator(); 0303 } 0304 0305 onZoomChanged: { 0306 zoomDetectionTimer.restart() 0307 } 0308 0309 Component.onCompleted: { 0310 setPluginSetting("coordinate-grid", "gridColor", "#999999"); 0311 setPluginSetting("coordinate-grid", "tropicsColor", "#888888"); 0312 setPluginSetting("coordinate-grid", "equatorColor", "#777777"); 0313 setPluginSetting("coordinate-grid", "primaryLabels", "false"); 0314 setPluginSetting("coordinate-grid", "secondaryLabels", "false"); 0315 marbleMaps.loadSettings() 0316 } 0317 Component.onDestruction: marbleMaps.writeSettings() 0318 0319 Connections { 0320 target: Qt.application 0321 onStateChanged: { 0322 if (Qt.application.state === Qt.ApplicationInactive || Qt.application.state === Qt.ApplicationSuspended) { 0323 marbleMaps.writeSettings() 0324 } 0325 } 0326 } 0327 0328 function updateIndicator() { 0329 if ( !positionVisible && positionAvailable ) { 0330 zoomToPositionButton.updateIndicator(); 0331 } 0332 } 0333 0334 RoutingManager { 0335 id: routingManager 0336 anchors.fill: parent 0337 marbleItem: marbleMaps 0338 visible: hasRoute 0339 0340 function addToRoute() { 0341 ensureRouteHasDeparture() 0342 routingManager.addViaByPlacemarkAtIndex(routingManager.waypointCount(), selectedPlacemark) 0343 routingManager.clearSearchResultPlacemarks() 0344 selectedPlacemark = null 0345 app.state = "route" 0346 } 0347 function ensureRouteHasDeparture() { 0348 if (routingManager.routeRequestModel.count === 0) { 0349 if (marbleMaps.positionAvailable) { 0350 routingManager.addViaByPlacemark(marbleMaps.currentPosition) 0351 } 0352 } 0353 } 0354 0355 } 0356 0357 Timer { 0358 id: zoomDetectionTimer 0359 interval: 1000 0360 } 0361 Timer { 0362 id: panningDetectionTimer 0363 interval: 1000 0364 } 0365 0366 PositionMarker { 0367 id: positionMarker 0368 x: navigationManager.snappedPositionMarkerScreenPosition.x - positionMarker.width / 2 0369 y: navigationManager.snappedPositionMarkerScreenPosition.y - positionMarker.height / 2 0370 angle: marbleMaps.angle 0371 visible: marbleMaps.positionAvailable && marbleMaps.positionVisible 0372 radius: navigationManager.screenAccuracy / 2 0373 showAccuracy: navigationManager.deviated 0374 allowRadiusAnimation: !zoomDetectionTimer.running 0375 allowPositionAnimation: !panningDetectionTimer.running 0376 speed: marbleMaps.speed 0377 0378 MouseArea { 0379 anchors.fill: parent 0380 onPressed: app.state = "position" 0381 } 0382 } 0383 0384 MouseArea { 0385 anchors.fill: parent 0386 propagateComposedEvents: true 0387 onPressed: { 0388 marbleMaps.focus = true; 0389 mouse.accepted = false; 0390 } 0391 } 0392 } 0393 0394 NavigationManager { 0395 id: navigationManager 0396 width: parent.width 0397 height: parent.height 0398 visible: false 0399 marbleItem: marbleMaps 0400 hasRoute: routingManager.hasRoute 0401 } 0402 } 0403 0404 BoxedText { 0405 id: distanceIndicator 0406 text: qsTr("%1 km").arg(zoomToPositionButton.distance < 10 ? zoomToPositionButton.distance.toFixed(1) : zoomToPositionButton.distance.toFixed(0)) 0407 anchors { 0408 bottom: zoomToPositionButton.top 0409 horizontalCenter: zoomToPositionButton.horizontalCenter 0410 } 0411 0412 visible: marbleMaps.positionAvailable && !marbleMaps.positionVisible 0413 } 0414 0415 PositionButton { 0416 id: zoomToPositionButton 0417 anchors { 0418 right: parent.right 0419 rightMargin: Screen.pixelDensity * 1 0420 bottom: mapItem.bottom 0421 bottomMargin: 10 0422 } 0423 0424 enabled: marbleMaps.positionAvailable 0425 0426 iconSource: marbleMaps.positionAvailable ? "qrc:///gps_fixed.png" : "qrc:///gps_not_fixed.png" 0427 0428 onClicked: marbleMaps.centerOnCurrentPosition() 0429 0430 property real distance: 0 0431 0432 function updateIndicator() { 0433 var point = marbleMaps.mapFromItem(zoomToPositionButton, diameter * 0.5, diameter * 0.5); 0434 distance = 0.001 * marbleMaps.distanceFromPointToCurrentLocation(point); 0435 angle = marbleMaps.angleFromPointToCurrentLocation(point); 0436 } 0437 0438 showDirection: marbleMaps.positionAvailable && !marbleMaps.positionVisible 0439 } 0440 } 0441 0442 0443 Row { 0444 id: bottomMenu 0445 anchors.left: parent.left 0446 anchors.right: parent.right 0447 anchors.bottom: dialogLoader.top 0448 width: parent.width 0449 height: bottomMenu.visible ? routeEditorButton.height + Screen.pixelDensity * 2 : 0 0450 anchors.topMargin: app.animatedMargin 0451 visible: app.state === "place" || app.state === "route" 0452 0453 onVisibleChanged: bottomMenuAnimation.start() 0454 0455 NumberAnimation { 0456 id: bottomMenuAnimation 0457 target: bottomMenu 0458 property: "y" 0459 from: app.height - bottomMenu.height 0460 to: 0 0461 duration: 500 0462 easing.type: Easing.InExpo 0463 } 0464 0465 Item { 0466 id: bottomMenuBackground 0467 anchors.fill: parent 0468 Rectangle { 0469 color: Material.accent 0470 anchors.fill : parent 0471 } 0472 } 0473 0474 Row { 0475 anchors.centerIn: parent 0476 spacing: Kirigami.Units.gridUnit * 2 0477 0478 FlatButton { 0479 id: routeEditorButton 0480 property string currentProfileIcon: "qrc:///material/directions-car.svg" 0481 height: Screen.pixelDensity * 6 0482 width: height 0483 enabled: app.state !== "route" || routingManager.hasRoute 0484 imageSource: "qrc:///material/directions.svg" 0485 0486 onClicked: { 0487 if (app.state === "route") { 0488 app.state = "none" 0489 navigationManager.visible = true 0490 } else if (app.state === "place") { 0491 app.state = "route" 0492 routingManager.addToRoute() 0493 } else { 0494 app.state = "route" 0495 navigationManager.visible = false 0496 } 0497 } 0498 states: [ 0499 State { 0500 name: "" 0501 PropertyChanges { target: routeEditorButton; imageSource: "qrc:///material/directions.svg"; } 0502 }, 0503 State { 0504 name: "routingAction" 0505 when: app.state === "route" 0506 PropertyChanges { target: routeEditorButton; imageSource: "qrc:///material/navigation.svg"; } 0507 }, 0508 State { 0509 name: "placeAction" 0510 when: app.state === "place" 0511 PropertyChanges { target: routeEditorButton; imageSource: "qrc:///material/directions.svg" } 0512 } 0513 ] 0514 } 0515 0516 FlatButton { 0517 id: bookmarkButton 0518 anchors.verticalCenter: parent.verticalCenter 0519 height: Screen.pixelDensity * 6 0520 width: height 0521 property bool bookmark: bookmarks.isBookmark(app.selectedPlacemark.longitude, app.selectedPlacemark.latitude) 0522 enabled: app.state === "place" 0523 visible: app.state === "place" 0524 imageSource: bookmark ? "qrc:///material/star.svg" : "qrc:///material/star_border.svg" 0525 onClicked: { 0526 if (bookmarkButton.bookmark) { 0527 bookmarks.removeBookmark(app.selectedPlacemark.longitude, app.selectedPlacemark.latitude) 0528 } else { 0529 bookmarks.addBookmark(app.selectedPlacemark, "Default") 0530 } 0531 bookmarkButton.bookmark = !bookmarkButton.bookmark 0532 } 0533 } 0534 } 0535 } 0536 0537 0538 BorderImage { 0539 anchors.top: mapItem.bottom 0540 anchors.bottom: dialogLoader.bottom 0541 anchors.right: parent.right 0542 anchors.left: parent.left 0543 anchors.margins: -14 0544 border { top: 14; left: 14; right: 14; bottom: 14 } 0545 source: "qrc:///border_shadow.png" 0546 } 0547 0548 Search { 0549 id: search 0550 anchors.fill: parent 0551 marbleQuickItem: marbleMaps 0552 visible: !navigationManager.visible 0553 0554 onItemSelected: { 0555 if (routingManager) { 0556 routingManager.addSearchResultAsPlacemark(suggestedPlacemark); 0557 } 0558 app.selectedPlacemark = suggestedPlacemark; 0559 app.state = "place" 0560 } 0561 onMenuButtonClicked: sidePanel.open() 0562 } 0563 0564 Loader { 0565 id: dialogLoader 0566 focus: true 0567 width: childrenRect.width 0568 height : childrenRect.height 0569 0570 anchors { 0571 left: parent.left 0572 right: parent.right 0573 top: parent.bottom 0574 bottom: bottomMenu.top 0575 topMargin: app.animatedMargin 0576 bottomMargin: Kirigami.Units.gridUnits * 10 0577 } 0578 0579 NumberAnimation { 0580 id: loaderAnimation 0581 target: dialogLoader.item 0582 property: "y" 0583 from: dialogLoader.height === 0 ? app.height : app.height - dialogLoader.item.height 0584 to: 0 0585 duration: 500 0586 easing.type: Easing.InExpo 0587 } 0588 0589 onLoaded: { 0590 app.state != "none" ? loaderAnimation.running = true : loaderAnimation.running = false 0591 if (app.state === "place") { 0592 dialogLoader.item.map = marbleMaps 0593 dialogLoader.item.placemark = app.selectedPlacemark 0594 dialogLoader.item.showOsmTags = app.showOsmTags 0595 dialogLoader.item.showAccessibility = sidePanel.showAccessibility 0596 } else if (app.state === "route") { 0597 item.routingManager = routingManager 0598 item.routingProfile = routingManager.routingProfile 0599 item.currentIndex = Qt.binding(function() { return app.currentWaypointIndex }) 0600 } else if (app.state == "position") { 0601 dialogLoader.item.map = marbleMaps 0602 dialogLoader.item.navigationManager = navigationManager 0603 } else if (app.state == "none"){ 0604 dialogLoader.height = 0 0605 } 0606 } 0607 0608 Connections { 0609 target: dialogLoader.item 0610 onCurrentProfileIconChanged: routeEditorButton.currentProfileIcon = dialogLoader.item.currentProfileIcon 0611 ignoreUnknownSignals: true 0612 } 0613 } 0614 0615 Rectangle { 0616 width: parent.width 0617 color: Kirigami.Theme.textColor 0618 opacity: 0.4 0619 height: 1 0620 anchors.bottom: dialogLoader.top 0621 } 0622 0623 Item { 0624 id: stateTracker 0625 state: "none" 0626 0627 states: [ 0628 State { 0629 name: "none" 0630 PropertyChanges { target: dialogLoader; source: "" } 0631 }, 0632 State { 0633 name: "position" 0634 PropertyChanges { target: dialogLoader; source: "CurrentPosition.qml" } 0635 }, 0636 State { 0637 name: "route" 0638 PropertyChanges { target: dialogLoader; source: "RouteEditor.qml" } 0639 }, 0640 State { 0641 name: "place" 0642 PropertyChanges { target: dialogLoader; source: "PlacemarkDialog.qml" } 0643 }, 0644 State { 0645 name: "about" 0646 PropertyChanges { target: dialogLoader; source: "" } 0647 }, 0648 State { 0649 name: "settings" 0650 PropertyChanges { target: dialogLoader; source: "SettingsDialog.qml" } 0651 }, 0652 State { 0653 name: "developer" 0654 PropertyChanges { target: dialogLoader; source: "DeveloperDialog.qml" } 0655 }, 0656 State { 0657 name: "options" 0658 PropertyChanges { target: dialogLoader; source: "" } 0659 }, 0660 State { 0661 name: "bookmarks" 0662 PropertyChanges { target: dialogLoader; source: "" } 0663 } 0664 ] 0665 } 0666 0667 BoxedText { 0668 id: quitHelper 0669 visible: false 0670 text: qsTr("Press again to close.") 0671 anchors.bottom: parent.bottom 0672 anchors.bottomMargin: Screen.pixelDensity * 5 0673 anchors.horizontalCenter: parent.horizontalCenter 0674 onVisibleChanged: { 0675 if (visible) { 0676 quitTimer.restart() 0677 } 0678 } 0679 0680 Timer { 0681 id: quitTimer 0682 interval: 3000; 0683 running: false; 0684 repeat: false 0685 onTriggered: { 0686 app.aboutToQuit = false 0687 quitHelper.visible = false 0688 } 0689 } 0690 } 0691 0692 Bookmarks { 0693 id: bookmarks 0694 map: marbleMaps 0695 } 0696 } 0697 } 0698