From b7ef6fe42134adaf39158fa2972ed5dc7a723a9b Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Wed, 23 Jun 2021 15:15:50 +0100 Subject: [PATCH] Add radio time transmitters to map --- doc/img/Map_plugin_radiotime_dialog.png | Bin 0 -> 14841 bytes plugins/feature/map/CMakeLists.txt | 3 + plugins/feature/map/icons.qrc | 1 + plugins/feature/map/icons/clock.png | Bin 0 -> 440 bytes plugins/feature/map/map.qrc | 1 + plugins/feature/map/map/antennatime.png | Bin 0 -> 6103 bytes plugins/feature/map/mapgui.cpp | 42 ++++++- plugins/feature/map/mapgui.h | 14 +++ plugins/feature/map/mapgui.ui | 16 +++ plugins/feature/map/mapradiotimedialog.cpp | 89 +++++++++++++ plugins/feature/map/mapradiotimedialog.h | 52 ++++++++ plugins/feature/map/mapradiotimedialog.ui | 140 +++++++++++++++++++++ plugins/feature/map/mapsettings.h | 3 +- plugins/feature/map/mapsettingsdialog.ui | 8 ++ plugins/feature/map/readme.md | 22 +++- 15 files changed, 384 insertions(+), 7 deletions(-) create mode 100644 doc/img/Map_plugin_radiotime_dialog.png create mode 100644 plugins/feature/map/icons/clock.png create mode 100644 plugins/feature/map/map/antennatime.png create mode 100644 plugins/feature/map/mapradiotimedialog.cpp create mode 100644 plugins/feature/map/mapradiotimedialog.h create mode 100644 plugins/feature/map/mapradiotimedialog.ui diff --git a/doc/img/Map_plugin_radiotime_dialog.png b/doc/img/Map_plugin_radiotime_dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..b2f7a11f395a7cdedec70e2d77e0cbada0dd1177 GIT binary patch literal 14841 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 literal 0 HcmV?d00001 diff --git a/plugins/feature/map/CMakeLists.txt b/plugins/feature/map/CMakeLists.txt index 21528646a..536ba6e22 100644 --- a/plugins/feature/map/CMakeLists.txt +++ b/plugins/feature/map/CMakeLists.txt @@ -33,6 +33,8 @@ if(NOT SERVER_MODE) mapsettingsdialog.ui mapbeacondialog.cpp mapbeacondialog.ui + mapradiotimedialog.cpp + mapradiotimedialog.ui map.qrc icons.qrc ) @@ -43,6 +45,7 @@ if(NOT SERVER_MODE) mapmaidenheaddialog.h mapsettingsdialog.h mapbeacondialog.h + mapradiotimedialog.h ) set(TARGET_NAME map) diff --git a/plugins/feature/map/icons.qrc b/plugins/feature/map/icons.qrc index f462b389c..ba855ff49 100644 --- a/plugins/feature/map/icons.qrc +++ b/plugins/feature/map/icons.qrc @@ -1,5 +1,6 @@ icons/groundtracks.png + icons/clock.png diff --git a/plugins/feature/map/icons/clock.png b/plugins/feature/map/icons/clock.png new file mode 100644 index 0000000000000000000000000000000000000000..a6dbea21049915cf96cd24bfaf717842ecd93cf5 GIT binary patch literal 440 zcmV;p0Z0CcP)T0w0I35&20(B}VgTp>NV&rT zRO!7H14M8y;!c==0gMd4(O=7MQrd_oy+fSm_Z<7z?;JSi*no-90^>;50u8VbCXoy9 zhE>8e2OoANfon(wOo5BUYF9#!LKrXL0k~Nk@d1jJbM8a2cFx&IqiIE>=Tusw#Zx7E zbIz3;jANEEC(NJ50X8x(wlEJYq7bVCp4E%o%EKb+jxPy5-V-Bb7!J!3p8=T7x+IQ)%f4bAP;_Yh zzPW-t0mZHF8-XRWb+4p4)|J=Q0=Z`Z?R7FPy=z i%zwG`HFo=L0lolPDtDess~i0Q0000map/map.qml map/map_5_12.qml map/antenna.png + map/antennatime.png diff --git a/plugins/feature/map/map/antennatime.png b/plugins/feature/map/map/antennatime.png new file mode 100644 index 0000000000000000000000000000000000000000..61b29c8aecf4b45b52269076081d8642542481b0 GIT binary patch literal 6103 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 literal 0 HcmV?d00001 diff --git a/plugins/feature/map/mapgui.cpp b/plugins/feature/map/mapgui.cpp index 5b8866570..c3cce4ed8 100644 --- a/plugins/feature/map/mapgui.cpp +++ b/plugins/feature/map/mapgui.cpp @@ -679,7 +679,8 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur m_doApplySettings(true), m_mapModel(this), m_beacons(nullptr), - m_beaconDialog(this) + m_beaconDialog(this), + m_radioTimeDialog(this) { ui->setupUi(this); @@ -738,6 +739,8 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur QList *beacons = Beacon::readIARUCSV(MapGUI::getBeaconFilename()); if (beacons != nullptr) setBeacons(beacons); + + addRadioTimeTransmitters(); } MapGUI::~MapGUI() @@ -770,6 +773,37 @@ void MapGUI::setBeacons(QList *beacons) } } +const QList MapGUI::m_radioTimeTransmitters = { + {"MSF", 60000, 54.9075f, -3.27333f, 17}, + {"DCF77", 77500, 50.01611111f, 9.00805556f, 50}, + {"TDF", 162000, 47.1694f, 2.2044f, 800}, + {"WWVB", 60000, 40.67805556f, -105.04666667f, 70}, + {"JJY", 60000, 33.465f, 130.175555f, 50} +}; + +void MapGUI::addRadioTimeTransmitters() +{ + for (int i = 0; i < m_radioTimeTransmitters.size(); i++) + { + SWGSDRangel::SWGMapItem timeMapItem; + // Need to suffix frequency, as there are multiple becaons with same callsign at different locations + QString name = QString("%1").arg(m_radioTimeTransmitters[i].m_callsign); + timeMapItem.setName(new QString(name)); + timeMapItem.setLatitude(m_radioTimeTransmitters[i].m_latitude); + timeMapItem.setLongitude(m_radioTimeTransmitters[i].m_longitude); + timeMapItem.setAltitude(0.0); + timeMapItem.setImage(new QString("antennatime.png")); + timeMapItem.setImageRotation(0); + timeMapItem.setImageMinZoom(8); + QString text = QString("Radio Time Transmitter\nCallsign: %1\nFrequency: %2 kHz\nPower: %3 kW") + .arg(m_radioTimeTransmitters[i].m_callsign) + .arg(m_radioTimeTransmitters[i].m_frequency/1000.0) + .arg(m_radioTimeTransmitters[i].m_power); + timeMapItem.setText(new QString(text)); + m_mapModel.update(m_map, &timeMapItem, MapSettings::SOURCE_RADIO_TIME); + } +} + void MapGUI::blockApplySettings(bool block) { m_doApplySettings = !block; @@ -1033,6 +1067,12 @@ void MapGUI::on_beacons_clicked() m_beaconDialog.show(); } +void MapGUI::on_radiotime_clicked() +{ + m_radioTimeDialog.updateTable(); + m_radioTimeDialog.show(); +} + quint32 MapGUI::getSourceMask(const PipeEndPoint *sourcePipe) { for (int i = 0; i < m_availablePipes.size(); i++) diff --git a/plugins/feature/map/mapgui.h b/plugins/feature/map/mapgui.h index 8bc3474e5..8b2c02005 100644 --- a/plugins/feature/map/mapgui.h +++ b/plugins/feature/map/mapgui.h @@ -31,6 +31,7 @@ #include "mapsettings.h" #include "SWGMapItem.h" #include "mapbeacondialog.h" +#include "mapradiotimedialog.h" class PluginAPI; class FeatureUISet; @@ -45,6 +46,14 @@ class MapModel; class QQuickItem; struct Beacon; +struct RadioTimeTransmitter { + QString m_callsign; + int m_frequency; // In Hz + float m_latitude; // In degrees + float m_longitude; // In degrees + int m_power; // In kW +}; + // Information required about each item displayed on the map class MapItem { @@ -471,6 +480,8 @@ public: static QString getBeaconFilename(); QList *getBeacons() { return m_beacons; } void setBeacons(QList *beacons); + QList getRadioTimeTransmitters() { return m_radioTimeTransmitters; } + void addRadioTimeTransmitters(); void find(const QString& target); private: @@ -487,6 +498,7 @@ private: AzEl m_azEl; // Position of station QList *m_beacons; MapBeaconDialog m_beaconDialog; + MapRadioTimeDialog m_radioTimeDialog; explicit MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent = nullptr); virtual ~MapGUI(); @@ -502,6 +514,7 @@ private: void enterEvent(QEvent*); static QString getDataDir(); + static const QList m_radioTimeTransmitters; private slots: void onMenuDialogCalled(const QPoint &p); @@ -516,6 +529,7 @@ private slots: void on_displaySettings_clicked(); void on_mapTypes_currentIndexChanged(int index); void on_beacons_clicked(); + void on_radiotime_clicked(); }; diff --git a/plugins/feature/map/mapgui.ui b/plugins/feature/map/mapgui.ui index 05bc51f4a..8a5a5b39b 100644 --- a/plugins/feature/map/mapgui.ui +++ b/plugins/feature/map/mapgui.ui @@ -140,6 +140,20 @@ + + + + Display radio time transmitters dialog + + + + + + + :/map/icons/clock.png:/map/icons/clock.png + + + @@ -165,6 +179,7 @@ Adobe Devanagari + 9 @@ -190,6 +205,7 @@ Adobe Devanagari + 9 diff --git a/plugins/feature/map/mapradiotimedialog.cpp b/plugins/feature/map/mapradiotimedialog.cpp new file mode 100644 index 000000000..4f2ebf478 --- /dev/null +++ b/plugins/feature/map/mapradiotimedialog.cpp @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "mapradiotimedialog.h" + +#include + +#include "channel/channelwebapiutils.h" +#include "mapgui.h" + +MapRadioTimeDialog::MapRadioTimeDialog(MapGUI *gui, QWidget* parent) : + QDialog(parent), + m_gui(gui), + ui(new Ui::MapRadioTimeDialog) +{ + ui->setupUi(this); + // Don't call updateTable until m_gui->getAzEl() will return valid location +} + +MapRadioTimeDialog::~MapRadioTimeDialog() +{ + delete ui; +} + +void MapRadioTimeDialog::updateTable() +{ + AzEl azEl = *m_gui->getAzEl(); + ui->transmitters->setSortingEnabled(false); + const QList transmitters = m_gui->getRadioTimeTransmitters(); + ui->transmitters->setRowCount(0); + ui->transmitters->setRowCount(transmitters.size()); + QListIterator i(transmitters); + int row = 0; + for (int i = 0; i < transmitters.size(); i++) + { + ui->transmitters->setItem(row, TRANSMITTER_COL_CALLSIGN, new QTableWidgetItem(transmitters[i].m_callsign)); + QTableWidgetItem *freq = new QTableWidgetItem(); + freq->setText(QString("%1").arg(transmitters[i].m_frequency/1000.0)); + freq->setData(Qt::UserRole, transmitters[i].m_frequency); + ui->transmitters->setItem(row, TRANSMITTER_COL_FREQUENCY, freq); + ui->transmitters->setItem(row, TRANSMITTER_COL_LOCATION, new QTableWidgetItem(QString("%1,%2").arg(transmitters[i].m_latitude).arg(transmitters[i].m_longitude))); + ui->transmitters->setItem(row, TRANSMITTER_COL_POWER, new QTableWidgetItem(QString("%1").arg(transmitters[i].m_power))); + azEl.setTarget(transmitters[i].m_latitude, transmitters[i].m_longitude, 1.0); + azEl.calculate(); + ui->transmitters->setItem(row, TRANSMITTER_COL_AZIMUTH, new QTableWidgetItem(QString("%1").arg(round(azEl.getAzimuth())))); + ui->transmitters->setItem(row, TRANSMITTER_COL_ELEVATION, new QTableWidgetItem(QString("%1").arg(round(azEl.getElevation())))); + int km = round(azEl.getDistance()/1000); + QTableWidgetItem *dist = new QTableWidgetItem(); + dist->setData(Qt::DisplayRole, km); + ui->transmitters->setItem(row, TRANSMITTER_COL_DISTANCE, dist); + row++; + } + ui->transmitters->setSortingEnabled(true); + ui->transmitters->resizeColumnsToContents(); +} + +void MapRadioTimeDialog::accept() +{ + QDialog::accept(); +} + +void MapRadioTimeDialog::on_transmitters_cellDoubleClicked(int row, int column) +{ + if ((column == TRANSMITTER_COL_CALLSIGN) || (column ==TRANSMITTER_COL_LOCATION)) + { + // Find transmitter on map + QString location = ui->transmitters->item(row, column)->text(); + m_gui->find(location); + } + else if (column == TRANSMITTER_COL_FREQUENCY) + { + // Tune to transmitter freq + ChannelWebAPIUtils::setCenterFrequency(0, ui->transmitters->item(row, column)->data(Qt::UserRole).toDouble()); + } +} diff --git a/plugins/feature/map/mapradiotimedialog.h b/plugins/feature/map/mapradiotimedialog.h new file mode 100644 index 000000000..b5f812814 --- /dev/null +++ b/plugins/feature/map/mapradiotimedialog.h @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_MAPRADIOTIMEDIALOG_H +#define INCLUDE_FEATURE_MAPRADIOTIMEDIALOG_H + +#include "ui_mapradiotimedialog.h" + +class MapGUI; + +class MapRadioTimeDialog : public QDialog { + Q_OBJECT + +public: + explicit MapRadioTimeDialog(MapGUI *gui, QWidget* parent = 0); + ~MapRadioTimeDialog(); + void updateTable(); + +private slots: + void accept(); + void on_transmitters_cellDoubleClicked(int row, int column); + +private: + MapGUI *m_gui; + Ui::MapRadioTimeDialog* ui; + + enum TransmitterCol { + TRANSMITTER_COL_CALLSIGN, + TRANSMITTER_COL_FREQUENCY, + TRANSMITTER_COL_LOCATION, + TRANSMITTER_COL_POWER, + TRANSMITTER_COL_AZIMUTH, + TRANSMITTER_COL_ELEVATION, + TRANSMITTER_COL_DISTANCE + }; +}; + +#endif // INCLUDE_FEATURE_MAPRADIOTIMEDIALOG_H diff --git a/plugins/feature/map/mapradiotimedialog.ui b/plugins/feature/map/mapradiotimedialog.ui new file mode 100644 index 000000000..f85e52ac3 --- /dev/null +++ b/plugins/feature/map/mapradiotimedialog.ui @@ -0,0 +1,140 @@ + + + MapRadioTimeDialog + + + + 0 + 0 + 773 + 279 + + + + + Liberation Sans + 9 + + + + Radio Time Transmitters + + + + + + + 0 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + Callsign + + + + + Frequency (kHz) + + + + + Location (°) + + + + + Power (kW) + + + + + Azimuth (°) + + + + + Elevation (°) + + + + + Distance (km) + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + + + buttonBox + accepted() + MapRadioTimeDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + MapRadioTimeDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/feature/map/mapsettings.h b/plugins/feature/map/mapsettings.h index fa512e551..04c0265aa 100644 --- a/plugins/feature/map/mapsettings.h +++ b/plugins/feature/map/mapsettings.h @@ -63,7 +63,8 @@ struct MapSettings static const quint32 SOURCE_STAR_TRACKER = 0x8; static const quint32 SOURCE_SATELLITE_TRACKER = 0x10; static const quint32 SOURCE_BEACONS = 0x20; - static const quint32 SOURCE_STATION = 0x40; + static const quint32 SOURCE_RADIO_TIME = 0x40; + static const quint32 SOURCE_STATION = 0x80; }; #endif // INCLUDE_FEATURE_MAPSETTINGS_H_ diff --git a/plugins/feature/map/mapsettingsdialog.ui b/plugins/feature/map/mapsettingsdialog.ui index 6308e36ce..d2de8745f 100644 --- a/plugins/feature/map/mapsettingsdialog.ui +++ b/plugins/feature/map/mapsettingsdialog.ui @@ -89,6 +89,14 @@ Checked + + + Radio Time Transmitters + + + Checked + + diff --git a/plugins/feature/map/readme.md b/plugins/feature/map/readme.md index c000a12aa..f9239f58e 100644 --- a/plugins/feature/map/readme.md +++ b/plugins/feature/map/readme.md @@ -11,6 +11,7 @@ On top of this, it can plot data from other plugins, such as: * Satellites from the Satellite Tracker, * The Sun, Moon and Stars from the Star Tracker, * Beacons based on the IARU Region 1 beacon database. +* Radio time transmitters. It can also create tracks showing the path aircraft, ships and APRS objects have taken, as well as predicted paths for satellites. @@ -48,23 +49,32 @@ The beacons will then be displayed in the table and on the map. ![Beacon dialog](../../../doc/img/Map_plugin_beacon_dialog.png) -

5: Display Names

+

5: Display Radio Time Transmitters dialog

+ +When clicked, opens the Radio Time Transmitters dialog. + +* Double clicking in a cell in the table in the Callsign or Location columns, will centre the map on that transmitter. +* Double clicking on the Frequency column will set the Device center frequency. + +![Radio Time transmitters dialog](../../../doc/img/Map_plugin_radiotime_dialog.png) + +

6: Display Names

When checked, names of objects are displayed in a bubble next to each object. -

6: Display tracks for selected object

+

7: Display tracks for selected object

When checked, displays the track (taken or predicted) for the selected object. -

7: Display tracks for all objects

+

8: Display tracks for all objects

When checked, displays the track (taken or predicted) for the all objects. -

8: Delete

+

9: Delete

When clicked, all items will be deleted from the map. -

9: Display settings

+

10: Display settings

When clicked, opens the Map Display Settings dialog, which allows setting: @@ -93,6 +103,8 @@ IARU Region 1 beacon list used with permission from: https://iaru-r1-c5-beacons. Mapping and geolocation services are by Open Street Map: https://www.openstreetmap.org/ esri: https://www.esri.com/ and Mapbox: https://www.mapbox.com/ +Icons made by Google from Flaticon https://www.flaticon.com +

API

Full details of the API can be found in the Swagger documentation. Here is a quick example of how to centre the map on an object from the command line: