diff --git a/src/apps/marble-maps/CircularButton.qml b/src/apps/marble-maps/CircularButton.qml index 03d66ca3c..e2e27554b 100644 --- a/src/apps/marble-maps/CircularButton.qml +++ b/src/apps/marble-maps/CircularButton.qml @@ -1,77 +1,78 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2015 Gábor Péterffy // import QtQuick 2.3 import QtQuick.Controls 1.3 import QtQuick.Controls.Styles 1.3 import QtQuick.Window 2.2 Item { id: root readonly property int diameter: Screen.pixelDensity * 9 property alias iconSource: icon.source property bool highlight: false signal clicked() Rectangle { id: button width: root.diameter height: root.diameter radius: root.diameter / 2 property color idleColor: root.highlight ? palette.highlight : palette.button property color activeColor: root.highlight ? palette.button : palette.highlight - color: touchHandler.pressed ? activeColor : idleColor + color: touchHandler.pressed && root.enabled ? activeColor : idleColor anchors { horizontalCenter: root.horizontalCenter verticalCenter: root.verticalCenter } Text { id: text anchors.fill: parent horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter color: palette.buttonText } Image { id: icon anchors { horizontalCenter: button.horizontalCenter verticalCenter: button.verticalCenter } fillMode: Image.PreserveAspectFit sourceSize.width: 0.6 * root.diameter + opacity: root.enabled ? 1 : 0.5 } MouseArea { id: touchHandler anchors.fill: parent onClicked: root.clicked() } border { width: Screen.pixelDensity * 0.2 color: palette.shadow } SystemPalette{ id: palette colorGroup: SystemPalette.Active } } width: diameter height: diameter } diff --git a/src/apps/marble-maps/DeveloperDialog.qml b/src/apps/marble-maps/DeveloperDialog.qml index 6df977648..73047fa6a 100644 --- a/src/apps/marble-maps/DeveloperDialog.qml +++ b/src/apps/marble-maps/DeveloperDialog.qml @@ -1,246 +1,246 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2015 Dennis Nienhüser // import QtQuick 2.3 import QtQuick.Controls 2.0 import QtQuick.Window 2.2 import QtQuick.Layouts 1.1 import QtQuick.Dialogs 1.0 import org.kde.marble 0.20 Item { id: root height: swipeView.height + Screen.pixelDensity * 4 SystemPalette { id: palette colorGroup: SystemPalette.Active } Settings { id: settings Component.onDestruction: { settings.setValue("localization", "translationsDisabled", ignoreTranslations.checked ? "true" : "false") settings.setValue("localization", "translationFile", localizationItem.translationFile) settings.setValue("Developer", "inertialGlobeRotation", marbleMaps.inertialGlobeRotation) settings.setValue("Developer", "positionProvider", marbleMaps.currentPositionProvider) settings.setValue("Developer", "runtimeTrace", runtimeTrace.checked ? "true" : "false") settings.setValue("Developer", "debugTags", debugTags.checked ? "true" : "false") settings.setValue("Developer", "debugPlacemarks", debugPlacemarks.checked ? "true" : "false") settings.setValue("Developer", "debugPolygons", debugPolygons.checked ? "true" : "false") settings.setValue("Developer", "debugBatches", debugBatches.checked ? "true" : "false") settings.setValue("Developer", "debugOutput", debugOutputEnabled ? "true" : "false") } } Rectangle { anchors.fill: parent color: palette.base } SwipeView { id: swipeView currentIndex: pageIndicator.currentIndex anchors.left: parent.left anchors.right: parent.right height: infoItem.height Item { id: toolsItem height: childrenRect.height Item { height: childrenRect.height anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top anchors.margins: Screen.pixelDensity * 2 Column { spacing: Screen.pixelDensity * 1 Text { text: "Tools" } Grid { columns: 2 flow: Grid.TopToBottom rowSpacing: Screen.pixelDensity * 0.5 columnSpacing: Screen.pixelDensity * 2 CheckBox { id: debugTags text: "OSM Tags" checked: settings.value("Developer", "debugTags") === "true" - onCheckedChanged: placemarkDialog.showTags = checked + onCheckedChanged: app.showOsmTags = checked } CheckBox { text: "Shell Output" checked: settings.value("Developer", "debugOutput") === "true" onCheckedChanged: settings.debugOutputEnabled = checked } CheckBox { text: "Inertial Rotation" checked: settings.value("Developer", "inertialGlobeRotation") === "true" onCheckedChanged: marbleMaps.inertialGlobeRotation = checked } CheckBox { text: "GPS Simulation" checked: settings.value("Developer", "positionProvider") === "RouteSimulationPositionProviderPlugin" onCheckedChanged: marbleMaps.currentPositionProvider = checked ? "RouteSimulationPositionProviderPlugin" : "QtPositioning" } } } } } Item { id: infoItem height: childrenRect.height Item { anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top height: childrenRect.height anchors.margins: Screen.pixelDensity * 2 Column { spacing: Screen.pixelDensity * 1 Text { text: "Debug Rendering" } Grid { columns: 2 flow: Grid.TopToBottom rowSpacing: Screen.pixelDensity * 0.5 columnSpacing: Screen.pixelDensity * 2 CheckBox { id: runtimeTrace text: "Performance" checked: settings.value("Developer", "runtimeTrace") === "true" onCheckedChanged: marbleMaps.setShowRuntimeTrace(checked) } CheckBox { id: debugBatches text: "Batches" checked: settings.value("Developer", "debugBatches") === "true" onCheckedChanged: marbleMaps.setShowDebugBatches(checked) } CheckBox { id: debugPolygons text: "Polygons" checked: settings.value("Developer", "debugPolygons") === "true" onCheckedChanged: marbleMaps.setShowDebugPolygons(checked) } CheckBox { id: debugPlacemarks text: "Placemarks" checked: settings.value("Developer", "debugPlacemarks") === "true" onCheckedChanged: marbleMaps.setShowDebugPlacemarks(checked) } } } } } Item { id: localizationItem height: childrenRect.height property string translationFile: settings.value("localization", "translationFile", "") property string displayFile: translationFile.length > 0 ? translationFile.replace(/^.*[\\\/]/, '') : "none" Item { height: childrenRect.height anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top anchors.margins: Screen.pixelDensity * 2 Column { spacing: Screen.pixelDensity * 1 Text { text: "Translations" } Grid { columns: 2 flow: Grid.TopToBottom rowSpacing: Screen.pixelDensity * 0.5 columnSpacing: Screen.pixelDensity * 3 Text { text: "Custom file: " + localizationItem.displayFile } Row { spacing: Screen.pixelDensity * 2 Button { text: "Change" onClicked: fileDialog.open() } Button { text: "Remove" onClicked: localizationItem.translationFile = "" } } CheckBox { id: ignoreTranslations text: "Disable all translations" checked: settings.value("localization", "translationsDisabled", "false") === "true" } Text { text: "Changes require a restart" } } } } } } PageIndicator { id: pageIndicator interactive: true count: swipeView.count currentIndex: swipeView.currentIndex anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter } FileDialog { id: fileDialog title: "Choose a translation file" folder: shortcuts.home sidebarVisible: false nameFilters: [ "Translation files (*.qm)" ] onAccepted: localizationItem.translationFile = fileUrl } } diff --git a/src/apps/marble-maps/MainScreen.qml b/src/apps/marble-maps/MainScreen.qml index f1f77a79e..ac45a0b56 100644 --- a/src/apps/marble-maps/MainScreen.qml +++ b/src/apps/marble-maps/MainScreen.qml @@ -1,385 +1,452 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2015 Gábor Péterffy // Copyright 2015 Dennis Nienhüser // Copyright 2015 Mikhail Ivchenko // import QtQuick 2.3 import QtQuick.Controls 1.3 import QtQuick.Window 2.2 import org.kde.marble 0.20 ApplicationWindow { - id: root + id: app title: qsTr("Marble Maps") visible: true width: 600 height: 400 - color: palette.window + color: "#f9f9f9" // Keep the background white while no dialog is loaded + + property alias state: stateTracker.state + + property var selectedPlacemark + property bool showOsmTags: false + property int currentWaypointIndex: 0 + + onSelectedPlacemarkChanged: { + if (!selectedPlacemark) { + app.state = "none" + } + } SystemPalette{ id: palette colorGroup: SystemPalette.Active } Item { id: mapItem anchors { top: parent.top left: parent.left right: parent.right - bottom: dialogContainer.top + bottom: dialogLoader.top } PinchArea { anchors.fill: parent enabled: true onPinchStarted: marbleMaps.handlePinchStarted(pinch.center) onPinchFinished: marbleMaps.handlePinchFinished(pinch.center) onPinchUpdated: marbleMaps.handlePinchUpdated(pinch.center, pinch.scale); MarbleMaps { id: marbleMaps property string currentPositionProvider: "QtPositioning" property bool wlanOnly: false - property bool smallZoom : radius < 2 * Math.max(root.width, root.height) + property bool smallZoom : radius < 2 * Math.max(app.width, app.height) anchors.fill: parent visible: true // Theme settings. projection: smallZoom ? MarbleItem.Spherical : MarbleItem.Mercator mapThemeId: "earth/vectorosm/vectorosm.dgml" // Visibility of layers/plugins. showFrameRate: false showAtmosphere: smallZoom showCompass: false showClouds: false showCrosshairs: false showGrid: smallZoom showOverviewMap: false showOtherPlaces: false showScaleBar: false showBackground: smallZoom positionProvider: suspended ? "" : currentPositionProvider keepScreenOn: !suspended && navigationManager.visible showPositionMarker: false + animationViewContext: dialogAnimation.running placemarkDelegate: Image { + id: balloon property int xPos: 0 property int yPos: 0 + property real animationOffset: 0 property var placemark: null x: xPos - 0.5 * width - y: yPos - height + y: yPos - height - 30 * Screen.pixelDensity * animationOffset + opacity: 1.0 - animationOffset + + Connections { + target: app + onSelectedPlacemarkChanged: balloonAnimation.restart() + } + + NumberAnimation { + id: balloonAnimation + target: balloon + property: "animationOffset" + from: 1 + to: 0 + duration: 1000 + easing.type: Easing.OutBounce + } + + width: Screen.pixelDensity*6 height: width source: "qrc:///ic_place.png" onPlacemarkChanged: { - placemarkDialog.placemark = placemark + app.selectedPlacemark = placemark + if (placemark) { + app.state = "place" + } else { + app.state = "none" + } } } onPositionAvailableChanged: { updateIndicator(); } onPositionVisibleChanged: { updateIndicator(); } onVisibleLatLonAltBoxChanged: { !panningDetectionTimer.restart(); updateIndicator(); } onCurrentPositionChanged: { updateIndicator(); } onZoomChanged: { zoomDetectionTimer.restart() } Component.onCompleted: { setPluginSetting("coordinate-grid", "gridColor", "#999999"); setPluginSetting("coordinate-grid", "tropicsColor", "#888888"); setPluginSetting("coordinate-grid", "equatorColor", "#777777"); setPluginSetting("coordinate-grid", "primaryLabels", "false"); setPluginSetting("coordinate-grid", "secondaryLabels", "false"); marbleMaps.loadSettings() } Component.onDestruction: marbleMaps.writeSettings() function updateIndicator() { if ( !positionVisible && positionAvailable ) { zoomToPositionButton.updateIndicator(); } } RoutingManager { - id: routing + id: routingManager anchors.fill: parent marbleItem: marbleMaps - routingProfile: routeEditor.routingProfile visible: hasRoute + + function addToRoute() { + ensureRouteHasDeparture() + routingManager.addViaByPlacemarkAtIndex(routingManager.waypointCount(), selectedPlacemark) + routingManager.clearSearchResultPlacemarks() + selectedPlacemark = null + app.state = "route" + } + function ensureRouteHasDeparture() { + if (routingManager.routeRequestModel.count === 0) { + if (marbleMaps.positionAvailable) { + routingManager.addViaByPlacemark(marbleMaps.currentPosition) + } + } + } + } Timer { id: zoomDetectionTimer interval: 1000 } Timer { id: panningDetectionTimer interval: 1000 } PositionMarker { id: positionMarker x: navigationManager.snappedPositionMarkerScreenPosition.x y: navigationManager.snappedPositionMarkerScreenPosition.y angle: marbleMaps.angle visible: marbleMaps.positionAvailable && marbleMaps.positionVisible radius: navigationManager.screenAccuracy / 2 showAccuracy: navigationManager.deviated allowRadiusAnimation: !zoomDetectionTimer.running allowPositionAnimation: !panningDetectionTimer.running speed: marbleMaps.speed } MouseArea { anchors.fill: parent propagateComposedEvents: true onPressed: { marbleMaps.focus = true; mouse.accepted = false; } } Search { id: search anchors.fill: parent marbleQuickItem: marbleMaps - routingManager: routing visible: !navigationManager.visible + + onItemSelected: { + if (routingManager) { + routingManager.addSearchResultAsPlacemark(suggestedPlacemark); + } + app.selectedPlacemark = suggestedPlacemark; + app.state = "place" + } } } NavigationManager { id: navigationManager width: parent.width height: parent.height visible: false marbleItem: marbleMaps - hasRoute: routing.hasRoute + hasRoute: routingManager.hasRoute } } BoxedText { id: distanceIndicator text: qsTr("%1 km").arg(zoomToPositionButton.distance < 10 ? zoomToPositionButton.distance.toFixed(1) : zoomToPositionButton.distance.toFixed(0)) anchors { bottom: zoomToPositionButton.top horizontalCenter: zoomToPositionButton.horizontalCenter } visible: marbleMaps.positionAvailable && !marbleMaps.positionVisible } PositionButton { id: zoomToPositionButton anchors { right: parent.right rightMargin: Screen.pixelDensity * 1 bottom: routeEditorButton.top bottomMargin: 10 } + enabled: marbleMaps.positionAvailable + iconSource: marbleMaps.positionAvailable ? "qrc:///gps_fixed.png" : "qrc:///gps_not_fixed.png" onClicked: marbleMaps.centerOnCurrentPosition() property real distance: 0 function updateIndicator() { var point = marbleMaps.mapFromItem(zoomToPositionButton, diameter * 0.5, diameter * 0.5); distance = 0.001 * marbleMaps.distanceFromPointToCurrentLocation(point); angle = marbleMaps.angleFromPointToCurrentLocation(point); } showDirection: marbleMaps.positionAvailable && !marbleMaps.positionVisible } CircularButton { id: routeEditorButton + + property string currentProfileIcon: "qrc:///material/directions-car.svg" + anchors { bottom: parent.bottom horizontalCenter: zoomToPositionButton.horizontalCenter bottomMargin: Screen.pixelDensity * 4 } onClicked: { - if (dialogContainer.currentIndex === dialogContainer.routing) { - dialogContainer.currentIndex = dialogContainer.none + if (app.state === "route") { + app.state = "none" navigationManager.visible = true - } else if (dialogContainer.currentIndex === dialogContainer.place) { - dialogContainer.currentIndex = dialogContainer.routing - placemarkDialog.addToRoute() + } else if (app.state === "place") { + app.state = "route" + routingManager.addToRoute() } else { - dialogContainer.currentIndex = dialogContainer.routing + app.state = "route" navigationManager.visible = false } } iconSource: "qrc:///material/directions.svg"; states: [ State { name: "" PropertyChanges { target: routeEditorButton; iconSource: "qrc:///material/directions.svg"; } }, State { name: "routingAction" - when: dialogContainer.currentIndex === dialogContainer.routing + when: app.state === "route" PropertyChanges { target: routeEditorButton; iconSource: "qrc:///material/navigation.svg"; } }, State { name: "placeAction" - when: dialogContainer.currentIndex === dialogContainer.place - PropertyChanges { target: routeEditorButton; iconSource: placemarkDialog.actionIconSource } + when: app.state === "place" + PropertyChanges { target: routeEditorButton; iconSource: currentProfileIcon } } ] } } - Item { - id: dialogContainer + Loader { + id: dialogLoader + + focus: true + anchors { left: parent.left right: parent.right - bottom: parent.bottom + top: parent.bottom + topMargin: animatedMargin } - visible: currentIndex >= 0 - - property var contentItem: routeEditor - - height: visible ? contentItem.height : 0 - - readonly property int none: -1 - readonly property int routing: 0 - readonly property int place: 1 - readonly property int about: 2 - readonly property int settings: 3 - readonly property int developer: 4 - - property int currentIndex: none - - onCurrentIndexChanged: - { - switch (currentIndex) { - case none: - case routing: contentItem = routeEditor; break; - case place: contentItem = placemarkDialog; break; - case about: contentItem = aboutDialog; break; - case settings: contentItem = settingsDialog; break; - case developer: contentItem = developerDialog; break; + + property real animatedMargin: app.state === "none" ? 0 : -height + Behavior on animatedMargin { + NumberAnimation { + id: dialogAnimation + duration: 200 + easing.type: Easing.OutQuart } } - RouteEditor { - id: routeEditor - visible: dialogContainer.currentIndex === dialogContainer.routing - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom + onLoaded: { + if (app.state === "place") { + dialogLoader.item.map = marbleMaps + dialogLoader.item.placemark = app.selectedPlacemark + dialogLoader.item.showOsmTags = app.showOsmTags + } + if (app.state === "route") { + item.routingManager = routingManager + item.routingProfile = routingManager.routingProfile + item.currentIndex = Qt.binding(function() { return app.currentWaypointIndex }) + } } - PlacemarkDialog { - id: placemarkDialog - visible: dialogContainer.currentIndex === dialogContainer.place - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - map: marbleMaps - } - AboutDialog { - id: aboutDialog - visible: dialogContainer.currentIndex === dialogContainer.about - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - } - SettingsDialog { - id: settingsDialog - visible: dialogContainer.currentIndex === dialogContainer.settings - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - } - DeveloperDialog { - id: developerDialog - visible: dialogContainer.currentIndex === dialogContainer.developer - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom + + Connections { + target: dialogLoader.item + onCurrentProfileIconChanged: routeEditorButton.currentProfileIcon = dialogLoader.item.currentProfileIcon + ignoreUnknownSignals: true } } BorderImage { - visible: dialogContainer.visible - anchors.fill: dialogContainer + visible: app.state != "none" + anchors.fill: dialogLoader anchors.margins: -14 border { top: 14; left: 14; right: 14; bottom: 14 } source: "qrc:///border_shadow.png" } BoxedText { id: quitHelper visible: false text: qsTr("Press again to close.") anchors.bottom: parent.bottom anchors.bottomMargin: Screen.pixelDensity * 5 anchors.horizontalCenter: parent.horizontalCenter onVisibleChanged: { if (visible) { quitTimer.restart() } } Timer { id: quitTimer interval: 3000; running: false; repeat: false onTriggered: { - root.aboutToQuit = false + app.aboutToQuit = false quitHelper.visible = false } } } property bool aboutToQuit: false onClosing: { - if (root.aboutToQuit === true) { + if (app.aboutToQuit === true) { close.accepted = true // we will quit return } else if (navigationManager.visible) { navigationManager.visible = false - } else if (dialogContainer.visible) { - dialogContainer.currentIndex = dialogContainer.none + } else if (app.state !== "none") { + app.state = "none" } else { - root.aboutToQuit = true + app.aboutToQuit = true quitHelper.visible = true } close.accepted = false } + + Item { + id: stateTracker + + state: "none" + + states: [ + State { + name: "none" + PropertyChanges { target: dialogLoader; source: "" } + }, + State { + name: "route" + PropertyChanges { target: dialogLoader; source: "RouteEditor.qml" } + }, + State { + name: "place" + PropertyChanges { target: dialogLoader; source: "PlacemarkDialog.qml" } + }, + State { + name: "about" + PropertyChanges { target: dialogLoader; source: "AboutDialog.qml" } + }, + State { + name: "settings" + PropertyChanges { target: dialogLoader; source: "SettingsDialog.qml" } + }, + State { + name: "developer" + PropertyChanges { target: dialogLoader; source: "DeveloperDialog.qml" } + } + ] + } } diff --git a/src/apps/marble-maps/PlacemarkDialog.qml b/src/apps/marble-maps/PlacemarkDialog.qml index c7f38935c..567502c8f 100644 --- a/src/apps/marble-maps/PlacemarkDialog.qml +++ b/src/apps/marble-maps/PlacemarkDialog.qml @@ -1,181 +1,163 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2015 Dennis Nienhüser // import QtQuick 2.3 import QtQuick.Controls 1.3 import QtQuick.Window 2.2 -import QtQuick.Layouts 1.1 import QtQuick.Controls 2.0 import org.kde.marble 0.20 Item { id: root property var placemark: null - property string actionIconSource: routeEditor.currentProfileIcon - property alias map: bookmarks.map - property alias showTags: tagsView.visible + property variant map + property alias showOsmTags: tagsView.visible height: placemark === null ? 0 : Screen.pixelDensity * 4 + (infoLayout.height > bookmarkButton.height ? infoLayout.height : bookmarkButton.height) - function addToRoute() { - ensureRouteHasDeparture() - routing.addViaByPlacemarkAtIndex(routing.waypointCount(), placemark) - routing.clearSearchResultPlacemarks() - placemark = null - dialogContainer.currentIndex = dialogContainer.routing - } - onPlacemarkChanged: { if (placemark) { bookmarkButton.bookmark = bookmarks.isBookmark(placemark.longitude, placemark.latitude) - dialogContainer.currentIndex = dialogContainer.place - } else { - dialogContainer.currentIndex = dialogContainer.none } } SystemPalette { id: palette colorGroup: SystemPalette.Active } Rectangle { anchors.fill: parent color: palette.base } Bookmarks { id: bookmarks } + onMapChanged: bookmarks.map = root.map + + Column { id: infoLayout anchors { top: parent.top left: parent.left right: bookmarkButton.left margins: Screen.pixelDensity * 2 } IconText { id: name width: parent.width visible: text.length > 0 text: placemark === null ? "" : placemark.name maximumLineCount: 2 font.pointSize: 20 } IconText { width: parent.width visible: text.length > 0 text: placemark === null ? "" : placemark.description } IconText { width: parent.width visible: text.length > 0 text: placemark === null ? "" : placemark.address maximumLineCount: 4 } IconText { width: parent.width visible: url.length > 0 property string url: placemark === null ? "" : placemark.website text: "" + url + "" icon: "qrc:/material/browser.svg" maximumLineCount: 4 onLinkActivated: Qt.openUrlExternally(link) } IconText { width: parent.width visible: url.length > 0 property string url: placemark === null ? "" : placemark.wikipedia text: "Wikipedia" icon: "qrc:/material/browser.svg" maximumLineCount: 4 onLinkActivated: Qt.openUrlExternally(link) } IconText { width: parent.width visible: text.length > 0 text: placemark === null ? "" : placemark.openingHours icon: "qrc:/material/access_time.svg" } IconText { width: parent.width visible: text.length > 0 text: placemark === null ? "" : "" + placemark.coordinates + "" icon: "qrc:/material/place.svg" linkColor: palette.text onLinkActivated: marbleMaps.centerOnCoordinates(placemark.longitude, placemark.latitude) } ListView { id: tagsView visible: false width: parent.width height: Math.min(contentHeight, Screen.pixelDensity * 24) clip: true model: placemark ? placemark.tags : undefined delegate: IconText { width: tagsView.width; icon: "qrc:/material/label.svg" text: modelData } ScrollBar.vertical: ScrollBar {} } } Image { id: bookmarkButton anchors.right: parent.right anchors.top: parent.top anchors.margins: Screen.pixelDensity * 2 visible: root.height > 0 property bool bookmark: false width: Screen.pixelDensity * 6 height: width sourceSize.height: height sourceSize.width: width source: bookmark ? "qrc:/material/star.svg" : "qrc:/material/star_border.svg" MouseArea { id: touchArea anchors.fill: parent onClicked: { if (bookmarkButton.bookmark) { bookmarks.removeBookmark(root.placemark.longitude, root.placemark.latitude) } else { bookmarks.addBookmark(root.placemark, "Default") } bookmarkButton.bookmark = !bookmarkButton.bookmark } } } - - function ensureRouteHasDeparture() { - if (routing.routeRequestModel.count === 0) { - if (marbleMaps.positionAvailable) { - routing.addViaByPlacemark(marbleMaps.currentPosition) - } - } - } } diff --git a/src/apps/marble-maps/ProfileSelectorMenu.qml b/src/apps/marble-maps/ProfileSelectorMenu.qml index 26274eee5..f608ae43b 100644 --- a/src/apps/marble-maps/ProfileSelectorMenu.qml +++ b/src/apps/marble-maps/ProfileSelectorMenu.qml @@ -1,64 +1,64 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2015 Gábor Péterffy // Copyright 2015 Dennis Nienhüser // import QtQuick 2.3 import QtQuick.Controls 1.3 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import org.kde.marble 0.20 Item { id: root property string selectedProfile: carProfileButton.profile property string profileIcon: "qrc:///material/directions-car.svg" height: rowLayout.height width: rowLayout.width Settings { id: settings Component.onDestruction: { settings.setValue("Routing", "profile", root.selectedProfile) } } RowLayout { id: rowLayout ExclusiveGroup { id: profileGroup onCurrentChanged: { profileIcon = current.imageSource selectedProfile = current.profile; } } RouteProfileRadioButton { id: carProfileButton - checked: settings.value("Routing", "profile", profile) === profile + checked: settings.value("Routing", "profile") === "" || settings.value("Routing", "profile", profile) === profile exclusiveGroup: profileGroup property string profile: qsTr("Car (fastest)") imageSource: "qrc:///material/directions-car.svg" } RouteProfileRadioButton { checked: settings.value("Routing", "profile") === profile exclusiveGroup: profileGroup property string profile: qsTr("Bicycle") imageSource: "qrc:///material/directions-bike.svg" } RouteProfileRadioButton { checked: settings.value("Routing", "profile") === profile exclusiveGroup: profileGroup property string profile: qsTr("Pedestrian") imageSource: "qrc:///material/directions-walk.svg" } } } diff --git a/src/apps/marble-maps/RouteEditor.qml b/src/apps/marble-maps/RouteEditor.qml index ed7914290..e4526af2b 100644 --- a/src/apps/marble-maps/RouteEditor.qml +++ b/src/apps/marble-maps/RouteEditor.qml @@ -1,168 +1,171 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2015 Gábor Péterffy // Copyright 2015 Dennis Nienhüser // import QtQuick 2.3 import QtQuick.Controls 1.3 import QtQuick.Window 2.2 import QtQuick.Layouts 1.1 import org.kde.marble 0.20 Item { id: root property alias routingProfile: profileSelector.selectedProfile property alias currentProfileIcon: profileSelector.profileIcon - property alias currentIndex: waypointList.currentIndex + property int currentIndex: 0 + property var routingManager height: visible ? Screen.pixelDensity * 4 + column.height : 0 SystemPalette{ id: palette colorGroup: SystemPalette.Active } Rectangle { anchors.fill: parent color: palette.base } Column { id: column spacing: Screen.pixelDensity * 2 anchors { top: parent.top left: parent.left right: parent.right margins: Screen.pixelDensity * 2 } Item { anchors { left: parent.left right: parent.right } height: profileSelector.height ProfileSelectorMenu { id: profileSelector anchors.left: parent.left } } Text { id: helpText visible: waypointList.count < 2 color: "gray" text: qsTr("Search for places to integrate them into a route.") } ListView { id: waypointList anchors { left: parent.left right: parent.right } height: Math.min(0.4 * Screen.height, contentHeight) clip: true - model: routing.routeRequestModel + model: routingManager.routeRequestModel + + currentIndex: root.currentIndex delegate: Rectangle { width: parent.width height: Screen.pixelDensity * 2 + Math.max(text.height, image.height) - color: touchArea.pressed || waypointList.currentIndex === index ? palette.highlight : palette.base + color: touchArea.pressed || root.currentIndex === index ? palette.highlight : palette.base WaypointImage { id: image anchors { left: parent.left verticalCenter: parent.verticalCenter } type: index === 0 ? "departure" : (index === waypointList.count-1 ? "destination" : "waypoint") } Text { id: text anchors { left: image.right right: buttonsRow.left leftMargin: parent.width * 0.05 verticalCenter: parent.verticalCenter } elide: Text.ElideMiddle text: name font.pointSize: 18 color: palette.text } MouseArea { id: touchArea anchors.fill: parent onClicked: { - if (index === waypointList.currentIndex) { - waypointList.currentIndex = -1 + if (index === root.currentIndex) { + root.currentIndex = -1 } else { - waypointList.currentIndex = index + root.currentIndex = index marbleMaps.centerOn(longitude, latitude) } } } Row { id: buttonsRow anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter ImageButton { id: upButton anchors.verticalCenter: parent.verticalCenter - visible: index > 0 && index === waypointList.currentIndex + visible: index > 0 && index === root.currentIndex imageSource: "qrc:///up.png" onClicked: { - routing.swapVias(index, index-1); - waypointList.currentIndex--; + routingManager.swapVias(index, index-1); + root.currentIndex--; } } ImageButton { id: downButton anchors.verticalCenter: parent.verticalCenter - visible: index+1 < routing.routeRequestModel.count && index === waypointList.currentIndex + visible: index+1 < routingManager.routeRequestModel.count && index === root.currentIndex imageSource: "qrc:///down.png" onClicked: { - routing.swapVias(index, index+1); - waypointList.currentIndex++; + routingManager.swapVias(index, index+1); + root.currentIndex++; } } ImageButton { id: deleteButton anchors.verticalCenter: parent.verticalCenter - visible: index === waypointList.currentIndex + visible: index === root.currentIndex imageSource: "qrc:///delete.png" onClicked: { - routing.removeVia(index); - waypointList.currentIndex = Math.max(0, waypointList.currentIndex-1); + routingManager.removeVia(index); + root.currentIndex = Math.max(0, root.currentIndex-1); } } } } ScrollBar { id: scrollBar flickableItem: waypointList } } } } diff --git a/src/apps/marble-maps/Search.qml b/src/apps/marble-maps/Search.qml index 26748e031..9ad1b522a 100644 --- a/src/apps/marble-maps/Search.qml +++ b/src/apps/marble-maps/Search.qml @@ -1,229 +1,210 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2015 Gábor Péterffy // import QtQuick 2.3 import QtQuick.Controls 2.0 import QtQuick.Window 2.2 import org.kde.marble 0.20 Item { id: root property var marbleQuickItem: null - property var routingManager: null - signal itemSelected() + signal itemSelected(var suggestedPlacemark) readonly property alias searchResultPlacemark: backend.selectedPlacemark readonly property alias searchResultsVisible: searchResults.visible onVisibleChanged: { if( !visible ) { searchResults.visible = false; searchField.query = ""; } } SystemPalette { id: palette colorGroup: SystemPalette.Active } SystemPalette { id: paletteDisabled colorGroup: SystemPalette.Disabled } SearchResults { id: searchResults anchors { top: searchField.bottom left: searchField.left } width: searchField.width height: delegateHeight * Math.min(10,count) visible: false onItemSelected: { backend.setSelectedPlacemark(index); - root.itemSelected(); + root.itemSelected(backend.selectedPlacemark); searchResults.visible = false; - if (routingManager) { - routingManager.addSearchResultAsPlacemark(backend.selectedPlacemark); - } - placemarkDialog.placemark = backend.selectedPlacemark; } } Rectangle { id: background visible: searchField.hasFocus && searchField.query === "" anchors.top: searchField.bottom anchors.left: searchField.left width: searchField.width height: childrenRect.height + 2 * itemSpacing color: palette.base property int delegateHeight: 0 property double itemSpacing: Screen.pixelDensity * 1 Column { anchors.top: parent.top anchors.topMargin: background.itemSpacing anchors.left: parent.left anchors.right: parent.right anchors.margins: background.itemSpacing spacing: background.itemSpacing ListView { id: bookmarksView anchors.left: parent.left anchors.right: parent.right height: background.delegateHeight * Math.min(6, model.count) clip: true ScrollIndicator.vertical: ScrollIndicator { } model: bookmarks.model delegate: Row { width: bookmarksView.width height: background.itemSpacing + Math.max(bookmarkIcon.height, bookmarkText.height) spacing: background.itemSpacing Image { id: bookmarkIcon anchors.verticalCenter: parent.verticalCenter source: iconPath.substr(0,1) === '/' ? "file://" + iconPath : iconPath width: Screen.pixelDensity * 4 height: width sourceSize.width: width sourceSize.height: height } Text { id: bookmarkText anchors.verticalCenter: parent.verticalCenter anchors.leftMargin: Screen.pixelDensity * 2 width: bookmarksView.width - bookmarksView.spacing - bookmarkIcon.width text: display font.pointSize: 18 color: palette.text elide: Text.ElideMiddle MouseArea { anchors.fill: parent onClicked: { bookmarksView.currentIndex = index - placemarkDialog.placemark = bookmarks.placemark(index); - marbleMaps.centerOn(placemarkDialog.placemark.longitude, placemarkDialog.placemark.latitude) - dialogContainer.focus = true + app.selectedPlacemark = bookmarks.placemark(index); + itemSelected(bookmarks.placemark(index)) + marbleMaps.centerOn(selectedPlacemark.longitude, selectedPlacemark.latitude) + dialogLoader.focus = true } } } onHeightChanged: { if( background.delegateHeight !== height ) { background.delegateHeight = height; } } } } Row { visible: bookmarksView.model.count === 0 width: parent.width Text { anchors.bottom: parent.bottom width: 0.8 * parent.width font.pointSize: 18 color: paletteDisabled.text text: qsTr("Your bookmarks will appear here.") wrapMode: Text.WrapAtWordBoundaryOrAnywhere elide: Text.ElideRight } Image { anchors.bottom: parent.bottom width: 0.2 * parent.width fillMode: Image.PreserveAspectFit source: "qrc:/konqi/books.png" } } Rectangle { height: 1 width: parent.width color: "gray" } Text { font.pointSize: 18 color: palette.text width: parent.width text: qsTr("About Marble Maps…") elide: Text.ElideRight MouseArea { anchors.fill: parent onClicked: { - dialogContainer.currentIndex = dialogContainer.about - dialogContainer.focus = true - } - } - } - - /* - Text { - font.pointSize: 18 - color: palette.text - text: qsTr("Settings") - MouseArea { - anchors.fill: parent - onClicked: { - dialogContainer.currentIndex = dialogContainer.settings - dialogContainer.focus = true + app.state = "about" + dialogLoader.focus = true } } } - */ } } SearchBackend { id: backend marbleQuickItem: root.marbleQuickItem onSearchResultChanged: { searchResults.model = model; searchResults.visible = true; } onSearchFinished: searchField.busy = false } SearchField { id: searchField width: parent.width - 2 * anchors.margins <= Screen.pixelDensity * 70 ? parent.width - 2 * anchors.margins : Screen.pixelDensity * 50 anchors { top: parent.top left: parent.left margins: Screen.pixelDensity * 3 } completionModel: backend.completionModel onSearchRequested: backend.search(query) onCompletionRequested: backend.setCompletionPrefix(query) onCleared: searchResults.visible = false } Bookmarks { id: bookmarks map: root.marbleQuickItem } } diff --git a/src/apps/marble-maps/SearchField.qml b/src/apps/marble-maps/SearchField.qml index fdc6726b0..d10d22a36 100644 --- a/src/apps/marble-maps/SearchField.qml +++ b/src/apps/marble-maps/SearchField.qml @@ -1,143 +1,143 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2015 Gábor Péterffy // Copyright 2015 Dennis Nienhüser // Copyright 2015 Mikhail Ivchenko // import QtQuick 2.3 import QtQuick.Controls 1.3 import QtQuick.Controls.Styles 1.3 Item { id: root height: field.height property alias query: field.text property alias hasFocus: field.activeFocus property alias completionModel: completion.model property bool busy: false signal searchRequested(string query) signal completionRequested(string query) signal cleared() function search(query) { - routing.clearSearchResultPlacemarks(); + routingManager.clearSearchResultPlacemarks(); query = query.trim(); if(query.toLowerCase() === "ok marble") { - dialogContainer.currentIndex = dialogContainer.developer; + app.state = "developer"; } else if(query !== "") { root.busy = true; searchRequested(query); field.focus = false; } } SystemPalette{ id: palette colorGroup: SystemPalette.Active } Rectangle { anchors.fill: parent color: palette.base border.color: palette.shadow border.width: 1 } TextField { id: field anchors.left: parent.left anchors.right: parent.right placeholderText: qsTr("Search") font.pointSize: 18 textColor: palette.text inputMethodHints: Qt.ImhNoPredictiveText onAccepted: root.search(text) onTextChanged: root.completionRequested(text) BusyIndicator { id: searchBusyIndicator anchors.verticalCenter: parent.verticalCenter anchors.right: clearButton.visible ? clearButton.left : clearButton.right anchors.rightMargin: 10 visible: running height: 0.7 * field.height width: height running: root.busy style: BusyIndicatorStyle { indicator: Image { visible: control.running source: "busy_indicator.png" RotationAnimator on rotation { running: control.running loops: Animation.Infinite duration: 1500 from: 0 ; to: 360 } } } } FlatButton { id: clearButton anchors.verticalCenter: parent.verticalCenter anchors.right: searchButton.visible ? searchButton.left : parent.right anchors.rightMargin: 10 height: 0.7 * field.height width: height visible: field.text !== "" imageSource: "qrc:///clear.png" MouseArea { anchors.fill: parent onClicked: { - placemarkDialog.placemark = null; - dialogContainer.currentIndex = dialogContainer.none - routing.clearSearchResultPlacemarks(); + app.selectedPlacemark = null; + app.state = "none" + routingManager.clearSearchResultPlacemarks(); field.text = ""; field.focus = true; cleared(); } } } FlatButton { id: searchButton anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right anchors.rightMargin: 10 height: 0.7 * field.height width: height visible: !root.busy enabled: field.text !== "" imageSource: "qrc:///search.png" onClicked: root.search(field.text) } } Completion { id: completion anchors { top: parent.bottom left: parent.left right: parent.right } height: delegateHeight * Math.min(2,count) visible: count > 0 && field.activeFocus onItemSelected: { field.text = name; search(name); } } } diff --git a/src/apps/marble-maps/Waypoint.qml b/src/apps/marble-maps/Waypoint.qml index f5627b618..c43c9b44c 100644 --- a/src/apps/marble-maps/Waypoint.qml +++ b/src/apps/marble-maps/Waypoint.qml @@ -1,55 +1,55 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2015 Gábor Péterffy // import QtQuick 2.3 import QtGraphicalEffects 1.0 import QtQuick.Window 2.2 import org.kde.marble 0.20 Item { id: root property alias type: image.type property int xPos: 0 property int yPos: 0 property var placemark: null property int index: -1 width: Screen.pixelDensity * 15 height: width x: xPos - 0.5 * width y: yPos - 0.5 * height WaypointImage { id: image onClicked: { if (type == "searchResult") { if (placemarkDialog.placemark === placemark) { placemarkDialog.placemark = null - dialogContainer.currentIndex = dialogContainer.none + app.state = "none" } else { placemarkDialog.placemark = placemark - dialogContainer.currentIndex = dialogContainer.place + app.state = "place" } } else { - routeEditor.currentIndex = index - dialogContainer.currentIndex = dialogContainer.routing + app.currentWaypointIndex = index + app.state = "route" } } anchors { bottom: parent.verticalCenter horizontalCenter: parent.horizontalCenter } x: 0.5 * parent.width - 0.5 * width y: 0.5 * parent.height - height } } diff --git a/src/lib/marble/declarative/MarbleQuickItem.cpp b/src/lib/marble/declarative/MarbleQuickItem.cpp index f2a39ddf3..49caabf57 100644 --- a/src/lib/marble/declarative/MarbleQuickItem.cpp +++ b/src/lib/marble/declarative/MarbleQuickItem.cpp @@ -1,986 +1,998 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2014 Adam Dabrowski // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Marble { //TODO - move to separate files class QuickItemSelectionRubber : public AbstractSelectionRubber { //TODO: support rubber selection in MarbleQuickItem public: void show() { m_visible = true; } void hide() { m_visible = false; } bool isVisible() const { return m_visible; } const QRect &geometry() const { return m_geometry; } void setGeometry(const QRect &/*geometry*/) {} private: QRect m_geometry; bool m_visible; }; //TODO - implement missing functionalities class MarbleQuickInputHandler : public MarbleDefaultInputHandler { public: MarbleQuickInputHandler(MarbleAbstractPresenter *marblePresenter, MarbleQuickItem *marbleQuick) : MarbleDefaultInputHandler(marblePresenter) ,m_marbleQuick(marbleQuick) { setInertialEarthRotationEnabled(false); //Disabled by default, it's buggy. TODO - fix } bool acceptMouse() { return true; } void pinch(QPointF center, qreal scale, Qt::GestureState state) { //TODO - this whole thing should be moved to MarbleAbstractPresenter (void)handlePinch(center, scale, state); } void handleMouseButtonPressAndHold(const QPoint &position) { m_marbleQuick->reverseGeocoding(position); } private Q_SLOTS: void showLmbMenu(int x, int y) { m_marbleQuick->selectPlacemarkAt(x, y); } void showRmbMenu(int, int) {} void openItemToolTip() {} void setCursor(const QCursor &cursor) { m_marbleQuick->setCursor(cursor); } private Q_SLOTS: void installPluginEventFilter(RenderPlugin *) {} private: bool layersEventFilter(QObject *o, QEvent *e) { return m_marbleQuick->layersEventFilter(o, e); } //empty - don't check. It would be invalid with quick items void checkReleasedMove(QMouseEvent *) {} bool handleTouch(QTouchEvent *event) { if (event->touchPoints().count() > 1) { //not handling multi-touch at all, let PinchArea or MultiPointTouchArea take care of it return false; } if (event->touchPoints().count() == 1) { //handle - but do not accept. I.e. pinchArea still needs to get this QTouchEvent::TouchPoint p = event->touchPoints().at(0); if (event->type() == QEvent::TouchBegin) { QMouseEvent press(QMouseEvent::MouseButtonPress, p.pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); handleMouseEvent(&press); } else if (event->type() == QEvent::TouchUpdate) { QMouseEvent move(QMouseEvent::MouseMove, p.pos(), Qt::NoButton, Qt::LeftButton, Qt::NoModifier); handleMouseEvent(&move); } else if (event->type() == QEvent::TouchEnd) { QMouseEvent release(QMouseEvent::MouseButtonRelease, p.pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); handleMouseEvent(&release); } } return false; } AbstractSelectionRubber *selectionRubber() { return &m_selectionRubber; } MarbleQuickItem *m_marbleQuick; QuickItemSelectionRubber m_selectionRubber; bool m_usePinchArea; }; class MarbleQuickItemPrivate { public: explicit MarbleQuickItemPrivate(MarbleQuickItem *marble) : m_marble(marble), m_model(), m_map(&m_model), m_presenter(&m_map), m_positionVisible(false), m_currentPosition(marble), m_inputHandler(&m_presenter, marble), m_placemarkDelegate(nullptr), m_placemarkItem(nullptr), m_placemark(nullptr), m_reverseGeocoding(&m_model), m_showScaleBar(false) { m_currentPosition.setName(QObject::tr("Current Location")); } private: MarbleQuickItem *m_marble; friend class MarbleQuickItem; MarbleModel m_model; MarbleMap m_map; MarbleAbstractPresenter m_presenter; bool m_positionVisible; Placemark m_currentPosition; MarbleQuickInputHandler m_inputHandler; QQmlComponent* m_placemarkDelegate; QQuickItem* m_placemarkItem; Placemark* m_placemark; ReverseGeocodingRunnerManager m_reverseGeocoding; bool m_showScaleBar; }; MarbleQuickItem::MarbleQuickItem(QQuickItem *parent) : QQuickPaintedItem(parent) ,d(new MarbleQuickItemPrivate(this)) { setRenderTarget(QQuickPaintedItem::FramebufferObject); setOpaquePainting(true); qRegisterMetaType("Placemark*"); foreach (AbstractFloatItem *item, d->m_map.floatItems()) { if (item->nameId() == QLatin1String("license")) { item->setPosition(QPointF(5.0, -10.0)); } else { item->hide(); } } d->m_model.positionTracking()->setTrackVisible(false); connect(&d->m_map, SIGNAL(repaintNeeded(QRegion)), this, SLOT(update())); connect(this, SIGNAL(widthChanged()), this, SLOT(resizeMap())); connect(this, SIGNAL(heightChanged()), this, SLOT(resizeMap())); connect(&d->m_map, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)), this, SLOT(updatePositionVisibility())); connect(&d->m_map, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)), this, SIGNAL(visibleLatLonAltBoxChanged())); connect(&d->m_map, SIGNAL(radiusChanged(int)), this, SIGNAL(radiusChanged(int))); connect(&d->m_map, SIGNAL(radiusChanged(int)), this, SIGNAL(zoomChanged())); connect(&d->m_reverseGeocoding, SIGNAL(reverseGeocodingFinished(GeoDataCoordinates,GeoDataPlacemark)), this, SLOT(handleReverseGeocoding(GeoDataCoordinates,GeoDataPlacemark))); setAcceptedMouseButtons(Qt::AllButtons); installEventFilter(&d->m_inputHandler); } void MarbleQuickItem::resizeMap() { const int minWidth = 100; const int minHeight = 100; int newWidth = width() > minWidth ? (int)width() : minWidth; int newHeight = height() > minHeight ? (int)height() : minHeight; d->m_map.setSize(newWidth, newHeight); update(); updatePositionVisibility(); } void MarbleQuickItem::positionDataStatusChanged(PositionProviderStatus status) { if (status == PositionProviderStatusAvailable) { emit positionAvailableChanged(true); } else { emit positionAvailableChanged(false); } updatePositionVisibility(); } void MarbleQuickItem::positionChanged(const GeoDataCoordinates &, GeoDataAccuracy) { updatePositionVisibility(); } void MarbleQuickItem::updatePositionVisibility() { updatePlacemarks(); bool isVisible = false; if ( positionAvailable() ) { qreal x, y; bool globeHidesPoint; bool const valid = d->m_map.viewport()->screenCoordinates(d->m_model.positionTracking()->currentLocation(), x, y, globeHidesPoint); isVisible = valid && !globeHidesPoint; } if ( isVisible != d->m_positionVisible ) { d->m_positionVisible = isVisible; emit positionVisibleChanged( isVisible ); } } void MarbleQuickItem::updateCurrentPosition(const GeoDataCoordinates &coordinates) { d->m_currentPosition.placemark().setCoordinate(coordinates); emit currentPositionChanged(&d->m_currentPosition); } void MarbleQuickItem::updatePlacemarks() { if (!d->m_placemarkDelegate || !d->m_placemark) { return; } if (!d->m_placemarkItem) { QQmlContext * context = new QQmlContext(qmlContext(d->m_placemarkDelegate)); QObject * component = d->m_placemarkDelegate->create(context); d->m_placemarkItem = qobject_cast( component ); if (d->m_placemarkItem) { d->m_placemarkItem->setParentItem( this ); d->m_placemarkItem->setProperty("placemark", QVariant::fromValue(d->m_placemark)); } else { delete component; return; } } qreal x = 0; qreal y = 0; const bool visible = d->m_map.viewport()->screenCoordinates(d->m_placemark->placemark().coordinate(), x, y); d->m_placemarkItem->setVisible(visible); if (visible) { d->m_placemarkItem->setProperty("xPos", QVariant(x)); d->m_placemarkItem->setProperty("yPos", QVariant(y)); } } void MarbleQuickItem::handleReverseGeocoding(const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark) { if (d->m_placemark && d->m_placemark->placemark().coordinate() == coordinates) { d->m_placemark->setGeoDataPlacemark(placemark); updatePlacemarks(); } } void MarbleQuickItem::paint(QPainter *painter) { //TODO - much to be done here still, i.e paint !enabled version QPaintDevice *paintDevice = painter->device(); QRect rect = contentsBoundingRect().toRect(); painter->end(); { GeoPainter geoPainter(paintDevice, d->m_map.viewport(), d->m_map.mapQuality()); d->m_map.paint(geoPainter, rect); } painter->begin(paintDevice); } void MarbleQuickItem::classBegin() { } void MarbleQuickItem::componentComplete() { } int MarbleQuickItem::mapWidth() const { return d->m_map.width(); } int MarbleQuickItem::mapHeight() const { return d->m_map.height(); } bool MarbleQuickItem::showFrameRate() const { return d->m_map.showFrameRate(); } MarbleQuickItem::Projection MarbleQuickItem::projection() const { return (Projection)d->m_map.projection(); } QString MarbleQuickItem::mapThemeId() const { return d->m_map.mapThemeId(); } bool MarbleQuickItem::showAtmosphere() const { return d->m_map.showAtmosphere(); } bool MarbleQuickItem::showCompass() const { return d->m_map.showCompass(); } bool MarbleQuickItem::showClouds() const { return d->m_map.showClouds(); } bool MarbleQuickItem::showCrosshairs() const { return d->m_map.showCrosshairs(); } bool MarbleQuickItem::showGrid() const { return d->m_map.showGrid(); } bool MarbleQuickItem::showOverviewMap() const { return d->m_map.showOverviewMap(); } bool MarbleQuickItem::showOtherPlaces() const { return d->m_map.showOtherPlaces(); } bool MarbleQuickItem::showScaleBar() const { return d->m_showScaleBar; } bool MarbleQuickItem::showBackground() const { return d->m_map.showBackground(); } bool MarbleQuickItem::showPositionMarker() const { QList plugins = d->m_map.renderPlugins(); foreach (const RenderPlugin * plugin, plugins) { if (plugin->nameId() == QLatin1String("positionMarker")) { return plugin->visible(); } } return false; } QString MarbleQuickItem::positionProvider() const { if ( d->m_model.positionTracking()->positionProviderPlugin() ) { return d->m_model.positionTracking()->positionProviderPlugin()->nameId(); } return QString(); } MarbleModel* MarbleQuickItem::model() { return &d->m_model; } const MarbleModel* MarbleQuickItem::model() const { return &d->m_model; } MarbleMap* MarbleQuickItem::map() { return &d->m_map; } const MarbleMap* MarbleQuickItem::map() const { return &d->m_map; } bool MarbleQuickItem::inertialGlobeRotation() const { return d->m_inputHandler.inertialEarthRotationEnabled(); } + bool MarbleQuickItem::animationViewContext() const + { + return d->m_map.viewContext() == Animation; + } + QQmlComponent *MarbleQuickItem::placemarkDelegate() const { return d->m_placemarkDelegate; } void MarbleQuickItem::reverseGeocoding(const QPoint &point) { qreal lon, lat; d->m_map.viewport()->geoCoordinates(point.x(), point.y(), lon, lat); auto const coordinates = GeoDataCoordinates(lon, lat, 0.0, GeoDataCoordinates::Degree); delete d->m_placemarkItem; d->m_placemarkItem = nullptr; delete d->m_placemark; d->m_placemark = new Placemark(this); d->m_placemark->placemark().setCoordinate(coordinates); d->m_reverseGeocoding.reverseGeocoding(coordinates); } qreal MarbleQuickItem::speed() const { return d->m_model.positionTracking()->speed(); } qreal MarbleQuickItem::angle() const { bool routeExists = d->m_model.routingManager()->routingModel()->route().distance() != 0; bool onRoute = !d->m_model.routingManager()->routingModel()->deviatedFromRoute(); if ( routeExists && onRoute) { GeoDataCoordinates curPoint = d->m_model.positionTracking()->positionProviderPlugin()->position(); return d->m_model.routingManager()->routingModel()->route().currentSegment().projectedDirection(curPoint); } else { return d->m_model.positionTracking()->direction(); } } bool MarbleQuickItem::positionAvailable() const { return d->m_model.positionTracking()->status() == PositionProviderStatusAvailable; } bool MarbleQuickItem::positionVisible() { return d->m_positionVisible; } qreal MarbleQuickItem::distanceFromPointToCurrentLocation(const QPoint & position) const { if ( positionAvailable() ) { qreal lon1; qreal lat1; d->m_map.viewport()->geoCoordinates(position.x(), position.y(), lon1, lat1, GeoDataCoordinates::Radian ); GeoDataCoordinates currentCoordinates = d->m_model.positionTracking()->currentLocation(); qreal lon2 = currentCoordinates.longitude(); qreal lat2 = currentCoordinates.latitude(); return distanceSphere(lon1, lat1, lon2, lat2) * d->m_model.planetRadius(); } return 0; } qreal MarbleQuickItem::angleFromPointToCurrentLocation( const QPoint & position ) const { if ( positionAvailable() ) { qreal x, y; PositionTracking const * positionTracking = d->m_model.positionTracking(); map()->viewport()->screenCoordinates( positionTracking->currentLocation(), x, y ); return atan2( y-position.y(), x-position.x() ) * RAD2DEG; } return 0; } Placemark * MarbleQuickItem::currentPosition() const { return &d->m_currentPosition; } QPointF MarbleQuickItem::screenCoordinatesFromCoordinate(Coordinate * coordinate) const { qreal x; qreal y; d->m_map.viewport()->screenCoordinates(coordinate->coordinates(), x, y); return QPointF(x, y); } void MarbleQuickItem::setRadius(int radius) { d->m_map.setRadius(radius); } void MarbleQuickItem::setZoom(int newZoom, FlyToMode mode) { d->m_presenter.setZoom(newZoom, mode); } void MarbleQuickItem::setZoomToMaximumLevel() { d->m_presenter.setZoom(d->m_map.maximumZoom()); } void MarbleQuickItem::centerOn(const GeoDataPlacemark& placemark, bool animated) { d->m_presenter.centerOn(placemark, animated); } void MarbleQuickItem::centerOn(const GeoDataLatLonBox& box, bool animated) { d->m_presenter.centerOn(box, animated); } void MarbleQuickItem::centerOn(const GeoDataCoordinates &coordinate) { GeoDataLookAt target = d->m_presenter.lookAt(); target.setCoordinates(coordinate); d->m_presenter.flyTo(target, Automatic); } void MarbleQuickItem::centerOn(qreal longitude, qreal latitude) { d->m_presenter.centerOn(longitude, latitude); } void MarbleQuickItem::centerOnCoordinates(qreal longitude, qreal latitude) { centerOn(longitude, latitude); } void MarbleQuickItem::centerOnCurrentPosition() { GeoDataCoordinates coordinates = d->m_model.positionTracking()->currentLocation(); if ( coordinates == GeoDataCoordinates() ) { return; } d->m_presenter.centerOn(coordinates, true); if (d->m_presenter.zoom() < 3000) { d->m_presenter.setZoom(3500); } } void MarbleQuickItem::selectPlacemarkAt(int x, int y) { auto features = d->m_map.whichFeatureAt(QPoint(x, y)); if (features.empty()) { features = d->m_map.whichBuildingAt(QPoint(x, y)); } QVector placemarks; foreach(auto feature, features) { if (feature->nodeType() == GeoDataTypes::GeoDataPlacemarkType) { placemarks << static_cast(feature); } } // Select bookmarks only if nothing else is found std::sort(placemarks.begin(), placemarks.end(), [] (GeoDataPlacemark const *a, GeoDataPlacemark const *b) { int const left = a->visualCategory() == GeoDataPlacemark::Bookmark ? -1 : a->visualCategory(); int const right = b->visualCategory() == GeoDataPlacemark::Bookmark ? -1 : b->visualCategory(); return left > right; }); foreach(auto placemark, placemarks) { if (d->m_placemark && placemark->coordinate() == d->m_placemark->placemark().coordinate()) { d->m_placemark->deleteLater(); d->m_placemark = nullptr; } else { d->m_placemark->deleteLater(); d->m_placemark = new Placemark(this); d->m_placemark->setGeoDataPlacemark(*placemark); } delete d->m_placemarkItem; d->m_placemarkItem = nullptr; updatePlacemarks(); return; } if (d->m_placemark) { d->m_placemark->deleteLater(); d->m_placemark = nullptr; delete d->m_placemarkItem; d->m_placemarkItem = nullptr; updatePlacemarks(); } } void MarbleQuickItem::goHome() { d->m_presenter.goHome(); } void MarbleQuickItem::zoomIn(FlyToMode mode) { d->m_presenter.zoomIn(mode); } void MarbleQuickItem::zoomOut(FlyToMode mode) { d->m_presenter.zoomOut(mode); } void MarbleQuickItem::handlePinchStarted(const QPointF &point) { pinch(point, 1, Qt::GestureStarted); } void MarbleQuickItem::handlePinchFinished(const QPointF &point) { pinch(point, 1, Qt::GestureFinished); } void MarbleQuickItem::handlePinchUpdated(const QPointF &point, qreal scale) { scale = sqrt(sqrt(scale)); scale = qBound(static_cast(0.5), scale, static_cast(2.0)); pinch(point, scale, Qt::GestureUpdated); } void MarbleQuickItem::setMapWidth(int mapWidth) { if (d->m_map.width() == mapWidth) { return; } d->m_map.setSize(mapWidth, mapHeight()); emit mapWidthChanged(mapWidth); } void MarbleQuickItem::setMapHeight(int mapHeight) { if (this->mapHeight() == mapHeight) { return; } d->m_map.setSize(mapWidth(), mapHeight); emit mapHeightChanged(mapHeight); } void MarbleQuickItem::setShowFrameRate(bool showFrameRate) { if (this->showFrameRate() == showFrameRate) { return; } d->m_map.setShowFrameRate(showFrameRate); emit showFrameRateChanged(showFrameRate); } void MarbleQuickItem::setProjection(Projection projection) { if (this->projection() == projection) { return; } d->m_map.setProjection((Marble::Projection)projection); emit projectionChanged(projection); } void MarbleQuickItem::setMapThemeId(const QString& mapThemeId) { if (this->mapThemeId() == mapThemeId) { return; } bool const showCompass = d->m_map.showCompass(); bool const showOverviewMap = d->m_map.showOverviewMap(); bool const showOtherPlaces = d->m_map.showOtherPlaces(); bool const showGrid = d->m_map.showGrid(); d->m_map.setMapThemeId(mapThemeId); // Map themes are allowed to change properties. Enforce ours. d->m_map.setShowCompass(showCompass); d->m_map.setShowOverviewMap(showOverviewMap); d->m_map.setShowOtherPlaces(showOtherPlaces); d->m_map.setShowGrid(showGrid); d->m_map.setShowScaleBar(d->m_showScaleBar); emit mapThemeIdChanged(mapThemeId); } void MarbleQuickItem::setShowAtmosphere(bool showAtmosphere) { if (this->showAtmosphere() == showAtmosphere) { return; } d->m_map.setShowAtmosphere(showAtmosphere); emit showAtmosphereChanged(showAtmosphere); } void MarbleQuickItem::setShowCompass(bool showCompass) { if (this->showCompass() == showCompass) { return; } d->m_map.setShowCompass(showCompass); emit showCompassChanged(showCompass); } void MarbleQuickItem::setShowClouds(bool showClouds) { if (this->showClouds() == showClouds) { return; } d->m_map.setShowClouds(showClouds); emit showCloudsChanged(showClouds); } void MarbleQuickItem::setShowCrosshairs(bool showCrosshairs) { if (this->showCrosshairs() == showCrosshairs) { return; } d->m_map.setShowCrosshairs(showCrosshairs); emit showCrosshairsChanged(showCrosshairs); } void MarbleQuickItem::setShowGrid(bool showGrid) { if (this->showGrid() == showGrid) { return; } d->m_map.setShowGrid(showGrid); emit showGridChanged(showGrid); } void MarbleQuickItem::setShowOverviewMap(bool showOverviewMap) { if (this->showOverviewMap() == showOverviewMap) { return; } d->m_map.setShowOverviewMap(showOverviewMap); emit showOverviewMapChanged(showOverviewMap); } void MarbleQuickItem::setShowOtherPlaces(bool showOtherPlaces) { if (this->showOtherPlaces() == showOtherPlaces) { return; } d->m_map.setShowOtherPlaces(showOtherPlaces); emit showOtherPlacesChanged(showOtherPlaces); } void MarbleQuickItem::setShowScaleBar(bool showScaleBar) { if (d->m_showScaleBar == showScaleBar) { return; } d->m_showScaleBar = showScaleBar; d->m_map.setShowScaleBar(d->m_showScaleBar); emit showScaleBarChanged(showScaleBar); } void MarbleQuickItem::setShowBackground(bool showBackground) { if (this->showBackground() == showBackground) { return; } d->m_map.setShowBackground(showBackground); emit showBackgroundChanged(showBackground); } void MarbleQuickItem::setShowPositionMarker(bool showPositionMarker) { if (this->showPositionMarker() == showPositionMarker) { return; } QList plugins = d->m_map.renderPlugins(); foreach ( RenderPlugin * plugin, plugins ) { if (plugin->nameId() == QLatin1String("positionMarker")) { plugin->setVisible(showPositionMarker); break; } } emit showPositionMarkerChanged(showPositionMarker); } void MarbleQuickItem::setPositionProvider(const QString &positionProvider) { QString name; if ( d->m_model.positionTracking()->positionProviderPlugin() ) { name = d->m_model.positionTracking()->positionProviderPlugin()->nameId(); if ( name == positionProvider ) { return; } } if ( positionProvider.isEmpty() ) { d->m_model.positionTracking()->setPositionProviderPlugin( nullptr ); return; } QList plugins = d->m_model.pluginManager()->positionProviderPlugins(); foreach (const PositionProviderPlugin* plugin, plugins) { if ( plugin->nameId() == positionProvider) { PositionProviderPlugin * newPlugin = plugin->newInstance(); d->m_model.positionTracking()->setPositionProviderPlugin(newPlugin); connect(newPlugin, SIGNAL(statusChanged(PositionProviderStatus)), this, SLOT(positionDataStatusChanged(PositionProviderStatus))); connect(newPlugin, SIGNAL(positionChanged(GeoDataCoordinates,GeoDataAccuracy)), this, SLOT(updateCurrentPosition(GeoDataCoordinates))); connect(newPlugin, SIGNAL(positionChanged(GeoDataCoordinates,GeoDataAccuracy)), this, SIGNAL(speedChanged())); connect(newPlugin, SIGNAL(positionChanged(GeoDataCoordinates,GeoDataAccuracy)), this, SIGNAL(angleChanged())); emit positionProviderChanged(positionProvider); break; } } } void MarbleQuickItem::setInertialGlobeRotation(bool inertialGlobeRotation) { if (inertialGlobeRotation == d->m_inputHandler.inertialEarthRotationEnabled()) { return; } d->m_inputHandler.setInertialEarthRotationEnabled(inertialGlobeRotation); emit inertialGlobeRotationChanged(inertialGlobeRotation); } + void MarbleQuickItem::setAnimationViewContext(bool animationViewContext) + { + d->m_map.setViewContext(animationViewContext ? Animation : Still ); + + emit inertialGlobeRotationChanged(animationViewContext); + } + void MarbleQuickItem::setPluginSetting(const QString &pluginId, const QString &key, const QString &value) { foreach (RenderPlugin* plugin, d->m_map.renderPlugins()) { if (plugin->nameId() == pluginId) { plugin->setSetting(key, value); } } } void MarbleQuickItem::setPropertyEnabled(const QString &property, bool enabled) { d->m_map.setPropertyValue(property, enabled); } bool MarbleQuickItem::isPropertyEnabled(const QString &property) const { return d->m_map.propertyValue(property); } void MarbleQuickItem::setShowRuntimeTrace(bool showRuntimeTrace) { d->m_map.setShowRuntimeTrace(showRuntimeTrace); update(); } void MarbleQuickItem::setShowDebugPolygons(bool showDebugPolygons) { d->m_map.setShowDebugPolygons(showDebugPolygons); update(); } void MarbleQuickItem::setShowDebugPlacemarks(bool showDebugPlacemarks) { d->m_map.setShowDebugPlacemarks(showDebugPlacemarks); update(); } void MarbleQuickItem::setShowDebugBatches(bool showDebugBatches) { d->m_map.setShowDebugBatchRender(showDebugBatches); update(); } void MarbleQuickItem::setPlacemarkDelegate(QQmlComponent *placemarkDelegate) { if (d->m_placemarkDelegate == placemarkDelegate) { return; } delete d->m_placemarkItem; d->m_placemarkItem = nullptr; d->m_placemarkDelegate = placemarkDelegate; emit placemarkDelegateChanged(placemarkDelegate); } void MarbleQuickItem::loadSettings() { QSettings settings; settings.beginGroup(QStringLiteral("MarbleQuickItem")); double lon = settings.value(QStringLiteral("centerLon"), QVariant(0.0)).toDouble(); double lat = settings.value(QStringLiteral("centerLat"), QVariant(0.0)).toDouble(); if (lat == 0.0 && lon == 0.0) { centerOnCurrentPosition(); } else { centerOn(lon, lat); } int const zoom = settings.value(QStringLiteral("zoom"), QVariant(0)).toInt(); if (zoom > 0) { setZoom(zoom); } settings.endGroup(); d->m_model.routingManager()->readSettings(); d->m_model.bookmarkManager()->loadFile(QStringLiteral("bookmarks/bookmarks.kml")); d->m_model.bookmarkManager()->setShowBookmarks(true); } void MarbleQuickItem::writeSettings() { QSettings settings; settings.beginGroup(QStringLiteral("MarbleQuickItem")); settings.setValue(QStringLiteral("centerLon"), QVariant(d->m_map.centerLongitude())); settings.setValue(QStringLiteral("centerLat"), QVariant(d->m_map.centerLatitude())); settings.setValue(QStringLiteral("zoom"), QVariant(zoom())); settings.endGroup(); d->m_model.routingManager()->writeSettings(); } QObject *MarbleQuickItem::getEventFilter() const { //We would want to install the same event filter for abstract layer QuickItems such as PinchArea return &d->m_inputHandler; } void MarbleQuickItem::pinch(const QPointF& center, qreal scale, Qt::GestureState state) { d->m_inputHandler.pinch(center, scale, state); } MarbleInputHandler *MarbleQuickItem::inputHandler() { return &d->m_inputHandler; } int MarbleQuickItem::radius() const { return d->m_map.radius(); } int MarbleQuickItem::zoom() const { return d->m_presenter.logzoom(); } bool MarbleQuickItem::layersEventFilter(QObject *, QEvent *) { //Does nothing, but can be reimplemented in a subclass return false; } } diff --git a/src/lib/marble/declarative/MarbleQuickItem.h b/src/lib/marble/declarative/MarbleQuickItem.h index d9cc4da87..b1d968608 100644 --- a/src/lib/marble/declarative/MarbleQuickItem.h +++ b/src/lib/marble/declarative/MarbleQuickItem.h @@ -1,234 +1,238 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2014 Adam Dabrowski // #ifndef MARBLEQUICKITEM_H #define MARBLEQUICKITEM_H #include "marble_declarative_export.h" #include #include #include "GeoDataAccuracy.h" #include "MarbleGlobal.h" #include "PositionProviderPluginInterface.h" #include "MarbleMap.h" #include "Placemark.h" #include "Coordinate.h" namespace Marble { class GeoDataLatLonBox; class GeoDataPlacemark; class MarbleModel; class MarbleInputHandler; class MarbleQuickItemPrivate; //Class is still being developed class MARBLE_DECLARATIVE_EXPORT MarbleQuickItem : public QQuickPaintedItem { Q_OBJECT Q_ENUMS(Projection) Q_PROPERTY(int mapWidth READ mapWidth WRITE setMapWidth NOTIFY mapWidthChanged) Q_PROPERTY(int mapHeight READ mapHeight WRITE setMapHeight NOTIFY mapHeightChanged) Q_PROPERTY(int zoom READ zoom WRITE setZoom NOTIFY zoomChanged) Q_PROPERTY(int radius READ radius WRITE setRadius NOTIFY radiusChanged) Q_PROPERTY(bool showFrameRate READ showFrameRate WRITE setShowFrameRate NOTIFY showFrameRateChanged) Q_PROPERTY(Projection projection READ projection WRITE setProjection NOTIFY projectionChanged) Q_PROPERTY(QString mapThemeId READ mapThemeId WRITE setMapThemeId NOTIFY mapThemeIdChanged) Q_PROPERTY(bool showAtmosphere READ showAtmosphere WRITE setShowAtmosphere NOTIFY showAtmosphereChanged) Q_PROPERTY(bool showCompass READ showCompass WRITE setShowCompass NOTIFY showCompassChanged) Q_PROPERTY(bool showClouds READ showClouds WRITE setShowClouds NOTIFY showCloudsChanged) Q_PROPERTY(bool showCrosshairs READ showCrosshairs WRITE setShowCrosshairs NOTIFY showCrosshairsChanged) Q_PROPERTY(bool showGrid READ showGrid WRITE setShowGrid NOTIFY showGridChanged) Q_PROPERTY(bool showOverviewMap READ showOverviewMap WRITE setShowOverviewMap NOTIFY showOverviewMapChanged) Q_PROPERTY(bool showOtherPlaces READ showOtherPlaces WRITE setShowOtherPlaces NOTIFY showOtherPlacesChanged) Q_PROPERTY(bool showScaleBar READ showScaleBar WRITE setShowScaleBar NOTIFY showScaleBarChanged) Q_PROPERTY(bool showBackground READ showBackground WRITE setShowBackground NOTIFY showBackgroundChanged) Q_PROPERTY(bool showPositionMarker READ showPositionMarker WRITE setShowPositionMarker NOTIFY showPositionMarkerChanged) Q_PROPERTY(QString positionProvider READ positionProvider WRITE setPositionProvider NOTIFY positionProviderChanged) Q_PROPERTY(bool positionAvailable READ positionAvailable NOTIFY positionAvailableChanged) Q_PROPERTY(bool positionVisible READ positionVisible NOTIFY positionVisibleChanged) Q_PROPERTY(MarbleMap* marbleMap READ map NOTIFY marbleMapChanged) Q_PROPERTY(Placemark* currentPosition READ currentPosition NOTIFY currentPositionChanged) Q_PROPERTY(qreal speed READ speed NOTIFY speedChanged) Q_PROPERTY(qreal angle READ angle NOTIFY angleChanged) Q_PROPERTY(bool inertialGlobeRotation READ inertialGlobeRotation WRITE setInertialGlobeRotation NOTIFY inertialGlobeRotationChanged) + Q_PROPERTY(bool animationViewContext READ animationViewContext WRITE setAnimationViewContext NOTIFY animationViewContextChanged) Q_PROPERTY(QQmlComponent* placemarkDelegate READ placemarkDelegate WRITE setPlacemarkDelegate NOTIFY placemarkDelegateChanged) public: explicit MarbleQuickItem(QQuickItem *parent = 0); enum Projection{ Spherical = Marble::Spherical, Equirectangular = Marble::Equirectangular, Mercator = Marble::Mercator, Gnomonic = Marble::Gnomonic, Stereographic = Marble::Stereographic, LambertAzimuthal = Marble::LambertAzimuthal, AzimuthalEquidistant = Marble::AzimuthalEquidistant, VerticalPerspective = Marble::VerticalPerspective }; MarbleInputHandler *inputHandler(); int zoom() const; int radius() const; public Q_SLOTS: void goHome(); void setZoom(int zoom, FlyToMode mode = Instant); Q_INVOKABLE void setZoomToMaximumLevel(); void setRadius(int radius); void centerOn(const GeoDataPlacemark& placemark, bool animated = false); void centerOn(const GeoDataLatLonBox& box, bool animated = false); void centerOn(const GeoDataCoordinates& coordinate); void centerOn(qreal longitude, qreal latitude); Q_INVOKABLE void centerOnCoordinates(qreal longitude, qreal latitude); Q_INVOKABLE void centerOnCurrentPosition(); Q_INVOKABLE void selectPlacemarkAt(int x, int y); void zoomIn(FlyToMode mode = Automatic); void zoomOut(FlyToMode mode = Automatic); Q_INVOKABLE void handlePinchStarted(const QPointF &point); Q_INVOKABLE void handlePinchFinished(const QPointF &point); Q_INVOKABLE void handlePinchUpdated(const QPointF &point, qreal scale); void setMapWidth(int mapWidth); void setMapHeight(int mapHeight); void setShowFrameRate(bool showFrameRate); void setProjection(Projection projection); void setMapThemeId(const QString& mapThemeId); void setShowAtmosphere(bool showAtmosphere); void setShowCompass(bool showCompass); void setShowClouds(bool showClouds); void setShowCrosshairs(bool showCrosshairs); void setShowGrid(bool showGrid); void setShowOverviewMap(bool showOverviewMap); void setShowOtherPlaces(bool showOtherPlaces); void setShowScaleBar(bool showScaleBar); void setShowBackground(bool showBackground); void setShowPositionMarker(bool showPositionMarker); void setPositionProvider(const QString & positionProvider); void setInertialGlobeRotation(bool inertialGlobeRotation); + void setAnimationViewContext(bool animationViewContext); void setPluginSetting(const QString &plugin, const QString &key, const QString &value); void setPropertyEnabled(const QString &property, bool enabled); bool isPropertyEnabled(const QString &property) const; Q_INVOKABLE void setShowRuntimeTrace(bool showRuntimeTrace); Q_INVOKABLE void setShowDebugPolygons(bool showDebugPolygons); Q_INVOKABLE void setShowDebugPlacemarks(bool showDebugPlacemarks); Q_INVOKABLE void setShowDebugBatches(bool showDebugBatches); void setPlacemarkDelegate(QQmlComponent* placemarkDelegate); Q_INVOKABLE void loadSettings(); Q_INVOKABLE void writeSettings(); public: void paint(QPainter *painter); // QQmlParserStatus interface public: void classBegin(); void componentComplete(); public: virtual bool layersEventFilter(QObject *o, QEvent *e); int mapWidth() const; int mapHeight() const; bool showFrameRate() const; Projection projection() const; QString mapThemeId() const; bool showAtmosphere() const; bool showCompass() const; bool showClouds() const; bool showCrosshairs() const; bool showGrid() const; bool showOverviewMap() const; bool showOtherPlaces() const; bool showScaleBar() const; bool showBackground() const; bool showPositionMarker() const; QString positionProvider() const; bool positionAvailable() const; bool positionVisible(); Q_INVOKABLE qreal distanceFromPointToCurrentLocation(const QPoint & position) const; Q_INVOKABLE qreal angleFromPointToCurrentLocation(const QPoint & position) const; Placemark* currentPosition() const; Q_INVOKABLE QPointF screenCoordinatesFromCoordinate(Coordinate * coordinate) const; qreal speed() const; qreal angle() const; MarbleModel* model(); const MarbleModel* model() const; MarbleMap* map(); const MarbleMap* map() const; bool inertialGlobeRotation() const; + bool animationViewContext() const; QQmlComponent* placemarkDelegate() const; void reverseGeocoding(const QPoint &point); Q_SIGNALS: void mapWidthChanged(int mapWidth); void mapHeightChanged(int mapHeight); void showFrameRateChanged(bool showFrameRate); void projectionChanged(Projection projection); void mapThemeIdChanged(const QString& mapThemeId); void showAtmosphereChanged(bool showAtmosphere); void showCompassChanged(bool showCompass); void showCloudsChanged(bool showClouds); void showCrosshairsChanged(bool showCrosshairs); void showGridChanged(bool showGrid); void showOverviewMapChanged(bool showOverviewMap); void showOtherPlacesChanged(bool showOtherPlaces); void showScaleBarChanged(bool showScaleBar); void showBackgroundChanged(bool showBackground); void showPositionMarkerChanged(bool showPositionMarker); void positionProviderChanged(const QString & positionProvider); void positionAvailableChanged(bool positionAvailable); void positionVisibleChanged(bool positionVisible); void marbleMapChanged(); void visibleLatLonAltBoxChanged(); void currentPositionChanged(Placemark* currentPosition); void angleChanged(); void speedChanged(); void zoomChanged(); void radiusChanged(int radius); void inertialGlobeRotationChanged(bool inertialGlobeRotation); + void animationViewContextChanged(bool animationViewContext); void placemarkDelegateChanged(QQmlComponent* placemarkDelegate); protected: QObject *getEventFilter() const; void pinch(const QPointF& center, qreal scale, Qt::GestureState state); private Q_SLOTS: void resizeMap(); void positionDataStatusChanged(PositionProviderStatus status); void positionChanged(const GeoDataCoordinates &, GeoDataAccuracy); void updatePositionVisibility(); void updateCurrentPosition(const GeoDataCoordinates & coordinates); void updatePlacemarks(); void handleReverseGeocoding(const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark); private: typedef QSharedPointer MarbleQuickItemPrivatePtr; MarbleQuickItemPrivatePtr d; friend class MarbleQuickItemPrivate; }; } #endif // MARBLEQUICKITEM_H