mirror of https://github.com/f4exb/sdrangel.git
VOR localizer: Get it working on Qt6.
This commit is contained in:
parent
b939a98f6b
commit
c27ea6d5d7
|
@ -1,7 +1,9 @@
|
||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/demodvor/">
|
<qresource prefix="/demodvor/">
|
||||||
<file>map/map.qml</file>
|
<file>map/map.qml</file>
|
||||||
|
<file>map/map_6.qml</file>
|
||||||
<file>map/MapStation.qml</file>
|
<file>map/MapStation.qml</file>
|
||||||
|
<file>map/ModifiedMapView.qml</file>
|
||||||
<file>map/antenna.png</file>
|
<file>map/antenna.png</file>
|
||||||
<file>map/VOR.png</file>
|
<file>map/VOR.png</file>
|
||||||
<file>map/VOR-DME.png</file>
|
<file>map/VOR-DME.png</file>
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtLocation as QL
|
||||||
|
import QtPositioning as QP
|
||||||
|
import Qt.labs.animation
|
||||||
|
/*!
|
||||||
|
\qmltype MapView
|
||||||
|
\inqmlmodule QtLocation
|
||||||
|
\brief An interactive map viewer component.
|
||||||
|
|
||||||
|
MapView wraps a Map and adds the typical interactive features:
|
||||||
|
changing the zoom level, panning and tilting the map.
|
||||||
|
|
||||||
|
The implementation is a QML assembly of smaller building blocks that are
|
||||||
|
available separately. In case you want to make changes in your own version
|
||||||
|
of this component, you can copy the QML, which is installed into the
|
||||||
|
\c qml/QtLocation module directory, and modify it as needed.
|
||||||
|
|
||||||
|
\sa Map
|
||||||
|
*/
|
||||||
|
Item {
|
||||||
|
/*!
|
||||||
|
\qmlproperty Map MapView::map
|
||||||
|
|
||||||
|
This property provides access to the underlying Map instance.
|
||||||
|
*/
|
||||||
|
property alias map: map
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\qmlproperty real minimumZoomLevel
|
||||||
|
|
||||||
|
The minimum zoom level according to the size of the view.
|
||||||
|
|
||||||
|
\sa Map::minimumZoomLevel
|
||||||
|
*/
|
||||||
|
property real minimumZoomLevel: map.minimumZoomLevel
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\qmlproperty real maximumZoomLevel
|
||||||
|
|
||||||
|
The maximum valid zoom level for the map.
|
||||||
|
|
||||||
|
\sa Map::maximumZoomLevel
|
||||||
|
*/
|
||||||
|
property real maximumZoomLevel: map.maximumZoomLevel
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
// implementation
|
||||||
|
id: root
|
||||||
|
Component.onCompleted: map.resetPinchMinMax()
|
||||||
|
|
||||||
|
QL.Map {
|
||||||
|
id: map
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
tilt: tiltHandler.persistentTranslation.y / -5
|
||||||
|
property bool pinchAdjustingZoom: false
|
||||||
|
|
||||||
|
BoundaryRule on zoomLevel {
|
||||||
|
id: br
|
||||||
|
minimum: map.minimumZoomLevel
|
||||||
|
maximum: map.maximumZoomLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
onZoomLevelChanged: {
|
||||||
|
br.returnToBounds();
|
||||||
|
if (!pinchAdjustingZoom) resetPinchMinMax()
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetPinchMinMax() {
|
||||||
|
pinch.persistentScale = 1
|
||||||
|
pinch.scaleAxis.minimum = Math.pow(2, root.minimumZoomLevel - map.zoomLevel + 1)
|
||||||
|
pinch.scaleAxis.maximum = Math.pow(2, root.maximumZoomLevel - map.zoomLevel - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
PinchHandler {
|
||||||
|
id: pinch
|
||||||
|
target: null
|
||||||
|
property real rawBearing: 0
|
||||||
|
property QP.geoCoordinate startCentroid
|
||||||
|
onActiveChanged: if (active) {
|
||||||
|
flickAnimation.stop()
|
||||||
|
pinch.startCentroid = map.toCoordinate(pinch.centroid.position, false)
|
||||||
|
} else {
|
||||||
|
flickAnimation.restart(centroid.velocity)
|
||||||
|
map.resetPinchMinMax()
|
||||||
|
}
|
||||||
|
onScaleChanged: (delta) => {
|
||||||
|
map.pinchAdjustingZoom = true
|
||||||
|
map.zoomLevel += Math.log2(delta)
|
||||||
|
map.alignCoordinateToPoint(pinch.startCentroid, pinch.centroid.position)
|
||||||
|
map.pinchAdjustingZoom = false
|
||||||
|
}
|
||||||
|
onRotationChanged: (delta) => {
|
||||||
|
pinch.rawBearing -= delta
|
||||||
|
// snap to 0° if we're close enough
|
||||||
|
map.bearing = (Math.abs(pinch.rawBearing) < 5) ? 0 : pinch.rawBearing
|
||||||
|
map.alignCoordinateToPoint(pinch.startCentroid, pinch.centroid.position)
|
||||||
|
}
|
||||||
|
grabPermissions: PointerHandler.TakeOverForbidden
|
||||||
|
}
|
||||||
|
WheelHandler {
|
||||||
|
id: wheel
|
||||||
|
// workaround for QTBUG-87646 / QTBUG-112394 / QTBUG-112432:
|
||||||
|
// Magic Mouse pretends to be a trackpad but doesn't work with PinchHandler
|
||||||
|
// and we don't yet distinguish mice and trackpads on Wayland either
|
||||||
|
acceptedDevices: Qt.platform.pluginName === "cocoa" || Qt.platform.pluginName === "wayland"
|
||||||
|
? PointerDevice.Mouse | PointerDevice.TouchPad
|
||||||
|
: PointerDevice.Mouse
|
||||||
|
onWheel: (event) => {
|
||||||
|
const loc = map.toCoordinate(wheel.point.position)
|
||||||
|
switch (event.modifiers) {
|
||||||
|
case Qt.NoModifier:
|
||||||
|
// jonb - Changed to make more like Qt5
|
||||||
|
//map.zoomLevel += event.angleDelta.y / 120
|
||||||
|
map.zoomLevel += event.angleDelta.y / 1000
|
||||||
|
break
|
||||||
|
case Qt.ShiftModifier:
|
||||||
|
map.bearing += event.angleDelta.y / 15
|
||||||
|
break
|
||||||
|
case Qt.ControlModifier:
|
||||||
|
map.tilt += event.angleDelta.y / 15
|
||||||
|
break
|
||||||
|
}
|
||||||
|
map.alignCoordinateToPoint(loc, wheel.point.position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DragHandler {
|
||||||
|
id: drag
|
||||||
|
signal flickStarted // for autotests only
|
||||||
|
signal flickEnded
|
||||||
|
target: null
|
||||||
|
onTranslationChanged: (delta) => map.pan(-delta.x, -delta.y)
|
||||||
|
onActiveChanged: if (active) {
|
||||||
|
flickAnimation.stop()
|
||||||
|
} else {
|
||||||
|
flickAnimation.restart(centroid.velocity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
property vector3d animDest
|
||||||
|
onAnimDestChanged: if (flickAnimation.running) {
|
||||||
|
const delta = Qt.vector2d(animDest.x - flickAnimation.animDestLast.x, animDest.y - flickAnimation.animDestLast.y)
|
||||||
|
map.pan(-delta.x, -delta.y)
|
||||||
|
flickAnimation.animDestLast = animDest
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3dAnimation on animDest {
|
||||||
|
id: flickAnimation
|
||||||
|
property vector3d animDestLast
|
||||||
|
from: Qt.vector3d(0, 0, 0)
|
||||||
|
duration: 500
|
||||||
|
easing.type: Easing.OutQuad
|
||||||
|
onStarted: drag.flickStarted()
|
||||||
|
onStopped: drag.flickEnded()
|
||||||
|
|
||||||
|
function restart(vel) {
|
||||||
|
stop()
|
||||||
|
map.animDest = Qt.vector3d(0, 0, 0)
|
||||||
|
animDestLast = Qt.vector3d(0, 0, 0)
|
||||||
|
to = Qt.vector3d(vel.x / duration * 100, vel.y / duration * 100, 0)
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DragHandler {
|
||||||
|
id: tiltHandler
|
||||||
|
minimumPointCount: 2
|
||||||
|
maximumPointCount: 2
|
||||||
|
target: null
|
||||||
|
xAxis.enabled: false
|
||||||
|
grabPermissions: PointerHandler.TakeOverForbidden
|
||||||
|
onActiveChanged: if (active) flickAnimation.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Window 2.14
|
||||||
|
import QtLocation 6.5
|
||||||
|
import QtPositioning 6.5
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: qmlMap
|
||||||
|
property int vorZoomLevel: 11
|
||||||
|
property string mapProvider: "osm"
|
||||||
|
property variant mapPtr
|
||||||
|
property string requestedMapType
|
||||||
|
property variant guiPtr
|
||||||
|
|
||||||
|
function createMap(pluginParameters, requestedMap, gui) {
|
||||||
|
requestedMapType = requestedMap
|
||||||
|
guiPtr = gui
|
||||||
|
|
||||||
|
var paramString = ""
|
||||||
|
for (var prop in pluginParameters) {
|
||||||
|
var parameter = 'PluginParameter { name: "' + prop + '"; value: "' + pluginParameters[prop] + '"}'
|
||||||
|
paramString = paramString + parameter
|
||||||
|
}
|
||||||
|
var pluginString = 'import QtLocation 6.5; Plugin{ name:"' + mapProvider + '"; ' + paramString + '}'
|
||||||
|
var plugin = Qt.createQmlObject (pluginString, qmlMap)
|
||||||
|
|
||||||
|
if (mapPtr) {
|
||||||
|
// Objects aren't destroyed immediately, so don't call findChild("map")
|
||||||
|
mapPtr.destroy()
|
||||||
|
mapPtr = null
|
||||||
|
}
|
||||||
|
mapPtr = actualMapComponent.createObject(page)
|
||||||
|
mapPtr.map.plugin = plugin
|
||||||
|
mapPtr.map.forceActiveFocus()
|
||||||
|
return mapPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: page
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: actualMapComponent
|
||||||
|
|
||||||
|
ModifiedMapView {
|
||||||
|
id: mapView
|
||||||
|
objectName: "mapView"
|
||||||
|
anchors.fill: parent
|
||||||
|
map.center: QtPositioning.coordinate(51.5, 0.125) // London
|
||||||
|
map.zoomLevel: 10
|
||||||
|
map.objectName: "map"
|
||||||
|
// not in 6
|
||||||
|
//gesture.enabled: true
|
||||||
|
//gesture.acceptedGestures: MapGestureArea.PinchGesture | MapGestureArea.PanGesture
|
||||||
|
|
||||||
|
MapItemView {
|
||||||
|
model: vorModel
|
||||||
|
delegate: vorRadialComponent
|
||||||
|
parent: mapView.map
|
||||||
|
}
|
||||||
|
|
||||||
|
MapStation {
|
||||||
|
id: station
|
||||||
|
objectName: "station"
|
||||||
|
stationName: "Home"
|
||||||
|
}
|
||||||
|
|
||||||
|
MapItemView {
|
||||||
|
model: vorModel
|
||||||
|
delegate: vorComponent
|
||||||
|
parent: mapView.map
|
||||||
|
}
|
||||||
|
|
||||||
|
map.onZoomLevelChanged: {
|
||||||
|
if (map.zoomLevel > 11) {
|
||||||
|
station.zoomLevel = map.zoomLevel
|
||||||
|
vorZoomLevel = map.zoomLevel
|
||||||
|
} else {
|
||||||
|
station.zoomLevel = 11
|
||||||
|
vorZoomLevel = 11
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
map.onSupportedMapTypesChanged : {
|
||||||
|
for (var i = 0; i < map.supportedMapTypes.length; i++) {
|
||||||
|
if (requestedMapType == map.supportedMapTypes[i].name) {
|
||||||
|
map.activeMapType = map.supportedMapTypes[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: vorRadialComponent
|
||||||
|
MapPolyline {
|
||||||
|
line.width: 2
|
||||||
|
line.color: 'gray'
|
||||||
|
path: vorRadial
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: vorComponent
|
||||||
|
MapQuickItem {
|
||||||
|
id: vor
|
||||||
|
anchorPoint.x: image.width/2
|
||||||
|
anchorPoint.y: bubble.height/2
|
||||||
|
coordinate: position
|
||||||
|
zoomLevel: vorZoomLevel
|
||||||
|
|
||||||
|
sourceItem: Grid {
|
||||||
|
columns: 1
|
||||||
|
Grid {
|
||||||
|
horizontalItemAlignment: Grid.AlignHCenter
|
||||||
|
verticalItemAlignment: Grid.AlignVCenter
|
||||||
|
columnSpacing: 5
|
||||||
|
layer.enabled: true
|
||||||
|
layer.smooth: true
|
||||||
|
Image {
|
||||||
|
id: image
|
||||||
|
source: vorImage
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
onDoubleClicked: (mouse) => {
|
||||||
|
selected = !selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
id: bubble
|
||||||
|
color: bubbleColour
|
||||||
|
border.width: 1
|
||||||
|
width: text.width + 5
|
||||||
|
height: text.height + 5
|
||||||
|
radius: 5
|
||||||
|
Text {
|
||||||
|
id: text
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: vorData
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
onDoubleClicked: (mouse) => {
|
||||||
|
selected = !selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1041,6 +1041,11 @@ void VORLocalizerGUI::applyMapSettings()
|
||||||
m_azEl.setLocation(stationLatitude, stationLongitude, stationAltitude);
|
m_azEl.setLocation(stationLatitude, stationLongitude, stationAltitude);
|
||||||
|
|
||||||
QQuickItem *item = ui->map->rootObject();
|
QQuickItem *item = ui->map->rootObject();
|
||||||
|
if (!item)
|
||||||
|
{
|
||||||
|
qCritical("VORLocalizerGUI::applyMapSettings: Map not found. Are all required Qt plugins installed?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QObject *object = item->findChild<QObject*>("map");
|
QObject *object = item->findChild<QObject*>("map");
|
||||||
QGeoCoordinate coords;
|
QGeoCoordinate coords;
|
||||||
|
@ -1146,7 +1151,11 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe
|
||||||
ui->map->setAttribute(Qt::WA_AcceptTouchEvents, true);
|
ui->map->setAttribute(Qt::WA_AcceptTouchEvents, true);
|
||||||
|
|
||||||
ui->map->rootContext()->setContextProperty("vorModel", &m_vorModel);
|
ui->map->rootContext()->setContextProperty("vorModel", &m_vorModel);
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
ui->map->setSource(QUrl(QStringLiteral("qrc:/demodvor/map/map.qml")));
|
ui->map->setSource(QUrl(QStringLiteral("qrc:/demodvor/map/map.qml")));
|
||||||
|
#else
|
||||||
|
ui->map->setSource(QUrl(QStringLiteral("qrc:/demodvor/map/map_6.qml")));
|
||||||
|
#endif
|
||||||
|
|
||||||
m_muteIcon.addPixmap(QPixmap("://sound_off.png"), QIcon::Normal, QIcon::On);
|
m_muteIcon.addPixmap(QPixmap("://sound_off.png"), QIcon::Normal, QIcon::On);
|
||||||
m_muteIcon.addPixmap(QPixmap("://sound_on.png"), QIcon::Normal, QIcon::Off);
|
m_muteIcon.addPixmap(QPixmap("://sound_on.png"), QIcon::Normal, QIcon::Off);
|
||||||
|
|
Loading…
Reference in New Issue