Files
pilotclient/src/blackgui/components/cockpitcomcomponent.cpp
Klaus Basan adba17da0f refs #335, improved size handling for cockpit
* minimum values set to avoid issues when docked
* no manual values when just toggled floating
2014-11-30 00:54:40 +01:00

301 lines
14 KiB
C++

/* Copyright (C) 2013
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "cockpitcomcomponent.h"
#include "ui_cockpitcomcomponent.h"
#include "../stylesheetutility.h"
#include "blackcore/context_network.h"
#include "blackcore/context_ownaircraft.h"
#include "blackcore/context_audio.h"
#include "blackmisc/avaircraft.h"
#include "blackmisc/voiceroomlist.h"
#include "blackmisc/logmessage.h"
#include <QDoubleSpinBox>
#include <QPushButton>
using namespace BlackGui;
using namespace BlackCore;
using namespace BlackMisc::Audio;
using namespace BlackMisc::Aviation;
using namespace BlackMisc::PhysicalQuantities;
namespace BlackGui
{
namespace Components
{
CCockpitComComponent::CCockpitComComponent(QWidget *parent) :
QFrame(parent),
ui(new Ui::CCockpitMainComponent)
{
ui->setupUi(this);
this->initLeds();
QObject::connect(this->ui->cbp_ComPanelTransponderMode, &CTransponderModeSelector::transponderModeChanged, this, &CCockpitComComponent::transponderModeChanged);
QObject::connect(this->ui->cbp_ComPanelTransponderMode, &CTransponderModeSelector::transponderStateIdentEnded, this, &CCockpitComComponent::transponderStateIdentEnded);
}
CCockpitComComponent::~CCockpitComComponent()
{ }
void CCockpitComComponent::setSelectedTransponderModeStateIdent()
{
this->ui->cbp_ComPanelTransponderMode->setSelectedTransponderModeStateIdent();
}
void CCockpitComComponent::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
CStyleSheetUtility::useStyleSheetInDerivedWidget(this);
}
void CCockpitComComponent::runtimeHasBeenSet()
{
// SELCAL pairs in cockpit
this->ui->frp_ComPanelSelcalBottom->clear();
connect(this->ui->pb_ComPanelSelcalTest, &QPushButton::clicked, this, &CCockpitComComponent::ps_testSelcal);
// COM GUI events
connect(this->ui->pb_ComPanelCom1Toggle, &QPushButton::clicked, this, &CCockpitComComponent::ps_guiChangedCockpitValues);
connect(this->ui->pb_ComPanelCom2Toggle, &QPushButton::clicked, this, &CCockpitComComponent::ps_guiChangedCockpitValues);
connect(this->ui->ds_ComPanelCom1Active, &QDoubleSpinBox::editingFinished, this, &CCockpitComComponent::ps_guiChangedCockpitValues);
connect(this->ui->ds_ComPanelCom2Active, &QDoubleSpinBox::editingFinished, this, &CCockpitComComponent::ps_guiChangedCockpitValues);
connect(this->ui->ds_ComPanelCom1Standby, &QDoubleSpinBox::editingFinished, this, &CCockpitComComponent::ps_guiChangedCockpitValues);
connect(this->ui->ds_ComPanelCom2Standby, &QDoubleSpinBox::editingFinished, this, &CCockpitComComponent::ps_guiChangedCockpitValues);
connect(this->ui->sbp_ComPanelTransponder, &QDoubleSpinBox::editingFinished, this, &CCockpitComComponent::ps_guiChangedCockpitValues);
connect(this->ui->cbp_ComPanelTransponderMode, &CTransponderModeSelector::transponderModeChanged, this, &CCockpitComComponent::ps_guiChangedCockpitValues);
connect(this->ui->frp_ComPanelSelcalBottom, &CSelcalCodeSelector::valueChanged, this, &CCockpitComComponent::ps_guiChangedSelcal);
// hook up with changes from own aircraft context
Q_ASSERT(this->getIContextOwnAircraft());
this->connect(this->getIContextOwnAircraft(), &IContextOwnAircraft::changedAircraftCockpit, this, &CCockpitComComponent::ps_updateCockpitFromContext);
this->connect(this->getIContextOwnAircraft(), &IContextOwnAircraft::changedSelcal, this, &CCockpitComComponent::ps_onChangedSelcal);
// hook up with audio context
Q_ASSERT(this->getIContextAudio());
this->connect(this->getIContextAudio(), &IContextAudio::changedVoiceRooms, this, &CCockpitComComponent::ps_onChangedVoiceRoomStatus);
}
void CCockpitComComponent::ps_guiChangedCockpitValues()
{
QObject *sender = QObject::sender();
if (sender == this->ui->pb_ComPanelCom1Toggle)
{
if (this->ui->ds_ComPanelCom1Standby->value() == this->ui->ds_ComPanelCom1Active->value()) return;
double f = this->ui->ds_ComPanelCom1Active->value();
this->ui->ds_ComPanelCom1Active->setValue(this->ui->ds_ComPanelCom1Standby->value());
this->ui->ds_ComPanelCom1Standby->setValue(f);
}
else if (sender == this->ui->pb_ComPanelCom2Toggle)
{
if (this->ui->ds_ComPanelCom2Standby->value() == this->ui->ds_ComPanelCom2Active->value()) return;
double f = this->ui->ds_ComPanelCom2Active->value();
this->ui->ds_ComPanelCom2Active->setValue(this->ui->ds_ComPanelCom2Standby->value());
this->ui->ds_ComPanelCom2Standby->setValue(f);
}
else if (sender == this->ui->cbp_ComPanelTransponderMode)
{
// toggle the external button
if (this->ui->cbp_ComPanelTransponderMode->isIdentSelected())
{
// todo
}
}
const CAircraft ownAircraft = this->cockpitValuesToAircraftObject();
this->updateOwnCockpitInContext(ownAircraft);
}
void CCockpitComComponent::ps_guiChangedSelcal()
{
this->getIContextOwnAircraft()->updateSelcal(this->getSelcal(), cockpitOriginator());
}
void CCockpitComComponent::ps_updateCockpitFromContext(const CAircraft &ownAircraft, const QString &originator)
{
if (originator == CCockpitComComponent::cockpitOriginator()) return; // comes from myself
// update GUI elements
// avoid unnecessary change events as far as possible
const CComSystem com1 = ownAircraft.getCom1System(); // aircraft just updated or set from context
const CComSystem com2 = ownAircraft.getCom2System();
const CTransponder transponder = ownAircraft.getTransponder();
// update the frequencies
this->updateFrequencyDisplaysFromComSystems(com1, com2);
// update transponder
qint32 tc = transponder.getTransponderCode();
if (tc != static_cast<qint32>(this->ui->sbp_ComPanelTransponder->value()))
this->ui->sbp_ComPanelTransponder->setValue(tc);
this->ui->cbp_ComPanelTransponderMode->setSelectedTransponderMode(transponder.getTransponderMode());
if (this->getIContextNetwork())
{
CAtcStationList selectedStations = this->getIContextNetwork()->getSelectedAtcStations();
CAtcStation com1Station = selectedStations[0];
CAtcStation com2Station = selectedStations[1];
if (com1Station.getCallsign().isEmpty())
{
this->ui->lbl_ComPanelCom1Active->setToolTip("");
this->ui->led_ComPanelCom1->setOn(false);
}
else
{
this->ui->lbl_ComPanelCom1Active->setToolTip(com1Station.getCallsign().getStringAsSet());
this->ui->led_ComPanelCom1->setOn(true);
}
if (com2Station.getCallsign().isEmpty())
{
this->ui->lbl_ComPanelCom2Active->setToolTip("");
this->ui->led_ComPanelCom2->setOn(false);
}
else
{
this->ui->lbl_ComPanelCom2Active->setToolTip(com2Station.getCallsign().getStringAsSet());
this->ui->led_ComPanelCom2->setOn(true);
}
}
}
void CCockpitComComponent::ps_testSelcal()
{
CSelcal selcal = this->getSelcal();
if (!selcal.isValid())
{
CLogMessage().validationWarning("Invalid SELCAL code");
}
else if (this->getIContextAudio())
{
CSelcal selcal(selcal);
this->getIContextAudio()->playSelcalTone(selcal);
}
else
{
CLogMessage().validationWarning("No audio available");
}
}
void CCockpitComComponent::ps_onChangedSelcal(const CSelcal &selcal, const QString &originator)
{
if (originator == CCockpitComComponent::cockpitOriginator()) return; // comes from myself
this->ui->frp_ComPanelSelcalBottom->setSelcalCode(selcal);
}
CSelcal CCockpitComComponent::getSelcal() const
{
return ui->frp_ComPanelSelcalBottom->getSelcal();
}
void CCockpitComComponent::initLeds()
{
CLedWidget::LedShape shape = CLedWidget::Rounded;
this->ui->led_ComPanelCom1->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "COM1 connected", "COM1 disconnected", 14);
this->ui->led_ComPanelCom2->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "COM2 connected", "COM2 disconnected", 14);
}
CAircraft CCockpitComComponent::cockpitValuesToAircraftObject()
{
CAircraft ownAircraft = this->getOwnAircraft();
CTransponder transponder = ownAircraft.getTransponder();
CComSystem com1 = ownAircraft.getCom1System();
CComSystem com2 = ownAircraft.getCom2System();
//
// Transponder
//
QString transponderCode = QString::number(this->ui->sbp_ComPanelTransponder->value());
if (CTransponder::isValidTransponderCode(transponderCode))
{
transponder.setTransponderCode(transponderCode);
}
else
{
CLogMessage().validationWarning("Wrong transponder code, reset");
this->ui->sbp_ComPanelTransponder->setValue(transponder.getTransponderCode());
}
transponder.setTransponderMode(this->ui->cbp_ComPanelTransponderMode->getSelectedTransponderMode());
//
// COM units
//
com1.setFrequencyActiveMHz(this->ui->ds_ComPanelCom1Active->value());
com1.setFrequencyStandbyMHz(this->ui->ds_ComPanelCom1Standby->value());
com2.setFrequencyActiveMHz(this->ui->ds_ComPanelCom2Active->value());
com2.setFrequencyStandbyMHz(this->ui->ds_ComPanelCom2Standby->value());
this->updateFrequencyDisplaysFromComSystems(com1, com2); // back annotation after rounding
ownAircraft.setCom1System(com1);
ownAircraft.setCom2System(com2);
ownAircraft.setTransponder(transponder);
return ownAircraft;
}
CAircraft CCockpitComComponent::getOwnAircraft() const
{
Q_ASSERT(this->getIContextOwnAircraft());
if (!this->getIContextOwnAircraft()) return CAircraft();
return this->getIContextOwnAircraft()->getOwnAircraft();
}
bool CCockpitComComponent::updateOwnCockpitInContext(const CAircraft &ownAircraft)
{
return this->getIContextOwnAircraft()->updateOwnCockpit(ownAircraft.getCom1System(), ownAircraft.getCom2System(), ownAircraft.getTransponder(), CCockpitComComponent::cockpitOriginator());
}
void CCockpitComComponent::updateFrequencyDisplaysFromComSystems(const CComSystem &com1, const CComSystem &com2)
{
double freq = com1.getFrequencyActive().valueRounded(CFrequencyUnit::MHz(), 3);
if (freq != this->ui->ds_ComPanelCom1Active->value())
{
this->ui->ds_ComPanelCom1Active->setValue(freq);
}
freq = com2.getFrequencyActive().valueRounded(CFrequencyUnit::MHz(), 3);
if (freq != this->ui->ds_ComPanelCom2Active->value())
{
this->ui->ds_ComPanelCom2Active->setValue(freq);
}
freq = com1.getFrequencyStandby().valueRounded(CFrequencyUnit::MHz(), 3);
if (freq != this->ui->ds_ComPanelCom1Standby->value())
{
this->ui->ds_ComPanelCom1Standby->setValue(freq);
}
freq = com2.getFrequencyStandby().valueRounded(CFrequencyUnit::MHz(), 3);
if (freq != this->ui->ds_ComPanelCom2Standby->value())
{
this->ui->ds_ComPanelCom2Standby->setValue(freq);
}
}
void CCockpitComComponent::ps_onChangedVoiceRoomStatus(const CVoiceRoomList &selectedVoiceRooms, bool connected)
{
Q_ASSERT(selectedVoiceRooms.size() == 2);
CVoiceRoom room1 = selectedVoiceRooms[0];
CVoiceRoom room2 = selectedVoiceRooms[1];
this->ui->led_ComPanelCom1->setOn(room1.isConnected());
this->ui->led_ComPanelCom2->setOn(room2.isConnected());
Q_UNUSED(connected);
}
const QString &CCockpitComComponent::cockpitOriginator()
{
// string is generated once, the timestamp allows to use multiple
// components (as long as they are not generated at the same ms)
static const QString o = QString("COCKPITCOMCOMPONENT:").append(QString::number(QDateTime::currentMSecsSinceEpoch()));
return o;
}
} // namespace
} // namespace