kopia lustrzana https://github.com/f4exb/sdrangel
815 wiersze
28 KiB
C++
815 wiersze
28 KiB
C++
///////////////////////////////////////////////////////////////////////////////////
|
||
// Copyright (C) 2020 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 <QMessageBox>
|
||
#include <QSerialPortInfo>
|
||
|
||
#include "SWGTargetAzimuthElevation.h"
|
||
|
||
#include "feature/featureuiset.h"
|
||
#include "gui/basicfeaturesettingsdialog.h"
|
||
#include "gui/dialogpositioner.h"
|
||
#include "mainwindow.h"
|
||
#include "device/deviceuiset.h"
|
||
#include "util/astronomy.h"
|
||
|
||
#include "ui_gs232controllergui.h"
|
||
#include "gs232controller.h"
|
||
#include "gs232controllergui.h"
|
||
#include "gs232controllerreport.h"
|
||
#include "dfmprotocol.h"
|
||
|
||
GS232ControllerGUI* GS232ControllerGUI::create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature)
|
||
{
|
||
GS232ControllerGUI* gui = new GS232ControllerGUI(pluginAPI, featureUISet, feature);
|
||
return gui;
|
||
}
|
||
|
||
void GS232ControllerGUI::destroy()
|
||
{
|
||
delete this;
|
||
}
|
||
|
||
void GS232ControllerGUI::resetToDefaults()
|
||
{
|
||
m_settings.resetToDefaults();
|
||
displaySettings();
|
||
applySettings(true);
|
||
}
|
||
|
||
QByteArray GS232ControllerGUI::serialize() const
|
||
{
|
||
return m_settings.serialize();
|
||
}
|
||
|
||
bool GS232ControllerGUI::deserialize(const QByteArray& data)
|
||
{
|
||
if (m_settings.deserialize(data))
|
||
{
|
||
m_feature->setWorkspaceIndex(m_settings.m_workspaceIndex);
|
||
displaySettings();
|
||
applySettings(true);
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
resetToDefaults();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
void GS232ControllerGUI::azElToDisplay(float az, float el, float& coord1, float& coord2) const
|
||
{
|
||
AzAlt aa;
|
||
double c1, c2;
|
||
if (m_settings.m_coordinates == GS232ControllerSettings::X_Y_85)
|
||
{
|
||
aa.az = az;
|
||
aa.alt = el;
|
||
Astronomy::azAltToXY85(aa, c1, c2);
|
||
coord1 = (float)c1;
|
||
coord2 = (float)c2;
|
||
}
|
||
else if (m_settings.m_coordinates == GS232ControllerSettings::X_Y_30)
|
||
{
|
||
aa.az = az;
|
||
aa.alt = el;
|
||
Astronomy::azAltToXY30(aa, c1, c2);
|
||
coord1 = (float)c1;
|
||
coord2 = (float)c2;
|
||
}
|
||
else
|
||
{
|
||
coord1 = az;
|
||
coord2 = el;
|
||
}
|
||
}
|
||
|
||
void GS232ControllerGUI::displayToAzEl(float coord1, float coord2)
|
||
{
|
||
if (m_settings.m_coordinates == GS232ControllerSettings::X_Y_85)
|
||
{
|
||
AzAlt aa = Astronomy::xy85ToAzAlt(coord1, coord2);
|
||
m_settings.m_azimuth = aa.az;
|
||
m_settings.m_elevation = aa.alt;
|
||
}
|
||
else if (m_settings.m_coordinates == GS232ControllerSettings::X_Y_30)
|
||
{
|
||
AzAlt aa = Astronomy::xy30ToAzAlt(coord1, coord2);
|
||
m_settings.m_azimuth = aa.az;
|
||
m_settings.m_elevation = aa.alt;
|
||
}
|
||
else
|
||
{
|
||
m_settings.m_azimuth = coord1;
|
||
m_settings.m_elevation = coord2;
|
||
}
|
||
m_settingsKeys.append("azimuth");
|
||
m_settingsKeys.append("elevation");
|
||
applySettings();
|
||
}
|
||
|
||
bool GS232ControllerGUI::handleMessage(const Message& message)
|
||
{
|
||
if (GS232Controller::MsgConfigureGS232Controller::match(message))
|
||
{
|
||
qDebug("GS232ControllerGUI::handleMessage: GS232Controller::MsgConfigureGS232Controller");
|
||
const GS232Controller::MsgConfigureGS232Controller& cfg = (GS232Controller::MsgConfigureGS232Controller&) message;
|
||
|
||
if (cfg.getForce()) {
|
||
m_settings = cfg.getSettings();
|
||
} else {
|
||
m_settings.applySettings(cfg.getSettingsKeys(), cfg.getSettings());
|
||
}
|
||
|
||
blockApplySettings(true);
|
||
displaySettings();
|
||
blockApplySettings(false);
|
||
|
||
return true;
|
||
}
|
||
else if (GS232Controller::MsgReportAvailableChannelOrFeatures::match(message))
|
||
{
|
||
GS232Controller::MsgReportAvailableChannelOrFeatures& report =
|
||
(GS232Controller::MsgReportAvailableChannelOrFeatures&) message;
|
||
updatePipeList(report.getItems());
|
||
return true;
|
||
}
|
||
else if (GS232ControllerReport::MsgReportAzAl::match(message))
|
||
{
|
||
GS232ControllerReport::MsgReportAzAl& azAl = (GS232ControllerReport::MsgReportAzAl&) message;
|
||
float coord1, coord2;
|
||
azElToDisplay(azAl.getAzimuth(), azAl.getElevation(), coord1, coord2);
|
||
ui->coord1CurrentText->setText(QString::number(coord1, 'f', m_settings.m_precision));
|
||
ui->coord2CurrentText->setText(QString::number(coord2, 'f', m_settings.m_precision));
|
||
return true;
|
||
}
|
||
else if (MainCore::MsgTargetAzimuthElevation::match(message))
|
||
{
|
||
MainCore::MsgTargetAzimuthElevation& msg = (MainCore::MsgTargetAzimuthElevation&) message;
|
||
SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = msg.getSWGTargetAzimuthElevation();
|
||
float coord1, coord2;
|
||
azElToDisplay(swgTarget->getAzimuth(), swgTarget->getElevation(), coord1, coord2);
|
||
ui->coord1->setValue(coord1);
|
||
ui->coord2->setValue(coord2);
|
||
ui->targetName->setText(*swgTarget->getName());
|
||
return true;
|
||
}
|
||
else if (GS232Controller::MsgReportSerialPorts::match(message))
|
||
{
|
||
GS232Controller::MsgReportSerialPorts& msg = (GS232Controller::MsgReportSerialPorts&) message;
|
||
updateSerialPortList(msg.getSerialPorts());
|
||
return true;
|
||
}
|
||
else if (DFMProtocol::MsgReportDFMStatus::match(message))
|
||
{
|
||
DFMProtocol::MsgReportDFMStatus& report = (DFMProtocol::MsgReportDFMStatus&) message;
|
||
m_dfmStatusDialog.displayStatus(report.getDFMStatus());
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
void GS232ControllerGUI::handleInputMessages()
|
||
{
|
||
Message* message;
|
||
|
||
while ((message = getInputMessageQueue()->pop()))
|
||
{
|
||
if (handleMessage(*message)) {
|
||
delete message;
|
||
}
|
||
}
|
||
}
|
||
|
||
void GS232ControllerGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||
{
|
||
(void) widget;
|
||
(void) rollDown;
|
||
|
||
getRollupContents()->saveState(m_rollupState);
|
||
applySettings();
|
||
}
|
||
|
||
GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent) :
|
||
FeatureGUI(parent),
|
||
ui(new Ui::GS232ControllerGUI),
|
||
m_pluginAPI(pluginAPI),
|
||
m_featureUISet(featureUISet),
|
||
m_doApplySettings(true),
|
||
m_lastFeatureState(0),
|
||
m_lastOnTarget(false),
|
||
m_dfmStatusDialog()
|
||
{
|
||
m_feature = feature;
|
||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||
m_helpURL = "plugins/feature/gs232controller/readme.md";
|
||
RollupContents *rollupContents = getRollupContents();
|
||
ui->setupUi(rollupContents);
|
||
rollupContents->arrangeRollups();
|
||
connect(rollupContents, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||
|
||
m_gs232Controller = reinterpret_cast<GS232Controller*>(feature);
|
||
m_gs232Controller->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(250);
|
||
|
||
ui->coord1CurrentText->setText("-");
|
||
ui->coord2CurrentText->setText("-");
|
||
setProtocol(m_settings.m_protocol); // Hide DFM buttons
|
||
|
||
updateSerialPortList();
|
||
if (ui->serialPort->currentIndex() >= 0) {
|
||
on_serialPort_currentIndexChanged(ui->serialPort->currentIndex());
|
||
}
|
||
|
||
m_settings.setRollupState(&m_rollupState);
|
||
|
||
displaySettings();
|
||
applySettings(true);
|
||
makeUIConnections();
|
||
|
||
// Get pre-existing pipes
|
||
m_gs232Controller->getInputMessageQueue()->push(GS232Controller::MsgScanAvailableChannelOrFeatures::create());
|
||
|
||
new DialogPositioner(&m_dfmStatusDialog, true);
|
||
}
|
||
|
||
GS232ControllerGUI::~GS232ControllerGUI()
|
||
{
|
||
m_dfmStatusDialog.close();
|
||
delete ui;
|
||
}
|
||
|
||
void GS232ControllerGUI::setWorkspaceIndex(int index)
|
||
{
|
||
m_settings.m_workspaceIndex = index;
|
||
m_feature->setWorkspaceIndex(index);
|
||
}
|
||
|
||
void GS232ControllerGUI::blockApplySettings(bool block)
|
||
{
|
||
m_doApplySettings = !block;
|
||
}
|
||
|
||
void GS232ControllerGUI::displaySettings()
|
||
{
|
||
setTitleColor(m_settings.m_rgbColor);
|
||
setWindowTitle(m_settings.m_title);
|
||
setTitle(m_settings.m_title);
|
||
blockApplySettings(true);
|
||
ui->precision->setValue(m_settings.m_precision); // Must set before protocol and az/el
|
||
ui->protocol->setCurrentIndex((int)m_settings.m_protocol);
|
||
ui->coordinates->setCurrentIndex((int)m_settings.m_coordinates);
|
||
float coord1, coord2;
|
||
azElToDisplay(m_settings.m_azimuth, m_settings.m_elevation, coord1, coord2);
|
||
ui->coord1->setValue(coord1);
|
||
ui->coord2->setValue(coord2);
|
||
ui->connection->setCurrentIndex((int)m_settings.m_connection);
|
||
if (m_settings.m_serialPort.length() > 0) {
|
||
ui->serialPort->lineEdit()->setText(m_settings.m_serialPort);
|
||
}
|
||
ui->baudRate->setCurrentText(QString("%1").arg(m_settings.m_baudRate));
|
||
ui->host->setText(m_settings.m_host);
|
||
ui->port->setValue(m_settings.m_port);
|
||
ui->track->setChecked(m_settings.m_track);
|
||
ui->sources->setCurrentIndex(ui->sources->findText(m_settings.m_source));
|
||
ui->azimuthOffset->setValue(m_settings.m_azimuthOffset);
|
||
ui->elevationOffset->setValue(m_settings.m_elevationOffset);
|
||
ui->azimuthMin->setValue(m_settings.m_azimuthMin);
|
||
ui->azimuthMax->setValue(m_settings.m_azimuthMax);
|
||
ui->elevationMin->setValue(m_settings.m_elevationMin);
|
||
ui->elevationMax->setValue(m_settings.m_elevationMax);
|
||
ui->tolerance->setValue(m_settings.m_tolerance);
|
||
ui->dfmTrack->setChecked(m_settings.m_dfmTrackOn);
|
||
ui->dfmLubePumps->setChecked(m_settings.m_dfmLubePumpsOn);
|
||
ui->dfmBrakes->setChecked(m_settings.m_dfmBrakesOn);
|
||
ui->dfmDrives->setChecked(m_settings.m_dfmDrivesOn);
|
||
getRollupContents()->restoreState(m_rollupState);
|
||
updateConnectionWidgets();
|
||
blockApplySettings(false);
|
||
}
|
||
|
||
void GS232ControllerGUI::updateConnectionWidgets()
|
||
{
|
||
bool serial = m_settings.m_connection == GS232ControllerSettings::SERIAL;
|
||
ui->serialPortLabel->setVisible(serial);
|
||
ui->serialPort->setVisible(serial);
|
||
ui->baudRateLabel->setVisible(serial);
|
||
ui->baudRate->setVisible(serial);
|
||
ui->hostLabel->setVisible(!serial);
|
||
ui->host->setVisible(!serial);
|
||
ui->portLabel->setVisible(!serial);
|
||
ui->port->setVisible(!serial);
|
||
}
|
||
|
||
void GS232ControllerGUI::updateSerialPortList()
|
||
{
|
||
ui->serialPort->clear();
|
||
QList<QSerialPortInfo> serialPorts = QSerialPortInfo::availablePorts();
|
||
QListIterator<QSerialPortInfo> i(serialPorts);
|
||
while (i.hasNext())
|
||
{
|
||
QSerialPortInfo info = i.next();
|
||
ui->serialPort->addItem(info.portName());
|
||
}
|
||
}
|
||
|
||
void GS232ControllerGUI::updateSerialPortList(const QStringList& serialPorts)
|
||
{
|
||
ui->serialPort->blockSignals(true);
|
||
ui->serialPort->clear();
|
||
for (const auto& serialPort : serialPorts) {
|
||
ui->serialPort->addItem(serialPort);
|
||
}
|
||
if (!m_settings.m_serialPort.isEmpty()) {
|
||
ui->serialPort->setCurrentText(m_settings.m_serialPort);
|
||
}
|
||
ui->serialPort->blockSignals(false);
|
||
}
|
||
|
||
void GS232ControllerGUI::updatePipeList(const QList<GS232ControllerSettings::AvailableChannelOrFeature>& sources)
|
||
{
|
||
QString currentText = ui->sources->currentText();
|
||
QString newText;
|
||
ui->sources->blockSignals(true);
|
||
ui->sources->clear();
|
||
|
||
for (const auto& source : sources)
|
||
{
|
||
QString name = tr("%1%2:%3 %4")
|
||
.arg(source.m_kind)
|
||
.arg(source.m_superIndex)
|
||
.arg(source.m_index)
|
||
.arg(source.m_type);
|
||
ui->sources->addItem(name);
|
||
}
|
||
|
||
int index = ui->sources->findText(m_settings.m_source);
|
||
ui->sources->setCurrentIndex(index);
|
||
|
||
if (index < 0) // current source is not found
|
||
{
|
||
m_settings.m_source = "";
|
||
ui->targetName->setText("");
|
||
m_settingsKeys.append("source");
|
||
applySettings();
|
||
}
|
||
|
||
// if (currentText.isEmpty())
|
||
// {
|
||
// // Source feature may be loaded after this, so may not have existed when
|
||
// // displaySettings was called
|
||
// if (sources.size() > 0) {
|
||
// ui->sources->setCurrentIndex(ui->sources->findText(m_settings.m_source));
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// ui->sources->setCurrentIndex(ui->sources->findText(currentText));
|
||
// }
|
||
|
||
ui->sources->blockSignals(false);
|
||
|
||
// QString newText = ui->sources->currentText();
|
||
|
||
// if (currentText != newText)
|
||
// {
|
||
// m_settings.m_source = newText;
|
||
// ui->targetName->setText("");
|
||
// applySettings();
|
||
// }
|
||
}
|
||
|
||
void GS232ControllerGUI::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);
|
||
dialog.setDefaultTitle(m_displayedName);
|
||
|
||
dialog.move(p);
|
||
new DialogPositioner(&dialog, false);
|
||
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();
|
||
|
||
setTitle(m_settings.m_title);
|
||
setTitleColor(m_settings.m_rgbColor);
|
||
|
||
m_settingsKeys.append("title");
|
||
m_settingsKeys.append("rgbColor");
|
||
m_settingsKeys.append("useReverseAPI");
|
||
m_settingsKeys.append("reverseAPIAddress");
|
||
m_settingsKeys.append("reverseAPIPort");
|
||
m_settingsKeys.append("reverseAPIFeatureSetIndex");
|
||
m_settingsKeys.append("reverseAPIFeatureIndex");
|
||
|
||
applySettings();
|
||
}
|
||
|
||
resetContextMenuType();
|
||
}
|
||
|
||
void GS232ControllerGUI::on_startStop_toggled(bool checked)
|
||
{
|
||
if (m_doApplySettings)
|
||
{
|
||
GS232Controller::MsgStartStop *message = GS232Controller::MsgStartStop::create(checked);
|
||
m_gs232Controller->getInputMessageQueue()->push(message);
|
||
}
|
||
}
|
||
|
||
void GS232ControllerGUI::setProtocol(GS232ControllerSettings::Protocol protocol)
|
||
{
|
||
if (protocol == GS232ControllerSettings::GS232)
|
||
{
|
||
ui->precision->setValue(0);
|
||
ui->precision->setEnabled(false);
|
||
ui->precisionLabel->setEnabled(false);
|
||
}
|
||
else if (protocol == GS232ControllerSettings::SPID)
|
||
<EFBFBD> |