| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2021 Jon Beniston, M7RCE                                        //
 | 
					
						
							|  |  |  | // Copyright (C) 2020 Edouard Griffiths, F4EXB                                   //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // 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 <http://www.gnu.org/licenses/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <cmath>
 | 
					
						
							|  |  |  | #include <algorithm>
 | 
					
						
							|  |  |  | #include <limits>
 | 
					
						
							|  |  |  | #include <QMessageBox>
 | 
					
						
							|  |  |  | #include <QLineEdit>
 | 
					
						
							|  |  |  | #include <QPixmap>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QtCharts/QChartView>
 | 
					
						
							|  |  |  | #include <QtCharts/QLineSeries>
 | 
					
						
							|  |  |  | #include <QtCharts/QDateTimeAxis>
 | 
					
						
							|  |  |  | #include <QtCharts/QValueAxis>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "SWGMapItem.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "feature/featureuiset.h"
 | 
					
						
							|  |  |  | #include "feature/featurewebapiutils.h"
 | 
					
						
							|  |  |  | #include "gui/basicfeaturesettingsdialog.h"
 | 
					
						
							|  |  |  | #include "mainwindow.h"
 | 
					
						
							|  |  |  | #include "maincore.h"
 | 
					
						
							|  |  |  | #include "device/deviceuiset.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "ui_aprsgui.h"
 | 
					
						
							|  |  |  | #include "aprs.h"
 | 
					
						
							|  |  |  | #include "aprsgui.h"
 | 
					
						
							|  |  |  | #include "aprssettingsdialog.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define PACKETS_COL_DATE                0
 | 
					
						
							|  |  |  | #define PACKETS_COL_TIME                1
 | 
					
						
							|  |  |  | #define PACKETS_COL_FROM                2
 | 
					
						
							|  |  |  | #define PACKETS_COL_TO                  3
 | 
					
						
							|  |  |  | #define PACKETS_COL_VIA                 4
 | 
					
						
							|  |  |  | #define PACKETS_COL_DATA                5
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define WEATHER_COL_DATE                0
 | 
					
						
							|  |  |  | #define WEATHER_COL_TIME                1
 | 
					
						
							|  |  |  | #define WEATHER_COL_WIND_DIRECTION      2
 | 
					
						
							|  |  |  | #define WEATHER_COL_WIND_SPEED          3
 | 
					
						
							|  |  |  | #define WEATHER_COL_GUSTS               4
 | 
					
						
							|  |  |  | #define WEATHER_COL_TEMPERATURE         5
 | 
					
						
							|  |  |  | #define WEATHER_COL_HUMIDITY            6
 | 
					
						
							|  |  |  | #define WEATHER_COL_PRESSURE            7
 | 
					
						
							|  |  |  | #define WEATHER_COL_RAIN_LAST_HOUR      8
 | 
					
						
							|  |  |  | #define WEATHER_COL_RAIN_LAST_24_HOURS  9
 | 
					
						
							|  |  |  | #define WEATHER_COL_RAIN_SINCE_MIDNIGHT 10
 | 
					
						
							|  |  |  | #define WEATHER_COL_LUMINOSITY          11
 | 
					
						
							|  |  |  | #define WEATHER_COL_SNOWFALL            12
 | 
					
						
							|  |  |  | #define WEATHER_COL_RADIATION_LEVEL     13
 | 
					
						
							|  |  |  | #define WEATHER_COL_FLOOD_LEVEL         14
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define STATUS_COL_DATE                 0
 | 
					
						
							|  |  |  | #define STATUS_COL_TIME                 1
 | 
					
						
							|  |  |  | #define STATUS_COL_STATUS               2
 | 
					
						
							|  |  |  | #define STATUS_COL_SYMBOL               3
 | 
					
						
							|  |  |  | #define STATUS_COL_MAIDENHEAD           4
 | 
					
						
							|  |  |  | #define STATUS_COL_BEAM_HEADING         5
 | 
					
						
							|  |  |  | #define STATUS_COL_BEAM_POWER           6
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MESSAGE_COL_DATE                0
 | 
					
						
							|  |  |  | #define MESSAGE_COL_TIME                1
 | 
					
						
							|  |  |  | #define MESSAGE_COL_ADDRESSEE           2
 | 
					
						
							|  |  |  | #define MESSAGE_COL_MESSAGE             3
 | 
					
						
							|  |  |  | #define MESSAGE_COL_NO                  4
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_DATE              0
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_TIME              1
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_SEQ_NO            2
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_A1                3
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_A2                4
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_A3                5
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_A4                6
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_A5                7
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_B1                8
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_B2                9
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_B3                10
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_B4                11
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_B5                12
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_B6                13
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_B7                14
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_B8                15
 | 
					
						
							|  |  |  | #define TELEMETRY_COL_COMMENT           16
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MOTION_COL_DATE                 0
 | 
					
						
							|  |  |  | #define MOTION_COL_TIME                 1
 | 
					
						
							|  |  |  | #define MOTION_COL_LATITUDE             2
 | 
					
						
							|  |  |  | #define MOTION_COL_LONGITUDE            3
 | 
					
						
							|  |  |  | #define MOTION_COL_ALTITUDE             4
 | 
					
						
							|  |  |  | #define MOTION_COL_COURSE               5
 | 
					
						
							|  |  |  | #define MOTION_COL_SPEED                6
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | APRSGUI* APRSGUI::create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     APRSGUI* gui = new APRSGUI(pluginAPI, featureUISet, feature); | 
					
						
							|  |  |  |     return gui; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::destroy() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     delete this; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::resetToDefaults() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_settings.resetToDefaults(); | 
					
						
							|  |  |  |     displaySettings(); | 
					
						
							|  |  |  |     applySettings(true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QByteArray APRSGUI::serialize() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return m_settings.serialize(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool APRSGUI::deserialize(const QByteArray& data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_settings.deserialize(data)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-05-13 22:24:48 +02:00
										 |  |  |         m_feature->setWorkspaceIndex(m_settings.m_workspaceIndex); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |         displaySettings(); | 
					
						
							|  |  |  |         applySettings(true); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         resetToDefaults(); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool APRSGUI::handleMessage(const Message& message) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (APRS::MsgConfigureAPRS::match(message)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug("APRSGUI::handleMessage: APRS::MsgConfigureAPRS"); | 
					
						
							|  |  |  |         const APRS::MsgConfigureAPRS& cfg = (APRS::MsgConfigureAPRS&) message; | 
					
						
							|  |  |  |         m_settings = cfg.getSettings(); | 
					
						
							|  |  |  |         qDebug() << m_settings.m_igateCallsign; | 
					
						
							|  |  |  |         blockApplySettings(true); | 
					
						
							|  |  |  |         displaySettings(); | 
					
						
							|  |  |  |         blockApplySettings(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-03-26 09:53:06 +01:00
										 |  |  |     else if (APRS::MsgReportAvailableChannels::match(message)) | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-03-26 09:53:06 +01:00
										 |  |  |         APRS::MsgReportAvailableChannels& report = (APRS::MsgReportAvailableChannels&) message; | 
					
						
							|  |  |  |         m_availableChannels = report.getChannels(); | 
					
						
							|  |  |  |         updateChannelList(); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (MainCore::MsgPacket::match(message)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         MainCore::MsgPacket& report = (MainCore::MsgPacket&) message; | 
					
						
							|  |  |  |         AX25Packet ax25; | 
					
						
							|  |  |  |         APRSPacket *aprs = new APRSPacket(); | 
					
						
							|  |  |  |         if (ax25.decode(report.getPacket())) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (aprs->decode(ax25)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 aprs->m_dateTime = report.getDateTime(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 APRSStation *station; | 
					
						
							|  |  |  |                 bool addToStationSel = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Is packet for an existing object or station?
 | 
					
						
							|  |  |  |                 if (!aprs->m_objectName.isEmpty() && m_stations.contains(aprs->m_objectName)) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     // Add packet to existing object
 | 
					
						
							|  |  |  |                     station = m_stations.value(aprs->m_objectName); | 
					
						
							|  |  |  |                     station->addPacket(aprs); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else if (!aprs->m_objectName.isEmpty()) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     // Add new object
 | 
					
						
							|  |  |  |                     station = new APRSStation(aprs->m_objectName); | 
					
						
							|  |  |  |                     station->m_isObject = true; | 
					
						
							|  |  |  |                     station->m_reportingStation = aprs->m_from; | 
					
						
							|  |  |  |                     station->addPacket(aprs); | 
					
						
							|  |  |  |                     m_stations.insert(aprs->m_objectName, station); | 
					
						
							|  |  |  |                     addToStationSel = true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else if (m_stations.contains(aprs->m_from)) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     // Add packet to existing station
 | 
					
						
							|  |  |  |                     station = m_stations.value(aprs->m_from); | 
					
						
							|  |  |  |                     station->addPacket(aprs); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     // Add new station
 | 
					
						
							|  |  |  |                     station = new APRSStation(aprs->m_from); | 
					
						
							|  |  |  |                     station->addPacket(aprs); | 
					
						
							|  |  |  |                     m_stations.insert(aprs->m_from, station); | 
					
						
							|  |  |  |                     addToStationSel = true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Update station
 | 
					
						
							|  |  |  |                 if (aprs->m_hasSymbol) | 
					
						
							|  |  |  |                     station->m_symbolImage = aprs->m_symbolImage; | 
					
						
							|  |  |  |                 if (aprs->m_hasTimestamp) | 
					
						
							|  |  |  |                     station->m_latestPacket = aprs->dateTime(); | 
					
						
							|  |  |  |                 if (aprs->m_hasStatus) | 
					
						
							|  |  |  |                     station->m_latestStatus = aprs->m_status; | 
					
						
							|  |  |  |                 if (!aprs->m_comment.isEmpty()) | 
					
						
							|  |  |  |                     station->m_latestComment = aprs->m_comment; | 
					
						
							|  |  |  |                 if (aprs->m_hasPosition) | 
					
						
							|  |  |  |                     station->m_latestPosition = aprs->position(); | 
					
						
							|  |  |  |                 if (aprs->m_hasAltitude) | 
					
						
							|  |  |  |                     station->m_latestAltitude = QString("%1").arg(aprs->m_altitudeFt); | 
					
						
							|  |  |  |                 if (aprs->m_hasCourseAndSpeed) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     station->m_latestCourse = QString("%1").arg(aprs->m_course); | 
					
						
							|  |  |  |                     station->m_latestSpeed = QString("%1").arg(aprs->m_speed); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (aprs->m_hasStationDetails) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     station->m_powerWatts = QString("%1").arg(aprs->m_powerWatts); | 
					
						
							|  |  |  |                     station->m_antennaHeightFt = QString("%1").arg(aprs->m_antennaHeightFt); | 
					
						
							|  |  |  |                     station->m_antennaGainDB = QString("%1").arg(aprs->m_antennaGainDB); | 
					
						
							|  |  |  |                     station->m_antennaDirectivity = aprs->m_antennaDirectivity; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (aprs->m_hasRadioRange) | 
					
						
							|  |  |  |                     station->m_radioRange = QString("%1").arg(aprs->m_radioRangeMiles); | 
					
						
							|  |  |  |                 if (aprs->m_hasWeather) | 
					
						
							|  |  |  |                     station->m_hasWeather = true; | 
					
						
							|  |  |  |                 if (aprs->m_hasTelemetry) | 
					
						
							|  |  |  |                     station->m_hasTelemetry = true; | 
					
						
							|  |  |  |                 if (aprs->m_hasCourseAndSpeed) | 
					
						
							|  |  |  |                     station->m_hasCourseAndSpeed = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Update messages, which aren't station specific
 | 
					
						
							|  |  |  |                 if (aprs->m_hasMessage) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     int row = ui->messagesTable->rowCount(); | 
					
						
							|  |  |  |                     ui->messagesTable->setRowCount(row + 1); | 
					
						
							|  |  |  |                     QTableWidgetItem *messageDateItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |                     QTableWidgetItem *messageTimeItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |                     QTableWidgetItem *messageAddresseeItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |                     QTableWidgetItem *messageMessageItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |                     QTableWidgetItem *messageNoItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |                     ui->messagesTable->setItem(row, MESSAGE_COL_DATE, messageDateItem); | 
					
						
							|  |  |  |                     ui->messagesTable->setItem(row, MESSAGE_COL_TIME, messageTimeItem); | 
					
						
							|  |  |  |                     ui->messagesTable->setItem(row, MESSAGE_COL_ADDRESSEE, messageAddresseeItem); | 
					
						
							|  |  |  |                     ui->messagesTable->setItem(row, MESSAGE_COL_MESSAGE, messageMessageItem); | 
					
						
							|  |  |  |                     ui->messagesTable->setItem(row, MESSAGE_COL_NO, messageNoItem); | 
					
						
							|  |  |  |                     messageDateItem->setData(Qt::DisplayRole, formatDate(aprs)); | 
					
						
							|  |  |  |                     messageTimeItem->setData(Qt::DisplayRole, formatTime(aprs)); | 
					
						
							|  |  |  |                     messageAddresseeItem->setText(aprs->m_addressee); | 
					
						
							|  |  |  |                     messageMessageItem->setText(aprs->m_message); | 
					
						
							|  |  |  |                     messageNoItem->setText(aprs->m_messageNo); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     // Process telemetry messages
 | 
					
						
							|  |  |  |                     if ((aprs->m_telemetryNames.size() > 0) || (aprs->m_telemetryLabels.size() > 0) || aprs->m_hasTelemetryCoefficients || aprs->m_hasTelemetryBitSense) | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         APRSStation *telemetryStation; | 
					
						
							|  |  |  |                         if (m_stations.contains(aprs->m_addressee)) | 
					
						
							|  |  |  |                             telemetryStation = m_stations.value(aprs->m_addressee); | 
					
						
							|  |  |  |                         else | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             telemetryStation = new APRSStation(aprs->m_addressee); | 
					
						
							|  |  |  |                             m_stations.insert(aprs->m_addressee, telemetryStation); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         if (aprs->m_telemetryNames.size() > 0) | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             telemetryStation->m_telemetryNames = aprs->m_telemetryNames; | 
					
						
							|  |  |  |                             for (int i = 0; i < aprs->m_telemetryNames.size(); i++) | 
					
						
							|  |  |  |                                 ui->telemetryPlotSelect->setItemText(i, aprs->m_telemetryNames[i]); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         else | 
					
						
							|  |  |  |                             telemetryStation->m_telemetryLabels = aprs->m_telemetryLabels; | 
					
						
							|  |  |  |                         if (aprs->m_hasTelemetryCoefficients > 0) | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             for (int j = 0; j < 5; j++) | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 telemetryStation->m_telemetryCoefficientsA[j] = aprs->m_telemetryCoefficientsA[j]; | 
					
						
							|  |  |  |                                 telemetryStation->m_telemetryCoefficientsB[j] = aprs->m_telemetryCoefficientsB[j]; | 
					
						
							|  |  |  |                                 telemetryStation->m_telemetryCoefficientsC[j] = aprs->m_telemetryCoefficientsC[j]; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                             telemetryStation->m_hasTelemetryCoefficients = aprs->m_hasTelemetryCoefficients; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         if (aprs->m_hasTelemetryBitSense) | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             for (int j = 0; j < 8; j++) | 
					
						
							|  |  |  |                                 telemetryStation->m_telemetryBitSense[j] = aprs->m_telemetryBitSense[j]; | 
					
						
							| 
									
										
										
										
											2021-01-13 23:03:55 +00:00
										 |  |  |                             telemetryStation->m_hasTelemetryBitSense = true; | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |                             telemetryStation->m_telemetryProjectName = aprs->m_telemetryProjectName; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         if (ui->stationSelect->currentText() == aprs->m_addressee) | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             for (int i = 0; i < station->m_telemetryNames.size(); i++) | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 QString header; | 
					
						
							|  |  |  |                                 if (station->m_telemetryLabels.size() <= i) | 
					
						
							|  |  |  |                                     header = station->m_telemetryNames[i]; | 
					
						
							|  |  |  |                                 else | 
					
						
							|  |  |  |                                     header = QString("%1 (%2)").arg(station->m_telemetryNames[i]).arg(station->m_telemetryLabels[i]); | 
					
						
							|  |  |  |                                 ui->telemetryTable->horizontalHeaderItem(TELEMETRY_COL_A1+i)->setText(header); | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (addToStationSel) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     if (!filterStation(station)) | 
					
						
							|  |  |  |                         ui->stationSelect->addItem(station->m_station); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Refresh GUI if currently selected station
 | 
					
						
							|  |  |  |                 if (ui->stationSelect->currentText() == aprs->m_from) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     updateSummary(station); | 
					
						
							|  |  |  |                     addPacketToGUI(station, aprs); | 
					
						
							|  |  |  |                     if (aprs->m_hasWeather) | 
					
						
							|  |  |  |                         plotWeather(); | 
					
						
							|  |  |  |                     if (aprs->m_hasTelemetry) | 
					
						
							|  |  |  |                         plotTelemetry(); | 
					
						
							|  |  |  |                     if (aprs->m_hasPosition || aprs->m_hasAltitude || aprs->m_hasCourseAndSpeed) | 
					
						
							|  |  |  |                         plotMotion(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Forward to map
 | 
					
						
							| 
									
										
										
										
											2022-03-29 20:12:15 +02:00
										 |  |  |                 if (aprs->m_hasPosition && (aprs->m_from != "")) | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2022-03-29 20:12:15 +02:00
										 |  |  |                     QList<ObjectPipe*> mapPipes; | 
					
						
							|  |  |  |                     MainCore::instance()->getMessagePipes().getMessagePipes(m_aprs, "mapitems", mapPipes); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     for (const auto& pipe : mapPipes) | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |                     { | 
					
						
							| 
									
										
										
										
											2022-03-29 20:12:15 +02:00
										 |  |  |                         MessageQueue *messageQueue = qobject_cast<MessageQueue*>(pipe->m_element); | 
					
						
							|  |  |  |                         SWGSDRangel::SWGMapItem *swgMapItem = new SWGSDRangel::SWGMapItem(); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-29 20:12:15 +02:00
										 |  |  |                         if (!aprs->m_objectName.isEmpty()) { | 
					
						
							|  |  |  |                             swgMapItem->setName(new QString(aprs->m_objectName)); | 
					
						
							|  |  |  |                         } else { | 
					
						
							|  |  |  |                             swgMapItem->setName(new QString(aprs->m_from)); | 
					
						
							|  |  |  |                         } | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-29 20:12:15 +02:00
										 |  |  |                         swgMapItem->setLatitude(aprs->m_latitude); | 
					
						
							|  |  |  |                         swgMapItem->setLongitude(aprs->m_longitude); | 
					
						
							|  |  |  |                         swgMapItem->setAltitude(aprs->m_hasAltitude ? Units::feetToMetres(aprs->m_altitudeFt) : 0); | 
					
						
							|  |  |  |                         swgMapItem->setAltitudeReference(1); // CLAMP_TO_GROUND
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         if (aprs->m_objectKilled) | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             swgMapItem->setImage(new QString("")); | 
					
						
							|  |  |  |                             swgMapItem->setText(new QString("")); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |                         } | 
					
						
							| 
									
										
										
										
											2022-03-29 20:12:15 +02:00
										 |  |  |                         else | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             swgMapItem->setImage(new QString(QString("qrc:///%1").arg(aprs->m_symbolImage))); | 
					
						
							|  |  |  |                             swgMapItem->setText(new QString( | 
					
						
							|  |  |  |                                 aprs->toText( | 
					
						
							|  |  |  |                                     true, | 
					
						
							|  |  |  |                                     false, | 
					
						
							|  |  |  |                                     '\n', | 
					
						
							|  |  |  |                                     m_settings.m_altitudeUnits == APRSSettings::METRES, | 
					
						
							|  |  |  |                                     (int)m_settings.m_speedUnits, | 
					
						
							|  |  |  |                                     m_settings.m_temperatureUnits == APRSSettings::CELSIUS, | 
					
						
							|  |  |  |                                     m_settings.m_rainfallUnits == APRSSettings::MILLIMETRE | 
					
						
							|  |  |  |                                 ) | 
					
						
							|  |  |  |                             )); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         MainCore::MsgMapItem *msg = MainCore::MsgMapItem::create(m_aprs, swgMapItem); | 
					
						
							|  |  |  |                         messageQueue->push(msg); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 qDebug() << "APRSGUI::handleMessage: Failed to decode as APRS"; | 
					
						
							|  |  |  |                 qDebug() << ax25.m_from << " " << ax25.m_to << " " << ax25.m_via << " " << ax25.m_type << " " << ax25.m_pid << " "<< ax25.m_dataASCII; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							| 
									
										
										
										
											2022-03-29 20:12:15 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |             qDebug() << "APRSGUI::handleMessage: Failed to decode as AX.25"; | 
					
						
							| 
									
										
										
										
											2022-03-29 20:12:15 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::handleInputMessages() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Message* message; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while ((message = getInputMessageQueue()->pop())) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (handleMessage(*message)) { | 
					
						
							|  |  |  |             delete message; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::onWidgetRolled(QWidget* widget, bool rollDown) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) widget; | 
					
						
							|  |  |  |     (void) rollDown; | 
					
						
							| 
									
										
										
										
											2021-11-23 13:35:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-04 10:23:52 +02:00
										 |  |  |     getRollupContents()->saveState(m_rollupState); | 
					
						
							| 
									
										
										
										
											2021-11-23 13:35:57 +00:00
										 |  |  |     applySettings(); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | APRSGUI::APRSGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent) : | 
					
						
							|  |  |  |     FeatureGUI(parent), | 
					
						
							|  |  |  |     ui(new Ui::APRSGUI), | 
					
						
							|  |  |  |     m_pluginAPI(pluginAPI), | 
					
						
							|  |  |  |     m_featureUISet(featureUISet), | 
					
						
							|  |  |  |     m_doApplySettings(true), | 
					
						
							|  |  |  |     m_lastFeatureState(0) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-05-13 22:24:48 +02:00
										 |  |  |     m_feature = feature; | 
					
						
							| 
									
										
										
										
											2022-04-24 19:34:48 +02:00
										 |  |  |     setAttribute(Qt::WA_DeleteOnClose, true); | 
					
						
							| 
									
										
										
										
											2021-11-24 11:31:51 +00:00
										 |  |  |     m_helpURL = "plugins/feature/aprs/readme.md"; | 
					
						
							| 
									
										
										
										
											2022-04-24 19:34:48 +02:00
										 |  |  |     RollupContents *rollupContents = getRollupContents(); | 
					
						
							|  |  |  | 	ui->setupUi(rollupContents); | 
					
						
							|  |  |  |     rollupContents->arrangeRollups(); | 
					
						
							|  |  |  | 	connect(rollupContents, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m_aprs = reinterpret_cast<APRS*>(feature); | 
					
						
							|  |  |  |     m_aprs->setMessageQueueToGUI(&m_inputMessageQueue); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); | 
					
						
							|  |  |  |     connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); | 
					
						
							|  |  |  |     m_statusTimer.start(1000); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Resize the table using dummy data
 | 
					
						
							|  |  |  |     resizeTable(); | 
					
						
							|  |  |  |     // Allow user to reorder columns
 | 
					
						
							|  |  |  |     ui->weatherTable->horizontalHeader()->setSectionsMovable(true); | 
					
						
							|  |  |  |     ui->packetsTable->horizontalHeader()->setSectionsMovable(true); | 
					
						
							|  |  |  |     ui->statusTable->horizontalHeader()->setSectionsMovable(true); | 
					
						
							|  |  |  |     ui->messagesTable->horizontalHeader()->setSectionsMovable(true); | 
					
						
							|  |  |  |     ui->telemetryTable->horizontalHeader()->setSectionsMovable(true); | 
					
						
							|  |  |  |     ui->motionTable->horizontalHeader()->setSectionsMovable(true); | 
					
						
							|  |  |  |     // Allow user to sort table by clicking on headers
 | 
					
						
							|  |  |  |     ui->weatherTable->setSortingEnabled(true); | 
					
						
							|  |  |  |     ui->packetsTable->setSortingEnabled(true); | 
					
						
							|  |  |  |     ui->statusTable->setSortingEnabled(true); | 
					
						
							|  |  |  |     ui->messagesTable->setSortingEnabled(true); | 
					
						
							|  |  |  |     ui->telemetryTable->setSortingEnabled(true); | 
					
						
							|  |  |  |     ui->motionTable->setSortingEnabled(true); | 
					
						
							|  |  |  |     // Add context menu to allow hiding/showing of columns
 | 
					
						
							|  |  |  |     packetsTableMenu = new QMenu(ui->packetsTable); | 
					
						
							|  |  |  |     for (int i = 0; i < ui->packetsTable->horizontalHeader()->count(); i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QString text = ui->packetsTable->horizontalHeaderItem(i)->text(); | 
					
						
							|  |  |  |         packetsTableMenu->addAction(packetsTable_createCheckableItem(text, i, true)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ui->packetsTable->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); | 
					
						
							|  |  |  |     connect(ui->packetsTable->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(packetsTable_columnSelectMenu(QPoint))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     weatherTableMenu = new QMenu(ui->weatherTable); | 
					
						
							|  |  |  |     for (int i = 0; i < ui->weatherTable->horizontalHeader()->count(); i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QString text = ui->weatherTable->horizontalHeaderItem(i)->text(); | 
					
						
							|  |  |  |         weatherTableMenu->addAction(weatherTable_createCheckableItem(text, i, true)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ui->weatherTable->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); | 
					
						
							|  |  |  |     connect(ui->weatherTable->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(weatherTable_columnSelectMenu(QPoint))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     statusTableMenu = new QMenu(ui->statusTable); | 
					
						
							|  |  |  |     for (int i = 0; i < ui->statusTable->horizontalHeader()->count(); i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QString text = ui->statusTable->horizontalHeaderItem(i)->text(); | 
					
						
							|  |  |  |         statusTableMenu->addAction(statusTable_createCheckableItem(text, i, true)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ui->statusTable->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); | 
					
						
							|  |  |  |     connect(ui->statusTable->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(statusTable_columnSelectMenu(QPoint))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     messagesTableMenu = new QMenu(ui->messagesTable); | 
					
						
							|  |  |  |     for (int i = 0; i < ui->messagesTable->horizontalHeader()->count(); i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QString text = ui->messagesTable->horizontalHeaderItem(i)->text(); | 
					
						
							|  |  |  |         messagesTableMenu->addAction(messagesTable_createCheckableItem(text, i, true)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ui->messagesTable->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); | 
					
						
							|  |  |  |     connect(ui->messagesTable->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(messagesTable_columnSelectMenu(QPoint))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     telemetryTableMenu = new QMenu(ui->telemetryTable); | 
					
						
							|  |  |  |     for (int i = 0; i < ui->telemetryTable->horizontalHeader()->count(); i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QString text = ui->telemetryTable->horizontalHeaderItem(i)->text(); | 
					
						
							|  |  |  |         telemetryTableMenu->addAction(telemetryTable_createCheckableItem(text, i, true)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ui->telemetryTable->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); | 
					
						
							|  |  |  |     connect(ui->telemetryTable->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(telemetryTable_columnSelectMenu(QPoint))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     motionTableMenu = new QMenu(ui->motionTable); | 
					
						
							|  |  |  |     for (int i = 0; i < ui->motionTable->horizontalHeader()->count(); i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QString text = ui->motionTable->horizontalHeaderItem(i)->text(); | 
					
						
							|  |  |  |         motionTableMenu->addAction(motionTable_createCheckableItem(text, i, true)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ui->motionTable->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); | 
					
						
							|  |  |  |     connect(ui->motionTable->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(motionTable_columnSelectMenu(QPoint))); | 
					
						
							|  |  |  |     // Get signals when columns change
 | 
					
						
							|  |  |  |     connect(ui->packetsTable->horizontalHeader(), SIGNAL(sectionMoved(int, int, int)), SLOT(packetsTable_sectionMoved(int, int, int))); | 
					
						
							|  |  |  |     connect(ui->packetsTable->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), SLOT(packetsTable_sectionResized(int, int, int))); | 
					
						
							|  |  |  |     connect(ui->weatherTable->horizontalHeader(), SIGNAL(sectionMoved(int, int, int)), SLOT(weatherTable_sectionMoved(int, int, int))); | 
					
						
							|  |  |  |     connect(ui->weatherTable->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), SLOT(weatherTable_sectionResized(int, int, int))); | 
					
						
							|  |  |  |     connect(ui->statusTable->horizontalHeader(), SIGNAL(sectionMoved(int, int, int)), SLOT(statusTable_sectionMoved(int, int, int))); | 
					
						
							|  |  |  |     connect(ui->statusTable->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), SLOT(statusTable_sectionResized(int, int, int))); | 
					
						
							|  |  |  |     connect(ui->messagesTable->horizontalHeader(), SIGNAL(sectionMoved(int, int, int)), SLOT(messagesTable_sectionMoved(int, int, int))); | 
					
						
							|  |  |  |     connect(ui->messagesTable->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), SLOT(messagesTable_sectionResized(int, int, int))); | 
					
						
							|  |  |  |     connect(ui->telemetryTable->horizontalHeader(), SIGNAL(sectionMoved(int, int, int)), SLOT(telemetryTable_sectionMoved(int, int, int))); | 
					
						
							|  |  |  |     connect(ui->telemetryTable->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), SLOT(telemetryTable_sectionResized(int, int, int))); | 
					
						
							|  |  |  |     connect(ui->motionTable->horizontalHeader(), SIGNAL(sectionMoved(int, int, int)), SLOT(motionTable_sectionMoved(int, int, int))); | 
					
						
							|  |  |  |     connect(ui->motionTable->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), SLOT(motionTable_sectionResized(int, int, int))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-25 13:05:04 +00:00
										 |  |  |     m_weatherChart.setTheme(QChart::ChartThemeDark); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     m_weatherChart.legend()->hide(); | 
					
						
							|  |  |  |     ui->weatherChart->setChart(&m_weatherChart); | 
					
						
							|  |  |  |     ui->weatherChart->setRenderHint(QPainter::Antialiasing); | 
					
						
							|  |  |  |     m_weatherChart.addAxis(&m_weatherChartXAxis, Qt::AlignBottom); | 
					
						
							|  |  |  |     m_weatherChart.addAxis(&m_weatherChartYAxis, Qt::AlignLeft); | 
					
						
							| 
									
										
										
										
											2021-02-26 20:32:33 +00:00
										 |  |  |     m_weatherChart.layout()->setContentsMargins(0, 0, 0, 0); | 
					
						
							|  |  |  |     m_weatherChart.setMargins(QMargins(1, 1, 1, 1)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-25 13:05:04 +00:00
										 |  |  |     m_telemetryChart.setTheme(QChart::ChartThemeDark); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     m_telemetryChart.legend()->hide(); | 
					
						
							|  |  |  |     ui->telemetryChart->setChart(&m_telemetryChart); | 
					
						
							|  |  |  |     ui->telemetryChart->setRenderHint(QPainter::Antialiasing); | 
					
						
							|  |  |  |     m_telemetryChart.addAxis(&m_telemetryChartXAxis, Qt::AlignBottom); | 
					
						
							|  |  |  |     m_telemetryChart.addAxis(&m_telemetryChartYAxis, Qt::AlignLeft); | 
					
						
							| 
									
										
										
										
											2021-02-26 20:32:33 +00:00
										 |  |  |     m_telemetryChart.layout()->setContentsMargins(0, 0, 0, 0); | 
					
						
							|  |  |  |     m_telemetryChart.setMargins(QMargins(1, 1, 1, 1)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-25 13:05:04 +00:00
										 |  |  |     m_motionChart.setTheme(QChart::ChartThemeDark); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     m_motionChart.legend()->hide(); | 
					
						
							|  |  |  |     ui->motionChart->setChart(&m_motionChart); | 
					
						
							|  |  |  |     ui->motionChart->setRenderHint(QPainter::Antialiasing); | 
					
						
							|  |  |  |     m_motionChart.addAxis(&m_motionChartXAxis, Qt::AlignBottom); | 
					
						
							|  |  |  |     m_motionChart.addAxis(&m_motionChartYAxis, Qt::AlignLeft); | 
					
						
							| 
									
										
										
										
											2021-02-26 20:32:33 +00:00
										 |  |  |     m_motionChart.layout()->setContentsMargins(0, 0, 0, 0); | 
					
						
							|  |  |  |     m_motionChart.setMargins(QMargins(1, 1, 1, 1)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-09 05:27:12 +01:00
										 |  |  |     m_settings.setRollupState(&m_rollupState); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-26 09:53:06 +01:00
										 |  |  |     m_aprs->getInputMessageQueue()->push(APRS::MsgQueryAvailableChannels::create()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     displaySettings(); | 
					
						
							|  |  |  |     applySettings(true); | 
					
						
							| 
									
										
										
										
											2022-04-04 10:23:52 +02:00
										 |  |  |     makeUIConnections(); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | APRSGUI::~APRSGUI() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     delete ui; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-13 22:24:48 +02:00
										 |  |  | void APRSGUI::setWorkspaceIndex(int index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_settings.m_workspaceIndex = index; | 
					
						
							|  |  |  |     m_feature->setWorkspaceIndex(index); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | void APRSGUI::blockApplySettings(bool block) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_doApplySettings = !block; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool APRSGUI::filterStation(APRSStation *station) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (m_settings.m_stationFilter) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case APRSSettings::ALL: | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     case APRSSettings::STATIONS: | 
					
						
							|  |  |  |         return station->m_isObject; | 
					
						
							|  |  |  |     case APRSSettings::OBJECTS: | 
					
						
							|  |  |  |         return !station->m_isObject; | 
					
						
							|  |  |  |     case APRSSettings::WEATHER: | 
					
						
							|  |  |  |         return !station->m_hasWeather; | 
					
						
							|  |  |  |     case APRSSettings::TELEMETRY: | 
					
						
							|  |  |  |         return !station->m_hasTelemetry; | 
					
						
							|  |  |  |     case APRSSettings::COURSE_AND_SPEED: | 
					
						
							|  |  |  |         return !station->m_hasCourseAndSpeed; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::filterStations() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ui->stationSelect->clear(); | 
					
						
							|  |  |  |     QHashIterator<QString,APRSStation *> i(m_stations); | 
					
						
							|  |  |  |     while (i.hasNext()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         i.next(); | 
					
						
							|  |  |  |         APRSStation *station = i.value(); | 
					
						
							|  |  |  |         if (!filterStation(station)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ui->stationSelect->addItem(station->m_station); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::displayTableSettings(QTableWidget *table, QMenu *menu, int *columnSizes, int *columnIndexes, int columns) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QHeaderView *header = table->horizontalHeader(); | 
					
						
							|  |  |  |     for (int i = 0; i < columns; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         bool hidden = columnSizes[i] == 0; | 
					
						
							|  |  |  |         header->setSectionHidden(i, hidden); | 
					
						
							|  |  |  |         menu->actions().at(i)->setChecked(!hidden); | 
					
						
							|  |  |  |         if (columnSizes[i] > 0) | 
					
						
							|  |  |  |             table->setColumnWidth(i, columnSizes[i]); | 
					
						
							|  |  |  |         header->moveSection(header->visualIndex(i), columnIndexes[i]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::displaySettings() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     setTitleColor(m_settings.m_rgbColor); | 
					
						
							|  |  |  |     setWindowTitle(m_settings.m_title); | 
					
						
							| 
									
										
										
										
											2022-04-04 10:23:52 +02:00
										 |  |  |     setTitle(m_settings.m_title); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     blockApplySettings(true); | 
					
						
							|  |  |  |     ui->igate->setChecked(m_settings.m_igateEnabled); | 
					
						
							|  |  |  |     ui->stationFilter->setCurrentIndex((int)m_settings.m_stationFilter); | 
					
						
							|  |  |  |     ui->filterAddressee->setText(m_settings.m_filterAddressee); | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |     setUnits(); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Order and size columns
 | 
					
						
							|  |  |  |     displayTableSettings(ui->packetsTable, packetsTableMenu, m_settings.m_packetsTableColumnSizes, m_settings.m_packetsTableColumnIndexes, APRS_PACKETS_TABLE_COLUMNS); | 
					
						
							|  |  |  |     displayTableSettings(ui->weatherTable, weatherTableMenu, m_settings.m_weatherTableColumnSizes, m_settings.m_weatherTableColumnIndexes, APRS_WEATHER_TABLE_COLUMNS); | 
					
						
							|  |  |  |     displayTableSettings(ui->statusTable, statusTableMenu, m_settings.m_statusTableColumnSizes, m_settings.m_statusTableColumnIndexes, APRS_STATUS_TABLE_COLUMNS); | 
					
						
							|  |  |  |     displayTableSettings(ui->messagesTable, messagesTableMenu, m_settings.m_messagesTableColumnSizes, m_settings.m_messagesTableColumnIndexes, APRS_MESSAGES_TABLE_COLUMNS); | 
					
						
							|  |  |  |     displayTableSettings(ui->telemetryTable, telemetryTableMenu, m_settings.m_telemetryTableColumnSizes, m_settings.m_telemetryTableColumnIndexes, APRS_TELEMETRY_TABLE_COLUMNS); | 
					
						
							|  |  |  |     displayTableSettings(ui->motionTable, motionTableMenu, m_settings.m_motionTableColumnSizes, m_settings.m_motionTableColumnIndexes, APRS_MOTION_TABLE_COLUMNS); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-04 10:23:52 +02:00
										 |  |  |     getRollupContents()->restoreState(m_rollupState); | 
					
						
							| 
									
										
										
										
											2021-11-23 13:35:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     blockApplySettings(false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-26 09:53:06 +01:00
										 |  |  | void APRSGUI::updateChannelList() | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     ui->sourcePipes->blockSignals(true); | 
					
						
							|  |  |  |     ui->sourcePipes->clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-26 09:53:06 +01:00
										 |  |  |     for (const auto& channel : m_availableChannels) { | 
					
						
							|  |  |  |         ui->sourcePipes->addItem(tr("R%1:%2 %3").arg(channel.m_deviceSetIndex).arg(channel.m_channelIndex).arg(channel.m_type)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ui->sourcePipes->blockSignals(false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												dd maximize button to MainSpectrum and expandible Channels and Features.
Add sizeToContents in ChannelGUI and FeatureGUI, called when widget is
rolled, so we can remove resizing code from all of the individual
channels and features.
In RollupContents, use minimumSizeHint for calculated size, so that
minimumWidth can come from .ui file.
In DeviceGUI::sizeToContents(), call adjustSize(), so Device GUIs start
out at minimum needed size (which should restore appearance prior to
last patch).
In stackSubWindows, use available space for channels if no
spectrum/features present.
In stackSubWindows, fix spectrum from being sized too big, resulting in
scroll bars appearing.
Reset user-defined channel width in stackSubWindows, when channels are
removed.
Don't stack maximized windows.
There's one hack in Channel/FeatureGUI::maximizeWindow(). It seems that
when maximimzing a window, QOpenGLWidgets aren't always paint properly
immediately afterwards, so the code forces an additional update. I can't
see why the first call to paintGL doesn't work.
											
										 
											2022-11-11 12:24:27 +00:00
										 |  |  | void APRSGUI::resizeEvent(QResizeEvent* event) | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     // Replot graphs to ensure Axis are visible
 | 
					
						
							|  |  |  |     plotWeather(); | 
					
						
							|  |  |  |     plotTelemetry(); | 
					
						
							|  |  |  |     plotMotion(); | 
					
						
							| 
									
										
											  
											
												dd maximize button to MainSpectrum and expandible Channels and Features.
Add sizeToContents in ChannelGUI and FeatureGUI, called when widget is
rolled, so we can remove resizing code from all of the individual
channels and features.
In RollupContents, use minimumSizeHint for calculated size, so that
minimumWidth can come from .ui file.
In DeviceGUI::sizeToContents(), call adjustSize(), so Device GUIs start
out at minimum needed size (which should restore appearance prior to
last patch).
In stackSubWindows, use available space for channels if no
spectrum/features present.
In stackSubWindows, fix spectrum from being sized too big, resulting in
scroll bars appearing.
Reset user-defined channel width in stackSubWindows, when channels are
removed.
Don't stack maximized windows.
There's one hack in Channel/FeatureGUI::maximizeWindow(). It seems that
when maximimzing a window, QOpenGLWidgets aren't always paint properly
immediately afterwards, so the code forces an additional update. I can't
see why the first call to paintGL doesn't work.
											
										 
											2022-11-11 12:24:27 +00:00
										 |  |  |     FeatureGUI::resizeEvent(event); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::onMenuDialogCalled(const QPoint &p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_contextMenuType == ContextMenuChannelSettings) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         BasicFeatureSettingsDialog dialog(this); | 
					
						
							|  |  |  |         dialog.setTitle(m_settings.m_title); | 
					
						
							|  |  |  |         dialog.setUseReverseAPI(m_settings.m_useReverseAPI); | 
					
						
							|  |  |  |         dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); | 
					
						
							|  |  |  |         dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); | 
					
						
							|  |  |  |         dialog.setReverseAPIFeatureSetIndex(m_settings.m_reverseAPIFeatureSetIndex); | 
					
						
							|  |  |  |         dialog.setReverseAPIFeatureIndex(m_settings.m_reverseAPIFeatureIndex); | 
					
						
							| 
									
										
										
										
											2022-04-18 12:08:33 +02:00
										 |  |  |         dialog.setDefaultTitle(m_displayedName); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         dialog.move(p); | 
					
						
							|  |  |  |         dialog.exec(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         m_settings.m_title = dialog.getTitle(); | 
					
						
							|  |  |  |         m_settings.m_useReverseAPI = dialog.useReverseAPI(); | 
					
						
							|  |  |  |         m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); | 
					
						
							|  |  |  |         m_settings.m_reverseAPIPort = dialog.getReverseAPIPort(); | 
					
						
							|  |  |  |         m_settings.m_reverseAPIFeatureSetIndex = dialog.getReverseAPIFeatureSetIndex(); | 
					
						
							|  |  |  |         m_settings.m_reverseAPIFeatureIndex = dialog.getReverseAPIFeatureIndex(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-18 12:08:33 +02:00
										 |  |  |         setTitle(m_settings.m_title); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |         setTitleColor(m_settings.m_rgbColor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         applySettings(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resetContextMenuType(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::updateSummary(APRSStation *station) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ui->station->setText(station->m_station); | 
					
						
							|  |  |  |     ui->reportingStation->setText(station->m_reportingStation); | 
					
						
							|  |  |  |     ui->symbol->setPixmap(QPixmap(QString(":%1").arg(station->m_symbolImage))); | 
					
						
							|  |  |  |     ui->status->setText(station->m_latestStatus); | 
					
						
							|  |  |  |     ui->comment->setText(station->m_latestComment); | 
					
						
							|  |  |  |     ui->position->setText(station->m_latestPosition); | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |     ui->altitude->setText(convertAltitude(station->m_latestAltitude)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     ui->course->setText(station->m_latestCourse); | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |     ui->speed->setText(convertSpeed(station->m_latestSpeed)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     ui->txPower->setText(station->m_powerWatts); | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |     ui->antennaHeight->setText(convertAltitude(station->m_antennaHeightFt)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     ui->antennaGain->setText(station->m_antennaGainDB); | 
					
						
							|  |  |  |     ui->antennaDirectivity->setText(station->m_antennaDirectivity); | 
					
						
							|  |  |  |     ui->radioRange->setText(station->m_radioRange); | 
					
						
							|  |  |  |     if (!station->m_packets.isEmpty()) | 
					
						
							|  |  |  |         ui->lastPacket->setText(station->m_packets.last()->m_dateTime.toString()); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         ui->lastPacket->setText(""); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString APRSGUI::formatDate(APRSPacket *aprs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (aprs->m_hasTimestamp) | 
					
						
							|  |  |  |         return aprs->date(); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return aprs->m_dateTime.date().toString("yyyy/MM/dd"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString APRSGUI::formatTime(APRSPacket *aprs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Add suffix T to indicate timestamp used
 | 
					
						
							|  |  |  |     if (aprs->m_hasTimestamp) | 
					
						
							|  |  |  |         return QString("%1 T").arg(aprs->time()); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return aprs->m_dateTime.time().toString("hh:mm:ss"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | double APRSGUI::applyCoefficients(int idx, int value, APRSStation *station) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (station->m_hasTelemetryCoefficients > idx) | 
					
						
							|  |  |  |         return station->m_telemetryCoefficientsA[idx] * value * value + station->m_telemetryCoefficientsB[idx] * value + station->m_telemetryCoefficientsC[idx]; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return (double)idx; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::addPacketToGUI(APRSStation *station, APRSPacket *aprs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int row; | 
					
						
							|  |  |  |     // Weather table
 | 
					
						
							|  |  |  |     if (aprs->m_hasWeather) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         row = ui->weatherTable->rowCount(); | 
					
						
							|  |  |  |         ui->weatherTable->setRowCount(row + 1); | 
					
						
							|  |  |  |         QTableWidgetItem *weatherDateItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *weatherTimeItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *windDirectionItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *windSpeedItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *gustsItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *temperatureItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *humidityItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *pressureItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *rainLastHourItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *rainLast24HoursItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *rainSinceMidnightItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *luminosityItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *snowfallItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *radiationLevelItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *floodLevelItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_DATE, weatherDateItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_TIME, weatherTimeItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_WIND_DIRECTION, windDirectionItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_WIND_SPEED, windSpeedItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_GUSTS, gustsItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_TEMPERATURE, temperatureItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_HUMIDITY, humidityItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_PRESSURE, pressureItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_RAIN_LAST_HOUR, rainLastHourItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_RAIN_LAST_24_HOURS, rainLast24HoursItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_RAIN_SINCE_MIDNIGHT, rainSinceMidnightItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_LUMINOSITY, luminosityItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_SNOWFALL, snowfallItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_RADIATION_LEVEL, radiationLevelItem); | 
					
						
							|  |  |  |         ui->weatherTable->setItem(row, WEATHER_COL_FLOOD_LEVEL, floodLevelItem); | 
					
						
							|  |  |  |         weatherDateItem->setData(Qt::DisplayRole, formatDate(aprs)); | 
					
						
							|  |  |  |         weatherTimeItem->setData(Qt::DisplayRole, formatTime(aprs)); | 
					
						
							|  |  |  |         if (aprs->m_hasWindDirection) | 
					
						
							|  |  |  |             windDirectionItem->setData(Qt::DisplayRole, aprs->m_windDirection); | 
					
						
							|  |  |  |         if (aprs->m_hasWindSpeed) | 
					
						
							|  |  |  |             windSpeedItem->setData(Qt::DisplayRole, aprs->m_windSpeed); | 
					
						
							|  |  |  |         if (aprs->m_hasGust) | 
					
						
							|  |  |  |             gustsItem->setData(Qt::DisplayRole, aprs->m_gust); | 
					
						
							|  |  |  |         if (aprs->m_hasTemp) | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |             temperatureItem->setData(Qt::DisplayRole, convertTemperature(aprs->m_temp)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |         if (aprs->m_hasHumidity) | 
					
						
							|  |  |  |             humidityItem->setData(Qt::DisplayRole, aprs->m_humidity); | 
					
						
							|  |  |  |         if (aprs->m_hasBarometricPressure) | 
					
						
							|  |  |  |             pressureItem->setData(Qt::DisplayRole, aprs->m_barometricPressure/10.0f); | 
					
						
							|  |  |  |         if (aprs->m_hasRainLastHr) | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |             rainLastHourItem->setData(Qt::DisplayRole, convertRainfall(aprs->m_rainLastHr)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |         if (aprs->m_hasRainLast24Hrs) | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |             rainLast24HoursItem->setData(Qt::DisplayRole, convertRainfall(aprs->m_rainLast24Hrs)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |         if (aprs->m_hasRainSinceMidnight) | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |             rainSinceMidnightItem->setData(Qt::DisplayRole, convertRainfall(aprs->m_rainSinceMidnight)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |         if (aprs->m_hasLuminsoity) | 
					
						
							|  |  |  |             luminosityItem->setData(Qt::DisplayRole, aprs->m_luminosity); | 
					
						
							|  |  |  |         if (aprs->m_hasSnowfallLast24Hrs) | 
					
						
							|  |  |  |             snowfallItem->setData(Qt::DisplayRole, aprs->m_snowfallLast24Hrs); | 
					
						
							|  |  |  |         if (aprs->m_hasRadiationLevel) | 
					
						
							|  |  |  |             radiationLevelItem->setData(Qt::DisplayRole, aprs->m_hasRadiationLevel); | 
					
						
							|  |  |  |         if (aprs->m_hasFloodLevel) | 
					
						
							|  |  |  |             floodLevelItem->setData(Qt::DisplayRole, aprs->m_floodLevel); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Status table
 | 
					
						
							|  |  |  |     if (aprs->m_hasStatus) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         row = ui->statusTable->rowCount(); | 
					
						
							|  |  |  |         ui->statusTable->setRowCount(row + 1); | 
					
						
							|  |  |  |         QTableWidgetItem *statusDateItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *statusTimeItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *statusItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *statusSymbolItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *statusMaidenheadItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *statusBeamHeadingItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *statusBeamPowerItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         ui->statusTable->setItem(row, STATUS_COL_DATE, statusDateItem); | 
					
						
							|  |  |  |         ui->statusTable->setItem(row, STATUS_COL_TIME, statusTimeItem); | 
					
						
							|  |  |  |         ui->statusTable->setItem(row, STATUS_COL_STATUS, statusItem); | 
					
						
							|  |  |  |         ui->statusTable->setItem(row, STATUS_COL_SYMBOL, statusSymbolItem); | 
					
						
							|  |  |  |         ui->statusTable->setItem(row, STATUS_COL_MAIDENHEAD, statusMaidenheadItem); | 
					
						
							|  |  |  |         ui->statusTable->setItem(row, STATUS_COL_BEAM_HEADING, statusBeamHeadingItem); | 
					
						
							|  |  |  |         ui->statusTable->setItem(row, STATUS_COL_BEAM_POWER, statusBeamPowerItem); | 
					
						
							|  |  |  |         statusDateItem->setData(Qt::DisplayRole, formatDate(aprs)); | 
					
						
							|  |  |  |         statusTimeItem->setData(Qt::DisplayRole, formatTime(aprs)); | 
					
						
							|  |  |  |         statusItem->setText(aprs->m_status); | 
					
						
							|  |  |  |         if (aprs->m_hasSymbol) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             statusSymbolItem->setSizeHint(QSize(24, 24)); | 
					
						
							|  |  |  |             statusSymbolItem->setIcon(QIcon(QString(":%1").arg(station->m_symbolImage))); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         statusMaidenheadItem->setText(aprs->m_maidenhead); | 
					
						
							|  |  |  |         if (aprs->m_hasBeam) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             statusBeamHeadingItem->setData(Qt::DisplayRole, aprs->m_beamHeading); | 
					
						
							|  |  |  |             statusBeamPowerItem->setData(Qt::DisplayRole, aprs->m_beamPower); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Telemetry table
 | 
					
						
							|  |  |  |     if (aprs->m_hasTelemetry) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         row = ui->telemetryTable->rowCount(); | 
					
						
							|  |  |  |         ui->telemetryTable->setRowCount(row + 1); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryDateItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryTimeItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetrySeqNoItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryA1Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryA2Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryA3Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryA4Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryA5Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryB1Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryB2Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryB3Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryB4Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryB5Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryB6Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryB7Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryB8Item = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *telemetryCommentItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_DATE, telemetryDateItem); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_TIME, telemetryTimeItem); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_SEQ_NO, telemetrySeqNoItem); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_A1, telemetryA1Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_A2, telemetryA2Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_A3, telemetryA3Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_A4, telemetryA4Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_A5, telemetryA5Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_B1, telemetryB1Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_B2, telemetryB2Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_B3, telemetryB3Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_B4, telemetryB4Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_B5, telemetryB5Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_B6, telemetryB6Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_B7, telemetryB7Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_B8, telemetryB8Item); | 
					
						
							|  |  |  |         ui->telemetryTable->setItem(row, TELEMETRY_COL_COMMENT, telemetryCommentItem); | 
					
						
							|  |  |  |         telemetryDateItem->setData(Qt::DisplayRole, formatDate(aprs)); | 
					
						
							|  |  |  |         telemetryTimeItem->setData(Qt::DisplayRole, formatTime(aprs)); | 
					
						
							|  |  |  |         if (aprs->m_hasSeqNo) | 
					
						
							|  |  |  |             telemetrySeqNoItem->setData(Qt::DisplayRole, aprs->m_seqNo); | 
					
						
							|  |  |  |         if (aprs->m_a1HasValue) | 
					
						
							|  |  |  |             telemetryA1Item->setData(Qt::DisplayRole, applyCoefficients(0, aprs->m_a1, station)); | 
					
						
							|  |  |  |         if (aprs->m_a2HasValue) | 
					
						
							|  |  |  |             telemetryA2Item->setData(Qt::DisplayRole, applyCoefficients(1, aprs->m_a2, station)); | 
					
						
							|  |  |  |         if (aprs->m_a3HasValue) | 
					
						
							|  |  |  |             telemetryA3Item->setData(Qt::DisplayRole, applyCoefficients(2, aprs->m_a3, station)); | 
					
						
							|  |  |  |         if (aprs->m_a4HasValue) | 
					
						
							|  |  |  |             telemetryA4Item->setData(Qt::DisplayRole, applyCoefficients(3, aprs->m_a4, station)); | 
					
						
							|  |  |  |         if (aprs->m_a5HasValue) | 
					
						
							|  |  |  |             telemetryA5Item->setData(Qt::DisplayRole, applyCoefficients(4, aprs->m_a5, station)); | 
					
						
							|  |  |  |         if (aprs->m_bHasValue) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             telemetryB1Item->setData(Qt::DisplayRole, aprs->m_b[0] ? 1 : 0); | 
					
						
							|  |  |  |             telemetryB2Item->setData(Qt::DisplayRole, aprs->m_b[1] ? 1 : 0); | 
					
						
							|  |  |  |             telemetryB3Item->setData(Qt::DisplayRole, aprs->m_b[2] ? 1 : 0); | 
					
						
							|  |  |  |             telemetryB4Item->setData(Qt::DisplayRole, aprs->m_b[3] ? 1 : 0); | 
					
						
							|  |  |  |             telemetryB5Item->setData(Qt::DisplayRole, aprs->m_b[4] ? 1 : 0); | 
					
						
							|  |  |  |             telemetryB6Item->setData(Qt::DisplayRole, aprs->m_b[5] ? 1 : 0); | 
					
						
							|  |  |  |             telemetryB7Item->setData(Qt::DisplayRole, aprs->m_b[6] ? 1 : 0); | 
					
						
							|  |  |  |             telemetryB8Item->setData(Qt::DisplayRole, aprs->m_b[7] ? 1 : 0); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         telemetryCommentItem->setText(aprs->m_telemetryComment); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (int i = 0; i < station->m_telemetryNames.size(); i++) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             QString header; | 
					
						
							|  |  |  |             if (station->m_telemetryLabels.size() <= i) | 
					
						
							|  |  |  |                 header = station->m_telemetryNames[i]; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 header = QString("%1 (%2)").arg(station->m_telemetryNames[i]).arg(station->m_telemetryLabels[i]); | 
					
						
							|  |  |  |             ui->telemetryTable->horizontalHeaderItem(TELEMETRY_COL_A1+i)->setText(header); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Motion table
 | 
					
						
							|  |  |  |     if (aprs->m_hasPosition || aprs->m_hasAltitude || aprs->m_hasCourseAndSpeed) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         row = ui->motionTable->rowCount(); | 
					
						
							|  |  |  |         ui->motionTable->setRowCount(row + 1); | 
					
						
							|  |  |  |         QTableWidgetItem *motionDateItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *motionTimeItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *latitudeItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *longitudeItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *altitudeItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *courseItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         QTableWidgetItem *speedItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |         ui->motionTable->setItem(row, MOTION_COL_DATE, motionDateItem); | 
					
						
							|  |  |  |         ui->motionTable->setItem(row, MOTION_COL_TIME, motionTimeItem); | 
					
						
							|  |  |  |         ui->motionTable->setItem(row, MOTION_COL_LATITUDE, latitudeItem); | 
					
						
							|  |  |  |         ui->motionTable->setItem(row, MOTION_COL_LONGITUDE, longitudeItem); | 
					
						
							|  |  |  |         ui->motionTable->setItem(row, MOTION_COL_ALTITUDE, altitudeItem); | 
					
						
							|  |  |  |         ui->motionTable->setItem(row, MOTION_COL_COURSE, courseItem); | 
					
						
							|  |  |  |         ui->motionTable->setItem(row, MOTION_COL_SPEED, speedItem); | 
					
						
							|  |  |  |         motionDateItem->setData(Qt::DisplayRole, formatDate(aprs)); | 
					
						
							|  |  |  |         motionTimeItem->setData(Qt::DisplayRole, formatTime(aprs)); | 
					
						
							|  |  |  |         if (aprs->m_hasPosition) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             latitudeItem->setData(Qt::DisplayRole, aprs->m_latitude); | 
					
						
							|  |  |  |             longitudeItem->setData(Qt::DisplayRole, aprs->m_longitude); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (aprs->m_hasAltitude) | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |             altitudeItem->setData(Qt::DisplayRole, convertAltitude(aprs->m_altitudeFt)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |         if (aprs->m_hasCourseAndSpeed) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             courseItem->setData(Qt::DisplayRole, aprs->m_course); | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |             speedItem->setData(Qt::DisplayRole, convertSpeed(aprs->m_speed)); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Packets table
 | 
					
						
							|  |  |  |     row = ui->packetsTable->rowCount(); | 
					
						
							|  |  |  |     ui->packetsTable->setRowCount(row + 1); | 
					
						
							|  |  |  |     QTableWidgetItem *dateItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |     QTableWidgetItem *timeItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |     QTableWidgetItem *fromItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |     QTableWidgetItem *toItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |     QTableWidgetItem *viaItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |     QTableWidgetItem *dataItem = new QTableWidgetItem(); | 
					
						
							|  |  |  |     ui->packetsTable->setItem(row, PACKETS_COL_DATE, dateItem); | 
					
						
							|  |  |  |     ui->packetsTable->setItem(row, PACKETS_COL_TIME, timeItem); | 
					
						
							|  |  |  |     ui->packetsTable->setItem(row, PACKETS_COL_FROM, fromItem); | 
					
						
							|  |  |  |     ui->packetsTable->setItem(row, PACKETS_COL_TO, toItem); | 
					
						
							|  |  |  |     ui->packetsTable->setItem(row, PACKETS_COL_VIA, viaItem); | 
					
						
							|  |  |  |     ui->packetsTable->setItem(row, PACKETS_COL_DATA, dataItem); | 
					
						
							|  |  |  |     dateItem->setData(Qt::DisplayRole, formatDate(aprs)); | 
					
						
							|  |  |  |     timeItem->setData(Qt::DisplayRole, formatTime(aprs)); | 
					
						
							|  |  |  |     fromItem->setText(aprs->m_from); | 
					
						
							|  |  |  |     toItem->setText(aprs->m_to); | 
					
						
							|  |  |  |     viaItem->setText(aprs->m_via); | 
					
						
							|  |  |  |     dataItem->setText(aprs->m_data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::on_stationFilter_currentIndexChanged(int index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_settings.m_stationFilter = static_cast<APRSSettings::StationFilter>(index); | 
					
						
							|  |  |  |     applySettings(); | 
					
						
							|  |  |  |     filterStations(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::on_stationSelect_currentIndexChanged(int index) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-13 23:03:55 +00:00
										 |  |  |     (void) index; | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     QString stationCallsign = ui->stationSelect->currentText(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     APRSStation *station = m_stations.value(stationCallsign); | 
					
						
							|  |  |  |     if (station == nullptr) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug() << "APRSGUI::on_stationSelect_currentIndexChanged - station==nullptr"; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Clear tables
 | 
					
						
							|  |  |  |     ui->weatherTable->setRowCount(0); | 
					
						
							|  |  |  |     ui->packetsTable->setRowCount(0); | 
					
						
							|  |  |  |     ui->statusTable->setRowCount(0); | 
					
						
							|  |  |  |     ui->telemetryTable->setRowCount(0); | 
					
						
							|  |  |  |     ui->motionTable->setRowCount(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Set telemetry plot select combo text
 | 
					
						
							|  |  |  |     const char *telemetryNames[] = {"A1", "A2", "A3", "A4", "A5", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8"}; | 
					
						
							|  |  |  |     int telemetryNamesSize = station->m_telemetryNames.size(); | 
					
						
							|  |  |  |     for (int i = 0; i < 12; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (i < telemetryNamesSize) | 
					
						
							|  |  |  |             ui->telemetryPlotSelect->setItemText(i, station->m_telemetryNames[i]); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             ui->telemetryPlotSelect->setItemText(i, telemetryNames[i]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Update summary table
 | 
					
						
							|  |  |  |     updateSummary(station); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Display/hide fields depending if station or object
 | 
					
						
							|  |  |  |     ui->stationObjectLabel->setText(station->m_isObject ? "Object" : "Station"); | 
					
						
							|  |  |  |     ui->station->setToolTip(station->m_isObject ? "Object name" : "Station callsign and substation ID"); | 
					
						
							|  |  |  |     ui->reportingStation->setVisible(station->m_isObject); | 
					
						
							|  |  |  |     ui->reportingStationLabel->setVisible(station->m_isObject); | 
					
						
							|  |  |  |     ui->status->setVisible(!station->m_isObject); | 
					
						
							|  |  |  |     ui->statusLabel->setVisible(!station->m_isObject); | 
					
						
							|  |  |  |     if (station->m_isObject) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ( ui->stationsTabWidget->count() == 6) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ui->stationsTabWidget->removeTab(3); | 
					
						
							|  |  |  |             ui->stationsTabWidget->removeTab(3); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ( ui->stationsTabWidget->count() != 6) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ui->stationsTabWidget->insertTab(3, ui->telemetryTab, "Telemetry"); | 
					
						
							|  |  |  |             ui->stationsTabWidget->insertTab(4, ui->statusTab, "Status"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Add packets to tables
 | 
					
						
							|  |  |  |     ui->packetsTable->setSortingEnabled(false); | 
					
						
							|  |  |  |     ui->weatherTable->setSortingEnabled(false); | 
					
						
							|  |  |  |     ui->statusTable->setSortingEnabled(false); | 
					
						
							|  |  |  |     ui->telemetryTable->setSortingEnabled(false); | 
					
						
							|  |  |  |     ui->motionTable->setSortingEnabled(false); | 
					
						
							|  |  |  |     QListIterator<APRSPacket *> i(station->m_packets); | 
					
						
							|  |  |  |     while (i.hasNext()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         APRSPacket *aprs = i.next(); | 
					
						
							|  |  |  |         addPacketToGUI(station, aprs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ui->packetsTable->setSortingEnabled(true); | 
					
						
							|  |  |  |     ui->weatherTable->setSortingEnabled(true); | 
					
						
							|  |  |  |     ui->statusTable->setSortingEnabled(true); | 
					
						
							|  |  |  |     ui->telemetryTable->setSortingEnabled(true); | 
					
						
							|  |  |  |     ui->motionTable->setSortingEnabled(true); | 
					
						
							|  |  |  |     plotWeather(); | 
					
						
							|  |  |  |     plotTelemetry(); | 
					
						
							|  |  |  |     plotMotion(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::on_filterAddressee_editingFinished() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_settings.m_filterAddressee = ui->filterAddressee->text(); | 
					
						
							|  |  |  |     filterMessages(); | 
					
						
							|  |  |  |     applySettings(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::filterMessageRow(int row) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bool hidden = false; | 
					
						
							|  |  |  |     if (m_settings.m_filterAddressee != "") | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QRegExp re(m_settings.m_filterAddressee); | 
					
						
							|  |  |  |         QTableWidgetItem *addressee = ui->messagesTable->item(row, MESSAGE_COL_ADDRESSEE); | 
					
						
							|  |  |  |         if (!re.exactMatch(addressee->text())) | 
					
						
							|  |  |  |             hidden = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ui->messagesTable->setRowHidden(row, hidden); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::filterMessages() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (int i = 0; i < ui->messagesTable->rowCount(); i++) | 
					
						
							|  |  |  |         filterMessageRow(i); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::on_deleteMessages_clicked() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<QTableWidgetItem *> list = ui->messagesTable->selectedItems(); | 
					
						
							|  |  |  |     QList<int> rows; | 
					
						
							|  |  |  |     if (list.isEmpty()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // Delete all messages
 | 
					
						
							|  |  |  |         if (QMessageBox::Yes == QMessageBox::question(this, "Delete all messages", "Delete all messages?", QMessageBox::Yes|QMessageBox::No)) | 
					
						
							|  |  |  |             ui->messagesTable->setRowCount(0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // Delete selected messages (in reverse order)
 | 
					
						
							|  |  |  |         for (int i = 0; i < list.size(); i++) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             int row = list[i]->row(); | 
					
						
							|  |  |  |             if (!rows.contains(row)) | 
					
						
							|  |  |  |                 rows.append(row); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         std::sort(rows.begin(), rows.end(), std::greater<int>()); | 
					
						
							|  |  |  |         QListIterator<int> itr(rows); | 
					
						
							|  |  |  |         while (itr.hasNext()) | 
					
						
							|  |  |  |             ui->messagesTable->removeRow(itr.next()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void addToSeries(QLineSeries *series, const QDateTime& dt, double value, double& min, double &max) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     series->append(dt.toMSecsSinceEpoch(), value); | 
					
						
							|  |  |  |     if (value < min) | 
					
						
							|  |  |  |         min = value; | 
					
						
							|  |  |  |     if (value > max) | 
					
						
							|  |  |  |         max = value; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::plotWeather() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString stationCallsign = ui->stationSelect->currentText(); | 
					
						
							|  |  |  |     if (stationCallsign.isEmpty()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     APRSStation *station = m_stations.value(stationCallsign); | 
					
						
							|  |  |  |     if (station == nullptr) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QLineSeries *series = new QLineSeries(); | 
					
						
							|  |  |  |     double minValue = INFINITY; | 
					
						
							|  |  |  |     double maxValue = -INFINITY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int timeSelectIdx = ui->weatherTimeSelect->currentIndex(); | 
					
						
							|  |  |  |     int plotSelectIdx = ui->weatherPlotSelect->currentIndex(); | 
					
						
							|  |  |  |     QDateTime limit = calcTimeLimit(timeSelectIdx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QListIterator<APRSPacket *> i(station->m_packets); | 
					
						
							|  |  |  |     while (i.hasNext()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         APRSPacket *aprs = i.next(); | 
					
						
							|  |  |  |         if (aprs->m_hasWeather) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             QDateTime dt; | 
					
						
							|  |  |  |             if (aprs->m_hasTimestamp) | 
					
						
							|  |  |  |                 dt = aprs->m_timestamp; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 dt = aprs->m_dateTime; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (dt >= limit) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 if (plotSelectIdx == 0 && aprs->m_hasWindDirection) | 
					
						
							|  |  |  |                     addToSeries(series, dt, aprs->m_windDirection, minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 1 && aprs->m_hasWindSpeed) | 
					
						
							|  |  |  |                     addToSeries(series, dt, aprs->m_windSpeed, minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 2 && aprs->m_hasGust) | 
					
						
							|  |  |  |                     addToSeries(series, dt, aprs->m_gust, minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 3 && aprs->m_hasTemp) | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |                     addToSeries(series, dt, convertTemperature(aprs->m_temp), minValue, maxValue); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |                 else if (plotSelectIdx == 4 && aprs->m_hasHumidity) | 
					
						
							|  |  |  |                     addToSeries(series, dt, aprs->m_humidity, minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 5 && aprs->m_hasBarometricPressure) | 
					
						
							|  |  |  |                     addToSeries(series, dt, aprs->m_barometricPressure/10.0, minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 6 && aprs->m_hasRainLastHr) | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |                     addToSeries(series, dt, convertRainfall(aprs->m_rainLastHr), minValue, maxValue); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |                 else if (plotSelectIdx == 7 && aprs->m_hasRainLast24Hrs) | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |                     addToSeries(series, dt, convertRainfall(aprs->m_rainLast24Hrs), minValue, maxValue); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |                 else if (plotSelectIdx == 8 && aprs->m_hasRainSinceMidnight) | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |                     addToSeries(series, dt, convertRainfall(aprs->m_rainSinceMidnight), minValue, maxValue); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |                 else if (plotSelectIdx == 9 && aprs->m_hasLuminsoity) | 
					
						
							|  |  |  |                     addToSeries(series, dt, aprs->m_luminosity, minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 10 && aprs->m_hasSnowfallLast24Hrs) | 
					
						
							|  |  |  |                     addToSeries(series, dt, aprs->m_snowfallLast24Hrs, minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 11 && aprs->m_hasRadiationLevel) | 
					
						
							|  |  |  |                     addToSeries(series, dt, aprs->m_radiationLevel, minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 12 && aprs->m_hasFloodLevel) | 
					
						
							|  |  |  |                     addToSeries(series, dt, aprs->m_floodLevel, minValue, maxValue); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     m_weatherChart.removeAllSeries(); | 
					
						
							|  |  |  |     m_weatherChart.removeAxis(&m_weatherChartXAxis); | 
					
						
							|  |  |  |     m_weatherChart.removeAxis(&m_weatherChartYAxis); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_weatherChart.addSeries(series); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     calcTimeAxis(timeSelectIdx, &m_weatherChartXAxis, series, ui->weatherChart->width()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_weatherChart.addAxis(&m_weatherChartXAxis, Qt::AlignBottom); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     series->attachAxis(&m_weatherChartXAxis); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_weatherChartYAxis.setTitleText(ui->weatherPlotSelect->currentText()); | 
					
						
							|  |  |  |     calcYAxis(minValue, maxValue, &m_weatherChartYAxis); | 
					
						
							|  |  |  |     m_weatherChart.addAxis(&m_weatherChartYAxis, Qt::AlignLeft); | 
					
						
							|  |  |  |     series->attachAxis(&m_weatherChartYAxis); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::on_weatherTimeSelect_currentIndexChanged(int index) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-13 23:03:55 +00:00
										 |  |  |     (void) index; | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     plotWeather(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::on_weatherPlotSelect_currentIndexChanged(int index) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-13 23:03:55 +00:00
										 |  |  |     (void) index; | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     plotWeather(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::calcTimeAxis(int timeSelectIdx, QDateTimeAxis *axis, QLineSeries *series, int width) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDateTime startX = QDateTime::currentDateTime(); | 
					
						
							|  |  |  |     QDateTime finishX = QDateTime::currentDateTime(); | 
					
						
							|  |  |  |     finishX.setTime(QTime(0,0,0)); | 
					
						
							|  |  |  |     finishX = finishX.addDays(1); | 
					
						
							|  |  |  |     int ticksScale = width < 650 ? 1 : 2; // FIXME: Should probably measure the width of some actual text
 | 
					
						
							|  |  |  |     switch (timeSelectIdx) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case 0: // Today
 | 
					
						
							|  |  |  |         startX.setTime(QTime(0,0,0)); | 
					
						
							|  |  |  |         axis->setTickCount(6*ticksScale+1); | 
					
						
							|  |  |  |         axis->setFormat("hh:mm"); | 
					
						
							|  |  |  |         axis->setTitleText(QString("Time (%1)").arg(startX.date().toString())); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 1: // Last hour
 | 
					
						
							|  |  |  |         startX.setTime(startX.time().addSecs(-60*60)); | 
					
						
							|  |  |  |         finishX = QDateTime::currentDateTime(); | 
					
						
							|  |  |  |         ticksScale = width < 750 ? 1 : 2; | 
					
						
							|  |  |  |         axis->setTickCount(8*ticksScale+1); | 
					
						
							|  |  |  |         axis->setFormat("hh:mm"); | 
					
						
							|  |  |  |         axis->setTitleText(QString("Time (%1)").arg(startX.date().toString())); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 2: // Last 24h
 | 
					
						
							|  |  |  |         startX.setDate(startX.date().addDays(-1)); | 
					
						
							|  |  |  |         finishX = QDateTime::currentDateTime(); | 
					
						
							|  |  |  |         axis->setTickCount(6*ticksScale+1); | 
					
						
							|  |  |  |         axis->setFormat("hh:mm"); | 
					
						
							|  |  |  |         axis->setTitleText(QString("Time (%1)").arg(startX.date().toString())); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 3: // Last 7 days
 | 
					
						
							|  |  |  |         startX.setTime(QTime(0,0,0)); | 
					
						
							|  |  |  |         startX.setDate(finishX.date().addDays(-7)); | 
					
						
							|  |  |  |         axis->setTickCount(4*ticksScale); | 
					
						
							|  |  |  |         axis->setFormat("MMM d"); | 
					
						
							|  |  |  |         axis->setTitleText("Date"); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 4: // Last 30 days
 | 
					
						
							|  |  |  |         startX.setTime(QTime(0,0,0)); | 
					
						
							|  |  |  |         startX.setDate(finishX.date().addDays(-30)); | 
					
						
							|  |  |  |         axis->setTickCount(5*ticksScale+1); | 
					
						
							|  |  |  |         axis->setFormat("MMM d"); | 
					
						
							|  |  |  |         axis->setTitleText("Date"); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 5: // All
 | 
					
						
							|  |  |  |         startX = QDateTime::fromMSecsSinceEpoch(series->at(0).x()); | 
					
						
							|  |  |  |         finishX = QDateTime::fromMSecsSinceEpoch(series->at(series->count()-1).x()); | 
					
						
							|  |  |  |         // FIXME: Problem when startX == finishX - axis not drawn
 | 
					
						
							|  |  |  |         if (startX.msecsTo(finishX) > 1000*60*60*24) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             axis->setFormat("MMM d"); | 
					
						
							|  |  |  |             axis->setTitleText("Date"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (startX.msecsTo(finishX) > 1000*60*60) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             axis->setFormat("hh:mm"); | 
					
						
							|  |  |  |             axis->setTitleText(QString("Time (hours on %1)").arg(startX.date().toString())); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             axis->setFormat("mm:ss"); | 
					
						
							|  |  |  |             axis->setTitleText(QString("Time (minutes on %1)").arg(startX.date().toString())); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         axis->setTickCount(5*ticksScale); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     axis->setRange(startX, finishX); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::calcYAxis(double minValue, double maxValue, QValueAxis *axis, bool binary, int precision) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     double range = std::abs(maxValue - minValue); | 
					
						
							|  |  |  |     double ticks = binary ? 2 : 5; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     axis->setTickCount(ticks); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (binary) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         minValue = 0.0; | 
					
						
							|  |  |  |         maxValue = 1.0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (range == 0.0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // Nothing is plotted if min and max are the same, so adjust range to non-zero
 | 
					
						
							|  |  |  |         if (precision == 1) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if ((minValue >= (ticks-1)/2) || (minValue < 0.0)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 maxValue += (ticks-1)/2; | 
					
						
							|  |  |  |                 minValue -= (ticks-1)/2; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 maxValue = maxValue + (ticks - 1 - minValue); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (maxValue == 0.0) | 
					
						
							|  |  |  |             maxValue = ticks-1; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             minValue -= minValue * (1.0/std::pow(10.0,precision)); | 
					
						
							|  |  |  |             maxValue += maxValue * (1.0/std::pow(10.0,precision)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         range = std::abs(maxValue - minValue); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     axis->setRange(minValue, maxValue); | 
					
						
							|  |  |  |     if (((range < (ticks-1)) || (precision > 1)) && !binary) | 
					
						
							|  |  |  |         axis->setLabelFormat(QString("%.%1f").arg(precision)); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         axis->setLabelFormat("%d"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QDateTime APRSGUI::calcTimeLimit(int timeSelectIdx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDateTime limit = QDateTime::currentDateTime(); | 
					
						
							|  |  |  |     switch (timeSelectIdx) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case 0: // Today
 | 
					
						
							|  |  |  |         limit.setTime(QTime(0,0,0)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 1: // Last hour
 | 
					
						
							|  |  |  |         limit.setTime(limit.time().addSecs(-60*60)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 2: // Last 24h
 | 
					
						
							|  |  |  |         limit.setDate(limit.date().addDays(-1)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 3: // Last 7 days
 | 
					
						
							|  |  |  |         limit.setTime(QTime(0,0,0)); | 
					
						
							|  |  |  |         limit.setDate(limit.date().addDays(-7)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 4: // Last 30 days
 | 
					
						
							|  |  |  |         limit.setTime(QTime(0,0,0)); | 
					
						
							|  |  |  |         limit.setDate(limit.date().addDays(-30)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 5: // All
 | 
					
						
							|  |  |  |         limit = QDateTime(QDate(1970, 1, 1), QTime()); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return limit; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::plotMotion() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString stationCallsign = ui->stationSelect->currentText(); | 
					
						
							|  |  |  |     if (stationCallsign.isEmpty()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     APRSStation *station = m_stations.value(stationCallsign); | 
					
						
							|  |  |  |     if (station == nullptr) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QLineSeries *series = new QLineSeries(); | 
					
						
							|  |  |  |     double minValue = INFINITY; | 
					
						
							|  |  |  |     double maxValue = -INFINITY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int timeSelectIdx = ui->motionTimeSelect->currentIndex(); | 
					
						
							|  |  |  |     int plotSelectIdx = ui->motionPlotSelect->currentIndex(); | 
					
						
							|  |  |  |     QDateTime limit = calcTimeLimit(timeSelectIdx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QListIterator<APRSPacket *> i(station->m_packets); | 
					
						
							|  |  |  |     while (i.hasNext()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         APRSPacket *aprs = i.next(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (aprs->m_hasPosition || aprs->m_hasAltitude || aprs->m_hasCourseAndSpeed) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             QDateTime dt; | 
					
						
							|  |  |  |             if (aprs->m_hasTimestamp) | 
					
						
							|  |  |  |                 dt = aprs->m_timestamp; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 dt = aprs->m_dateTime; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (dt >= limit) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 if (plotSelectIdx == 0 && aprs->m_hasPosition) | 
					
						
							|  |  |  |                     addToSeries(series, dt, aprs->m_latitude, minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 1 && aprs->m_hasPosition) | 
					
						
							|  |  |  |                     addToSeries(series, dt, aprs->m_longitude, minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 2 && aprs->m_hasAltitude) | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |                     addToSeries(series, dt, convertAltitude(aprs->m_altitudeFt), minValue, maxValue); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |                 else if (plotSelectIdx == 3 && aprs->m_hasCourseAndSpeed) | 
					
						
							|  |  |  |                     addToSeries(series, dt, aprs->m_course, minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 4 && aprs->m_hasCourseAndSpeed) | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |                     addToSeries(series, dt, convertSpeed(aprs->m_speed), minValue, maxValue); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_motionChart.removeAllSeries(); | 
					
						
							|  |  |  |     m_motionChart.removeAxis(&m_motionChartXAxis); | 
					
						
							|  |  |  |     m_motionChart.removeAxis(&m_motionChartYAxis); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_motionChart.addSeries(series); | 
					
						
							|  |  |  |     calcTimeAxis(timeSelectIdx, &m_motionChartXAxis, series, ui->motionChart->width()); | 
					
						
							|  |  |  |     m_motionChart.addAxis(&m_motionChartXAxis, Qt::AlignBottom); | 
					
						
							|  |  |  |     series->attachAxis(&m_motionChartXAxis); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_motionChartYAxis.setTitleText(ui->motionPlotSelect->currentText()); | 
					
						
							|  |  |  |     calcYAxis(minValue, maxValue, &m_motionChartYAxis, false, plotSelectIdx <= 1 ? 5 : 1); | 
					
						
							|  |  |  |     m_motionChart.addAxis(&m_motionChartYAxis, Qt::AlignLeft); | 
					
						
							|  |  |  |     series->attachAxis(&m_motionChartYAxis); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::on_motionTimeSelect_currentIndexChanged(int index) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-13 23:03:55 +00:00
										 |  |  |     (void) index; | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     plotMotion(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::on_motionPlotSelect_currentIndexChanged(int index) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-13 23:03:55 +00:00
										 |  |  |     (void) index; | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     plotMotion(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::plotTelemetry() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString stationCallsign = ui->stationSelect->currentText(); | 
					
						
							|  |  |  |     if (stationCallsign.isEmpty()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     APRSStation *station = m_stations.value(stationCallsign); | 
					
						
							|  |  |  |     if (station == nullptr) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QLineSeries *series = new QLineSeries(); | 
					
						
							|  |  |  |     double minValue = INFINITY; | 
					
						
							|  |  |  |     double maxValue = -INFINITY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int timeSelectIdx = ui->telemetryTimeSelect->currentIndex(); | 
					
						
							|  |  |  |     int plotSelectIdx = ui->telemetryPlotSelect->currentIndex(); | 
					
						
							|  |  |  |     QDateTime limit = calcTimeLimit(timeSelectIdx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QListIterator<APRSPacket *> i(station->m_packets); | 
					
						
							|  |  |  |     while (i.hasNext()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         APRSPacket *aprs = i.next(); | 
					
						
							|  |  |  |         if (aprs->m_hasTelemetry) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (aprs->m_dateTime >= limit) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 if (plotSelectIdx == 0 && aprs->m_a1HasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, applyCoefficients(0, aprs->m_a1, station), minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 1 && aprs->m_a2HasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, applyCoefficients(1, aprs->m_a2, station), minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 2 && aprs->m_a3HasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, applyCoefficients(2, aprs->m_a3, station), minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 3 && aprs->m_a4HasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, applyCoefficients(3, aprs->m_a4, station), minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 4 && aprs->m_a5HasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, applyCoefficients(4, aprs->m_a5, station), minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 5 && aprs->m_bHasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, aprs->m_b[0], minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 6 && aprs->m_bHasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, aprs->m_b[1], minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 7 && aprs->m_bHasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, aprs->m_b[2], minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 8 && aprs->m_bHasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, aprs->m_b[3], minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 9 && aprs->m_bHasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, aprs->m_b[4], minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 10 && aprs->m_bHasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, aprs->m_b[5], minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 11 && aprs->m_bHasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, aprs->m_b[6], minValue, maxValue); | 
					
						
							|  |  |  |                 else if (plotSelectIdx == 12 && aprs->m_bHasValue) | 
					
						
							|  |  |  |                     addToSeries(series, aprs->m_dateTime, aprs->m_b[7], minValue, maxValue); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_telemetryChart.removeAllSeries(); | 
					
						
							|  |  |  |     m_telemetryChart.removeAxis(&m_telemetryChartXAxis); | 
					
						
							|  |  |  |     m_telemetryChart.removeAxis(&m_telemetryChartYAxis); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_telemetryChart.addSeries(series); | 
					
						
							|  |  |  |     calcTimeAxis(timeSelectIdx, &m_telemetryChartXAxis, series, ui->telemetryChart->width()); | 
					
						
							|  |  |  |     m_telemetryChart.addAxis(&m_telemetryChartXAxis, Qt::AlignBottom); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     series->attachAxis(&m_telemetryChartXAxis); | 
					
						
							|  |  |  |     m_telemetryChartYAxis.setTitleText(ui->telemetryPlotSelect->currentText()); | 
					
						
							|  |  |  |     calcYAxis(minValue, maxValue, &m_telemetryChartYAxis, plotSelectIdx >= 5); | 
					
						
							|  |  |  |     m_telemetryChart.addAxis(&m_telemetryChartYAxis, Qt::AlignLeft); | 
					
						
							|  |  |  |     series->attachAxis(&m_telemetryChartYAxis); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::on_telemetryTimeSelect_currentIndexChanged(int index) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-13 23:03:55 +00:00
										 |  |  |     (void) index; | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     plotTelemetry(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::on_telemetryPlotSelect_currentIndexChanged(int index) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-13 23:03:55 +00:00
										 |  |  |     (void) index; | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     plotTelemetry(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::updateStatus() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int state = m_aprs->getState(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_lastFeatureState != state) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch (state) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             case Feature::StNotStarted: | 
					
						
							|  |  |  |                 ui->igate->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case Feature::StIdle: | 
					
						
							|  |  |  |                 ui->igate->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case Feature::StRunning: | 
					
						
							|  |  |  |                 ui->igate->setStyleSheet("QToolButton { background-color : green; }"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case Feature::StError: | 
					
						
							|  |  |  |                 ui->igate->setStyleSheet("QToolButton { background-color : red; }"); | 
					
						
							|  |  |  |                 QMessageBox::information(this, tr("Message"), m_aprs->getErrorMessage()); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         m_lastFeatureState = state; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::applySettings(bool force) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_doApplySettings) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         APRS::MsgConfigureAPRS* message = APRS::MsgConfigureAPRS::create(m_settings, force); | 
					
						
							|  |  |  |         m_aprs->getInputMessageQueue()->push(message); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::resizeTable() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int row; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Fill tables with a row of dummy data that will size the columns nicely
 | 
					
						
							|  |  |  |     row = ui->packetsTable->rowCount(); | 
					
						
							|  |  |  |     ui->packetsTable->setRowCount(row + 1); | 
					
						
							|  |  |  |     ui->packetsTable->setItem(row, PACKETS_COL_DATE, new QTableWidgetItem("31/12/2020")); | 
					
						
							|  |  |  |     ui->packetsTable->setItem(row, PACKETS_COL_TIME, new QTableWidgetItem("23:59:39 T")); | 
					
						
							|  |  |  |     ui->packetsTable->setItem(row, PACKETS_COL_FROM, new QTableWidgetItem("123456-15-")); | 
					
						
							|  |  |  |     ui->packetsTable->setItem(row, PACKETS_COL_TO, new QTableWidgetItem("123456-15-")); | 
					
						
							|  |  |  |     ui->packetsTable->setItem(row, PACKETS_COL_VIA, new QTableWidgetItem("123456-15-")); | 
					
						
							|  |  |  |     ui->packetsTable->setItem(row, PACKETS_COL_DATA, new QTableWidgetItem("ABCEDGHIJKLMNOPQRSTUVWXYZABCEDGHIJKLMNOPQRSTUVWXYZABCEDGHIJKLMNOPQRSTUVWXYZ")); | 
					
						
							|  |  |  |     ui->packetsTable->resizeColumnsToContents(); | 
					
						
							|  |  |  |     ui->packetsTable->removeRow(row); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     row = ui->weatherTable->rowCount(); | 
					
						
							|  |  |  |     ui->weatherTable->setRowCount(row + 1); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_DATE, new QTableWidgetItem("31/12/2020")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_TIME, new QTableWidgetItem("23:59:39 T")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_WIND_DIRECTION, new QTableWidgetItem("Dir (o)-")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_WIND_SPEED, new QTableWidgetItem("Speed (mph)-")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_GUSTS, new QTableWidgetItem("Gusts (mph)-")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_TEMPERATURE, new QTableWidgetItem("Temp (F)-")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_HUMIDITY, new QTableWidgetItem("Humidity (%)-")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_PRESSURE, new QTableWidgetItem("Pressure (mbar)-")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_RAIN_LAST_HOUR, new QTableWidgetItem("Rain 1h-")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_RAIN_LAST_24_HOURS, new QTableWidgetItem("Rain 24h-")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_RAIN_SINCE_MIDNIGHT, new QTableWidgetItem("Rain-")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_LUMINOSITY, new QTableWidgetItem("Luminosity-")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_SNOWFALL, new QTableWidgetItem("Snowfall-")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_RADIATION_LEVEL, new QTableWidgetItem("Radiation-")); | 
					
						
							|  |  |  |     ui->weatherTable->setItem(row, WEATHER_COL_FLOOD_LEVEL, new QTableWidgetItem("Flood level-")); | 
					
						
							|  |  |  |     ui->weatherTable->resizeColumnsToContents(); | 
					
						
							|  |  |  |     ui->weatherTable->removeRow(row); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     row = ui->statusTable->rowCount(); | 
					
						
							|  |  |  |     ui->statusTable->setRowCount(row + 1); | 
					
						
							|  |  |  |     ui->statusTable->setIconSize(QSize(24, 24)); | 
					
						
							|  |  |  |     ui->statusTable->setItem(row, STATUS_COL_DATE, new QTableWidgetItem("31/12/2020")); | 
					
						
							|  |  |  |     ui->statusTable->setItem(row, STATUS_COL_TIME, new QTableWidgetItem("23:59:39 T")); | 
					
						
							|  |  |  |     ui->statusTable->setItem(row, STATUS_COL_STATUS, new QTableWidgetItem("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); | 
					
						
							|  |  |  |     ui->statusTable->setItem(row, STATUS_COL_SYMBOL, new QTableWidgetItem("WWW")); | 
					
						
							|  |  |  |     ui->statusTable->setItem(row, STATUS_COL_MAIDENHEAD, new QTableWidgetItem("WW00WW")); | 
					
						
							|  |  |  |     ui->statusTable->setItem(row, STATUS_COL_BEAM_HEADING, new QTableWidgetItem("359")); | 
					
						
							|  |  |  |     ui->statusTable->setItem(row, STATUS_COL_BEAM_POWER, new QTableWidgetItem("8000")); | 
					
						
							|  |  |  |     ui->statusTable->resizeColumnsToContents(); | 
					
						
							|  |  |  |     ui->statusTable->removeRow(row); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     row = ui->messagesTable->rowCount(); | 
					
						
							|  |  |  |     ui->messagesTable->setRowCount(row + 1); | 
					
						
							|  |  |  |     ui->messagesTable->setIconSize(QSize(24, 24)); | 
					
						
							|  |  |  |     ui->messagesTable->setItem(row, MESSAGE_COL_DATE, new QTableWidgetItem("31/12/2020")); | 
					
						
							|  |  |  |     ui->messagesTable->setItem(row, MESSAGE_COL_TIME, new QTableWidgetItem("23:59:39 T")); | 
					
						
							|  |  |  |     ui->messagesTable->setItem(row, MESSAGE_COL_ADDRESSEE, new QTableWidgetItem("WWWWWWWWW")); | 
					
						
							|  |  |  |     ui->messagesTable->setItem(row, MESSAGE_COL_MESSAGE, new QTableWidgetItem("ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ")); | 
					
						
							|  |  |  |     ui->messagesTable->setItem(row, MESSAGE_COL_NO, new QTableWidgetItem("Message No")); | 
					
						
							|  |  |  |     ui->messagesTable->resizeColumnsToContents(); | 
					
						
							|  |  |  |     ui->messagesTable->removeRow(row); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     row = ui->motionTable->rowCount(); | 
					
						
							|  |  |  |     ui->motionTable->setRowCount(row + 1); | 
					
						
							|  |  |  |     ui->motionTable->setItem(row, MOTION_COL_DATE, new QTableWidgetItem("31/12/2020")); | 
					
						
							|  |  |  |     ui->motionTable->setItem(row, MOTION_COL_TIME, new QTableWidgetItem("23:59:39 T")); | 
					
						
							|  |  |  |     ui->motionTable->setItem(row, MOTION_COL_LATITUDE, new QTableWidgetItem("Latitude")); | 
					
						
							|  |  |  |     ui->motionTable->setItem(row, MOTION_COL_LONGITUDE, new QTableWidgetItem("Longitude")); | 
					
						
							|  |  |  |     ui->motionTable->setItem(row, MOTION_COL_ALTITUDE, new QTableWidgetItem("Message No")); | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |     ui->motionTable->setItem(row, MOTION_COL_COURSE, new QTableWidgetItem("Course")); | 
					
						
							|  |  |  |     ui->motionTable->setItem(row, MOTION_COL_SPEED, new QTableWidgetItem("Speed")); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     ui->motionTable->resizeColumnsToContents(); | 
					
						
							|  |  |  |     ui->motionTable->removeRow(row); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     row = ui->telemetryTable->rowCount(); | 
					
						
							|  |  |  |     ui->telemetryTable->setRowCount(row + 1); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_DATE, new QTableWidgetItem("31/12/2020")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_TIME, new QTableWidgetItem("23:59:39 T")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_SEQ_NO, new QTableWidgetItem("Seq No")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_A1, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_A2, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_A3, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_A4, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_A5, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_B1, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_B2, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_B3, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_B4, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_B5, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_B6, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_B7, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->setItem(row, TELEMETRY_COL_B8, new QTableWidgetItem("ABCEDF")); | 
					
						
							|  |  |  |     ui->telemetryTable->resizeColumnsToContents(); | 
					
						
							|  |  |  |     ui->telemetryTable->removeRow(row); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Columns in table reordered
 | 
					
						
							|  |  |  | void APRSGUI::packetsTable_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) oldVisualIndex; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings.m_packetsTableColumnIndexes[logicalIndex] = newVisualIndex; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Column in table resized (when hidden size is 0)
 | 
					
						
							|  |  |  | void APRSGUI::packetsTable_sectionResized(int logicalIndex, int oldSize, int newSize) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) oldSize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings.m_packetsTableColumnSizes[logicalIndex] = newSize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Right click in table header - show column select menu
 | 
					
						
							|  |  |  | void APRSGUI::packetsTable_columnSelectMenu(QPoint pos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     packetsTableMenu->popup(ui->packetsTable->horizontalHeader()->viewport()->mapToGlobal(pos)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Hide/show column when menu selected
 | 
					
						
							|  |  |  | void APRSGUI::packetsTable_columnSelectMenuChecked(bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) checked; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QAction* action = qobject_cast<QAction*>(sender()); | 
					
						
							|  |  |  |     if (action != nullptr) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int idx = action->data().toInt(nullptr); | 
					
						
							|  |  |  |         ui->packetsTable->setColumnHidden(idx, !action->isChecked()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Columns in table reordered
 | 
					
						
							|  |  |  | void APRSGUI::weatherTable_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) oldVisualIndex; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings.m_weatherTableColumnIndexes[logicalIndex] = newVisualIndex; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Column in table resized (when hidden size is 0)
 | 
					
						
							|  |  |  | void APRSGUI::weatherTable_sectionResized(int logicalIndex, int oldSize, int newSize) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) oldSize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings.m_weatherTableColumnSizes[logicalIndex] = newSize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Right click in table header - show column select menu
 | 
					
						
							|  |  |  | void APRSGUI::weatherTable_columnSelectMenu(QPoint pos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     weatherTableMenu->popup(ui->weatherTable->horizontalHeader()->viewport()->mapToGlobal(pos)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Hide/show column when menu selected
 | 
					
						
							|  |  |  | void APRSGUI::weatherTable_columnSelectMenuChecked(bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) checked; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QAction* action = qobject_cast<QAction*>(sender()); | 
					
						
							|  |  |  |     if (action != nullptr) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int idx = action->data().toInt(nullptr); | 
					
						
							|  |  |  |         ui->weatherTable->setColumnHidden(idx, !action->isChecked()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Columns in table reordered
 | 
					
						
							|  |  |  | void APRSGUI::statusTable_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) oldVisualIndex; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings.m_statusTableColumnIndexes[logicalIndex] = newVisualIndex; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Column in table resized (when hidden size is 0)
 | 
					
						
							|  |  |  | void APRSGUI::statusTable_sectionResized(int logicalIndex, int oldSize, int newSize) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) oldSize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings.m_statusTableColumnSizes[logicalIndex] = newSize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Right click in table header - show column select menu
 | 
					
						
							|  |  |  | void APRSGUI::statusTable_columnSelectMenu(QPoint pos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     statusTableMenu->popup(ui->statusTable->horizontalHeader()->viewport()->mapToGlobal(pos)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Hide/show column when menu selected
 | 
					
						
							|  |  |  | void APRSGUI::statusTable_columnSelectMenuChecked(bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) checked; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QAction* action = qobject_cast<QAction*>(sender()); | 
					
						
							|  |  |  |     if (action != nullptr) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int idx = action->data().toInt(nullptr); | 
					
						
							|  |  |  |         ui->statusTable->setColumnHidden(idx, !action->isChecked()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Columns in table reordered
 | 
					
						
							|  |  |  | void APRSGUI::messagesTable_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) oldVisualIndex; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings.m_messagesTableColumnIndexes[logicalIndex] = newVisualIndex; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Column in table resized (when hidden size is 0)
 | 
					
						
							|  |  |  | void APRSGUI::messagesTable_sectionResized(int logicalIndex, int oldSize, int newSize) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) oldSize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings.m_messagesTableColumnSizes[logicalIndex] = newSize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Right click in table header - show column select menu
 | 
					
						
							|  |  |  | void APRSGUI::messagesTable_columnSelectMenu(QPoint pos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     messagesTableMenu->popup(ui->messagesTable->horizontalHeader()->viewport()->mapToGlobal(pos)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Hide/show column when menu selected
 | 
					
						
							|  |  |  | void APRSGUI::messagesTable_columnSelectMenuChecked(bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) checked; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QAction* action = qobject_cast<QAction*>(sender()); | 
					
						
							|  |  |  |     if (action != nullptr) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int idx = action->data().toInt(nullptr); | 
					
						
							|  |  |  |         ui->messagesTable->setColumnHidden(idx, !action->isChecked()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Columns in table reordered
 | 
					
						
							|  |  |  | void APRSGUI::telemetryTable_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) oldVisualIndex; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings.m_telemetryTableColumnIndexes[logicalIndex] = newVisualIndex; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Column in table resized (when hidden size is 0)
 | 
					
						
							|  |  |  | void APRSGUI::telemetryTable_sectionResized(int logicalIndex, int oldSize, int newSize) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) oldSize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings.m_telemetryTableColumnSizes[logicalIndex] = newSize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Right click in table header - show column select menu
 | 
					
						
							|  |  |  | void APRSGUI::telemetryTable_columnSelectMenu(QPoint pos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     telemetryTableMenu->popup(ui->telemetryTable->horizontalHeader()->viewport()->mapToGlobal(pos)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Hide/show column when menu selected
 | 
					
						
							|  |  |  | void APRSGUI::telemetryTable_columnSelectMenuChecked(bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) checked; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QAction* action = qobject_cast<QAction*>(sender()); | 
					
						
							|  |  |  |     if (action != nullptr) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int idx = action->data().toInt(nullptr); | 
					
						
							|  |  |  |         ui->telemetryTable->setColumnHidden(idx, !action->isChecked()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Columns in table reordered
 | 
					
						
							|  |  |  | void APRSGUI::motionTable_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) oldVisualIndex; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings.m_motionTableColumnIndexes[logicalIndex] = newVisualIndex; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Column in table resized (when hidden size is 0)
 | 
					
						
							|  |  |  | void APRSGUI::motionTable_sectionResized(int logicalIndex, int oldSize, int newSize) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) oldSize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings.m_motionTableColumnSizes[logicalIndex] = newSize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Right click in table header - show column select menu
 | 
					
						
							|  |  |  | void APRSGUI::motionTable_columnSelectMenu(QPoint pos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     motionTableMenu->popup(ui->motionTable->horizontalHeader()->viewport()->mapToGlobal(pos)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Hide/show column when menu selected
 | 
					
						
							|  |  |  | void APRSGUI::motionTable_columnSelectMenuChecked(bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) checked; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QAction* action = qobject_cast<QAction*>(sender()); | 
					
						
							|  |  |  |     if (action != nullptr) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int idx = action->data().toInt(nullptr); | 
					
						
							|  |  |  |         ui->motionTable->setColumnHidden(idx, !action->isChecked()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Create column select menu items
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QAction *APRSGUI::packetsTable_createCheckableItem(QString &text, int idx, bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QAction *action = new QAction(text, this); | 
					
						
							|  |  |  |     action->setCheckable(true); | 
					
						
							|  |  |  |     action->setChecked(checked); | 
					
						
							|  |  |  |     action->setData(QVariant(idx)); | 
					
						
							|  |  |  |     connect(action, SIGNAL(triggered()), this, SLOT(packetsTable_columnSelectMenuChecked())); | 
					
						
							|  |  |  |     return action; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QAction *APRSGUI::weatherTable_createCheckableItem(QString &text, int idx, bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QAction *action = new QAction(text, this); | 
					
						
							|  |  |  |     action->setCheckable(true); | 
					
						
							|  |  |  |     action->setChecked(checked); | 
					
						
							|  |  |  |     action->setData(QVariant(idx)); | 
					
						
							|  |  |  |     connect(action, SIGNAL(triggered()), this, SLOT(weatherTable_columnSelectMenuChecked())); | 
					
						
							|  |  |  |     return action; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QAction *APRSGUI::statusTable_createCheckableItem(QString &text, int idx, bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QAction *action = new QAction(text, this); | 
					
						
							|  |  |  |     action->setCheckable(true); | 
					
						
							|  |  |  |     action->setChecked(checked); | 
					
						
							|  |  |  |     action->setData(QVariant(idx)); | 
					
						
							|  |  |  |     connect(action, SIGNAL(triggered()), this, SLOT(statusTable_columnSelectMenuChecked())); | 
					
						
							|  |  |  |     return action; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QAction *APRSGUI::messagesTable_createCheckableItem(QString &text, int idx, bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QAction *action = new QAction(text, this); | 
					
						
							|  |  |  |     action->setCheckable(true); | 
					
						
							|  |  |  |     action->setChecked(checked); | 
					
						
							|  |  |  |     action->setData(QVariant(idx)); | 
					
						
							|  |  |  |     connect(action, SIGNAL(triggered()), this, SLOT(messagesTable_columnSelectMenuChecked())); | 
					
						
							|  |  |  |     return action; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QAction *APRSGUI::telemetryTable_createCheckableItem(QString &text, int idx, bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QAction *action = new QAction(text, this); | 
					
						
							|  |  |  |     action->setCheckable(true); | 
					
						
							|  |  |  |     action->setChecked(checked); | 
					
						
							|  |  |  |     action->setData(QVariant(idx)); | 
					
						
							|  |  |  |     connect(action, SIGNAL(triggered()), this, SLOT(telemetryTable_columnSelectMenuChecked())); | 
					
						
							|  |  |  |     return action; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QAction *APRSGUI::motionTable_createCheckableItem(QString &text, int idx, bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QAction *action = new QAction(text, this); | 
					
						
							|  |  |  |     action->setCheckable(true); | 
					
						
							|  |  |  |     action->setChecked(checked); | 
					
						
							|  |  |  |     action->setData(QVariant(idx)); | 
					
						
							|  |  |  |     connect(action, SIGNAL(triggered()), this, SLOT(motionTable_columnSelectMenuChecked())); | 
					
						
							|  |  |  |     return action; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  | void APRSGUI::setUnits() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ui->altitudeUnitsLabel->setText(APRSSettings::m_altitudeUnitNames[m_settings.m_altitudeUnits]); | 
					
						
							|  |  |  |     ui->antennaHeightUnitsLabel->setText(APRSSettings::m_altitudeUnitNames[m_settings.m_altitudeUnits]); | 
					
						
							|  |  |  |     ui->speedUnitsLabel->setText(APRSSettings::m_speedUnitNames[m_settings.m_speedUnits]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ui->weatherTable->horizontalHeaderItem(WEATHER_COL_TEMPERATURE)->setText(QString("Temp (%1)").arg(APRSSettings::m_temperatureUnitNames[m_settings.m_temperatureUnits])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Display data using new units
 | 
					
						
							|  |  |  |     int idx = ui->stationSelect->currentIndex(); | 
					
						
							|  |  |  |     if (idx >= 0) | 
					
						
							|  |  |  |         on_stationSelect_currentIndexChanged(idx); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString APRSGUI::convertAltitude(const QString& altitude) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if ((m_settings.m_altitudeUnits == APRSSettings::FEET) || altitude.isEmpty()) | 
					
						
							|  |  |  |         return altitude; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return QString::number((int)std::round(Units::feetToMetres(altitude.toFloat()))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float APRSGUI::convertAltitude(float altitude) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_settings.m_altitudeUnits == APRSSettings::FEET) | 
					
						
							|  |  |  |         return altitude; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return std::round(Units::feetToMetres(altitude)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString APRSGUI::convertSpeed(const QString& speed) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if ((m_settings.m_speedUnits == APRSSettings::KNOTS) || speed.isEmpty()) | 
					
						
							|  |  |  |         return speed; | 
					
						
							|  |  |  |     else if (m_settings.m_speedUnits == APRSSettings::MPH) | 
					
						
							|  |  |  |         return QString::number(Units::knotsToIntegerMPH(speed.toFloat())); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return QString::number(Units::knotsToIntegerKPH(speed.toFloat())); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int APRSGUI::convertSpeed(int speed) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_settings.m_speedUnits == APRSSettings::KNOTS) | 
					
						
							|  |  |  |         return speed; | 
					
						
							|  |  |  |     else if (m_settings.m_speedUnits == APRSSettings::MPH) | 
					
						
							|  |  |  |         return Units::knotsToIntegerMPH(speed); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return Units::knotsToIntegerKPH(speed); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int APRSGUI::convertTemperature(int temperature) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_settings.m_temperatureUnits == APRSSettings::FAHRENHEIT) | 
					
						
							|  |  |  |         return temperature; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return (int)std::round(Units::fahrenheitToCelsius(temperature)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int APRSGUI::convertRainfall(int rainfall) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_settings.m_rainfallUnits == APRSSettings::HUNDREDTHS_OF_AN_INCH) | 
					
						
							|  |  |  |         return rainfall; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return (int)std::round(Units::inchesToMilimetres(rainfall/100.0f)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  | // Show settings dialog
 | 
					
						
							|  |  |  | void APRSGUI::on_displaySettings_clicked() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |     APRSSettingsDialog dialog(&m_settings); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |     if (dialog.exec() == QDialog::Accepted) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-04-02 21:14:49 +01:00
										 |  |  |         setUnits(); | 
					
						
							| 
									
										
										
										
											2021-01-13 20:37:09 +00:00
										 |  |  |         applySettings(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::on_igate_toggled(bool checked) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_settings.m_igateEnabled = checked; | 
					
						
							|  |  |  |     applySettings(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Find the selected station on the Map
 | 
					
						
							|  |  |  | void APRSGUI::on_viewOnMap_clicked() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString stationName = ui->stationSelect->currentText(); | 
					
						
							|  |  |  |     if (!stationName.isEmpty()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         APRSStation *station = m_stations.value(stationName); | 
					
						
							|  |  |  |         if (station != nullptr) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             FeatureWebAPIUtils::mapFind(station->m_station); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-04-04 10:23:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | void APRSGUI::makeUIConnections() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QObject::connect(ui->stationFilter, qOverload<int>(&QComboBox::currentIndexChanged), this, &APRSGUI::on_stationFilter_currentIndexChanged); | 
					
						
							|  |  |  |     QObject::connect(ui->stationSelect, qOverload<int>(&QComboBox::currentIndexChanged), this, &APRSGUI::on_stationSelect_currentIndexChanged); | 
					
						
							|  |  |  |     QObject::connect(ui->filterAddressee, &QLineEdit::editingFinished, this, &APRSGUI::on_filterAddressee_editingFinished); | 
					
						
							|  |  |  |     QObject::connect(ui->deleteMessages, &QPushButton::clicked, this, &APRSGUI::on_deleteMessages_clicked); | 
					
						
							|  |  |  |     QObject::connect(ui->weatherTimeSelect, qOverload<int>(&QComboBox::currentIndexChanged), this, &APRSGUI::on_weatherTimeSelect_currentIndexChanged); | 
					
						
							|  |  |  |     QObject::connect(ui->weatherPlotSelect, qOverload<int>(&QComboBox::currentIndexChanged), this, &APRSGUI::on_weatherPlotSelect_currentIndexChanged); | 
					
						
							|  |  |  |     QObject::connect(ui->telemetryTimeSelect, qOverload<int>(&QComboBox::currentIndexChanged), this, &APRSGUI::on_telemetryTimeSelect_currentIndexChanged); | 
					
						
							|  |  |  |     QObject::connect(ui->telemetryPlotSelect, qOverload<int>(&QComboBox::currentIndexChanged), this, &APRSGUI::on_telemetryPlotSelect_currentIndexChanged); | 
					
						
							|  |  |  |     QObject::connect(ui->motionTimeSelect, qOverload<int>(&QComboBox::currentIndexChanged), this, &APRSGUI::on_motionTimeSelect_currentIndexChanged); | 
					
						
							|  |  |  |     QObject::connect(ui->motionPlotSelect, qOverload<int>(&QComboBox::currentIndexChanged), this, &APRSGUI::on_motionPlotSelect_currentIndexChanged); | 
					
						
							|  |  |  |     QObject::connect(ui->displaySettings, &QPushButton::clicked, this, &APRSGUI::on_displaySettings_clicked); | 
					
						
							|  |  |  |     QObject::connect(ui->igate, &ButtonSwitch::toggled, this, &APRSGUI::on_igate_toggled); | 
					
						
							|  |  |  |     QObject::connect(ui->viewOnMap, &QPushButton::clicked, this, &APRSGUI::on_viewOnMap_clicked); | 
					
						
							|  |  |  | } |