1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-15 12:51:49 -05:00

Support Map plugin for Qt 6.5. Some Qt 6.6 fixes.

This commit is contained in:
Jon Beniston 2023-08-06 09:08:53 +01:00
parent 958078c37b
commit 5567c708e7
15 changed files with 690 additions and 15 deletions

View File

@ -593,7 +593,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Qt requirements # Qt requirements
# See: https://doc-snapshots.qt.io/qt6-dev/cmake-qt5-and-qt6-compatibility.html # See: https://doc-snapshots.qt.io/qt6-dev/cmake-qt5-and-qt6-compatibility.html
if(ENABLE_QT6) if(ENABLE_QT6)
# Qt6 doesn't currently support Location
find_package(Qt6 find_package(Qt6
COMPONENTS COMPONENTS
Core Core
@ -657,7 +656,8 @@ if (BUILD_GUI)
WebEngineQuick WebEngineQuick
WebEngineCore WebEngineCore
WebEngineWidgets WebEngineWidgets
TextToSpeech) TextToSpeech
Location)
else() else()
find_package(Qt5 find_package(Qt5
REQUIRED COMPONENTS REQUIRED COMPONENTS
@ -947,6 +947,7 @@ if (BUILD_GUI)
${OPENGL_LIBRARIES} ${OPENGL_LIBRARIES}
Qt::Widgets Qt::Widgets
Qt::Multimedia Qt::Multimedia
Qt::Quick
sdrbase sdrbase
sdrgui sdrgui
logging logging

View File

@ -29,6 +29,9 @@
#ifdef ANDROID #ifdef ANDROID
#include "util/android.h" #include "util/android.h"
#endif #endif
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
#include <QQuickWindow>
#endif
#include "loggerwithfile.h" #include "loggerwithfile.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -52,6 +55,14 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) && (QT_VERSION <= QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) && (QT_VERSION <= QT_VERSION_CHECK(6, 0, 0))
QApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton); QApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton);
#endif #endif
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
// Only use OpenGL, to easily combine QOpenGLWidget, QQuickWidget and QWebEngine
// in a single window
// See https://www.qt.io/blog/qt-quick-and-widgets-qt-6.4-edition
// This prevents Direct3D/Vulcan being used on Windows/Mac though for QQuickWidget
// and QWebEngine, so possibly should be reviewed in the future
QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
#endif
#ifndef ANDROID #ifndef ANDROID
QApplication::setAttribute(Qt::AA_DontUseNativeDialogs); // Don't use on Android, otherwise we can't access files on internal storage QApplication::setAttribute(Qt::AA_DontUseNativeDialogs); // Don't use on Android, otherwise we can't access files on internal storage
#endif #endif

View File

@ -22,11 +22,13 @@ set(map_HEADERS
webserver.h webserver.h
) )
if(Qt${QT_DEFAULT_MAJOR_VERSION}WebEngine_FOUND) # WebEngine on Qt5, WebEngineCore on Qt6
if(Qt${QT_DEFAULT_MAJOR_VERSION}WebEngine_FOUND OR Qt${QT_DEFAULT_MAJOR_VERSION}WebEngineCore_FOUND)
add_compile_definitions(QT_WEBENGINE_FOUND) add_compile_definitions(QT_WEBENGINE_FOUND)
configure_file(mapguiwebengine.ui mapgui.ui) configure_file(mapguiwebengine.ui mapgui.ui)
else() else()
configure_file(mapguinowebengine.ui mapgui.ui) configure_file(mapguinowebengine.ui mapgui.ui)
message(STATUS "Not building 3D map (Qt${QT_DEFAULT_MAJOR_VERSION}WebEngine_FOUND=${Qt${QT_DEFAULT_MAJOR_VERSION}WebEngine_FOUND} Qt${QT_DEFAULT_MAJOR_VERSION}WebEngineCore_FOUND=${Qt${QT_DEFAULT_MAJOR_VERSION}WebEngineCore_FOUND})")
endif() endif()
set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_CURRENT_BINARY_DIR}) set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_CURRENT_BINARY_DIR})
@ -84,7 +86,9 @@ if(NOT SERVER_MODE)
set(TARGET_LIB_GUI "sdrgui") set(TARGET_LIB_GUI "sdrgui")
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
if(Qt${QT_DEFAULT_MAJOR_VERSION}WebEngine_FOUND) if(Qt${QT_DEFAULT_MAJOR_VERSION}WebEngineCore_FOUND)
set(TARGET_LIB "Qt::Widgets" Qt::Quick Qt::QuickWidgets Qt::Positioning Qt::Location Qt::WebEngineCore Qt::WebEngineWidgets)
elseif(Qt${QT_DEFAULT_MAJOR_VERSION}WebEngine_FOUND)
set(TARGET_LIB "Qt::Widgets" Qt::Quick Qt::QuickWidgets Qt::Positioning Qt::Location Qt::WebEngine Qt::WebEngineCore Qt::WebEngineWidgets) set(TARGET_LIB "Qt::Widgets" Qt::Quick Qt::QuickWidgets Qt::Positioning Qt::Location Qt::WebEngine Qt::WebEngineCore Qt::WebEngineWidgets)
else() else()
set(TARGET_LIB "Qt::Widgets" Qt::Quick Qt::QuickWidgets Qt::Positioning Qt::Location) set(TARGET_LIB "Qt::Widgets" Qt::Quick Qt::QuickWidgets Qt::Positioning Qt::Location)

View File

@ -1,7 +1,8 @@
<RCC> <RCC>
<qresource prefix="/map/"> <qresource prefix="/map/">
<file>map/map.qml</file> <file>map/map.qml</file>
<file>map/map_5_12.qml</file> <file>map/map_6.qml</file>
<file>map/ModifiedMapView.qml</file>
<file>map/antenna.png</file> <file>map/antenna.png</file>
<file>map/antennatime.png</file> <file>map/antennatime.png</file>
<file>map/antennadab.png</file> <file>map/antennadab.png</file>

View 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()
}
}
}

View File

@ -0,0 +1,413 @@
import QtQuick 2.14
import QtQuick.Window 2.14
import QtQuick.Controls 2.14
import QtPositioning 6.5
import QtLocation 6.5
Item {
id: qmlMap
property int mapZoomLevel: 11
property string mapProvider: "osm"
property variant mapPtr
property variant guiPtr
property bool smoothing
function createMap(pluginParameters, gui) {
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
}
function getMapTypes() {
var mapTypes = []
if (mapPtr) {
for (var i = 0; i < mapPtr.map.supportedMapTypes.length; i++) {
mapTypes[i] = mapPtr.map.supportedMapTypes[i].name
}
}
return mapTypes
}
function setMapType(mapTypeIndex) {
if (mapPtr && (mapTypeIndex < mapPtr.map.supportedMapTypes.length)) {
if (mapPtr.map.supportedMapTypes[mapTypeIndex] !== undefined) {
mapPtr.map.activeMapType = mapPtr.map.supportedMapTypes[mapTypeIndex]
}
}
}
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: imageModelFiltered
delegate: imageComponent
parent: mapView.map
}
MapItemView {
model: polygonModelFiltered
delegate: polygonComponent
parent: mapView.map
}
MapItemView {
model: polygonModelFiltered
delegate: polygonNameComponent
parent: mapView.map
}
MapItemView {
model: polylineModelFiltered
delegate: polylineComponent
parent: mapView.map
}
MapItemView {
model: polylineModelFiltered
delegate: polylineNameComponent
parent: mapView.map
}
// Tracks first, so drawn under other items
MapItemView {
model: mapModelFiltered
delegate: groundTrack1Component
parent: mapView.map
}
MapItemView {
model: mapModelFiltered
delegate: groundTrack2Component
parent: mapView.map
}
MapItemView {
model: mapModelFiltered
delegate: predictedGroundTrack1Component
parent: mapView.map
}
MapItemView {
model: mapModelFiltered
delegate: predictedGroundTrack2Component
parent: mapView.map
}
MapItemView {
model: mapModelFiltered
delegate: mapComponent
parent: mapView.map
}
map.onZoomLevelChanged: {
mapZoomLevel = map.zoomLevel
mapModelFiltered.viewChanged(map.visibleRegion.boundingGeoRectangle().topLeft.longitude, map.visibleRegion.boundingGeoRectangle().topLeft.latitude, map.visibleRegion.boundingGeoRectangle().bottomRight.longitude, map.visibleRegion.boundingGeoRectangle().bottomRight.latitude, map.zoomLevel);
imageModelFiltered.viewChanged(map.visibleRegion.boundingGeoRectangle().topLeft.longitude, map.visibleRegion.boundingGeoRectangle().topLeft.latitude, map.visibleRegion.boundingGeoRectangle().bottomRight.longitude, map.visibleRegion.boundingGeoRectangle().bottomRight.latitude, map.zoomLevel);
polygonModelFiltered.viewChanged(map.visibleRegion.boundingGeoRectangle().topLeft.longitude, map.visibleRegion.boundingGeoRectangle().topLeft.latitude, map.visibleRegion.boundingGeoRectangle().bottomRight.longitude, map.visibleRegion.boundingGeoRectangle().bottomRight.latitude, map.zoomLevel);
polylineModelFiltered.viewChanged(map.visibleRegion.boundingGeoRectangle().topLeft.longitude, map.visibleRegion.boundingGeoRectangle().topLeft.latitude, map.visibleRegion.boundingGeoRectangle().bottomRight.longitude, map.visibleRegion.boundingGeoRectangle().bottomRight.latitude, map.zoomLevel);
}
// The map displays MapPolyLines in the wrong place (+360 degrees) if
// they start to the left of the visible region, so we need to
// split them so they don't, each time the visible region is changed. meh.
map.onCenterChanged: {
polylineModelFiltered.viewChanged(map.visibleRegion.boundingGeoRectangle().topLeft.longitude, map.visibleRegion.boundingGeoRectangle().topLeft.latitude, map.visibleRegion.boundingGeoRectangle().bottomRight.longitude, map.visibleRegion.boundingGeoRectangle().bottomRight.latitude, map.zoomLevel);
polygonModelFiltered.viewChanged(map.visibleRegion.boundingGeoRectangle().topLeft.longitude, map.visibleRegion.boundingGeoRectangle().topLeft.latitude, map.visibleRegion.boundingGeoRectangle().bottomRight.longitude, map.visibleRegion.boundingGeoRectangle().bottomRight.latitude, map.zoomLevel);
imageModelFiltered.viewChanged(map.visibleRegion.boundingGeoRectangle().topLeft.longitude, map.visibleRegion.boundingGeoRectangle().topLeft.latitude, map.visibleRegion.boundingGeoRectangle().bottomRight.longitude, map.visibleRegion.boundingGeoRectangle().bottomRight.latitude, map.zoomLevel);
mapModelFiltered.viewChanged(map.visibleRegion.boundingGeoRectangle().topLeft.longitude, map.visibleRegion.boundingGeoRectangle().topLeft.latitude, map.visibleRegion.boundingGeoRectangle().bottomRight.longitude, map.visibleRegion.boundingGeoRectangle().bottomRight.latitude, map.zoomLevel);
mapModel.viewChanged(map.visibleRegion.boundingGeoRectangle().bottomLeft.longitude, map.visibleRegion.boundingGeoRectangle().bottomRight.longitude);
}
map.onSupportedMapTypesChanged : {
guiPtr.supportedMapsChanged()
}
}
}
function mapRect() {
if (mapPtr)
return mapPtr.map.visibleRegion.boundingGeoRectangle();
else
return null;
}
Component {
id: imageComponent
MapQuickItem {
coordinate: position
anchorPoint.x: imageId.width/2
anchorPoint.y: imageId.height/2
zoomLevel: imageZoomLevel
sourceItem: Image {
id: imageId
source: imageData
}
autoFadeIn: false
}
}
Component {
id: polygonComponent
MapPolygon {
border.width: 1
border.color: borderColor
color: fillColor
path: polygon
autoFadeIn: false
}
}
Component {
id: polygonNameComponent
MapQuickItem {
coordinate: position
anchorPoint.x: polygonText.width/2
anchorPoint.y: polygonText.height/2
zoomLevel: mapZoomLevel > 11 ? mapZoomLevel : 11
sourceItem: Grid {
columns: 1
Grid {
layer.enabled: smoothing
layer.smooth: smoothing
horizontalItemAlignment: Grid.AlignHCenter
Text {
id: polygonText
text: label
textFormat: TextEdit.RichText
}
}
}
}
}
Component {
id: polylineComponent
MapPolyline {
line.width: 1
line.color: lineColor
path: coordinates
autoFadeIn: false
}
}
Component {
id: polylineNameComponent
MapQuickItem {
coordinate: position
anchorPoint.x: polylineText.width/2
anchorPoint.y: polylineText.height/2
zoomLevel: mapZoomLevel > 11 ? mapZoomLevel : 11
sourceItem: Grid {
columns: 1
Grid {
layer.enabled: smoothing
layer.smooth: smoothing
horizontalItemAlignment: Grid.AlignHCenter
Text {
id: polylineText
text: label
textFormat: TextEdit.RichText
}
}
}
}
}
Component {
id: mapComponent
MapQuickItem {
id: mapElement
anchorPoint.x: image.width/2
anchorPoint.y: image.height/2
coordinate: position
// when zooming, mapImageMinZoom can be temporarily undefined. Not sure why
zoomLevel: (typeof mapImageMinZoom !== 'undefined') ? (mapZoomLevel > mapImageMinZoom ? mapZoomLevel : mapImageMinZoom) : zoomLevel
autoFadeIn: false // not in 5.12
sourceItem: Grid {
id: gridItem
columns: 1
Grid {
horizontalItemAlignment: Grid.AlignHCenter
columnSpacing: 5
layer.enabled: smoothing
layer.smooth: smoothing
Image {
id: image
rotation: mapImageRotation
source: mapImage
visible: mapImageVisible
MouseArea {
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button === Qt.LeftButton) {
selected = !selected
if (selected) {
mapModel.moveToFront(mapModelFiltered.mapRowToSource(index))
}
} else if (mouse.button === Qt.RightButton) {
if (frequency > 0) {
freqMenuItem.text = "Set frequency to " + frequencyString
freqMenuItem.enabled = true
} else {
freqMenuItem.text = "No frequency available"
freqMenuItem.enabled = false
}
var c = mapPtr.map.toCoordinate(Qt.point(mouse.x, mouse.y))
coordsMenuItem.text = "Coords: " + c.latitude.toFixed(6) + ", " + c.longitude.toFixed(6)
contextMenu.popup()
}
}
}
}
Rectangle {
id: bubble
color: bubbleColour
border.width: 1
width: text.width + 5
height: text.height + 5
radius: 5
visible: mapTextVisible
Text {
id: text
anchors.centerIn: parent
text: mapText
textFormat: TextEdit.RichText
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button === Qt.LeftButton) {
selected = !selected
if (selected) {
mapModel.moveToFront(mapModelFiltered.mapRowToSource(index))
}
} else if (mouse.button === Qt.RightButton) {
if (frequency > 0) {
freqMenuItem.text = "Set frequency to " + frequencyString
freqMenuItem.enabled = true
} else {
freqMenuItem.text = "No frequency available"
freqMenuItem.enabled = false
}
var c = mapPtr.map.toCoordinate(Qt.point(mouse.x, mouse.y))
coordsMenuItem.text = "Coords: " + c.latitude.toFixed(6) + ", " + c.longitude.toFixed(6)
contextMenu.popup()
}
}
Menu {
id: contextMenu
MenuItem {
text: "Set as target"
onTriggered: target = true
}
MenuItem {
id: freqMenuItem
text: "Not set"
onTriggered: mapModel.setFrequency(frequency)
}
MenuItem {
text: "Move to front"
onTriggered: mapModel.moveToFront(mapModelFiltered.mapRowToSource(index))
}
MenuItem {
text: "Move to back"
onTriggered: mapModel.moveToBack(mapModelFiltered.mapRowToSource(index))
}
MenuItem {
text: "Track on 3D map"
onTriggered: mapModel.track3D(mapModelFiltered.mapRowToSource(index))
}
MenuItem {
id: coordsMenuItem
text: ""
}
}
}
}
}
}
}
}
Component {
id: predictedGroundTrack1Component
MapPolyline {
line.width: 2
line.color: predictedGroundTrackColor
path: predictedGroundTrack1
autoFadeIn: false
}
}
// Part of the line that crosses edge of map
Component {
id: predictedGroundTrack2Component
MapPolyline {
line.width: 2
line.color: predictedGroundTrackColor
path: predictedGroundTrack2
autoFadeIn: false
}
}
Component {
id: groundTrack1Component
MapPolyline {
line.width: 2
line.color: groundTrackColor
path: groundTrack1
autoFadeIn: false
}
}
// Part of the line that crosses edge of map
Component {
id: groundTrack2Component
MapPolyline {
line.width: 2
line.color: groundTrackColor
path: groundTrack2
autoFadeIn: false
}
}
}

View File

@ -27,8 +27,8 @@
#ifdef QT_WEBENGINE_FOUND #ifdef QT_WEBENGINE_FOUND
#include <QtWebEngineWidgets/QWebEngineView> #include <QtWebEngineWidgets/QWebEngineView>
#include <QtWebEngineWidgets/QWebEngineSettings> #include <QWebEngineSettings>
#include <QtWebEngineWidgets/QWebEngineProfile> #include <QWebEngineProfile>
#endif #endif
#include "feature/featureuiset.h" #include "feature/featureuiset.h"
@ -235,7 +235,12 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur
ui->map->rootContext()->setContextProperty("imageModelFiltered", &m_imageMapFilter); ui->map->rootContext()->setContextProperty("imageModelFiltered", &m_imageMapFilter);
ui->map->rootContext()->setContextProperty("polygonModelFiltered", &m_polygonMapFilter); ui->map->rootContext()->setContextProperty("polygonModelFiltered", &m_polygonMapFilter);
ui->map->rootContext()->setContextProperty("polylineModelFiltered", &m_polylineMapFilter); ui->map->rootContext()->setContextProperty("polylineModelFiltered", &m_polylineMapFilter);
connect(ui->map, &QQuickWidget::statusChanged, this, &MapGUI::statusChanged);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
ui->map->setSource(QUrl(QStringLiteral("qrc:/map/map/map.qml"))); ui->map->setSource(QUrl(QStringLiteral("qrc:/map/map/map.qml")));
#else
ui->map->setSource(QUrl(QStringLiteral("qrc:/map/map/map_6.qml")));
#endif
m_settings.m_modelURL = QString("http://127.0.0.1:%1/3d/").arg(m_webPort); m_settings.m_modelURL = QString("http://127.0.0.1:%1/3d/").arg(m_webPort);
m_webServer->addPathSubstitution("3d", m_settings.m_modelDir); m_webServer->addPathSubstitution("3d", m_settings.m_modelDir);
@ -252,6 +257,10 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur
QWebEngineSettings *settings = ui->web->settings(); QWebEngineSettings *settings = ui->web->settings();
settings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); settings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
connect(ui->web->page(), &QWebEnginePage::fullScreenRequested, this, &MapGUI::fullScreenRequested); connect(ui->web->page(), &QWebEnginePage::fullScreenRequested, this, &MapGUI::fullScreenRequested);
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
connect(ui->web->page(), &QWebEnginePage::loadingChanged, this, &MapGUI::loadingChanged);
connect(ui->web, &QWebEngineView::renderProcessTerminated, this, &MapGUI::renderProcessTerminated);
#endif
#endif #endif
// Get station position // Get station position
@ -1103,7 +1112,7 @@ void MapGUI::clearOSMCache()
{ {
QFile file(dir.filePath(filename)); QFile file(dir.filePath(filename));
if (!file.remove()) { if (!file.remove()) {
qDebug() << "MapGUI::clearOSMCache: Failed to remove " << file; qDebug() << "MapGUI::clearOSMCache: Failed to remove " << file.fileName();
} }
} }
} }
@ -1126,7 +1135,7 @@ void MapGUI::clearWikiMediaOSMCache()
{ {
QFile file(dir.filePath(filename)); QFile file(dir.filePath(filename));
if (!file.remove()) { if (!file.remove()) {
qDebug() << "MapGUI::clearWikiMediaOSMCache: Failed to remove " << file; qDebug() << "MapGUI::clearWikiMediaOSMCache: Failed to remove " << file.fileName();
} }
} }
} }
@ -1213,7 +1222,6 @@ void MapGUI::applyMap2DSettings(bool reloadMap)
qCritical() << "MapGUI::applyMap2DSettings - Failed to invoke createMap"; qCritical() << "MapGUI::applyMap2DSettings - Failed to invoke createMap";
} }
QObject *newMap = retVal.value<QObject *>(); QObject *newMap = retVal.value<QObject *>();
// Restore position of map // Restore position of map
if (newMap != nullptr) if (newMap != nullptr)
{ {
@ -1399,6 +1407,39 @@ void MapGUI::applyMap3DSettings(bool reloadMap)
#endif #endif
} }
void MapGUI::statusChanged(QQuickWidget::Status status)
{
// In Qt6, it seems a page can be loaded multiple times, and this slot is too
// This causes a problem in that the map created by the call to createMap can
// be lost, so we recreate it here each time
if (status == QQuickWidget::Ready) {
applyMap2DSettings(true);
}
}
#ifdef QT_WEBENGINE_FOUND
void MapGUI::renderProcessTerminated(QWebEnginePage::RenderProcessTerminationStatus terminationStatus, int exitCode)
{
qDebug() << "MapGUI::renderProcessTerminated: " << terminationStatus << "exitCode" << exitCode;
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
void MapGUI::loadingChanged(const QWebEngineLoadingInfo &loadingInfo)
{
if (loadingInfo.status() == QWebEngineLoadingInfo::LoadFailedStatus)
{
qDebug() << "MapGUI::loadingChanged: Failed to load " << loadingInfo.url().toString()
<< "errorString: " << loadingInfo.errorString() << " "
<< "errorDomain:" << loadingInfo.errorDomain()
<< "errorCode:" << loadingInfo.errorCode()
;
}
}
#endif
#endif
void MapGUI::init3DMap() void MapGUI::init3DMap()
{ {
#ifdef QT_WEBENGINE_FOUND #ifdef QT_WEBENGINE_FOUND

View File

@ -21,9 +21,14 @@
#include <QTimer> #include <QTimer>
#include <QQuickItem> #include <QQuickItem>
#include <QQuickWidget>
#include <QJsonObject> #include <QJsonObject>
#ifdef QT_WEBENGINE_FOUND #ifdef QT_WEBENGINE_FOUND
#include <QWebEngineFullScreenRequest> #include <QWebEngineFullScreenRequest>
#include <QWebEnginePage>
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
#include <QWebEngineLoadingInfo>
#endif
#endif #endif
#include <math.h> #include <math.h>
@ -255,7 +260,12 @@ private slots:
virtual bool eventFilter(QObject *obj, QEvent *event) override; virtual bool eventFilter(QObject *obj, QEvent *event) override;
#ifdef QT_WEBENGINE_FOUND #ifdef QT_WEBENGINE_FOUND
void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest); void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest);
void renderProcessTerminated(QWebEnginePage::RenderProcessTerminationStatus terminationStatus, int exitCode);
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
void loadingChanged(const QWebEngineLoadingInfo &loadingInfo);
#endif #endif
#endif
void statusChanged(QQuickWidget::Status status);
void preferenceChanged(int elementType); void preferenceChanged(int elementType);
void giroDataUpdated(const GIRO::GIROStationData& data); void giroDataUpdated(const GIRO::GIROStationData& data);
void mufUpdated(const QJsonDocument& document); void mufUpdated(const QJsonDocument& document);

View File

@ -15,6 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // // along with this program. If not, see <http://www.gnu.org/licenses/>. //
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#include <QRegExp>
#include "mapitem.h" #include "mapitem.h"
MapItem::MapItem(const QObject *sourcePipe, const QString &group, MapSettings::MapItemSettings *itemSettings, SWGSDRangel::SWGMapItem *mapItem) : MapItem::MapItem(const QObject *sourcePipe, const QString &group, MapSettings::MapItemSettings *itemSettings, SWGSDRangel::SWGMapItem *mapItem) :

View File

@ -30,7 +30,7 @@
const PluginDescriptor MapPlugin::m_pluginDescriptor = { const PluginDescriptor MapPlugin::m_pluginDescriptor = {
Map::m_featureId, Map::m_featureId,
QStringLiteral("Map"), QStringLiteral("Map"),
QStringLiteral("7.12.0"), QStringLiteral("7.15.3"),
QStringLiteral("(c) Jon Beniston, M7RCE"), QStringLiteral("(c) Jon Beniston, M7RCE"),
QStringLiteral("https://github.com/f4exb/sdrangel"), QStringLiteral("https://github.com/f4exb/sdrangel"),
true, true,

View File

@ -152,7 +152,7 @@ MapSettings::~MapSettings()
void MapSettings::resetToDefaults() void MapSettings::resetToDefaults()
{ {
m_displayNames = true; m_displayNames = true;
#ifdef LINUX #if defined(LINUX) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
m_mapProvider = "mapboxgl"; // osm maps do not work in some versions of Linux https://github.com/f4exb/sdrangel/issues/1169 & 1369 m_mapProvider = "mapboxgl"; // osm maps do not work in some versions of Linux https://github.com/f4exb/sdrangel/issues/1169 & 1369
#else #else
m_mapProvider = "osm"; m_mapProvider = "osm";
@ -252,7 +252,7 @@ bool MapSettings::deserialize(const QByteArray& data)
d.readBool(1, &m_displayNames, true); d.readBool(1, &m_displayNames, true);
d.readString(2, &m_mapProvider, "osm"); d.readString(2, &m_mapProvider, "osm");
#ifdef LINUX #if defined(LINUX) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
if (m_mapProvider == "osm") { if (m_mapProvider == "osm") {
m_mapProvider = "mapboxgl"; m_mapProvider = "mapboxgl";
} }

View File

@ -21,7 +21,11 @@
#include <QToolButton> #include <QToolButton>
#include <QFileDialog> #include <QFileDialog>
#if (QT_VERSION < QT_VERSION_CHECK(6, 6, 0))
#include <QtGui/private/qzipreader_p.h> #include <QtGui/private/qzipreader_p.h>
#else
#include <QtCore/private/qzipreader_p.h>
#endif
#include "util/units.h" #include "util/units.h"
@ -113,6 +117,10 @@ MapSettingsDialog::MapSettingsDialog(MapSettings *settings, QWidget* parent) :
ui(new Ui::MapSettingsDialog) ui(new Ui::MapSettingsDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
ui->mapProvider->clear();
ui->mapProvider->addItem("OpenStreetMap");
#endif
ui->mapProvider->setCurrentIndex(MapSettings::m_mapProviders.indexOf(settings->m_mapProvider)); ui->mapProvider->setCurrentIndex(MapSettings::m_mapProviders.indexOf(settings->m_mapProvider));
ui->thunderforestAPIKey->setText(settings->m_thunderforestAPIKey); ui->thunderforestAPIKey->setText(settings->m_thunderforestAPIKey);
ui->maptilerAPIKey->setText(settings->m_maptilerAPIKey); ui->maptilerAPIKey->setText(settings->m_maptilerAPIKey);

View File

@ -20,6 +20,7 @@
#include <QTcpServer> #include <QTcpServer>
#include <QTcpSocket> #include <QTcpSocket>
#include <QRegularExpression>
#include <QDebug> #include <QDebug>
class OSMTemplateServer : public QTcpServer class OSMTemplateServer : public QTcpServer
@ -61,7 +62,7 @@ private slots:
{ {
QString line = socket->readLine(); QString line = socket->readLine();
qDebug() << "HTTP Request: " << line; qDebug() << "HTTP Request: " << line;
QStringList tokens = QString(line).split(QRegExp("[ \r\n][ \r\n]*")); QStringList tokens = QString(line).split(QRegularExpression("[ \r\n][ \r\n]*"));
if (tokens[0] == "GET") if (tokens[0] == "GET")
{ {
bool hires = tokens[1].contains("hires"); bool hires = tokens[1].contains("hires");

View File

@ -17,6 +17,7 @@
#include <QResource> #include <QResource>
#include <QFile> #include <QFile>
#include <QRegularExpression>
#include <QDebug> #include <QDebug>
#include "webserver.h" #include "webserver.h"
@ -126,7 +127,7 @@ void WebServer::readClient()
QString line = socket->readLine(); QString line = socket->readLine();
//qDebug() << "WebServer HTTP Request: " << line; //qDebug() << "WebServer HTTP Request: " << line;
QStringList tokens = QString(line).split(QRegExp("[ \r\n][ \r\n]*")); QStringList tokens = QString(line).split(QRegularExpression("[ \r\n][ \r\n]*"));
if (tokens[0] == "GET") if (tokens[0] == "GET")
{ {
// Get file type from extension // Get file type from extension

View File

@ -18,7 +18,11 @@
#include <QFileInfo> #include <QFileInfo>
#include <QResource> #include <QResource>
#if (QT_VERSION < QT_VERSION_CHECK(6, 6, 0))
#include <QtGui/private/qzipreader_p.h> #include <QtGui/private/qzipreader_p.h>
#else
#include <QtCore/private/qzipreader_p.h>
#endif
#include "util/osndb.h" #include "util/osndb.h"