From 070f8077b2871a262a1112b5128d18f7a065354d Mon Sep 17 00:00:00 2001 From: srcejon Date: Tue, 5 Dec 2023 12:30:25 +0000 Subject: [PATCH] Map updates: Allow selection of which device to tune to frequency. Support tuning of multiple frequencies per map item. Update maplibre to maplibregl. --- plugins/feature/map/map/map.qml | 91 +++++++++++++++++++----- plugins/feature/map/map/map_6.qml | 91 +++++++++++++++++++----- plugins/feature/map/mapgui.cpp | 7 +- plugins/feature/map/mapitem.cpp | 40 ++++++----- plugins/feature/map/mapitem.h | 6 +- plugins/feature/map/mapmodel.cpp | 34 +++++---- plugins/feature/map/mapmodel.h | 8 ++- plugins/feature/map/mapsettings.cpp | 2 +- plugins/feature/map/mapsettingsdialog.ui | 2 +- 9 files changed, 206 insertions(+), 75 deletions(-) diff --git a/plugins/feature/map/map/map.qml b/plugins/feature/map/map/map.qml index 5d807c985..2501a74e3 100644 --- a/plugins/feature/map/map/map.qml +++ b/plugins/feature/map/map/map.qml @@ -269,12 +269,24 @@ Item { 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 + menuItems.clear() + menus.clear() + if (frequencies.length > 0) { + var deviceSets = mapModel.getDeviceSets() + for (var i = 0; i < deviceSets.length; i++) { + menus.append({ + title: "Set " + deviceSets[i] + " to...", + deviceSet: i + }) + for (var j = 0; j < frequencies.length; j++) { + menuItems.append({ + text: frequencyStrings[j], + frequency: frequencies[j], + deviceSet: deviceSets[i], + menuIndex: i + }) + } + } } var c = mapPtr.toCoordinate(Qt.point(mouse.x, mouse.y)) coordsMenuItem.text = "Coords: " + c.latitude.toFixed(6) + ", " + c.longitude.toFixed(6) @@ -308,29 +320,42 @@ Item { 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 + menuItems.clear() + menus.clear() + if (frequencies.length > 0) { + var deviceSets = mapModel.getDeviceSets() + for (var i = 0; i < deviceSets.length; i++) { + menus.append({ + title: "Set " + deviceSets[i] + " to...", + deviceSet: i + }) + for (var j = 0; j < frequencies.length; j++) { + menuItems.append({ + text: frequencyStrings[j], + frequency: frequencies[j], + deviceSet: deviceSets[i], + menuIndex: i + }) + } + } } var c = mapPtr.toCoordinate(Qt.point(mouse.x, mouse.y)) coordsMenuItem.text = "Coords: " + c.latitude.toFixed(6) + ", " + c.longitude.toFixed(6) contextMenu.popup() } } + ListModel { + id: menus + } + ListModel { + id: menuItems + } 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)) @@ -347,6 +372,38 @@ Item { id: coordsMenuItem text: "" } + Instantiator { + model: menus + delegate: Menu { + //cascade: true + id: contextSubMenu + title: model.title + } + onObjectAdded: function(index, object) { + contextMenu.insertMenu(index, object) + } + onObjectRemoved: function(index, object) { + contextMenu.removeMenu(object) + } + } + Instantiator { + model: menuItems + delegate: MenuItem { + text: model.text + onTriggered: mapModel.setFrequency(model.frequency, model.deviceSet) + } + onObjectAdded: function(index, object) { + // index is index in to menuItems model + // object is the MenuItem + var menuItem = menuItems.get(index) + var menu = menus.get(menuItem.menuIndex) + contextMenu.menuAt(menuItem.menuIndex).insertItem(index, object) + } + onObjectRemoved: function(index, object) { + // Can't use menuItems.get(index) here, as already removed from model + object.menu.removeItem(object) + } + } } } } diff --git a/plugins/feature/map/map/map_6.qml b/plugins/feature/map/map/map_6.qml index 897b93657..a774e695c 100644 --- a/plugins/feature/map/map/map_6.qml +++ b/plugins/feature/map/map/map_6.qml @@ -282,12 +282,24 @@ Item { 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 + menuItems.clear() + menus.clear() + if (frequencies.length > 0) { + var deviceSets = mapModel.getDeviceSets() + for (var i = 0; i < deviceSets.length; i++) { + menus.append({ + title: "Set " + deviceSets[i] + " to...", + deviceSet: i + }) + for (var j = 0; j < frequencies.length; j++) { + menuItems.append({ + text: frequencyStrings[j], + frequency: frequencies[j], + deviceSet: deviceSets[i], + menuIndex: i + }) + } + } } var c = mapPtr.map.toCoordinate(Qt.point(mouse.x, mouse.y)) coordsMenuItem.text = "Coords: " + c.latitude.toFixed(6) + ", " + c.longitude.toFixed(6) @@ -321,29 +333,42 @@ Item { 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 + menuItems.clear() + menus.clear() + if (frequencies.length > 0) { + var deviceSets = mapModel.getDeviceSets() + for (var i = 0; i < deviceSets.length; i++) { + menus.append({ + title: "Set " + deviceSets[i] + " to...", + deviceSet: i + }) + for (var j = 0; j < frequencies.length; j++) { + menuItems.append({ + text: frequencyStrings[j], + frequency: frequencies[j], + deviceSet: deviceSets[i], + menuIndex: i + }) + } + } } var c = mapPtr.map.toCoordinate(Qt.point(mouse.x, mouse.y)) coordsMenuItem.text = "Coords: " + c.latitude.toFixed(6) + ", " + c.longitude.toFixed(6) contextMenu.popup() } } + ListModel { + id: menus + } + ListModel { + id: menuItems + } 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)) @@ -360,6 +385,38 @@ Item { id: coordsMenuItem text: "" } + Instantiator { + model: menus + delegate: Menu { + //cascade: true + id: contextSubMenu + title: model.title + } + onObjectAdded: function(index, object) { + contextMenu.insertMenu(index, object) + } + onObjectRemoved: function(index, object) { + contextMenu.removeMenu(object) + } + } + Instantiator { + model: menuItems + delegate: MenuItem { + text: model.text + onTriggered: mapModel.setFrequency(model.frequency, model.deviceSet) + } + onObjectAdded: function(index, object) { + // index is index in to menuItems model + // object is the MenuItem + var menuItem = menuItems.get(index) + var menu = menus.get(menuItem.menuIndex) + contextMenu.menuAt(menuItem.menuIndex).insertItem(index, object) + } + onObjectRemoved: function(index, object) { + // Can't use menuItems.get(index) here, as already removed from model + object.menu.removeItem(object) + } + } } } } diff --git a/plugins/feature/map/mapgui.cpp b/plugins/feature/map/mapgui.cpp index b0c3ac652..f1c9df910 100644 --- a/plugins/feature/map/mapgui.cpp +++ b/plugins/feature/map/mapgui.cpp @@ -1189,11 +1189,12 @@ void MapGUI::applyMap2DSettings(bool reloadMap) if (!m_settings.m_mapBoxStyles.isEmpty()) parameters["mapboxgl.mapping.additional_style_urls"] = m_settings.m_mapBoxStyles; } - if (m_settings.m_mapProvider == "maplibre") + if (m_settings.m_mapProvider == "maplibregl") { - parameters["maplibre.access_token"] = m_settings.m_mapBoxAPIKey; + parameters["maplibregl.settings_template"] = "maptiler"; // Or "mapbox" + parameters["maplibregl.access_token"] = m_settings.m_maptilerAPIKey; if (!m_settings.m_mapBoxStyles.isEmpty()) - parameters["maplibre.mapping.additional_style_urls"] = m_settings.m_mapBoxStyles; + parameters["maplibregl.mapping.additional_style_urls"] = m_settings.m_mapBoxStyles; } if (m_settings.m_mapProvider == "osm") { diff --git a/plugins/feature/map/mapitem.cpp b/plugins/feature/map/mapitem.cpp index 9caa819e3..bfe9b1728 100644 --- a/plugins/feature/map/mapitem.cpp +++ b/plugins/feature/map/mapitem.cpp @@ -90,7 +90,7 @@ void ObjectMapItem::update(SWGSDRangel::SWGMapItem *mapItem) m_animations.append(new CesiumInterface::Animation(animation)); } } - findFrequency(); + findFrequencies(); if (!m_fixedPosition) { updateTrack(mapItem->getTrack()); @@ -192,29 +192,33 @@ void PolylineMapItem::update(SWGSDRangel::SWGMapItem *mapItem) m_bounds = QGeoRectangle(QGeoCoordinate(latMax, lonMin), QGeoCoordinate(latMin, lonMax)); } -void ObjectMapItem::findFrequency() +// Look for a frequency in the text for this object +void ObjectMapItem::findFrequencies() { - // Look for a frequency in the text for this object - QRegExp re("(([0-9]+(\\.[0-9]+)?) *([kMG])?Hz)"); - if (re.indexIn(m_text) != -1) + m_frequencies.clear(); + m_frequencyStrings.clear(); + + const QRegularExpression re("(([0-9]+(\\.[0-9]+)?) *([kMG])?Hz)"); + QRegularExpressionMatchIterator itr = re.globalMatch(m_text); + while (itr.hasNext()) { - QStringList capture = re.capturedTexts(); - m_frequency = capture[2].toDouble(); + QRegularExpressionMatch match = itr.next(); + QStringList capture = match.capturedTexts(); + double frequency = capture[2].toDouble(); + if (capture.length() == 5) { QChar unit = capture[4][0]; - if (unit == 'k') - m_frequency *= 1000.0; - else if (unit == 'M') - m_frequency *= 1000000.0; - else if (unit == 'G') - m_frequency *= 1000000000.0; + if (unit == 'k') { + frequency *= 1000; + } else if (unit == 'M') { + frequency *= 1000000; + } else if (unit == 'G') { + frequency *= 1000000000; + } } - m_frequencyString = capture[0]; - } - else - { - m_frequency = 0.0; + m_frequencies.append((qint64)frequency); + m_frequencyStrings.append(capture[0]); } } diff --git a/plugins/feature/map/mapitem.h b/plugins/feature/map/mapitem.h index b10d22295..f49b9e1c3 100644 --- a/plugins/feature/map/mapitem.h +++ b/plugins/feature/map/mapitem.h @@ -77,7 +77,7 @@ public: void update(SWGSDRangel::SWGMapItem *mapItem) override; protected: - void findFrequency(); + void findFrequencies(); void updateTrack(QList *track); void updatePredictedTrack(QList *track); @@ -92,8 +92,8 @@ protected: QString m_image; int m_imageRotation; QString m_text; - double m_frequency; // Frequency to set - QString m_frequencyString; + QList m_frequencies; // Frequencies that can be tuned (currently only extracted from text) + QStringList m_frequencyStrings; bool m_fixedPosition; // Don't record/display track QList m_predictedTrackCoords; QList m_predictedTrackDateTimes; diff --git a/plugins/feature/map/mapmodel.cpp b/plugins/feature/map/mapmodel.cpp index 3db790af0..58f107546 100644 --- a/plugins/feature/map/mapmodel.cpp +++ b/plugins/feature/map/mapmodel.cpp @@ -516,8 +516,8 @@ QHash ObjectMapModel::roleNames() const roles[bubbleColourRole] = "bubbleColour"; roles[selectedRole] = "selected"; roles[targetRole] = "target"; - roles[frequencyRole] = "frequency"; - roles[frequencyStringRole] = "frequencyString"; + roles[frequenciesRole] = "frequencies"; + roles[frequencyStringsRole] = "frequencyStrings"; roles[predictedGroundTrack1Role] = "predictedGroundTrack1"; roles[predictedGroundTrack2Role] = "predictedGroundTrack2"; roles[groundTrack1Role] = "groundTrack1"; @@ -675,10 +675,10 @@ QVariant ObjectMapModel::data(const QModelIndex &index, int role) const return QVariant::fromValue(m_selected[row]); case targetRole: return QVariant::fromValue(m_target == row); - case frequencyRole: - return QVariant::fromValue(mapItem->m_frequency); - case frequencyStringRole: - return QVariant::fromValue(mapItem->m_frequencyString); + case frequenciesRole: + return QVariant::fromValue(mapItem->m_frequencies); + case frequencyStringsRole: + return QVariant::fromValue(mapItem->m_frequencyStrings); case predictedGroundTrack1Role: { if ( (m_displayAllGroundTracks || (m_displaySelectedGroundTracks && m_selected[row])) @@ -780,12 +780,6 @@ void ObjectMapModel::setDisplayAllGroundTracks(bool displayGroundTracks) allUpdated(); } -void ObjectMapModel::setFrequency(double frequency) -{ - // Set as centre frequency - ChannelWebAPIUtils::setCenterFrequency(0, frequency); -} - void ObjectMapModel::track3D(int index) { if (index < m_items.count()) @@ -795,6 +789,22 @@ void ObjectMapModel::track3D(int index) } } +QStringList ObjectMapModel::getDeviceSets() const +{ + return MainCore::instance()->getDeviceSetIds(true, true, false); // FIXME: MIMO currently disabled, as we can't get channel stream indexes +} + +void ObjectMapModel::setFrequency(qint64 frequency, const QString& deviceSetId) +{ + unsigned int deviceSetIndex; + + if (MainCore::getDeviceSetIndexFromId(deviceSetId, deviceSetIndex)) + { + // Set as centre frequency + ChannelWebAPIUtils::setCenterFrequency(deviceSetIndex, frequency); + } +} + void ObjectMapModel::splitTracks(ObjectMapItem *item) { if (item->m_takenTrackCoords.size() > 1) diff --git a/plugins/feature/map/mapmodel.h b/plugins/feature/map/mapmodel.h index 4d57570de..2a038f39c 100644 --- a/plugins/feature/map/mapmodel.h +++ b/plugins/feature/map/mapmodel.h @@ -211,8 +211,8 @@ public: bubbleColourRole = MapModel::lastRole + 4, selectedRole = MapModel::lastRole + 5, targetRole = MapModel::lastRole + 6, - frequencyRole = MapModel::lastRole + 7, - frequencyStringRole = MapModel::lastRole + 8, + frequenciesRole = MapModel::lastRole + 7, + frequencyStringsRole = MapModel::lastRole + 8, predictedGroundTrack1Role = MapModel::lastRole + 9, predictedGroundTrack2Role = MapModel::lastRole + 10, groundTrack1Role = MapModel::lastRole + 11, @@ -244,8 +244,10 @@ public: void setDisplayNames(bool displayNames); void setDisplaySelectedGroundTracks(bool displayGroundTracks); void setDisplayAllGroundTracks(bool displayGroundTracks); - Q_INVOKABLE void setFrequency(double frequency); Q_INVOKABLE void track3D(int index); + Q_INVOKABLE QStringList getDeviceSets() const; + Q_INVOKABLE void setFrequency(qint64 frequency, const QString& deviceSet); + Q_INVOKABLE void viewChanged(double bottomLeftLongitude, double bottomRightLongitude); diff --git a/plugins/feature/map/mapsettings.cpp b/plugins/feature/map/mapsettings.cpp index 0ac4a7938..c280d95c7 100644 --- a/plugins/feature/map/mapsettings.cpp +++ b/plugins/feature/map/mapsettings.cpp @@ -66,7 +66,7 @@ const QStringList MapSettings::m_mapProviders = { QStringLiteral("esri"), QStringLiteral("mapbox"), QStringLiteral("mapboxgl"), - QStringLiteral("maplibre") + QStringLiteral("maplibregl") }; MapSettings::MapSettings() : diff --git a/plugins/feature/map/mapsettingsdialog.ui b/plugins/feature/map/mapsettingsdialog.ui index 6728e47c5..53f2c962c 100644 --- a/plugins/feature/map/mapsettingsdialog.ui +++ b/plugins/feature/map/mapsettingsdialog.ui @@ -95,7 +95,7 @@ - MapLibre + MapLibreGL