From f3cc62cef603d4f864b5c916832d6f90b38a4539 Mon Sep 17 00:00:00 2001 From: Matthias Rauter Date: Tue, 21 Feb 2023 11:48:13 +0100 Subject: Add drawing of mapItems to GeoJson viewer example Change-Id: I362acbb6a428e83c3490742824b54aa68890c47f Reviewed-by: Volker Hilsheimer (cherry picked from commit 0d7a0d92c64a906748b0676ea502ec3d6ccf27d0) Reviewed-by: Qt Cherry-pick Bot --- examples/location/geojson_viewer/CMakeLists.txt | 4 + .../location/geojson_viewer/GeoJsonDelegate.qml | 2 +- examples/location/geojson_viewer/main.cpp | 30 ++++- examples/location/geojson_viewer/main.qml | 124 +++++++++++++++++++++ .../geojson_viewer/mapitems/CircleItem.qml | 30 +++++ .../geojson_viewer/mapitems/PolygonItem.qml | 34 ++++++ .../geojson_viewer/mapitems/PolylineItem.qml | 32 ++++++ .../geojson_viewer/mapitems/RectangleItem.qml | 28 +++++ 8 files changed, 279 insertions(+), 5 deletions(-) create mode 100644 examples/location/geojson_viewer/mapitems/CircleItem.qml create mode 100644 examples/location/geojson_viewer/mapitems/PolygonItem.qml create mode 100644 examples/location/geojson_viewer/mapitems/PolylineItem.qml create mode 100644 examples/location/geojson_viewer/mapitems/RectangleItem.qml diff --git a/examples/location/geojson_viewer/CMakeLists.txt b/examples/location/geojson_viewer/CMakeLists.txt index 0b452a7c..994e5d4b 100644 --- a/examples/location/geojson_viewer/CMakeLists.txt +++ b/examples/location/geojson_viewer/CMakeLists.txt @@ -41,6 +41,10 @@ target_link_libraries(qml_location_geojsonviewer PUBLIC set(qml_resource_files "GeoJsonDelegate.qml" "main.qml" + "mapitems/CircleItem.qml" + "mapitems/PolygonItem.qml" + "mapitems/PolylineItem.qml" + "mapitems/RectangleItem.qml" ) qt6_add_resources(qml_location_geojsonviewer "qml" diff --git a/examples/location/geojson_viewer/GeoJsonDelegate.qml b/examples/location/geojson_viewer/GeoJsonDelegate.qml index 3e2cd257..81d23c54 100644 --- a/examples/location/geojson_viewer/GeoJsonDelegate.qml +++ b/examples/location/geojson_viewer/GeoJsonDelegate.qml @@ -19,7 +19,7 @@ DelegateChooser { property string geojsonType: "Point" property var props: modelData.properties geoShape: modelData.data - radius: 20*1000 + radius: (props && props.radius) || 20*1000 border.width: 3 border.color: hh.hovered ? "magenta" : "black" opacity: dc.defaultOpacity diff --git a/examples/location/geojson_viewer/main.cpp b/examples/location/geojson_viewer/main.cpp index 97364c3e..ba390c7d 100644 --- a/examples/location/geojson_viewer/main.cpp +++ b/examples/location/geojson_viewer/main.cpp @@ -75,8 +75,24 @@ public: QVariantMap pt; pt["type"] = "Point"; pt["data"] = QVariant::fromValue(mapCircle->geoShape()); - if (hasProperties(mapCircle)) - pt["properties"] = mapCircle->property("props").toMap(); + QVariantMap propMap = mapCircle->property("props").toMap(); + propMap["radius"] = mapCircle->radius(); + pt["properties"] = propMap; + return pt; + } + static QVariantMap toVariant(QDeclarativeRectangleMapItem *mapRectangle) + { + QVariantMap pt; + pt["type"] = "Polygon"; + QGeoRectangle rectanlge = mapRectangle->geoShape(); + QGeoPolygon poly; + poly.addCoordinate(rectanlge.topLeft()); + poly.addCoordinate(rectanlge.topRight()); + poly.addCoordinate(rectanlge.bottomRight()); + poly.addCoordinate(rectanlge.bottomLeft()); + pt["data"] = QVariant::fromValue(poly); + if (hasProperties(mapRectangle)) + pt["properties"] = mapRectangle->property("props").toMap(); return pt; } @@ -110,13 +126,19 @@ public: entry = toVariant(polygon); } else if (QDeclarativeCircleMapItem *circle = qobject_cast(kid)) { entry = toVariant(circle); // If GeoJSON Point type is visualized in other ways, handle those types here instead. + } else if (QDeclarativeRectangleMapItem *rectangle = qobject_cast(kid)) { + entry = toVariant(rectangle); // For the self-drawn rectangles. Will be exported as Polygons + } features.append(entry); } - if (nodeType.isEmpty()) { // Dirty hack to handle (=skip) the first MIV used to process the fictitious list with 1 element + if (nodeType.isEmpty()) { if (features.isEmpty()) return root; - return features.first().toMap(); + else if (features.size() == 1) + return features.first().toMap(); + else + root["type"] = "FeatureCollection"; } root["data"] = features; return root; diff --git a/examples/location/geojson_viewer/main.qml b/examples/location/geojson_viewer/main.qml index e5d87040..d514ef1e 100644 --- a/examples/location/geojson_viewer/main.qml +++ b/examples/location/geojson_viewer/main.qml @@ -9,6 +9,7 @@ import QtPositioning import QtLocation import QtCore import Qt.GeoJson +import "mapitems" ApplicationWindow { id: win @@ -29,6 +30,7 @@ ApplicationWindow { currentFolder: dataPath nameFilters: ["GeoJSON files (*.geojson *.json)"] onAccepted: { + view.clearAllItems() geoJsoner.load(fileDialog.selectedFile) } } @@ -120,6 +122,35 @@ ApplicationWindow { map.plugin: Plugin { name: "osm" } map.zoomLevel: 4 + property variant unfinishedItem: 'undefined' + + signal showMainMenu(variant coordinate) + + function addGeoItem(item) + { + var count = view.map.mapItems.length + var co = Qt.createComponent('mapitems/'+item+'.qml') + if (co.status === Component.Ready) { + unfinishedItem = co.createObject(map) + unfinishedItem.setGeometry(tapHandler.lastCoordinate) + unfinishedItem.addGeometry(hoverHandler.currentCoordinate, false) + view.map.addMapItem(unfinishedItem) + unfinishedItem.parent = miv + } else { + console.log(item + " is not supported right now, please call us later.") + } + } + + function clearAllItems() + { + var count = view.map.mapItems.length + for (var i = count-1; i>=0; i--){ + var item = view.map.mapItems[i] + item.parent = view.map + view.map.removeMapItem(item) + } + } + MapItemView { id: miv parent: view.map @@ -127,5 +158,98 @@ ApplicationWindow { delegate: GeoJsonDelegate { } } + + Menu { + id: mapPopupMenu + + property variant coordinate + + MenuItem { + text: qsTr("Rectangle") + onTriggered: view.addGeoItem("RectangleItem") + } + MenuItem { + text: qsTr("Circle") + onTriggered: view.addGeoItem("CircleItem") + } + MenuItem { + text: qsTr("Polyline") + onTriggered: view.addGeoItem("PolylineItem") + } + MenuItem { + text: qsTr("Polygon") + onTriggered: view.addGeoItem("PolygonItem") + } + MenuItem { + text: qsTr("Clear all") + onTriggered: view.clearAllItems() + } + + function show(coordinate) { + mapPopupMenu.coordinate = coordinate + mapPopupMenu.popup() + } + } + + HoverHandler { + id: hoverHandler + property variant currentCoordinate + grabPermissions: PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType + + onPointChanged: { + currentCoordinate = view.map.toCoordinate(hoverHandler.point.position) + if (view.unfinishedItem !== 'undefined') + view.unfinishedItem.addGeometry(view.map.toCoordinate(hoverHandler.point.position), true) + } + + } + + TapHandler { + id: tapHandler + property variant lastCoordinate + acceptedButtons: Qt.LeftButton | Qt.RightButton + + onSingleTapped: (eventPoint, button) => { + lastCoordinate = view.map.toCoordinate(tapHandler.point.position) + if (button === Qt.RightButton) { + if (view.unfinishedItem !== 'undefined') { + view.unfinishedItem.finishAddGeometry() + view.unfinishedItem = 'undefined' + } else + mapPopupMenu.show(lastCoordinate) + } else if (button === Qt.LeftButton) { + if (view.unfinishedItem !== 'undefined') { + if (view.unfinishedItem.addGeometry(view.map.toCoordinate(tapHandler.point.position), false)) { + view.unfinishedItem.finishAddGeometry() + view.unfinishedItem = 'undefined' + } + } + } + } + } + TapHandler { + acceptedButtons: Qt.LeftButton + onDoubleTapped: (eventPoint, button) => { + var preZoomPoint = view.map.toCoordinate(eventPoint.position); + view.map.zoomLevel = Math.floor(view.map.zoomLevel + 1) + var postZoomPoint = view.map.toCoordinate(eventPoint.position); + var dx = postZoomPoint.latitude - preZoomPoint.latitude; + var dy = postZoomPoint.longitude - preZoomPoint.longitude; + view.map.center = QtPositioning.coordinate(view.map.center.latitude - dx, + view.map.center.longitude - dy); + } + } + TapHandler { + acceptedButtons: Qt.RightButton + onDoubleTapped: (eventPoint, button) => { + var preZoomPoint = view.map.toCoordinate(eventPoint.position); + view.map.zoomLevel = Math.floor(view.map.zoomLevel - 1) + var postZoomPoint = view.map.toCoordinate(eventPoint.position); + var dx = postZoomPoint.latitude - preZoomPoint.latitude; + var dy = postZoomPoint.longitude - preZoomPoint.longitude; + view.map.center = QtPositioning.coordinate(view.map.center.latitude - dx, + view.map.center.longitude - dy); + } + } } } diff --git a/examples/location/geojson_viewer/mapitems/CircleItem.qml b/examples/location/geojson_viewer/mapitems/CircleItem.qml new file mode 100644 index 00000000..08709357 --- /dev/null +++ b/examples/location/geojson_viewer/mapitems/CircleItem.qml @@ -0,0 +1,30 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +import QtQuick +import QtLocation + +MapCircle { + color: "#da5546" + border.color: "#330a0a" + border.width: 2 + smooth: true + opacity: 0.75 + autoFadeIn: false + + property string geojsonType: "Point" + + function setGeometry(anchorCoordinate) { + center = anchorCoordinate + } + + function addGeometry(newCoordinate, changeLast){ + radius = center.distanceTo(newCoordinate) + return true + } + + function finishAddGeometry(){ + color = "#46a2da" + border.color = "#190a33" + opacity = 0.25 + } +} diff --git a/examples/location/geojson_viewer/mapitems/PolygonItem.qml b/examples/location/geojson_viewer/mapitems/PolygonItem.qml new file mode 100644 index 00000000..b17c4c84 --- /dev/null +++ b/examples/location/geojson_viewer/mapitems/PolygonItem.qml @@ -0,0 +1,34 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +import QtQuick +import QtLocation + +MapPolygon { + color: "#da5546" + border.color: "#330a0a" + border.width: 2 + smooth: true + opacity: 0.75 + autoFadeIn: false + + property string geojsonType: "Polygon" + + function setGeometry(anchorCoordinate){ + addCoordinate(anchorCoordinate) + } + + function addGeometry(newCoordinate, changeLast){ + if (changeLast && path.length > 0) + removeCoordinate(path[path.length-1]) + addCoordinate(newCoordinate) + return false + } + + function finishAddGeometry(){ + if (path.length > 0) + removeCoordinate(path[path.length-1]) + color = "#46a2da" + border.color = "#190a33" + opacity = 0.25 + } +} diff --git a/examples/location/geojson_viewer/mapitems/PolylineItem.qml b/examples/location/geojson_viewer/mapitems/PolylineItem.qml new file mode 100644 index 00000000..f2922d26 --- /dev/null +++ b/examples/location/geojson_viewer/mapitems/PolylineItem.qml @@ -0,0 +1,32 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +import QtQuick +import QtLocation + +MapPolyline { + line.color: "#330a0a" + line.width: 4 + opacity: 0.75 + smooth: true + autoFadeIn: false + + property string geojsonType: "Polyline" + + function setGeometry(anchorCoordinate){ + addCoordinate(anchorCoordinate) + } + + function addGeometry(newCoordinate, changeLast){ + if (changeLast) + replaceCoordinate(pathLength()-1, newCoordinate) + else + addCoordinate(newCoordinate) + return false + } + + function finishAddGeometry(){ + removeCoordinate(pathLength()-1) + line.color = "#46a2da" + opacity = 0.5 + } +} diff --git a/examples/location/geojson_viewer/mapitems/RectangleItem.qml b/examples/location/geojson_viewer/mapitems/RectangleItem.qml new file mode 100644 index 00000000..51b6d538 --- /dev/null +++ b/examples/location/geojson_viewer/mapitems/RectangleItem.qml @@ -0,0 +1,28 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +import QtQuick +import QtLocation + +MapRectangle { + color: "#da5546" + border.color: "#330a0a" + border.width: 2 + smooth: true + opacity: 0.75 + autoFadeIn: false + + function setGeometry(anchorCoordinate) { + topLeft = anchorCoordinate + } + + function addGeometry(newCoordinate, changeLast){ + bottomRight = newCoordinate + return true //finished + } + + function finishAddGeometry(){ + color = "#46a2da" + border.color = "#190a33" + opacity = 0.25 + } +} -- cgit v1.2.1