mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-22 23:05:36 +08:00
In order to better identify the models, the model members have been prefixed with "model"
393 lines
14 KiB
C++
393 lines
14 KiB
C++
#include "mainwindow.h"
|
|
#include "ui_mainwindow.h"
|
|
#include "blackgui/atcstationlistmodel.h"
|
|
#include "blackcore/dbus_server.h"
|
|
#include "blackcore/context_network.h"
|
|
#include "blackmisc/vvoiceroom.h"
|
|
|
|
using namespace BlackCore;
|
|
using namespace BlackMisc;
|
|
using namespace BlackGui;
|
|
using namespace BlackMisc::Network;
|
|
using namespace BlackMisc::Aviation;
|
|
using namespace BlackMisc::PhysicalQuantities;
|
|
using namespace BlackMisc::Geo;
|
|
using namespace BlackMisc::Settings;
|
|
using namespace BlackMisc::Math;
|
|
using namespace BlackMisc::Voice;
|
|
|
|
/*
|
|
* Cockpit values
|
|
*/
|
|
void MainWindow::cockpitValuesChanged()
|
|
{
|
|
Q_ASSERT(this->m_timerCollectedCockpitUpdates);
|
|
|
|
// frequency switch?
|
|
QObject *sender = QObject::sender();
|
|
if (sender == this->ui->pb_CockpitToggleCom1)
|
|
{
|
|
if (this->ui->ds_CockpitCom1Standby->value() == this->ui->ds_CockpitCom1Active->value()) return;
|
|
double f = this->ui->ds_CockpitCom1Active->value();
|
|
this->ui->ds_CockpitCom1Active->setValue(this->ui->ds_CockpitCom1Standby->value());
|
|
this->ui->ds_CockpitCom1Standby->setValue(f);
|
|
}
|
|
else if (sender == this->ui->pb_CockpitToggleCom2)
|
|
{
|
|
if (this->ui->ds_CockpitCom2Standby->value() == this->ui->ds_CockpitCom2Active->value()) return;
|
|
double f = this->ui->ds_CockpitCom2Active->value();
|
|
this->ui->ds_CockpitCom2Active->setValue(this->ui->ds_CockpitCom2Standby->value());
|
|
this->ui->ds_CockpitCom2Standby->setValue(f);
|
|
}
|
|
else if (sender == this->ui->pb_CockpitIdent)
|
|
{
|
|
// trigger the real button
|
|
if (this->ui->cb_CockpitTransponderMode->currentText() == "I")
|
|
{
|
|
this->ui->pb_CockpitIdent->setStyleSheet("");
|
|
this->resetTransponderMode();
|
|
}
|
|
else
|
|
{
|
|
this->ui->pb_CockpitIdent->setStyleSheet("background: red");
|
|
this->ui->cb_CockpitTransponderMode->setCurrentText("I"); // trigger real button and whole process
|
|
}
|
|
return;
|
|
}
|
|
|
|
// this will call send cockpit updates with all changes made
|
|
// send cockpit updates
|
|
this->m_timerCollectedCockpitUpdates->stop();
|
|
this->m_timerCollectedCockpitUpdates->start(1000); // start
|
|
this->m_timerCollectedCockpitUpdates->setSingleShot(true);
|
|
}
|
|
|
|
/*
|
|
* Is pending update
|
|
*/
|
|
bool MainWindow::isCockpitUpdatePending() const
|
|
{
|
|
return (this->m_timerCollectedCockpitUpdates && this->m_timerCollectedCockpitUpdates->isActive());
|
|
}
|
|
|
|
/*
|
|
* Own cockpit
|
|
*/
|
|
void MainWindow::updateCockpitFromContext()
|
|
{
|
|
// update GUI elements
|
|
// avoid unnecessary change events as far as possible
|
|
const CComSystem com1 = this->m_ownAircraft.getCom1System(); // aircraft just updated or set from context
|
|
const CComSystem com2 = this->m_ownAircraft.getCom2System();
|
|
const CTransponder transponder = this->m_ownAircraft.getTransponder();
|
|
|
|
// update the frequencies
|
|
this->updateComFrequencyDisplays(com1, com2);
|
|
|
|
if (this->m_inputFocusedWidget != this->ui->ds_CockpitTransponder)
|
|
{
|
|
// update transponder if this is not input focused
|
|
qint32 tc = transponder.getTransponderCode();
|
|
if (tc != static_cast<qint32>(this->ui->ds_CockpitTransponder->value()))
|
|
this->ui->ds_CockpitTransponder->setValue(tc);
|
|
}
|
|
|
|
QString tm = this->ui->cb_CockpitTransponderMode->currentText().trimmed().toUpper();
|
|
switch (transponder.getTransponderMode())
|
|
{
|
|
case CTransponder::StateStandby:
|
|
case CTransponder::ModeS:
|
|
if (tm != "S")
|
|
this->ui->cb_CockpitTransponderMode->setCurrentText("S");
|
|
break;
|
|
case CTransponder::ModeC:
|
|
if (tm != "C")
|
|
this->ui->cb_CockpitTransponderMode->setCurrentText("C");
|
|
break;
|
|
case CTransponder::StateIdent:
|
|
if (tm != "I")
|
|
this->ui->cb_CockpitTransponderMode->setCurrentText("I");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (this->m_contextNetworkAvailable)
|
|
{
|
|
CAtcStationList selectedStations = this->m_contextNetwork->getSelectedAtcStations();
|
|
CAtcStation com1Station = selectedStations[0];
|
|
CAtcStation com2Station = selectedStations[1];
|
|
if (com1Station.getCallsign().isEmpty())
|
|
this->ui->lbl_CockpitCom1->setToolTip("");
|
|
else
|
|
this->ui->lbl_CockpitCom1->setToolTip(com1Station.getCallsign().getStringAsSet());
|
|
if (com2Station.getCallsign().isEmpty())
|
|
this->ui->lbl_CockpitCom2->setToolTip("");
|
|
else
|
|
this->ui->lbl_CockpitCom2->setToolTip(com2Station.getCallsign().getStringAsSet());
|
|
}
|
|
|
|
//
|
|
// Voice room override
|
|
//
|
|
if (this->m_contextVoiceAvailable)
|
|
{
|
|
// get all rooms, it is important to get the rooms from voice context here
|
|
// these are the ones featuring the real audio status
|
|
CVoiceRoomList rooms = this->m_contextVoice->getComVoiceRoomsWithAudioStatus();
|
|
Q_ASSERT(rooms.size() == 2);
|
|
Q_ASSERT(this->m_modelUsersVoiceCom1);
|
|
Q_ASSERT(this->m_modelUsersVoiceCom2);
|
|
|
|
CVoiceRoom room1 = rooms[0];
|
|
CVoiceRoom room2 = rooms[1];
|
|
bool com1Connected = room1.isConnected();
|
|
bool com2Connected = room2.isConnected();
|
|
|
|
// update views
|
|
this->m_modelUsersVoiceCom1->update(this->m_contextVoice->getCom1RoomUsers());
|
|
this->ui->tv_CockpitVoiceRoom1->resizeColumnsToContents();
|
|
this->ui->tv_CockpitVoiceRoom1->resizeRowsToContents();
|
|
this->ui->tv_CockpitVoiceRoom1->horizontalHeader()->setStretchLastSection(true);
|
|
|
|
this->m_modelUsersVoiceCom2->update(this->m_contextVoice->getCom2RoomUsers());
|
|
this->ui->tv_CockpitVoiceRoom2->resizeColumnsToContents();
|
|
this->ui->tv_CockpitVoiceRoom2->resizeRowsToContents();
|
|
this->ui->tv_CockpitVoiceRoom2->horizontalHeader()->setStretchLastSection(true);
|
|
|
|
// highlite voice room according to status
|
|
QString vrStyle1;
|
|
QString vrStyle2;
|
|
if (!room1.getVoiceRoomUrl(true).isEmpty()) vrStyle1 = com1Connected ? "background: green" : "background: red";
|
|
if (!room2.getVoiceRoomUrl(true).isEmpty()) vrStyle2 = com2Connected ? "background: green" : "background: red";
|
|
this->ui->le_CockpitVoiceRoomCom1->setStyleSheet(vrStyle1);
|
|
this->ui->le_CockpitVoiceRoomCom2->setStyleSheet(vrStyle2);
|
|
|
|
// display URL if not override mode
|
|
if (!this->ui->cb_CockpitVoiceRoom1Override->isChecked())
|
|
{
|
|
// no override
|
|
QString s = room1.getVoiceRoomUrl();
|
|
this->ui->le_CockpitVoiceRoomCom1->setText(s);
|
|
}
|
|
|
|
// display URL if not override mode
|
|
if (!this->ui->cb_CockpitVoiceRoom2Override->isChecked())
|
|
{
|
|
// no overrride
|
|
QString s = room2.getVoiceRoomUrl();
|
|
this->ui->le_CockpitVoiceRoomCom2->setText(s);
|
|
}
|
|
}
|
|
|
|
// update some other GUI elements
|
|
this->ui->tw_TextMessages->setTabToolTip(this->ui->tw_TextMessages->indexOf(this->ui->tb_TextMessagesCOM1), com1.getFrequencyActive().valueRoundedWithUnit(3));
|
|
this->ui->tw_TextMessages->setTabToolTip(this->ui->tw_TextMessages->indexOf(this->ui->tb_TextMessagesCOM2), com2.getFrequencyActive().valueRoundedWithUnit(3));
|
|
}
|
|
|
|
/*
|
|
* Round the com frequency displays
|
|
*/
|
|
void MainWindow::updateComFrequencyDisplays(const CComSystem &com1, const CComSystem &com2)
|
|
{
|
|
// do not just set! Leads to unwanted signals fired
|
|
// only update if not focused
|
|
|
|
if (this->m_inputFocusedWidget != ui->ds_CockpitCom1Active)
|
|
{
|
|
double freq = com1.getFrequencyActive().valueRounded(3);
|
|
if (freq != this->ui->ds_CockpitCom1Active->value())
|
|
this->ui->ds_CockpitCom1Active->setValue(freq);
|
|
}
|
|
|
|
if (this->m_inputFocusedWidget != ui->ds_CockpitCom2Active)
|
|
{
|
|
double freq = com2.getFrequencyActive().valueRounded(3);
|
|
if (freq != this->ui->ds_CockpitCom2Active->value())
|
|
this->ui->ds_CockpitCom2Active->setValue(freq);
|
|
}
|
|
|
|
if (this->m_inputFocusedWidget != ui->ds_CockpitCom1Standby)
|
|
{
|
|
double freq = com1.getFrequencyStandby().valueRounded(3);
|
|
if (freq != this->ui->ds_CockpitCom1Standby->value())
|
|
this->ui->ds_CockpitCom1Standby->setValue(freq);
|
|
}
|
|
|
|
if (this->m_inputFocusedWidget != ui->ds_CockpitCom2Standby)
|
|
{
|
|
double freq = com2.getFrequencyStandby().valueRounded(3);
|
|
if (freq != this->ui->ds_CockpitCom2Standby->value())
|
|
this->ui->ds_CockpitCom2Standby->setValue(freq);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Reset transponder mode to Standby / Charly
|
|
*/
|
|
void MainWindow::resetTransponderMode()
|
|
{
|
|
this->ui->pb_CockpitIdent->setStyleSheet("");
|
|
if (this->ui->cb_CockpitTransponderMode->currentText() == "I")
|
|
{
|
|
// only reset if still "I"
|
|
this->ui->cb_CockpitTransponderMode->setCurrentText(this->m_transponderResetValue);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Send cockpit updates
|
|
*/
|
|
void MainWindow::sendCockpitUpdates()
|
|
{
|
|
CTransponder transponder = this->m_ownAircraft.getTransponder();
|
|
CComSystem com1 = this->m_ownAircraft.getCom1System();
|
|
CComSystem com2 = this->m_ownAircraft.getCom2System();
|
|
|
|
//
|
|
// Transponder
|
|
//
|
|
QString transponderCode = QString::number(qRound(this->ui->ds_CockpitTransponder->value()));
|
|
if (CTransponder::isValidTransponderCode(transponderCode))
|
|
{
|
|
transponder.setTransponderCode(transponderCode);
|
|
}
|
|
else
|
|
{
|
|
this->displayStatusMessage(CStatusMessage::getValidationError("Wrong transponder code, reset"));
|
|
this->ui->ds_CockpitTransponder->setValue(transponder.getTransponderCode());
|
|
}
|
|
|
|
QString tm = this->ui->cb_CockpitTransponderMode->currentText().toUpper();
|
|
if (tm == "S")
|
|
transponder.setTransponderMode(CTransponder::ModeS);
|
|
else if (tm == "C")
|
|
transponder.setTransponderMode(CTransponder::ModeC);
|
|
else if (tm == "I")
|
|
{
|
|
// ident shall be sent for some time, then reset
|
|
transponder.setTransponderMode(CTransponder::StateIdent);
|
|
this->ui->pb_CockpitIdent->setStyleSheet("background: red");
|
|
if (this->m_ownAircraft.getTransponderMode() == CTransponder::ModeS)
|
|
{
|
|
this->m_transponderResetValue = "S";
|
|
}
|
|
else
|
|
{
|
|
this->m_transponderResetValue = "C";
|
|
}
|
|
QTimer::singleShot(5000, this, SLOT(resetTransponderMode()));
|
|
}
|
|
|
|
//
|
|
// COM units
|
|
//
|
|
com1.setFrequencyActiveMHz(this->ui->ds_CockpitCom1Active->value());
|
|
com1.setFrequencyStandbyMHz(this->ui->ds_CockpitCom1Standby->value());
|
|
com2.setFrequencyActiveMHz(this->ui->ds_CockpitCom2Active->value());
|
|
com2.setFrequencyStandbyMHz(this->ui->ds_CockpitCom2Standby->value());
|
|
this->updateComFrequencyDisplays(com1, com2);
|
|
|
|
//
|
|
// Send to context
|
|
//
|
|
bool changedCockpit = false;
|
|
if (this->m_contextNetworkAvailable)
|
|
{
|
|
if (this->m_ownAircraft.getCom1System() != com1 ||
|
|
this->m_ownAircraft.getCom2System() != com2 ||
|
|
this->m_ownAircraft.getTransponder() != transponder)
|
|
{
|
|
this->m_contextNetwork->updateOwnCockpit(com1, com2, transponder);
|
|
this->reloadOwnAircraft(); // also loads resolved voice rooms
|
|
changedCockpit = true;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now with the new voice room data, really set the
|
|
// voice rooms in the context
|
|
//
|
|
if (changedCockpit) this->setAudioVoiceRooms();
|
|
}
|
|
|
|
/*
|
|
* Voice room override
|
|
*/
|
|
void MainWindow::setAudioVoiceRooms()
|
|
{
|
|
if (!this->m_contextVoiceAvailable) return;
|
|
if (!this->m_contextNetworkAvailable) return;
|
|
|
|
// make fields readonly if not overriding
|
|
this->ui->le_CockpitVoiceRoomCom1->setReadOnly(!this->ui->cb_CockpitVoiceRoom1Override->isChecked());
|
|
this->ui->le_CockpitVoiceRoomCom2->setReadOnly(!this->ui->cb_CockpitVoiceRoom2Override->isChecked());
|
|
|
|
CVoiceRoom room1;
|
|
CVoiceRoom room2;
|
|
CVoiceRoomList selectedVoiceRooms = this->m_contextNetwork->getSelectedVoiceRooms();
|
|
Q_ASSERT(selectedVoiceRooms.size() == 2);
|
|
|
|
if (this->ui->cb_CockpitVoiceRoom1Override->isChecked())
|
|
room1 = CVoiceRoom(this->ui->le_CockpitVoiceRoomCom1->text().trimmed());
|
|
else
|
|
{
|
|
room1 = selectedVoiceRooms[0];
|
|
room1.setAudioPlaying(true);
|
|
this->ui->le_CockpitVoiceRoomCom1->setText(room1.getVoiceRoomUrl());
|
|
}
|
|
|
|
if (this->ui->cb_CockpitVoiceRoom2Override->isChecked())
|
|
room2 = CVoiceRoom(this->ui->le_CockpitVoiceRoomCom1->text().trimmed());
|
|
else
|
|
{
|
|
room2 = selectedVoiceRooms[1];
|
|
room2.setAudioPlaying(true);
|
|
this->ui->le_CockpitVoiceRoomCom2->setText(room2.getVoiceRoomUrl());
|
|
}
|
|
|
|
// set the real voice rooms for audio output
|
|
this->m_contextVoice->setComVoiceRooms(room1, room2);
|
|
}
|
|
|
|
/*
|
|
* Test SELCAL code
|
|
*/
|
|
void MainWindow::testSelcal()
|
|
{
|
|
QString selcalCode = this->getSelcalCode();
|
|
if (!CSelcal::isValidCode(selcalCode))
|
|
{
|
|
this->displayStatusMessage(
|
|
CStatusMessage(CStatusMessage::TypeValidation, CStatusMessage::SeverityWarning, "invalid SELCAL codde"));
|
|
return;
|
|
}
|
|
if (this->m_contextVoiceAvailable)
|
|
{
|
|
CSelcal selcal(selcalCode);
|
|
this->m_contextVoice->playSelcalTone(selcal);
|
|
}
|
|
else
|
|
{
|
|
this->displayStatusMessage(CStatusMessage(CStatusMessage::TypeAudio, CStatusMessage::SeverityError, "No audi available"));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SELCAL value selected
|
|
*/
|
|
QString MainWindow::getSelcalCode() const
|
|
{
|
|
QString selcal = this->ui->cb_CockpitSelcal1->currentText().append(this->ui->cb_CockpitSelcal2->currentText());
|
|
return selcal;
|
|
}
|
|
|
|
/*
|
|
* Current input focus
|
|
*/
|
|
void MainWindow::inputFocusChanged(QWidget *oldWidget, QWidget *newWidget)
|
|
{
|
|
Q_UNUSED(oldWidget);
|
|
this->m_inputFocusedWidget = newWidget;
|
|
}
|